win32 interface: prevent recursion when redirecting a WM_MOUSEWHEEL message

git-svn-id: trunk@10845 -
This commit is contained in:
vincents 2007-04-01 20:57:35 +00:00
parent a0cd202e73
commit 50948b0577
2 changed files with 43 additions and 39 deletions

View File

@ -83,12 +83,12 @@ begin
MessageStackDepth[depthLen] := '#'; MessageStackDepth[depthLen] := '#';
{$endif} {$endif}
PrevWndProc := GetWindowInfo(Window)^.DefWndProc; PrevWndProc := GetWindowInfo(Window)^.DefWndProc;
if PrevWndProc = nil if PrevWndProc = nil
then begin then begin
if UnicodeEnabledOS if UnicodeEnabledOS
then Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam) then Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam)
else Result := Windows.DefWindowProc(Window, Msg, WParam, LParam) else Result := Windows.DefWindowProc(Window, Msg, WParam, LParam)
end end
else begin else begin
// combobox child edit weirdness: combobox handling WM_SIZE will compare text // combobox child edit weirdness: combobox handling WM_SIZE will compare text
// to list of strings, and if appears in there, will set the text, and select it // to list of strings, and if appears in there, will set the text, and select it
@ -163,7 +163,7 @@ end;
function GetNeedParentPaint(AWindowInfo: PWindowInfo; AWinControl: TWinControl): boolean; function GetNeedParentPaint(AWindowInfo: PWindowInfo; AWinControl: TWinControl): boolean;
begin begin
Result := AWindowInfo^.needParentPaint Result := AWindowInfo^.needParentPaint
and ((AWinControl = nil) or not (csOpaque in AWinControl.ControlStyle)); and ((AWinControl = nil) or not (csOpaque in AWinControl.ControlStyle));
end; end;
@ -177,8 +177,8 @@ type
Length : Integer; Length : Integer;
Position : Integer; Position : Integer;
UserData : Pointer; UserData : Pointer;
end; end;
TCustomListViewAccess = class(TCustomListView) TCustomListViewAccess = class(TCustomListView)
end; end;
@ -232,7 +232,7 @@ Var
LMNotify: TLMNotify; // used by WM_NOTIFY LMNotify: TLMNotify; // used by WM_NOTIFY
DrawListItemStruct: TDrawListItemStruct; //used by WM_DRAWITEM DrawListItemStruct: TDrawListItemStruct; //used by WM_DRAWITEM
CancelEndSession : Boolean;//use by WM_QUERYENDSESSION CancelEndSession : Boolean;//use by WM_QUERYENDSESSION
NMHdr: PNMHdr absolute LParam; // used by WM_NOTIFY NMHdr: PNMHdr absolute LParam; // used by WM_NOTIFY
TmpSize: TSize; // used by WM_MEASUREITEM TmpSize: TSize; // used by WM_MEASUREITEM
@ -259,7 +259,7 @@ Var
end; end;
function GetMenuItemObject: TObject; function GetMenuItemObject: TObject;
var var
MenuInfo: MENUITEMINFO; MenuInfo: MENUITEMINFO;
MainMenuHandle: HMENU; MainMenuHandle: HMENU;
PopupMenu: TPopupMenu; PopupMenu: TPopupMenu;
@ -289,7 +289,7 @@ Var
Result := TObject(MenuInfo.dwItemData); Result := TObject(MenuInfo.dwItemData);
end; end;
end; end;
procedure SendPaintMessage(ControlDC: HDC); procedure SendPaintMessage(ControlDC: HDC);
var var
DC: HDC; DC: HDC;
@ -706,7 +706,7 @@ Var
if ACursor = crDefault then if ACursor = crDefault then
begin begin
// statictext controls do not get WM_SETCURSOR messages... // statictext controls do not get WM_SETCURSOR messages...
lControl := lWinControl.ControlAtPos(P, [capfOnlyClientAreas, lControl := lWinControl.ControlAtPos(P, [capfOnlyClientAreas,
capfAllowWinControls, capfHasScrollOffset]); capfAllowWinControls, capfHasScrollOffset]);
if lControl = nil then if lControl = nil then
lControl := lWinControl; lControl := lWinControl;
@ -757,7 +757,7 @@ Var
end; end;
end; end;
end; end;
SC_MINIMIZE: SC_MINIMIZE:
begin begin
@ -775,7 +775,7 @@ Var
Application.MainForm.Width, 0, SWP_NOACTIVATE); Application.MainForm.Width, 0, SWP_NOACTIVATE);
if Application.MainForm.HandleAllocated then if Application.MainForm.HandleAllocated then
Windows.ShowWindow(Application.MainForm.Handle,SW_HIDE); Windows.ShowWindow(Application.MainForm.Handle,SW_HIDE);
Application.IntfAppMinimize; Application.IntfAppMinimize;
end; end;
end; end;
@ -793,7 +793,7 @@ Var
if Windows.IsWindowEnabled(Application.MainForm.Handle) if Windows.IsWindowEnabled(Application.MainForm.Handle)
then Windows.SetActiveWindow(Application.MainForm.Handle); then Windows.SetActiveWindow(Application.MainForm.Handle);
WinProcess := false; WinProcess := false;
Application.IntfAppRestore; Application.IntfAppRestore;
end; end;
end; end;
@ -866,7 +866,7 @@ Var
SetWin32SizePoint(MaxWidth, MaxHeight, MinMaxInfo.ptMaxTrackSize); SetWin32SizePoint(MaxWidth, MaxHeight, MinMaxInfo.ptMaxTrackSize);
end; end;
end; end;
procedure HandleListViewCustomDraw(ALV: TCustomListViewAccess); procedure HandleListViewCustomDraw(ALV: TCustomListViewAccess);
function ConvState(const State: uint): TCustomDrawState; function ConvState(const State: uint): TCustomDrawState;
begin begin
@ -881,8 +881,8 @@ Var
if state and CDIS_MARKED <> 0 then Include(Result, cdsMarked); if state and CDIS_MARKED <> 0 then Include(Result, cdsMarked);
if state and CDIS_SELECTED <> 0 then Include(Result, cdsSelected); if state and CDIS_SELECTED <> 0 then Include(Result, cdsSelected);
end; end;
const const
CDRFRESULT: array[TCustomDrawResultFlag] of Integer = ( CDRFRESULT: array[TCustomDrawResultFlag] of Integer = (
CDRF_SKIPDEFAULT, CDRF_SKIPDEFAULT,
CDRF_NOTIFYPOSTPAINT, CDRF_NOTIFYPOSTPAINT,
@ -891,7 +891,7 @@ Var
CDRF_NOTIFYPOSTERASE, CDRF_NOTIFYPOSTERASE,
CDRF_NOTIFYITEMERASE CDRF_NOTIFYITEMERASE
); );
var var
DrawInfo: PNMLVCustomDraw absolute NMHdr; DrawInfo: PNMLVCustomDraw absolute NMHdr;
Stage: TCustomDrawStage; Stage: TCustomDrawStage;
DrawResult: TCustomDrawResult; DrawResult: TCustomDrawResult;
@ -902,12 +902,12 @@ Var
case DrawInfo^.dwDrawStage and $7 of //Get drawing state case DrawInfo^.dwDrawStage and $7 of //Get drawing state
CDDS_PREPAINT: Stage := cdPrePaint; CDDS_PREPAINT: Stage := cdPrePaint;
CDDS_POSTPAINT: Stage := cdPostPaint; CDDS_POSTPAINT: Stage := cdPostPaint;
CDDS_PREERASE: Stage := cdPreErase; CDDS_PREERASE: Stage := cdPreErase;
CDDS_POSTERASE: Stage := cdPostErase; CDDS_POSTERASE: Stage := cdPostErase;
else else
Exit; Exit;
end; end;
case DrawInfo^.dwDrawStage and (CDDS_ITEM or CDDS_SUBITEM) of case DrawInfo^.dwDrawStage and (CDDS_ITEM or CDDS_SUBITEM) of
0: begin //Whole control 0: begin //Whole control
DrawResult := ALV.IntfCustomDraw(dtControl, Stage, -1, -1, [], @DrawInfo^.rc); DrawResult := ALV.IntfCustomDraw(dtControl, Stage, -1, -1, [], @DrawInfo^.rc);
@ -920,7 +920,7 @@ Var
if DrawInfo^.iSubItem = 0 then Exit; if DrawInfo^.iSubItem = 0 then Exit;
DrawResult := ALV.IntfCustomDraw(dtItem, Stage, DrawInfo^.dwItemSpec, DrawInfo^.iSubItem, ConvState(DrawInfo^.uItemState), nil); DrawResult := ALV.IntfCustomDraw(dtItem, Stage, DrawInfo^.dwItemSpec, DrawInfo^.iSubItem, ConvState(DrawInfo^.uItemState), nil);
end; end;
else else
Exit; Exit;
end; end;
@ -947,7 +947,7 @@ Var
end; end;
Result := PointToSmallPoint(P); Result := PointToSmallPoint(P);
end; end;
begin begin
Assert(False, 'Trace:WindowProc - Start'); Assert(False, 'Trace:WindowProc - Start');
@ -1037,7 +1037,7 @@ begin
Windows.SetWindowPos(TWin32WidgetSet(WidgetSet).AppHandle, HWND_TOP, Windows.SetWindowPos(TWin32WidgetSet(WidgetSet).AppHandle, HWND_TOP,
0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE); 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end; end;
// activate/deactivate main window // activate/deactivate main window
if (Application <> nil) and (Application.MainForm <> nil) and if (Application <> nil) and (Application.MainForm <> nil) and
Application.MainForm.HandleAllocated then Application.MainForm.HandleAllocated then
@ -1190,7 +1190,7 @@ begin
case Msg of case Msg of
WM_CTLCOLORSTATIC, WM_CTLCOLORSTATIC,
WM_CTLCOLORBTN: begin WM_CTLCOLORBTN: begin
if GetNeedParentPaint(ChildWindowInfo, ChildWinControl) if GetNeedParentPaint(ChildWindowInfo, ChildWinControl)
and not ChildWindowInfo^.ThemedCustomDraw then and not ChildWindowInfo^.ThemedCustomDraw then
begin begin
// need to draw transparently, draw background // need to draw transparently, draw background
@ -1204,7 +1204,7 @@ begin
WinProcess := false; WinProcess := false;
end; end;
end; end;
if WinProcess then if WinProcess then
begin begin
if ChildWinControl <> nil then if ChildWinControl <> nil then
@ -1343,7 +1343,7 @@ begin
if DoubleBufferDC <> 0 then if DoubleBufferDC <> 0 then
WParam := DoubleBufferDC; WParam := DoubleBufferDC;
if WindowInfo^.isTabPage then if WindowInfo^.isTabPage then
EraseBkgndStack := (EraseBkgndStack and not ((1 shl EraseBkgndStackShift)-1)) EraseBkgndStack := (EraseBkgndStack and not ((1 shl EraseBkgndStackShift)-1))
or dword(ecDiscardNoRemove); or dword(ecDiscardNoRemove);
end else if eraseBkgndCommand <> ecDiscardNoRemove then end else if eraseBkgndCommand <> ecDiscardNoRemove then
EraseBkgndStack := EraseBkgndStack shr EraseBkgndStackShift; EraseBkgndStack := EraseBkgndStack shr EraseBkgndStackShift;
@ -1587,13 +1587,15 @@ begin
// check if the window is an edit control of a combobox, if so, // check if the window is an edit control of a combobox, if so,
// redirect it to the combobox, not the edit control // redirect it to the combobox, not the edit control
if GetWindowInfo(TargetWindow)^.isComboEdit then if GetWindowInfo(TargetWindow)^.isComboEdit then
begin
TargetWindow := Windows.GetParent(TargetWindow); TargetWindow := Windows.GetParent(TargetWindow);
if (TargetWindow <> Window) then
begin // check InMouseWheelRedirection to prevent recursion
Result := SendMessage(TargetWindow, WM_MOUSEWHEEL, WParam, LParam); if not InMouseWheelRedirection and (TargetWindow <> Window) then
exit; begin
end; InMouseWheelRedirection := true;
Result := SendMessage(TargetWindow, WM_MOUSEWHEEL, WParam, LParam);
InMouseWheelRedirection := false;
exit;
end; end;
// the mousewheel message is for us // the mousewheel message is for us
@ -1703,7 +1705,7 @@ begin
begin begin
if WindowInfo^.WinControl is TCustomListView if WindowInfo^.WinControl is TCustomListView
then HandleListViewCustomDraw(TCustomListViewAccess(WindowInfo^.WinControl)) then HandleListViewCustomDraw(TCustomListViewAccess(WindowInfo^.WinControl))
else if GetNeedParentPaint(WindowInfo, lWinControl) else if GetNeedParentPaint(WindowInfo, lWinControl)
and WindowInfo^.ThemedCustomDraw then and WindowInfo^.ThemedCustomDraw then
begin begin
case PNMCustomDraw(LParam)^.dwDrawStage of case PNMCustomDraw(LParam)^.dwDrawStage of
@ -1716,7 +1718,7 @@ begin
begin begin
case PNMCustomDraw(LParam)^.dwItemSpec of case PNMCustomDraw(LParam)^.dwItemSpec of
TBCD_TICS, TBCD_CHANNEL: TBCD_TICS, TBCD_CHANNEL:
SendParentPaintMessage(Window, Windows.GetParent(Window), SendParentPaintMessage(Window, Windows.GetParent(Window),
PNMCustomDraw(LParam)^.hDC); PNMCustomDraw(LParam)^.hDC);
end; end;
Result := CDRF_DODEFAULT; Result := CDRF_DODEFAULT;
@ -1946,7 +1948,7 @@ begin
WM_LCL_SOCK_ASYNC: WM_LCL_SOCK_ASYNC:
begin begin
if (Window = TWin32WidgetSet(WidgetSet).AppHandle) and if (Window = TWin32WidgetSet(WidgetSet).AppHandle) and
Assigned(TWin32WidgetSet(WidgetSet).FOnAsyncSocketMsg) then Assigned(TWin32WidgetSet(WidgetSet).FOnAsyncSocketMsg) then
exit(TWin32WidgetSet(WidgetSet).FOnAsyncSocketMsg(WParam, LParam)) exit(TWin32WidgetSet(WidgetSet).FOnAsyncSocketMsg(WParam, LParam))
end; end;
@ -2109,7 +2111,7 @@ begin
if PLMsg^.Result = 0 then if PLMsg^.Result = 0 then
WinProcess := true; WinProcess := true;
end; end;
CN_CHAR, CN_SYSCHAR: CN_CHAR, CN_SYSCHAR:
begin begin
// if key not yet processed, let windows process it // if key not yet processed, let windows process it
@ -2141,7 +2143,7 @@ begin
if MouseDownFocusStatus = mfFocusSense then if MouseDownFocusStatus = mfFocusSense then
MouseDownFocusStatus := mfNone; MouseDownFocusStatus := mfNone;
end; end;
WM_NCDESTROY: WM_NCDESTROY:
begin begin
@ -2299,8 +2301,8 @@ begin
// free our own data associated with window // free our own data associated with window
DisposeWindowInfo(Window); DisposeWindowInfo(Window);
end; end;
else else
if UnicodeEnabledOS if UnicodeEnabledOS
then Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam) then Result := Windows.DefWindowProcW(Window, Msg, WParam, LParam)
else Result := Windows.DefWindowProc(Window, Msg, WParam, LParam); else Result := Windows.DefWindowProc(Window, Msg, WParam, LParam);
end; end;

View File

@ -302,6 +302,8 @@ var
MouseDownFocusStatus: TMouseDownFocusStatus = mfNone; MouseDownFocusStatus: TMouseDownFocusStatus = mfNone;
ComboBoxHandleSizeWindow: HWND = 0; ComboBoxHandleSizeWindow: HWND = 0;
IgnoreNextCharWindow: HWND = 0; // ignore next WM_(SYS)CHAR message IgnoreNextCharWindow: HWND = 0; // ignore next WM_(SYS)CHAR message
// set to true, if we are redirecting a WM_MOUSEWHEEL message, to prevent recursion
InMouseWheelRedirection: boolean = false;
OnClipBoardRequest: TClipboardRequestEvent; OnClipBoardRequest: TClipboardRequestEvent;
{$ifdef MSG_DEBUG} {$ifdef MSG_DEBUG}
MessageStackDepth: string = ''; MessageStackDepth: string = '';