There are two panels. Panel B is embedded in Panel A. How to redirect WM_NCHITTEST from B so that Panel A would process this message. It is supposed to make panel B as a splitter. That is, when you hover the mouse cursor on it, a cursor appeared as if you were resizing and you could change the size of panel A. I use Delphi 7

enter image description here

Here is the handler for A

procedure TPanelEx.WMNCHitTest(var Msg: TWMNCHitTest); var zScreenPt: TPoint; zOwnerPt: TPoint; begin inherited; if not (csDesigning in ComponentState) then begin if not Assigned(Parent) then Exit; zScreenPt := ScreenToClient(Point(Msg.Xpos, Msg.Ypos)); zOwnerPt := TControl(Parent).ScreenToClient(Point(Msg.Xpos, Msg.Ypos)); if (zScreenPt.y >= Height - BevelWidth) and (zOwnerPt.y < TControl(Parent).Height - BevelWidth - 1) then Msg.Result := HTBOTTOM end; end; 

Panel B is created like this

 constructor TPanelEx.Create(aOwner: TComponent); begin inherited; FShiftingPanel := nil; OnCanResize := OnCanPanelResize; BevelWidth := 2; Ctl3D := false; FPrevPanel := nil; FBottomPanel := TsPanel.Create(Self); FBottomPanel.Parent := Self; FBottomPanel.Height := 16; FBottomPanel.Align := alBottom; FBottomPanel.OnMouseEnter := OnMouseEnter; FBottomPanel.OnMouseLeave := OnMouseLeave; end; 

    1 answer 1

    According to MSDN , if you need to "skip" WM_NCHitTest to the parent window, you must return HTTRANSPARENT .

    Thus, BottomPanel also needs to get its handler (the example is based on standard TPanel , change the parent type to work with TsPanel . Simplified, you can add csDesigning yourself):

     type TSizeBoxPanel = class(TPanel) private procedure WMNCHHitTest(var Message: TWMNCHitMessage); message WM_NCHITTEST; end; TSizedPanel = class(TPanel) private FSizeBoxPanel: TSizeBoxPanel; procedure WMNCHHitTest(var Message: TWMNCHitMessage); message WM_NCHITTEST; public constructor Create(AOwner: TComponent); override; end; { TSizedPanel } procedure TSizeBoxPanel.WMNCHHitTest(var Message: TWMNCHitMessage); begin // если панель, которую считаем "сплиттером" приняла сообщение, // значит курсор находится где-то над ней. Просто пропускаем сообщение выше. Message.Result := HTTRANSPARENT; end; { TSizedPanel } constructor TSizedPanel.Create(AOwner: TComponent); begin inherited; FSizeBoxPanel:=TSizeBoxPanel.Create(nil); FSizeBoxPanel.Parent:=Self; FSizeBoxPanel.Align:=alBottom; FSizeBoxPanel.Height:=20; end; procedure TSizedPanel.WMNCHHitTest(var Message: TWMNCHitMessage); var p: TPoint; begin p:=ScreenToClient(Point(Message.XCursor, Message.YCursor)); // если курсор находится над сплиттером - возвращаем нужное значение. if ControlAtPos(p, True, True) = FSizeBoxPanel then Message.Result := HTBOTTOM; end; 

    Example of use:

     TForm9 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } FPanel: TSizedPanel; public { Public declarations } end; procedure TForm9.FormCreate(Sender: TObject); begin FPanel:=TSizedPanel.Create(nil); FPanel.Parent:=Self; FPanel.Left:=10; FPanel.Top:=10; end; 
    • @gregor, unfortunately, does not have the installed D7, so part of the code may differ in names. At a minimum, your code uses Msg.Xpos , and in recent versions of Delphi, it Msg.XCursor . Hope this will not be a big obstacle. - kami