更新程序后,SetForgroundWindow()失败 我写了一个图像匹配C++工具,它是一个通知区域工具(没有可见窗口)。它得到了另一个窗口的控制柄并对其进行了聚焦,然后对保存的图像进行匹配。现在这个工具工作得很好,但是我关注的程序(不是我写的)的制作者推动了一个更新,它稍微改变了他们的程序

更新程序后,SetForgroundWindow()失败 我写了一个图像匹配C++工具,它是一个通知区域工具(没有可见窗口)。它得到了另一个窗口的控制柄并对其进行了聚焦,然后对保存的图像进行匹配。现在这个工具工作得很好,但是我关注的程序(不是我写的)的制作者推动了一个更新,它稍微改变了他们的程序,c++,windows,winapi,windows-7,C++,Windows,Winapi,Windows 7,因此,我似乎无法再设置程序的焦点(将其置于所有窗口的顶部)。我尝试以管理员的身份运行,但运气不佳。我可以看到任务栏上的图标呈橙色闪烁,这意味着它处于活动状态,但窗口不会出现在前台 这是我的工具的隐形硬件: hwnd = CreateWindowEx (0, className, TEXT( "" ), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); 这是我在函数顶部的代码,它使图像匹配: ShowWindow

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

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

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 with showWindow,因为这修复了我的一个问题,即如果工具最小化,它将无法匹配图像,因为窗口被隐藏

setForeGroundIndow()以前工作时,现在似乎返回0(失败)。我没有找到有效的在线解决方案

唯一有效的方法是:

这似乎可以最小化窗口并使其恢复,从而使其聚焦,但这不是一个解决方案,因为图像匹配过程应该持续用户想要的时间


感谢您的帮助

让应用程序通过注册(精心选择的)热键,然后通过模拟热键

在消息处理过程中,您应该能够“窃取焦点”

//注册Ctrl+5(numpad热键)
BOOL BWin32Success=RegisterHotKey(hWnd,4242,MOD_CONTROL,VK_NUMPAD5);
[...]
//稍后,模拟热键
向量输入;
输入一个输入;
OneInput.type=输入\键盘;
OneInput.ki.time=0;
OneInput.ki.dwExtraInfo=0;
OneInput.ki.wScan=0;
OneInput.ki.dwFlags=0;
OneInput.ki.wVk=VK_控制;
输入。推回(一个输入);
OneInput.ki.wVk=VK_NUMPAD5;
输入。推回(一个输入);
OneInput.ki.dwFlags |=KEYEVENTF_KEYUP;
输入。推回(一个输入);
OneInput.ki.wVk=VK_控制;
输入。推回(一个输入);
//使用目标HWND更新全局HWND变量
UINT Sent=SendInput(静态_转换(vInputs.size()),&vInputs[0]);
[...]
//WM_热键处理程序(消息已发布)
案例WM_热键:{
如果(wParam==4242){
//这里使用带有API的全局“目标”HWND
}
打破
}

当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;
}

我最终使用了如下所示的方法:

SetForegroundWindow
失败时,
GetLastError()
返回的值是多少?您是否阅读了中的
备注
?我似乎无法从GetLastError()中获得任何信息,但SetForegroundWindow的返回值肯定是0(失败)。我看了这些评论,不知道自己是否不及格Windows闪烁任务栏“是我得到的暗示,我不符合条件。我只是试着在通知区域双击我的图标,而工具试图在循环中设置前景窗口,它成功了,它成功地设置了它(因为我发送了最后一个事件?)。有什么想法吗?这个页面上的Alt-Tab方法似乎对我很有用:使用这个“黑客”有什么意义。如果我找不到其他选择,我很想使用它。Window努力禁止“焦点窃取”,理由很充分。其中一条规则是,如果你不是前台,你就不能更改前台窗口。您从未设置过窗口前景,这意味着您没有更改前景的权限。解决方案:在您的隐藏窗口上调用SetForeGroundIndow(现在您拥有前台并有权更改前台),然后在另一个窗口上调用SetForeGroundIndow。因此,此解决方案将发送一条control+7消息(WM_热键),允许我的程序在其中更改前台窗口?我将尝试一下,看看它是否有效,与我发布的其他方法相比,它有什么好处。非常感谢:事实上,DControl+7(numpad)是个糟糕的选择。我认为这可能会影响标准的Ctrl+Home。您必须选择其他选项,可能是Ctrl+5(Num Pad)。其好处也许是:与假鼠标点击相比更可靠。确保处理
RegisterHotKey
failing`(并使用其他组合重试)
// 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;
}
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;
}