我有一些似乎有错误的代码。我没有写它,事实上它是在c ++中,直到几周前我还没有用c ++编写任何代码。
我们有一个触摸屏键盘,我们在需要键盘输入时显示,而在键盘输入时则关闭。使用我们多年前开发的触摸屏键盘(仅限于a-z,0-9,输入,移位,制表符),我们的软件可以在没有物理键盘的信息亭上使用。
在某些装有Windows 7的计算机上,键盘位于应用程序的“后面”(可能是其他计算机,但在其他操作系统上没有看到问题)。
工作多年。我更新了其他部分,最终使用Windows 7,现在66%的Windows 7安装键盘根本没有出现(在应用程序后面)。在我的电脑上,我起初认为它在100%的时间内出现,但是继续测试发现它在95-99%的时间内出现,这使得拍摄困难变得困难。
此外,关于GetForegroundWindow()的大多数帖子都必须处理向其他应用程序发送消息或从其他应用程序获取消息,而不是关于分层应用程序(我需要)。
当我开始时,代码看起来像这样:
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;
}
我尝试过几件事 捕获ShellExecute的HWND并将其传递给SetActiveWindow(ShellHand)似乎有一些影响。但仍然不一致。 HWND shellHand = ShellExecute(NULL,“open”,ShowFile.c_str(),Params.c_str(),NULL,SW_SHOWNORMAL);
在HWND Hand = GetForegroundWindow()之前添加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;
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;
}
似乎可以解决问题。