gpt4 book ai didi

c++ - 使用 PostMessage 与 SendNotifyMessage 广播到拥有的窗口

转载 作者:可可西里 更新时间:2023-11-01 10:37:42 24 4
gpt4 key购买 nike

最近我发现了两个 Win32 API 调用“PostMessage”和“SendNotifyMessage”之间的奇怪区别(至少在 Win7 64 位 SP1 上注意到了):另一个进程拥有的顶级窗口似乎没有接收到使用“PostMessage”广播的消息 (HWND_BROADCAST),而它在其 WndProc 中接收到使用“SendNotifyMessage”广播的消息。

发送的消息已在调用“RegisterWindowMessage”的帮助下注册。

即使使用 Spy++,在使用“PostMessage”时我也看不到消息到达。此外,我想提一下,如果我使用“PostMessage”将消息直接发送到特定的 HWND,它会按预期到达。所以看起来“PostMessage”的 Windows 内部实现在迭代执行广播时只是跳过了我的窗口。

阅读相应的 MSDN 文档,我看不到关于此差异的任何声明,我想知道这是否是 PostMessage 或 SendNotifyMessage 中的错误,我是否可以依靠 SendNotifyMessage 在未来的 Windows 版本中继续显示此行为。

那么有人有一个合理的解释为什么这两个函数在这种情况下对广播的处理方式不同吗?

另外,我想问一下有没有办法仍然使用 PostMessage 广播到一个拥有的顶层窗口,因为我更愿意发布消息,因为我宁愿不跳过消息队列(哪个是 SendNotifyMessage 所做的)。

如果您好奇我为什么要访问顶级拥有的窗口:在 WPF 中,窗口从任务栏(Window.ShowInTaskbar 属性)中隐藏,方法是使它们拥有带有隐藏所有者窗口的顶级窗口。

非常感谢您对此主题的任何想法或评论。

附件:这里是一个显示行为的示例……只需构建它,然后启动它两次……第二个过程应该使消息显示在第一个过程中。这里还有一个完整解决方案的链接,包括一个构建 EXE:Link to the complete VS solution

#include <windows.h>
#include <stdio.h>

#include <string>
#include <vector>


HWND hwndMain = NULL;
HWND ownerHwnd = NULL;

std::vector<std::string> theOutput;
UINT MyRegisteredMessage1 = 0;


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc = NULL;

if (message == MyRegisteredMessage1 && wParam != (WPARAM) hwndMain)
{
if (lParam == (LPARAM) 1)
theOutput.push_back("Got a 'MyRegisteredMessage1' via PostMessage");
if (lParam == (LPARAM) 2)
theOutput.push_back("Got a 'MyRegisteredMessage1' via SendNotifyMessage");

InvalidateRect(hwndMain, NULL, TRUE);
}

switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for(size_t i = 0, pos = 0; i < theOutput.size(); ++i, pos += 20)
TextOutA(hdc, 0, pos, theOutput[i].c_str(), theOutput[i].size());
EndPaint (hWnd, &ps);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}

return 0;
}


LRESULT CALLBACK WndProcHidden(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}


int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
WNDCLASSA wc;
UNREFERENCED_PARAMETER(lpszCmdLine);

if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) WndProcHidden;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);;
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MyOwnerWindowClass";

if (!RegisterClassA(&wc))
return FALSE;

wc.lpfnWndProc = (WNDPROC) WndProc;
wc.lpszClassName = "MyOwnedWindowClass";

if (!RegisterClassA(&wc))
return FALSE;
}

ownerHwnd = CreateWindowA("MyOwnerWindowClass", "OwnerWindow",
WS_OVERLAPPEDWINDOW, 0, 0, 800, 400, (HWND) NULL,
(HMENU) NULL, hInstance, (LPVOID) NULL);

hwndMain = CreateWindowA("MyOwnedWindowClass", "OwnedWindow",
WS_OVERLAPPEDWINDOW, 0, 0, 800, 400, ownerHwnd,
(HMENU) NULL, hInstance, (LPVOID) NULL);

// only show the "real" window
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);

MyRegisteredMessage1 = RegisterWindowMessageA("MyRegisteredMessage1");

char infoText[256];
_snprintf_s(infoText, 256,
"HWND = %X, registered message code for 'MyRegisteredMessage1' = %d",
hwndMain, MyRegisteredMessage1);
theOutput.push_back(infoText);
InvalidateRect(hwndMain, NULL, TRUE);

PostMessage(HWND_BROADCAST, MyRegisteredMessage1, (WPARAM) hwndMain, (LPARAM) 1);
Sleep(1000);
SendNotifyMessageA(HWND_BROADCAST, MyRegisteredMessage1, (WPARAM) hwndMain, (LPARAM) 2);


while( (bRet = ::GetMessage( &msg, NULL, 0, 0 )) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

最佳答案

您可能需要使用 RegisterWindowMessage() 注册您的消息——请参阅此 MSDN article 的备注部分

关于c++ - 使用 PostMessage 与 SendNotifyMessage 广播到拥有的窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15987051/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com