关闭

delphi的消息处理机制TWinControl.WndProc

标签: delphiuser
4373人阅读 评论(0) 收藏 举报
分类:

delphi在处理消息的时候是逐级调用的,最基础的算是 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;
            _TrackMouseEvent(@LMouseEvent);
          end;
        end;
        if IsControlMouseMsg(TWMMouse(Message)) then
        begin
          { Check HandleAllocated because IsControlMouseMsg might have freed the
            window if user code executed something like Parent := nil. }
          if (Message.Result = 0) and HandleAllocated then
            DefWindowProc(Handle, Message.Msg, Message.wParam, Message.lParam);
          Exit;
        end;
      end;
    WM_MOUSEACTIVATE:
      if IsControlActivateMsg(TWMMouseActivate(Message)) then
      begin
        if (Message.Result = 0) and HandleAllocated then
          inherited WndProc(Message);
        Exit;
      end;
    WM_KEYFIRST..WM_KEYLAST:
      if Dragging then Exit;
    WM_CANCELMODE:
      if (GetCapture = Handle) and (CaptureControl <> nil) and
        (CaptureControl.Parent = Self) then
        CaptureControl.Perform(WM_CANCELMODE, 0, 0);
    CM_DESTROYHANDLE:
      begin
        if Boolean(Message.WParam) then // Sender has csRecreating set
          UpdateRecreatingFlag(True);
        try
          DestroyHandle;
        finally
          if Boolean(Message.WParam) then
            UpdateRecreatingFlag(False);
        end;
        Exit;
      end;
  end;
  inherited WndProc(Message);

  if Message.Msg = WM_UPDATEUISTATE then
    Invalidate; // Ensure control is repainted
end;

这里面有很多消息。欢迎大家讨论分享。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    关注我谢谢。

    欢迎扫描关注我的公众号。


    公众号二维码
    个人资料
    • 访问:1147090次
    • 积分:12694
    • 等级:
    • 排名:第1125名
    • 原创:184篇
    • 转载:22篇
    • 译文:18篇
    • 评论:458条
    博客专栏
    最新评论