自定义控件和 Windows 消息

发布于 2024-11-30 09:18:35 字数 1577 浏览 0 评论 0原文

我在纯 Windows API 中制作了一个自定义 Splitter 控件。它由 4 个控件组成:主容器、拆分器和 2 个窗格。

现在,我需要挂钩 Windows 过程,以便查明其子控件之一何时移动或调整大小,因此我使用了 SetWindowsHookEx。我在挂钩过程中得到了 WM_SIZE 消息,但没有从我的 Splitter 的子窗口中捕获到 WM_MOVE 消息。

我尝试向 Groupbox 添加一个子窗口(我知道这不是它们应该使用的方式),只是为了查看 WM_MOVE 消息是否被挂钩过程捕获,并且它们是。

那么我在这里缺少什么?我需要在 Splitter 窗口过程中添加什么才能发送那些 WM_MOVE?或者我的错误在其他地方?

PS:SetWindowPos确实适用于这些子窗口,它只是没有捕获WM_MOVE

编辑:根据要求,这里是 Splitter 窗口类的完整代码: http://pastebin.com/Lgvb0Vfv

以下是重要的代码部分:

LRESULT WINAPI AnchorProc(int nCode, WPARAM wParam, LPARAM lParam) {
    CWPRETSTRUCT* theMessage = (CWPRETSTRUCT*)lParam;

    if (theMessage->message == WM_MOVE) printf ("!");
}    

在主窗口 WM_CREATE 之后的某个时间:

SetWindowsHookEx(WH_CALLWNDPROCRET,AnchorProc,NULL,GetCurrentThreadId());

// groupbox

HWND gb = CreateWindowEx(0,"button",NULL,BS_GROUPBOX|WS_CHILD,0,0,200,200,hwndMain,0,hInst,NULL);
HWND but = CreateWindowEx(0,"button",NULL,BS_PUSHBUTTON|WS_CHILD,0,0,40,40,gb,0,hInst,NULL);

// custom control

HWND split = CreateWindowEx(0,"FSplitterClass",NULL,WS_CHILD,200,0,200,200,hwndMain,0,hInst,NULL);
HWND pane1 = (HWND)SendMessage(split,WM_SPGETPANE,0,0);
HWND but1 = CreateWindowEx(0,"button",NULL,BS_PUSHBUTTON|WS_CHILD,0,0,40,40,pane1,0,hInst,NULL);

SetWindowPos(but, NULL, 1,1,0,0,SWP_NOSIZE|SWP_NOZORDER); // triggers WM_MOVE
SetWindowPos(but1, NULL, 1,1,0,0,SWP_NOSIZE|SWP_NOZORDER); // doesn't

I made a custom Splitter control in pure Windows API. It's made of 4 controls: the main container, the splitter and the 2 panes.

Now I needed to hook into the windows procedure in order to find out when one of its child controls was moving or resizing, so I used SetWindowsHookEx. I get the WM_SIZE messages in my hook procedure just fine, but no WM_MOVE messages are ever caught from my Splitter's child windows.

I tried adding a child window to a Groupbox (which I know isn't the way they're supposed to be used) just to see if the WM_MOVE messages were caught by the hook procedure, and they were.

So what am I missing here? What do I need to add to my Splitter window procedure so those WM_MOVEs get sent? Or was my error somewhere else?

PS: SetWindowPos does work on those child windows, it's just not catching WM_MOVE.

EDIT: As requested, here is the full code of the Splitter window class: http://pastebin.com/Lgvb0Vfv

Here is the part of the code that matters:

LRESULT WINAPI AnchorProc(int nCode, WPARAM wParam, LPARAM lParam) {
    CWPRETSTRUCT* theMessage = (CWPRETSTRUCT*)lParam;

    if (theMessage->message == WM_MOVE) printf ("!");
}    

Sometime after the main window's WM_CREATE:

SetWindowsHookEx(WH_CALLWNDPROCRET,AnchorProc,NULL,GetCurrentThreadId());

// groupbox

HWND gb = CreateWindowEx(0,"button",NULL,BS_GROUPBOX|WS_CHILD,0,0,200,200,hwndMain,0,hInst,NULL);
HWND but = CreateWindowEx(0,"button",NULL,BS_PUSHBUTTON|WS_CHILD,0,0,40,40,gb,0,hInst,NULL);

// custom control

HWND split = CreateWindowEx(0,"FSplitterClass",NULL,WS_CHILD,200,0,200,200,hwndMain,0,hInst,NULL);
HWND pane1 = (HWND)SendMessage(split,WM_SPGETPANE,0,0);
HWND but1 = CreateWindowEx(0,"button",NULL,BS_PUSHBUTTON|WS_CHILD,0,0,40,40,pane1,0,hInst,NULL);

SetWindowPos(but, NULL, 1,1,0,0,SWP_NOSIZE|SWP_NOZORDER); // triggers WM_MOVE
SetWindowPos(but1, NULL, 1,1,0,0,SWP_NOSIZE|SWP_NOZORDER); // doesn't

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森罗 2024-12-07 09:18:35
  1. windows 钩子在这里是多余的。子类化效率更高。
  2. 仅当窗口过程传递 WM_WINDOWPOSCHANGED 时,才会生成 WM_MOVE 发送给 DefWindowProc 的消息。如果你不能保证这一点,那么你就不能保证收到 WM_MOVE 消息。监听 WM_WINDOWPOSCHANGED。
  1. A windows hook is overkill here. Subclassing is much more efficient.
  2. WM_MOVE is generated only if the window procedure passes the WM_WINDOWPOSCHANGED message to DefWindowProc. If you cannot guarantee that, then you are not guaranteed a WM_MOVE message. Listen for WM_WINDOWPOSCHANGED.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文