我正在尝试使用win32 API在按钮单击事件上打开已打开的记事本应用程序的“打开文件对话框”。这是代码:
void onButonClicked()
{
HWND hWnd = ::FindWindow(NULL, L"Untitled - Notepad");
HMENU hWndMenu = ::GetMenu(hWnd);
HMENU hWndSubMenu = ::GetSubMenu(hWndMenu, 0);
SendMessage(hWnd, WM_COMMAND, GetMenuItemID(hWndSubMenu, 1), 0);
}
这很好用并打开“打开对话框”。但它冻结了我的应用程序。如果我尝试使用鼠标移动我的应用程序窗口,它会挂起并在标题栏上显示“无响应”。我也尝试在一个单独的线程中打开这个对话框窗口,但没有运气。如何解决这个问题?
答案 0 :(得分:2)
您向我们展示的代码看起来像您要控制NOTEPAD: 它阻塞的原因很简单。 SendMessage将WM_COMMAND消息发送到NOTEPAD并等待直到它被处理。 Notpad本身接收WM_COMMAND消息并显示文件打开对话框并等待用户输入。
这一切都是在处理WM_COMMAND消息时完成的,而SendMessage只会在完成此处理时返回。因此,要么用户中止对话框,要么选择文件并打开文件。
PS:你的问题不够详细,你真正想做什么。
答案 1 :(得分:2)
在评论中说明:
我想用win32代码打开一个文件而无需用户干预。
在这种情况下,你的整个方法都是错误的。将文件名传递给ShellExecuteEx
,让系统打开文件。
至于为什么你当前的代码阻塞,这很简单。 SendMessage
是同步的,只有在处理完消息后才会返回。当模态文件对话框关闭时,消息处理完成。但是以这种方式破坏记事本永远不是解决问题的正确方法。请不要。
答案 2 :(得分:1)
为防止程序被挂起,您可以使用PostMessage
代替SendMessage
:
PostMessage(hWnd, WM_COMMAND, GetMenuItemID(hWndSubMenu, 1), 0);
答案 3 :(得分:0)
一般来说,Windows API中SendMessage和PostMessage之间存在很大差异。
SendMessage将直接运行相关的回调(即应该接收消息的东西),并在消息完全处理后返回。这是“阻止”您的应用程序,因为记事本仅在(模态)文件对话框返回后才从此调用返回。
PostMessage将向应用程序消息队列添加消息并立即返回;稍后,应用程序(记事本)将处理此消息。
所有这些都说明你所做的可能不是一个好主意 - 这种对其他应用程序的远程控制引起了一些严重的安全问题。