高分求 TWinControl.WndProc相关消息及处理的注释解决思路
高分求 TWinControl.WndProc相关消息及处理的注释
procedure TWinControl.WndProc(var Message: TMessage);
var
Form: TCustomForm;
LMouseEvent: TTrackMouseEvent;
P: TPoint;
Target: TControl;
begin
case Message.Msg of
CM_UNTHEMECONTROL:
if (csDesigning in ComponentState) and ThemeServices.ThemesAvailable then
begin
SetWindowTheme(Handle, ' ', ' ');
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_FRAMECHANGED);
end;
CM_SETACTIVECONTROL:
begin
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) then
Form.Perform(CM_SETACTIVECONTROL, Message.WParam, Message.LParam);
end;
WM_SETFOCUS:
begin
Form := GetParentForm(Self);
if (Form <> nil) and (not (csDesigning in Form.ComponentState) or (Form.Parent = nil)) then
if not Form.SetFocusedControl(Self) then Exit;
end;
WM_KILLFOCUS:
if csFocusing in ControlState then Exit;
WM_NCHITTEST:
begin
inherited WndProc(Message);
if (Message.Result = HTTRANSPARENT) and (ControlAtPos(ScreenToClient(
SmallPointToPoint(TWMNCHitTest(Message).Pos)), False) <> nil) then
Message.Result := HTCLIENT;
Exit;
end;
WM_MOUSELEAVE:
begin
FMouseInClient := False;
if FMouseControl <> nil then
FMouseControl.Perform(CM_MOUSELEAVE, 0, 0)
else
Perform(CM_MOUSELEAVE, 0, 0);
FMouseControl := nil;
end;
WM_MOUSEFIRST..WM_MOUSELAST:
begin
if Message.Msg = WM_MOUSEMOVE then
begin
P := ClientToScreen(Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos));
CaptureControl := GetCaptureControl;
if CaptureControl = nil then
Target := FindDragTarget(P, True)
else
Target := CaptureControl;
if (FMouseControl <> Target) then
begin
if ((FMouseControl <> nil) and (CaptureControl = nil)) or
((CaptureControl <> nil) and (FMouseControl = CaptureControl)) or
((CaptureControl is TControl) and (CaptureControl.Parent = FMouseControl)) then
FMouseControl.Perform(CM_MOUSELEAVE, 0, 0);
if FMouseControl <> nil then
FMouseControl.RemoveFreeNotification(Self);
FMouseControl := Target;
if FMouseControl <> nil then
FMouseControl.FreeNotification(Self);
if ((FMouseControl <> nil) and (CaptureControl = nil)) or
((CaptureControl <> nil) and (FMouseControl = CaptureControl)) then
FMouseControl.Perform(CM_MOUSEENTER, 0, 0);
end;
if not FMouseInClient then
begin
FMouseInClient := True;
// Register for a WM_MOUSELEAVE message which ensures CM_MOUSELEAVE
// is called when the mouse leaves the TWinControl
LMouseEvent.cbSize := SizeOf(LMouseEvent);
LMouseEvent.dwFlags := TME_LEAVE;
LMouseEvent.hwndTrack := Handle;
LMouseEvent.dwHoverTime := HOVER_DEFAULT;
procedure TWinControl.WndProc(var Message: TMessage);
var
Form: TCustomForm;
LMouseEvent: TTrackMouseEvent;
P: TPoint;
Target: TControl;
begin
case Message.Msg of
CM_UNTHEMECONTROL:
if (csDesigning in ComponentState) and ThemeServices.ThemesAvailable then
begin
SetWindowTheme(Handle, ' ', ' ');
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_FRAMECHANGED);
end;
CM_SETACTIVECONTROL:
begin
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) then
Form.Perform(CM_SETACTIVECONTROL, Message.WParam, Message.LParam);
end;
WM_SETFOCUS:
begin
Form := GetParentForm(Self);
if (Form <> nil) and (not (csDesigning in Form.ComponentState) or (Form.Parent = nil)) then
if not Form.SetFocusedControl(Self) then Exit;
end;
WM_KILLFOCUS:
if csFocusing in ControlState then Exit;
WM_NCHITTEST:
begin
inherited WndProc(Message);
if (Message.Result = HTTRANSPARENT) and (ControlAtPos(ScreenToClient(
SmallPointToPoint(TWMNCHitTest(Message).Pos)), False) <> nil) then
Message.Result := HTCLIENT;
Exit;
end;
WM_MOUSELEAVE:
begin
FMouseInClient := False;
if FMouseControl <> nil then
FMouseControl.Perform(CM_MOUSELEAVE, 0, 0)
else
Perform(CM_MOUSELEAVE, 0, 0);
FMouseControl := nil;
end;
WM_MOUSEFIRST..WM_MOUSELAST:
begin
if Message.Msg = WM_MOUSEMOVE then
begin
P := ClientToScreen(Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos));
CaptureControl := GetCaptureControl;
if CaptureControl = nil then
Target := FindDragTarget(P, True)
else
Target := CaptureControl;
if (FMouseControl <> Target) then
begin
if ((FMouseControl <> nil) and (CaptureControl = nil)) or
((CaptureControl <> nil) and (FMouseControl = CaptureControl)) or
((CaptureControl is TControl) and (CaptureControl.Parent = FMouseControl)) then
FMouseControl.Perform(CM_MOUSELEAVE, 0, 0);
if FMouseControl <> nil then
FMouseControl.RemoveFreeNotification(Self);
FMouseControl := Target;
if FMouseControl <> nil then
FMouseControl.FreeNotification(Self);
if ((FMouseControl <> nil) and (CaptureControl = nil)) or
((CaptureControl <> nil) and (FMouseControl = CaptureControl)) then
FMouseControl.Perform(CM_MOUSEENTER, 0, 0);
end;
if not FMouseInClient then
begin
FMouseInClient := True;
// Register for a WM_MOUSELEAVE message which ensures CM_MOUSELEAVE
// is called when the mouse leaves the TWinControl
LMouseEvent.cbSize := SizeOf(LMouseEvent);
LMouseEvent.dwFlags := TME_LEAVE;
LMouseEvent.hwndTrack := Handle;
LMouseEvent.dwHoverTime := HOVER_DEFAULT;