更新程序后,SetForgroundWindow()失败

SetForgroundWindow() fails after program was Updated

本文关键字:失败 SetForgroundWindow 程序 更新      更新时间:2023-10-16

我写了一个图像匹配C++工具,它是一个通知区域工具(没有可见窗口)。它获得了另一个窗口的句柄并将其聚焦,然后进行了保存的图像匹配。现在这个工具正在完善,但我关注的程序的制作者(不是我写的)推送了一个更新,这对他们的程序有很大的改变。

因此,我似乎无法再设置程序的焦点(将它放在所有窗口的顶部)。我试着以管理员的身份运行,但没有成功。我可以看到任务栏中的图标闪烁橙色,这意味着它处于活动状态,但窗口不会出现在前台。

这是我的工具的隐形硬件:

hwnd =  CreateWindowEx (0, className,
TEXT( "" ),
WS_OVERLAPPEDWINDOW,
0, 0, 
0, 0, 
NULL, NULL, 
hInstance, NULL);

这是我在进行图像匹配的函数顶部的代码:

ShowWindow(handle, SW_SHOWDEFAULT); //maximize handle
SetForegroundWindow(handle); //bring to foreground

我使用SW_SHOWDEFAULT,而不是SW_SHOW和showWindow,因为这修复了我遇到的一个问题,即如果最小化该工具,它将无法匹配图像,因为窗口是隐藏的。

看起来SetForegroundWindow()在以前工作时现在返回0(fail)。我找不到有效的在线解决方案。

唯一起作用的是:

ShowWindow(handle, SW_MINIMIZE);
ShowWindow(handle, SW_SHOWDEFAULT);

这似乎可以最小化窗口并将其重新打开,从而使其聚焦,但这不是一个解决方案,因为图像匹配过程应该根据用户的意愿持续多久。

感谢您的帮助!

当SetForeground不工作时,则需要"焦点窃取"。由于其他程序可能依赖于聚焦窗口,因此被淹没。基本上,只有当前的前台窗口才能将属于另一个程序的窗口设置为前台。我相信这是在Vista中引入的。

请小心使用。

bool ForceToForeground(HWND hWnd)
{
HWND hForeground = GetForegroundWindow(); 
int curThread    = GetCurrentThreadId();
int remoteThread = GetWindowThreadProcessId(hForeground,0);
AttachThreadInput( curThread, remoteThread, TRUE);
SetForegroundWindow(hWnd);
AttachThreadInput( curThread, remoteThread, FALSE);
return GetForegroundWindow() == hWnd;
}

让您的应用程序通过RegisterHotKey注册一个(精心选择的)热键,然后通过SendInput 模拟密钥

在处理WM_HOTKEY消息时,您应该能够"窃取焦点"。

// Register the Ctrl+5 (numpad Hot Key)
BOOL BWin32Success = RegisterHotKey( hWnd, 4242, MOD_CONTROL, VK_NUMPAD5 );
[...]
// Later, Emulate the Hot Key
std::vector<INPUT> vInputs;
INPUT OneInput;
OneInput.type = INPUT_KEYBOARD;
OneInput.ki.time = 0;
OneInput.ki.dwExtraInfo = 0;
OneInput.ki.wScan = 0;
OneInput.ki.dwFlags = 0;
OneInput.ki.wVk = VK_CONTROL;
vInputs.push_back( OneInput );
OneInput.ki.wVk = VK_NUMPAD5;
vInputs.push_back( OneInput );
OneInput.ki.dwFlags |= KEYEVENTF_KEYUP;
vInputs.push_back( OneInput );
OneInput.ki.wVk = VK_CONTROL;
vInputs.push_back( OneInput );
// Update a global HWND variable with the target hWnd 
UINT Sent = SendInput( static_cast<UINT>( vInputs.size() ), &vInputs[ 0 ] );
[...]
// WM_HOTKEY Handler (message is posted)
case WM_HOTKEY: {
if ( wParam == 4242 ) {
// HERE USE THE GLOBAL "TARGET" HWND WITH APIs
}
break;
}

我最终使用了这里显示的方法:http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo