【问题标题】:Win32 API: App Freezes after opening dialog windowWin32 API:打开对话框窗口后应用程序冻结
【发布时间】:2015-08-13 06:33:24
【问题描述】:

我正在尝试使用 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);
}

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

【问题讨论】:

  • 打开文件对话框不应该是模态对话框吗?
  • 我是 win32 API 的新手。是不是想说有更好的打开Open Dialog的方式?
  • 打开打开对话框后,我想在没有用户干预的情况下打开一个带有win32代码的文件。但是,由于应用程序在显示打开对话框后冻结,下一段代码不会执行。
  • 你在尝试什么。想要控制 NOTEPAD?
  • 停止黑客攻击,开始开发可靠的代码。模块 1:向UI Automation 介绍自己。

标签: c++ winapi


【解决方案1】:

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

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

PS:你的问题不够详细,你真正想做什么。

【讨论】:

  • 记事本只是一个例子。我试图做一些不同的事情。 PostMessage 为我工作。
  • 永远不会!因为你永远不知道程序什么时候真正完成了它的工作。
【解决方案2】:

在您声明的 cmets 中:

我想在没有用户干预的情况下打开一个带有 win32 代码的文件。

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

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

【讨论】:

  • 记事本文件打开只是一个例子。我正在尝试做一些不同的事情。 PostMessage 为我工作。
  • 无论你在做什么,这肯定不是解决方案。
  • 好的,请指导我以正确的方式进行操作。我正在尝试在已运行的 3rd 方应用中打开配置文件。
  • 这样做真的没有建设性。您问如何在记事本中打开文件。现在你想做点别的。您不会告诉我们任何有关 3rd 方应用程序的信息,我们必须努力获取详细信息。我们每天都有很多这样的问题,提问者很少想使用官方的自动化方法,而且由于我不知道的原因,我似乎一心想以你正在做的方式破解。您已经在这里接受了一个答案,告诉我们您对自己所做的事情感到满意。没关系。
  • 对此我深表歉意。但我不被允许透露那个第 3 方应用程序。记事本对我来说是类似的例子。这就是为什么我用它来举例。显然使用 PostMessage 而不是 ShowMessge 解决了我的问题。这就是我接受这个答案的原因。无论如何感谢您的建议。
【解决方案3】:

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

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

您可能想进一步研究差异:What is the difference between Send Message and Post Message and how these relate to C# ,WPF and Pure windows programming?

【讨论】:

    【解决方案4】:

    总的来说,windows API 中的 SendMessage 和 PostMessage 有很大的不同。

    SendMessage 将直接运行相关的回调(即应该接收消息的事物)并在消息完全处理后返回。这是“阻止”您的应用程序,因为记事本仅在(模态)文件对话框返回后从此调用中返回。

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

    所有这些都表明您正在做的事情可能不是一个好主意 - 这种对其他应用程序的远程控制会引发一些严重的安全问题。

    【讨论】:

    • 我不明白,在 UIPI 到位的情况下,这会如何引入任何类型的安全问题。但是,这确实会造成支持的噩梦。毕竟,您依赖于未记录的行为,这种行为可能会在没有事先通知的情况下发生变化。
    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    相关资源
    最近更新 更多