Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 启用窗口(hWnd,false)不';t禁用键盘输入_C++_Winapi - Fatal编程技术网

C++ 启用窗口(hWnd,false)不';t禁用键盘输入

C++ 启用窗口(hWnd,false)不';t禁用键盘输入,c++,winapi,C++,Winapi,我试图在特定条件下使用EnableWindow(hWnd,false)禁用窗口 根据,这应该“禁用对指定窗口的鼠标和键盘输入” 我看到的问题是,事实上,它确实像它所说的那样禁用,除非光标当前位于窗口中的文本框内,并且窗口的焦点没有被禁用。我也在考虑编写一些代码,把焦点从窗口上移开 有没有更好的办法 注意:被禁用的窗口是通过\u spawnl()运行的二进制文件,我不确定这是Windows功能还是错误。无论哪种方式,禁用前景窗口都不是一个好主意 如果您能够修改从\u spawnl()开始的程序,那

我试图在特定条件下使用
EnableWindow(hWnd,false)禁用窗口

根据,这应该“禁用对指定窗口的鼠标和键盘输入”

我看到的问题是,事实上,它确实像它所说的那样禁用,除非光标当前位于窗口中的文本框内,并且窗口的焦点没有被禁用。我也在考虑编写一些代码,把焦点从窗口上移开

有没有更好的办法


注意:被禁用的窗口是通过
\u spawnl()
运行的二进制文件,我不确定这是Windows功能还是错误。无论哪种方式,禁用前景窗口都不是一个好主意

如果您能够修改从
\u spawnl()
开始的程序,那么这是一个更好的解决方案。当你需要控制它时,你可以让它响应WM_应用程序或类似的东西

如果它是第三方应用程序,那么您将面临黑客攻击

您可以尝试使用
setforegroundindow
更改前景窗口,但只有在线程丢失前景锁之前的
\u spawnl()
之后很快执行此操作时,此操作才会起作用。在
之前使用
locksetforegroundindow
\u spawnl()
可能有助于延长锁定时间。也有其他各种黑客改变前景等

如果你不想改变前景,我可以想出一个解决办法:

  ShellExecute(NULL, NULL, TEXT("Notepad"), NULL, NULL, SW_SHOW);
  Sleep(2000);
  HWND hNP = FindWindow(TEXT("Notepad"), NULL);
  Sleep(2000); // Start typing in Notepad now...
  if (hNP)
  {
    DWORD tid = GetWindowThreadProcessId(hNP, NULL);
    GUITHREADINFO gti;
    gti.cbSize = sizeof(gti);
    if (tid && GetGUIThreadInfo(tid, &gti))
    {
      HWND hChild = NULL;
      if (gti.hwndFocus != hNP && gti.hwndFocus)
      {
        EnableWindow(hChild = gti.hwndFocus, false);
      }
      if (GetForegroundWindow() == hNP)
      {
        SendNotifyMessage(hNP, WM_ACTIVATE, WA_INACTIVE, NULL);
        SendNotifyMessage(hNP, WM_ACTIVATE, WA_ACTIVE, NULL);
        SendNotifyMessage(hNP, WM_SETFOCUS, NULL, NULL);
        // SendNotifyMessage(hNP, WM_NCACTIVATE, false, NULL); // Uncomment to make it look like it is inactive
      }
      EnableWindow(hNP, false);
      if (hChild)
      {
        EnableWindow(hChild, true);
      }
    }
    MessageBox(NULL, TEXT("Done?"), NULL, MB_TOPMOST);
    SetForegroundWindow(hNP);
    PostMessage(hNP, WM_CLOSE, 0, 0);
  }
这当然不是最优的,它会使记事本处于一种似乎已启用但实际上未启用的状态。其想法是禁用聚焦子窗口,触发一个虚假的激活更改,并强制更改焦点。它可能不适用于其他应用程序,谁知道呢

如果您愿意冒陷入僵局的风险,您可以这样做:

    DWORD tid = GetWindowThreadProcessId(hNP, NULL);
    GUITHREADINFO gti;
    gti.cbSize = sizeof(gti);
    if (tid && GetGUIThreadInfo(tid, &gti))
    {
      if (GetForegroundWindow() == hNP)
      {
        if (AttachThreadInput(GetCurrentThreadId(), tid, true))
        {
          SetFocus(NULL);
          AttachThreadInput(GetCurrentThreadId(), tid, false);
        }
      }
      EnableWindow(hNP, false);
    }

我认为您必须使用
EnumChildWindows
在每个子窗口上调用
EnableWindow
否,您不需要禁用每个子窗口,禁用父窗口将禁用所有子窗口的输入。然而,一般来说,跨进程边界使用
EnableWindow()
并不是一件好事。因此,第二部分非常有效,我很好奇您是否能详细说明为什么它会有死锁风险。@RyanBoykin等。