C++ GetForegroundWindow不总是正确的?
我有一些代码似乎有错误。我没有写,实际上它是在C++中,直到几周前我从未在C++中编写任何代码。 我们有一个用于触摸屏的键盘,当需要键盘输入时,我们会将其打开,当不需要时,我们会将其关闭。我们的软件可以在信息亭上使用,而无需使用多年前开发的触摸屏键盘(限于a-z、0-9、enter、shift、tab) 键盘位于Windows 7的某些计算机上的应用程序“后面”(可能是其他计算机,但在其他操作系统上未发现问题) 工作多年。我更新了其他部分以最终使用Windows7,现在我们安装的Windows7中有66%的键盘根本没有出现(在应用程序后面)。起初在我的电脑上,我以为它能100%的显示出来,但继续测试发现它能显示95-99%的时间,这使得故障排除变得困难 此外,关于GetForegroundWindow()的大多数帖子都必须处理与其他应用程序之间的消息发送或获取,而不是分层应用程序(如我所需) 当我开始时,代码如下所示:C++ GetForegroundWindow不总是正确的?,c++,touchscreen,hwnd,C++,Touchscreen,Hwnd,我有一些代码似乎有错误。我没有写,实际上它是在C++中,直到几周前我从未在C++中编写任何代码。 我们有一个用于触摸屏的键盘,当需要键盘输入时,我们会将其打开,当不需要时,我们会将其关闭。我们的软件可以在信息亭上使用,而无需使用多年前开发的触摸屏键盘(限于a-z、0-9、enter、shift、tab) 键盘位于Windows 7的某些计算机上的应用程序“后面”(可能是其他计算机,但在其他操作系统上未发现问题) 工作多年。我更新了其他部分以最终使用Windows7,现在我们安装的Windows7
bool ShowKeyBoad(bool Show)
{
int WizHeight = 422;
int KeyWidth,KeyHeight,KeyLeft, KeyTop;
AnsiString Params;
AnsiString ShowFile = GetFullPath(GetExeDir(), "OnscreenKeyboard.exe");
AnsiString HideFile = GetFullPath(GetExeDir(), "bkecekeyboard.exe");
KeyHeight = Screen->Height - WizHeight;
KeyWidth = Screen->Width;
if (KeyWidth > Screen->Width)
KeyWidth = Screen->Width;
KeyLeft = (Screen->Width - KeyWidth) / 2;
KeyTop = (Screen->Height) - KeyHeight;
Params = "x-" + IntToStr(KeyLeft) + " y-" + IntToStr(KeyTop) +
" h-" + IntToStr(KeyHeight) + " w-" + IntToStr(KeyWidth);
if (Show)
{
HWND Hand= GetForegroundWindow();
ShellExecute(NULL, "open", ShowFile.c_str(), Params.c_str(), NULL, SW_SHOWNORMAL);
Sleep(100);
SetForegroundWindow(Hand);
SetActiveWindow(Hand);
}
else
ShellExecute(NULL, "open", HideFile.c_str(), "/stop", NULL, SW_HIDE);
return true;
}
bool ShowKeyBoad(bool Show)
{
int WizHeight = 422;
int KeyWidth,KeyHeight,KeyLeft, KeyTop;
AnsiString Params;
AnsiString ShowFile = GetFullPath(GetExeDir(), "OnscreenKeyboard.exe");
AnsiString HideFile = GetFullPath(GetExeDir(), "bkecekeyboard.exe");
KeyHeight = Screen->Height - WizHeight;
KeyWidth = Screen->Width;
if (KeyWidth > Screen->Width)
KeyWidth = Screen->Width;
KeyLeft = (Screen->Width - KeyWidth) / 2;
KeyTop = (Screen->Height) - KeyHeight;
Params = "x-" + IntToStr(KeyLeft) + " y-" + IntToStr(KeyTop) +
" h-" + IntToStr(KeyHeight) + " w-" + IntToStr(KeyWidth);
if (Show)
{
HWND Hand;
int intfail=1000; // count down seems correct in this case, usually don't
while (Hand = NULL)
{
if (intfail <=0)
break;
Hand = GetForegroundWindow();
intfail--;
}
if (Hand == NULL)
{
// Send Message to screen giving instructions to try again
return false;
}
ShellExecute(NULL, "open", ShowFile.c_str(), Params.c_str(), NULL, SW_SHOWNORMAL);
Sleep(100);
SetForegroundWindow(Hand);
SetActiveWindow(Hand);
}
else
ShellExecute(NULL, "open", HideFile.c_str(), "/stop", NULL, SW_HIDE);
return true;
}
我试过一些东西。捕获ShellExecute的HWND并将其传递给SetActiveWindow(ShellHand)似乎有一些效果。但仍然不一致。 HWND shellHand=ShellExecute(NULL,“打开”,ShowFile.c_str(),Params.c_str(),NULL,SW_SHOWNORMAL) 在HWND Hand=getforegroundindow()之前添加Sleep(25);对GUI有最好的影响-但我不想依赖于正确的时机 各种各样的网络搜索给我指出了一些看起来也很不错的代码。但它改变了注册表设置,这似乎不是一个明智的选择 使用该解决方案,我们将SetForeground更改为SetForegroundInternal
void SetForegroundWindowInternal(HWND hWnd)
{
if(!::IsWindow(hWnd)) return;
//relation time of SetForegroundWindow lock
DWORD lockTimeOut = 0;
HWND hCurrWnd = ::GetForegroundWindow();
DWORD dwThisTID = ::GetCurrentThreadId(),
dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0);
//we need to bypass some limitations from Microsoft :)
if(dwThisTID != dwCurrTID)
{
::AttachThreadInput(dwThisTID, dwCurrTID, TRUE);
::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0);
::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
::AllowSetForegroundWindow(ASFW_ANY);
}
::SetForegroundWindow(hWnd);
if(dwThisTID != dwCurrTID)
{
::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
::AttachThreadInput(dwThisTID, dwCurrTID, FALSE);
}
}
更新
猜测Hand=NULL是我的问题,我使代码如下所示:
bool ShowKeyBoad(bool Show)
{
int WizHeight = 422;
int KeyWidth,KeyHeight,KeyLeft, KeyTop;
AnsiString Params;
AnsiString ShowFile = GetFullPath(GetExeDir(), "OnscreenKeyboard.exe");
AnsiString HideFile = GetFullPath(GetExeDir(), "bkecekeyboard.exe");
KeyHeight = Screen->Height - WizHeight;
KeyWidth = Screen->Width;
if (KeyWidth > Screen->Width)
KeyWidth = Screen->Width;
KeyLeft = (Screen->Width - KeyWidth) / 2;
KeyTop = (Screen->Height) - KeyHeight;
Params = "x-" + IntToStr(KeyLeft) + " y-" + IntToStr(KeyTop) +
" h-" + IntToStr(KeyHeight) + " w-" + IntToStr(KeyWidth);
if (Show)
{
HWND Hand= GetForegroundWindow();
ShellExecute(NULL, "open", ShowFile.c_str(), Params.c_str(), NULL, SW_SHOWNORMAL);
Sleep(100);
SetForegroundWindow(Hand);
SetActiveWindow(Hand);
}
else
ShellExecute(NULL, "open", HideFile.c_str(), "/stop", NULL, SW_HIDE);
return true;
}
bool ShowKeyBoad(bool Show)
{
int WizHeight = 422;
int KeyWidth,KeyHeight,KeyLeft, KeyTop;
AnsiString Params;
AnsiString ShowFile = GetFullPath(GetExeDir(), "OnscreenKeyboard.exe");
AnsiString HideFile = GetFullPath(GetExeDir(), "bkecekeyboard.exe");
KeyHeight = Screen->Height - WizHeight;
KeyWidth = Screen->Width;
if (KeyWidth > Screen->Width)
KeyWidth = Screen->Width;
KeyLeft = (Screen->Width - KeyWidth) / 2;
KeyTop = (Screen->Height) - KeyHeight;
Params = "x-" + IntToStr(KeyLeft) + " y-" + IntToStr(KeyTop) +
" h-" + IntToStr(KeyHeight) + " w-" + IntToStr(KeyWidth);
if (Show)
{
HWND Hand;
int intfail=1000; // count down seems correct in this case, usually don't
while (Hand = NULL)
{
if (intfail <=0)
break;
Hand = GetForegroundWindow();
intfail--;
}
if (Hand == NULL)
{
// Send Message to screen giving instructions to try again
return false;
}
ShellExecute(NULL, "open", ShowFile.c_str(), Params.c_str(), NULL, SW_SHOWNORMAL);
Sleep(100);
SetForegroundWindow(Hand);
SetActiveWindow(Hand);
}
else
ShellExecute(NULL, "open", HideFile.c_str(), "/stop", NULL, SW_HIDE);
return true;
}
bool ShowKeyBoad(bool Show)
{
int WizHeight=422;
int键宽、键高、键左、键顶;
解析参数;
AnsiString ShowFile=GetFullPath(GetExeDir(),“OnscreenKeyboard.exe”);
AnsiString HideFile=GetFullPath(GetExeDir(),“bkecekeyboard.exe”);
KeyHeight=屏幕->高度-WizHeight;
KeyWidth=屏幕->宽度;
如果(键宽度>屏幕->宽度)
KeyWidth=屏幕->宽度;
KeyLeft=(屏幕->宽度-键宽度)/2;
按键高度=(屏幕->高度)-按键高度;
Params=“x-”+IntToStr(键左)+“y-”+IntToStr(键顶)+
“h-”+IntToStr(键高)+“w-”+IntToStr(键宽);
如果(显示)
{
右手;
int intfail=1000;//在这种情况下倒计时似乎是正确的,但通常不正确
while(Hand=NULL)
{
如果(intfailShellExecute()
不返回HWND
。其返回值是一个整数错误代码类型,转换为HINSTANCE
句柄指针(用于向后兼容16位代码)。若要定位生成的进程的HWND
,请改用FindWindow()
(可能您在编写该exe之后就知道了它的类名),或者使用CreateProcess()
,然后调用EnumWindows()'运行一个GetWindowThreadProcessId()`循环,查找与生成的进程匹配的HWND
s。如果您使用CreateProcess()
或ShellExecuteEx())
,您可以访问进程句柄,您可以将其传递到WaitForInputIdle()
而不是Sleep()
。我猜HWND Hand=GetForeGroundIndow()中的“Hand”=NULL就是这个问题。为什么它只在某些Windows 7安装中出现是非常奇怪的。