如何修复窗口焦点问题?

时间:2010-05-31 14:25:29

标签: c++ windows winapi

我正在处理的应用程序中有一个非常令人沮丧的错误。该例程应该在一个窗口中执行某些操作,然后在方法结束时将焦点返回到另一个窗口,但是当我在前一天开始使用大型数据集时,焦点在结束时停止返回。我一次一行地执行代码,错误停止了。所以,我认为它是某种时间问题。我追查直到找到我怀疑是罪魁祸首。调用ShellExecute(...),终止我使用的图像编辑器。 (http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx

现在,如果我跳过此调用,然后继续运行该程序,一切正常,但如果我只是跑过这一行,则会发生错误。怎么会这样?我在这个方法的最后调用了SetFocus()。不管怎样,程序都不会打这个?

这一切都非常令人沮丧......

2 个答案:

答案 0 :(得分:4)

首先应该明确的是Win32 API调用与windows / messages / focus等相关。取决于时间。 每个线程都有自己的窗口/消息子系统,这里没有竞争条件。

你描述的是别的东西。您实际上启动了另一个与您同时运行的进程(应用程序)。 请注意,ShellExecute异步功能。它在创建流程后立即返回,从现在开始,您的应用程序和您创建的流程将同时运行。

现在,由于系统中只有一个窗口可能同时具有焦点 - 您创建的过程很可能只会从您那里窃取焦点。 为了避免这种情况,您应该先等待该过程完成工作,然后将焦点恢复到窗口并继续工作。

为此,您必须获取已创建进程的句柄,并在其上调用Win32等待函数。 ShellExecute不会返回已创建进程的句柄。但是ShellExecuteEx - 确实如此。 顺便说一句,它还允许您启动一个过程,其中包含不显示UI的说明,如果这是您想要的。

你应该这样写:

SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpFile = L"notepad.exe";
sei.nShow = SW_SHOWNORMAL; // or SW_HIDE if you don't want to show it

if (ShellExecuteEx(&sei))
{
    // wait for completion
    WaitForSingleObject(sei.hProcess, INFINITE);
    CloseHandle(sei.hProcess);
}

这应该有用

P.S。当然,您应该关闭创建过程的句柄。也就是说,CloseHandle之后必须调用WaitForSingleObject

答案 1 :(得分:0)

正如你所说,这个问题听起来像是时间问题。

我不熟悉ShellExecute函数,但是从你链接的页面开始:

“因为ShellExecute可以将执行委托给使用组件对象模型(COM)激活的Shell扩展(数据源,上下文菜单处理程序,动词实现),所以在调用ShellExecute之前应该初始化COM。一些Shell扩展需要COM单个 - 螺纹公寓(STA)类型。“

也许那是相关的?