Win32 API:打开对话框窗口后应用程序冻结



我试图在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);
}

这工作正常,并打开"打开对话框"。但是它会冻结我的应用程序。如果我尝试用鼠标移动我的应用程序窗口,它会挂起并在标题栏上显示"未响应"。我也试过在一个单独的线程中打开这个对话框窗口,但没有运气。如何解决这个问题?

你给我们看的代码看起来像你想控制NOTEPAD:它阻塞的原因很简单。SendMessage发送WM_COMMAND消息到NOTEPAD并等待它被处理。Notpad本身接收WM_COMMAND消息,并显示文件打开对话框,等待用户输入。

这都是在WM_COMMAND消息的处理中完成的,SendMessage只会在处理完成时返回。因此,用户要么终止对话框,要么选择一个文件并打开该文件。

PS:你的问题没有详细说明你真正想做什么。

在评论中声明:

我想打开一个文件与win32代码没有用户干预。

在这种情况下,你的整个方法是错误的。将文件名传递给ShellExecuteEx,让系统打开该文件。

至于为什么你当前的代码阻塞,这很简单。SendMessage是同步的,只有在消息被处理后才返回。当模态文件对话框关闭时,消息处理完成。但以这种方式破解记事本绝不是解决问题的正确方法。请避免。

为了防止你的程序挂起,你可以使用PostMessage代替SendMessage:

PostMessage(hWnd, WM_COMMAND, GetMenuItemID(hWndSubMenu, 1), 0);

你可能想进一步研究它们之间的区别:Send Message和Post Message之间的区别是什么,它们与c#、WPF和纯windows编程有什么关系?

一般来说,在windows API中SendMessage和PostMessage之间有很大的区别。

SendMessage将直接运行相关的回调(即应该接收消息的东西),并在消息被完全处理后返回。这是"阻塞"你的应用程序,因为记事本只有在(modal)文件对话框返回后才会从这个调用返回。

PostMessage将向应用程序消息队列中添加一条消息并立即返回;稍后,应用程序(记事本)将处理此消息。

所有这一切都说明你所做的可能不是一个好主意——这种对其他应用程序的远程控制会引起一些严重的安全问题。

最新更新