2012年2月26日日曜日

日記ちゃん

いつだかに言ってたフリック入力なスクリーンキーボードを作るべく
ちょいちょい調べているが、
まずスクリーンキーボードの機能を組む段階で詰まった。
 
 ひとつしたのウィンドウにキーを送信すればいいのだけど、
キー送信はアクティブなウィンドウにしかできないっぽいのね。
でも自分をクリックすると自分がアクティブなっちゃってキーをうまく送信できなくなる。
AttachThreadInputだとか、WM_NCACTIVATEだとかいろいろ調べたら出てきたんだけど
どうにもうまくいきそうでいかない。
 
 で、結局はCreateWindowExにWS_EX_NOACTIVATE | WS_EX_TOPMOSTをしていして、
自信はアクティブにならず最善面表示するウィンドウを作成するようにしたらかなり簡単にうまくいった。
キー送信も自分はアクティブにならないから
自動的にターゲットのウィンドウがアクティブになってて、そのままキー送信される便利具合。
 
 テスト的な実装で、WM_LBUTTONDOWNがきたらkeybd_eventをするだけで想定したの動きになった。
これからスクリーンキーボードを作ろうという方は、この方法はどうだろうか?
あとはボタンを置いてボタンごとにkeybd_eventの処理を書くだけ。半角全角キーがちょっと面倒なようだけど。
 
 タスクバーにのらないみたいだからまだなんかウィンドウスタイルを指定する必要があるみたいだけど。
CreateWindowEx 関数
思いっきり書いてあったけど。WS_EX_APPWINDOWを足せよ!とのこと。

#define _WIN32_WINNT 0x0500
#include
 
 
LRESULT CALLBACK wndProc(
  HWND hWnd,
  UINT msg,
  WPARAM wParam,
  LPARAM lParam )
{
  switch (msg)
  {
  case WM_DESTROY:
    ShowWindow( hWnd, SW_HIDE );
    PostQuitMessage(0);
 
    break;
  case WM_CREATE:
    break;
  case WM_LBUTTONDOWN:
    {
      keybd_event( 'A', 0, 0, 0 );
      keybd_event( 'B', 0, 0, 0 );
      keybd_event( 'C', 0, 0, 0 );
      keybd_event( VK_RETURN, 0, 0, 0 );
    }
 
    break;
  default:
    return DefWindowProc( hWnd, msg, wParam, lParam );
  }
 
  return 0;
}
 
 
 
int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE, PSTR, int )
{
  LPCTSTR WINDOW_NAME = TEXT("sample");
 
  WNDCLASSEX wc;
  wc.style    = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc  = reinterpret_cast( wndProc );
  wc.cbClsExtra  = 0;
  wc.cbWndExtra  = 0;
  wc.cbSize    = sizeof( WNDCLASSEX );
  wc.hInstance  = hInstance;
  wc.hIcon    = NULL;
  wc.hIconSm    = NULL;
  wc.hCursor    = LoadCursor( NULL, IDC_ARROW );
  wc.hbrBackground= reinterpret_cast( GetStockObject(WHITE_BRUSH) );
  wc.lpszMenuName  = NULL;
  wc.lpszClassName= WINDOW_NAME;
  if ( !RegisterClassEx(&wc) ) return 0;
 
  HWND hWnd = CreateWindowEx(
    WS_EX_NOACTIVATE | WS_EX_TOPMOST | WS_EX_APPWINDOW,
    WINDOW_NAME, NULL, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL);
  if ( !hWnd ) return -1;
 
  ShowWindow( hWnd, SW_SHOWNORMAL );
  UpdateWindow( hWnd );
  
  MSG msg;
  for (;;)
  {
    if ( !GetMessage(&msg, NULL, 0, 0) ) break;
    TranslateMessage( &msg );
    DispatchMessage( &msg );
  }
 
  
  UnregisterClass( WINDOW_NAME, hInstance );
  return msg.wParam;
}

0 件のコメント: