lcl: redo MouseEnter/MouseLeave notifications:

- move application mouse events notification from various message handlers to the WND proc of TWinControl
  - don't assume that control at mouse is the current control which has mouse events. If some control has a mouse capture set then it has the mouse messages and not the control at mouse
  - don't perform a control search in TApplication.DoBeforeMouseMessage - it already has an argument which contains the new mouse control (fixes bug #0016715)
  - fix CM_MOUSEENTER, CM_MOUSELEAVE message handlers so Parent controls will always get CM_ notification before the event handler and inspite of who is the message owner

git-svn-id: trunk@27770 -
This commit is contained in:
paul 2010-10-20 08:02:22 +00:00
parent 084fed8f6c
commit d5cb0e2fbe
7 changed files with 46 additions and 69 deletions

View File

@ -285,7 +285,6 @@ type
procedure CMButtonPressed(var Message: TLMessage); message CM_BUTTONPRESSED;
procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED;
private
procedure DoBeforeMouseMessage;
procedure DoMouseUp(var Message: TLMMouse; Button: TMouseButton);
procedure WMLButtonDown(Var Message: TLMLButtonDown); message LM_LBUTTONDOWN;
procedure WMLButtonUp(var Message: TLMLButtonUp); message LM_LBUTTONUP;

View File

@ -1106,8 +1106,8 @@ type
procedure CMBiDiModeChanged(var Message: TLMessage); message CM_BIDIMODECHANGED;
procedure CMEnabledChanged(var Message: TLMEssage); message CM_ENABLEDCHANGED;
procedure CMHitTest(var Message: TCMHittest) ; message CM_HITTEST;
procedure CMMouseEnter(var Message :TLMessage); message CM_MouseEnter;
procedure CMMouseLeave(var Message :TLMessage); message CM_MouseLeave;
procedure CMMouseEnter(var Message :TLMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message :TLMessage); message CM_MOUSELEAVE;
procedure CMHintShow(var Message: TLMessage); message CM_HINTSHOW;
procedure CMParentBiDiModeChanged(var Message: TLMessage); message CM_PARENTBIDIMODECHANGED;
procedure CMParentColorChanged(var Message: TLMessage); message CM_PARENTCOLORCHANGED;
@ -2768,7 +2768,7 @@ begin
begin
Result := WinControl;
Control := WinControl.ControlAtPos(WinControl.ScreenToClient(Position),
[capfAllowDisabled,capfAllowWinControls,capfRecursive]);
[capfAllowDisabled, capfAllowWinControls, capfRecursive]);
//debugln(['FindControlAtPosition ',dbgs(Position),' ',DbgSName(WinControl),' ',dbgs(WinControl.ScreenToClient(Position)),' ',DbgSName(Control)]);
if Control <> nil then
Result := Control;

View File

@ -1242,7 +1242,6 @@ type
function GetTitle: string;
procedure FreeIconHandles;
procedure IconChanged(Sender: TObject);
function GetControlAtMouse: TControl;
procedure SetBidiMode(const AValue: TBiDiMode);
procedure SetFlags(const AValue: TApplicationFlags);
procedure SetNavigation(const AValue: TApplicationNavigationOptions);
@ -1293,6 +1292,7 @@ type
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ActivateHint(CursorPos: TPoint; CheckHintControlChange: Boolean = False);
function GetControlAtMouse: TControl;
procedure ControlDestroyed(AControl: TControl);
function BigIconHandle: HIcon;
function SmallIconHandle: HIcon;

View File

@ -495,18 +495,18 @@ var
begin
GetCursorPos(P);
//debugln(['TApplication.GetControlAtMouse p=',dbgs(p),' FLastMousePos=',dbgs(FLastMousePos)]);
if FLastMouseControlValid and (P.X=FLastMousePos.x) and (P.Y=FLastMousePos.Y)
then
if FLastMouseControlValid and (P.X = FLastMousePos.x) and (P.Y = FLastMousePos.Y) then
Result := FLastMouseControl
else
Result := FindControlAtPosition(P, True);
if (Result <> nil) and (csDesigning in Result.ComponentState) then
Result := nil;
if Result<> nil then begin
FLastMouseControlValid:=true;
FLastMousePos:=p;
FLastMouseControl:=Result;
if Result <> nil then
begin
FLastMouseControlValid := True;
FLastMousePos := p;
FLastMouseControl := Result;
end;
end;
@ -1959,7 +1959,7 @@ end;
procedure TApplication.DoBeforeMouseMessage(CurMouseControl: TControl);
begin
//debugln(['TApplication.DoBeforeMouseMessage ',DbgSName(CurMouseControl)]);
UpdateMouseControl(GetControlAtMouse);
UpdateMouseControl(CurMouseControl);
end;
function TApplication.IsShortcut(var Message: TLMKey): boolean;

View File

@ -667,15 +667,18 @@ end;
------------------------------------------------------------------------------}
procedure TControl.CMMouseEnter(var Message: TLMessage);
begin
// this is a LCL based mouse message, so don't call DoBeforeMouseMessage
//DebugLn('TControl.CMMouseEnter ',Name,':',ClassName,' ',FMouseEntered,' ',Message.LParam);
if (Message.LParam=0) and (not FMouseEntered) then
begin
FMouseEntered := True;
if FMouseEntered then
Exit;
FMouseEntered := True;
// broadcast to parents first
if Assigned(Parent) then
Parent.Perform(CM_MOUSEENTER, 0, LParam(Self));
// if it is not a child message then perform an event
if (Message.LParam = 0) then
MouseEnter;
if FParent <> nil then
FParent.Perform(CM_MOUSEENTER, 0, LParam(Self));
end;
end;
{------------------------------------------------------------------------------
@ -683,15 +686,18 @@ end;
------------------------------------------------------------------------------}
procedure TControl.CMMouseLeave(var Message: TLMessage);
begin
// this is a LCL based mouse message, so don't call DoBeforeMouseMessage
//DebugLn('TControl.CMMouseLeave ',Name,':',ClassName,' ',FMouseEntered,' ',Message.LParam);
if (Message.LParam = 0) and FMouseEntered then
begin
FMouseEntered := False;
if not FMouseEntered then
Exit;
FMouseEntered := False;
// broadcast to parents first
if Assigned(Parent) then
Parent.Perform(CM_MOUSELEAVE, 0, LParam(Self));
// if it is not a child message then perform an event
if (Message.LParam = 0) then
MouseLeave;
if FParent <> nil then
FParent.Perform(CM_MOUSELEAVE, 0, LParam(Self));
end;
end;
{------------------------------------------------------------------------------
@ -873,9 +879,16 @@ end;
procedure TControl.DoBeforeMouseMessage;
------------------------------------------------------------------------------}
procedure TControl.DoBeforeMouseMessage;
var
NewMouseControl: TControl;
begin
if Application<>nil then
Application.DoBeforeMouseMessage(Self);
if Assigned(Application) then
begin
NewMouseControl := CaptureControl;
if NewMouseControl = nil then
NewMouseControl := Application.GetControlAtMouse;
Application.DoBeforeMouseMessage(NewMouseControl);
end;
end;
{------------------------------------------------------------------------------
@ -1785,7 +1798,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMLButtonDown(var Message: TLMLButtonDown);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1807,7 +1819,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMRButtonDown(var Message: TLMRButtonDown);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbRight in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1827,7 +1838,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMMButtonDown(var Message: TLMMButtonDown);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbMiddle in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1849,7 +1859,6 @@ begin
Btn := mbExtra2
else
Exit;
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (Btn in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1870,7 +1879,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMLButtonDblClk(var Message: TLMLButtonDblClk);
begin
DoBeforeMouseMessage;
//TODO: SendCancelMode(self);
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin
@ -1894,7 +1902,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMRButtonDblClk(var Message: TLMRButtonDblClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbRight in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1914,7 +1921,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMMButtonDblClk(var Message: TLMMButtonDblClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbMiddle in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1936,7 +1942,6 @@ begin
Btn := mbExtra2
else
Exit;
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (Btn in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1956,7 +1961,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMLButtonTripleClk(var Message: TLMLButtonTripleClk);
begin
DoBeforeMouseMessage;
//TODO: SendCancelMode(self);
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin
@ -1978,7 +1982,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMRButtonTripleClk(var Message: TLMRButtonTripleClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbRight in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -1998,7 +2001,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMMButtonTripleClk(var Message: TLMMButtonTripleClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbMiddle in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2020,7 +2022,6 @@ begin
Btn := mbExtra2
else
Exit;
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (Btn in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2040,7 +2041,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMLButtonQuadClk(var Message: TLMLButtonQuadClk);
begin
DoBeforeMouseMessage;
//TODO: SendCancelMode(self);
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin
@ -2062,7 +2062,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMRButtonQuadClk(var Message: TLMRButtonQuadClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbRight in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2082,7 +2081,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMMButtonQuadClk(var Message: TLMMButtonQuadClk);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbMiddle in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2104,7 +2102,6 @@ begin
Btn := mbExtra2
else
Exit;
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (Btn in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2124,7 +2121,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMLButtonUp(var Message: TLMLButtonUp);
begin
DoBeforeMouseMessage;
//DebugLn('TControl.WMLButtonUp A ',Name,':',ClassName,' csCaptureMouse=',DbgS(csCaptureMouse in ControlStyle),' csClicked=',DbgS(csClicked in ControlState));
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin
@ -2158,7 +2154,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMRButtonUp(var Message: TLMRButtonUp);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbRight in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2179,7 +2174,6 @@ end;
------------------------------------------------------------------------------}
procedure TControl.WMMButtonUp(var Message: TLMMButtonUp);
begin
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (mbMiddle in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2202,7 +2196,6 @@ begin
Btn := mbExtra2
else
Exit;
DoBeforeMouseMessage;
if (csCaptureMouse in ControlStyle) and (Btn in CaptureMouseButtons) then
begin
{$IFDEF VerboseMouseCapture}
@ -2225,8 +2218,6 @@ procedure TControl.WMMouseWheel(var Message: TLMMouseEvent);
var
MousePos: TPoint;
begin
DoBeforeMouseMessage;
MousePos.X := Message.X;
MousePos.Y := Message.Y;
@ -3550,7 +3541,6 @@ begin
{$IFDEF VerboseMouseBugfix}
DebugLn(['[TControl.WMMouseMove] ',Name,':',ClassName,' ',Message.XPos,',',Message.YPos]);
{$ENDIF}
DoBeforeMouseMessage;
UpdateMouseCursor(Message.XPos,Message.YPos);
if not (csNoStdEvents in ControlStyle) then
with Message do

View File

@ -704,15 +704,6 @@ begin
inherited MouseUp(Button, Shift, X, Y);
end;
{------------------------------------------------------------------------------
procedure TCustomSpeedButton.DoBeforeMouseMessage;
------------------------------------------------------------------------------}
procedure TCustomSpeedButton.DoBeforeMouseMessage;
begin
if Application<>nil then
Application.DoBeforeMouseMessage(Self);
end;
{------------------------------------------------------------------------------
TCustomSpeedButton DoMouseUp "Event Handler"
------------------------------------------------------------------------------}
@ -758,7 +749,6 @@ procedure TCustomSpeedButton.WMLButtonUp(var Message: TLMLButtonUp);
var
OldState: TButtonState;
begin
DoBeforeMouseMessage;
//DebugLn('TCustomSpeedButton.WMLButtonUp A ',DbgSName(Self),' csCaptureMouse=',DbgS(csCaptureMouse in ControlStyle),' csClicked=',DbgS(csClicked in ControlState));
if (csCaptureMouse in ControlStyle) and (mbLeft in CaptureMouseButtons) then
begin

View File

@ -5157,18 +5157,16 @@ begin
Exit;
end;
// exclude only LM_MOUSEENTER, LM_MOUSELEAVE
LM_MOUSEFIRST..LM_MOUSELAST,
LM_LBUTTONTRIPLECLK,
LM_LBUTTONQUADCLK,
LM_MBUTTONTRIPLECLK,
LM_MBUTTONQUADCLK,
LM_RBUTTONTRIPLECLK,
LM_RBUTTONQUADCLK:
LM_MOUSEFIRST2..LM_RBUTTONQUADCLK,
LM_XBUTTONTRIPLECLK..LM_MOUSELAST2:
begin
{$IFDEF VerboseMouseBugfix}
DebugLn('TWinControl.WndPRoc A ',Name,':',ClassName);
{$ENDIF}
//if Message.Msg=LM_RBUTTONUP then begin DebugLn(['TWinControl.WndProc ',DbgSName(Self)]); DumpStack end;
DoBeforeMouseMessage;
if IsControlMouseMSG(Message) then
Exit
else