エラーがあると思われるコードがいくつかあります。私はそれを書きませんでした。実際、これは C++ で書かれており、数週間前まで C++ でコードを書いたことはありませんでした。
キーボード入力が必要な場合は表示し、必要でない場合は閉じるタッチ スクリーン用のキーボードがあります。当社のソフトウェアは、数年前に開発したタッチ スクリーン キーボード (az、0-9、enter、shift、tab に限定) を使用して、物理キーボードなしでキオスクで使用できます。
Windows 7 を搭載した一部のコンピューターでは、キーボードがアプリケーションの「背後」にあります (他のコンピューターでは可能性がありますが、他の OS では問題は見られません)。
何年も働いた。最終的に Windows 7 で動作するように他の部分を更新しましたが、Windows 7 インストールの 66% で、キーボードがまったく表示されません (アプリケーションの背後にあります)。私のコンピュータでは、最初は 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 の前に Sleep(25) を追加する Hand= GetForegroundWindow(); 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;
}
問題を解決するようです。