MSGFILTER lParmで得られるキーコードとは?

このQ&Aのポイント
  • MSGFILTER lParmで得られるキーコードは、キーボードの並び順になっているようです。
  • VK_??に変換する方法は特にありませんが、VK_SHIFTを使用してシフトデータと組み合わせて文字コードに変換することができます。
  • 他に良い方法があればアドバイスしてください。
回答を見る
  • ベストアンサー

MSGFILTER lParmで得られるキーコード?

いつもお世話になっております。 以下のような関数で押されたキーを判定しています。 lParmで得られるキーコードはVK_??のコードと違うようなのですが、 (キーボードの並び方順になってる?) これをVK_??に変換するような方法はあるのでしょうか? (本当はSHIFTデータもプラスして文字コードに変換したいのですが・・・) 何か良い方法があればアドバイスお願いいたします。 void CCtypeView::OnMsgfilterEdit1(NMHDR* pNMHDR, LRESULT* pResult) { MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR); if( pMsgFilter->msg == WM_KEYDOWN ) { SHORT sho = GetAsyncKeyState(VK_SHIFT); TRACE( "%d : \nWM_LBUTTON x=%x,y=%d sho=%x", pMsgFilter->msg, HIWORD( pMsgFilter->lParam), LOWORD( pMsgFilter->lParam), sho ); } *pResult = 0; }

  • ystk
  • お礼率83% (55/66)

質問者が選んだベストアンサー

  • ベストアンサー
  • alfeim
  • ベストアンサー率58% (114/195)
回答No.3

もっかい追記(^^;(調べ方が甘いなぁ・・・) MapVirtualKey() APIでその場で変換できます。 第一引数に仮想キーコード、第二引数に2を指定してやれば仮想キーコードからASCII文字に変換できるはずです。 詳細はMSDNでどうぞ。

ystk
質問者

お礼

MapVirtualKey() 便利な関数があるのにそれを見つけることが出来ないというのは歯がゆいです やっぱりリファレンスに一通り目を通さないといけないのかなぁ(^^; lParamの説明大変参考になりました。 ホントにありがとうございました。

その他の回答 (2)

  • alfeim
  • ベストアンサー率58% (114/195)
回答No.2

追記です。 どうも記号あたりなんかはOEM指定部分にマッピングされているようで、ハードコートすると不都合が発生する危険性がありそうです。 なので入力されたキャラクタが知りたいのであれば、TranslateMessage APIを使って仮想キーコードからWM_CHARメッセージに変換するのが一番良さそうです。 なおTranslateMessage()では直接変換後のWM_CHARメッセージがもらえるわけではなく、変換結果がメッセージキューに詰まれるだけなのでご注意を。

  • alfeim
  • ベストアンサー率58% (114/195)
回答No.1

MSGFILTER構造体の説明を見た限りではメンバのmsgに対応したwparamとlparamが仕込まれているだけのようです。 であればWM_KEYDOWN時のlParamの意味を観ればいいだけです。 で、WM_KEYDOWNのlParamはというと・・・ 0から15bit・・・リピート回数。キーを押しつづけた時に発生するリピートの回数が入っています。 16から23bit・・・スキャンコード。いわゆるOEMコードです。多分使わない。 24bit・・・右Ctrl、右Alt等の拡張キー。詳細はMSDNを参照。 25から28bit・・・予約。 29bit・・・コンテキストコード。WM_KEYDOWNでは常に0。 30bit・・・直前のキーの状態。押下されていた場合は1。 31bit・・・キーの遷移状態。WM_KEYDOWNでは常に0。 というようになっているようです。 また、仮想キーコードはwParamに入っていますのでそれを利用するのが良いと思います。 ただし@(アットマーク)や\(バックスラッシュ)等のキーに付いてはWINUSER.Hに定義がありません(実際にはVK_1からVK-0、VK_AからVK_Zも定義されてませんが)。 VK_1からVK_0、VK_AからVK_ZはASCIIにおけるそれぞれのキャラクタと同値なのでそのキャラクタ値と比較すれば判別できますが、その他の記号類に付いては文字コードなどと関連を付けてあるわけではないのでテーブルを用意しないと駄目だと思います。 なお、コードに関してはSpyやSpy++を使って調べてください。

関連するQ&A

  • なぜCreateHatchBushの設定が途中で喪失するのか

    いつもお世話になります。 縦縞の四角形を表示するプログラムですが、ある一定の四角形を描画すると四角形の中の縦縞がなくなり、白色になります。 原因が分かりません。アドバイスをお願い致します。 (四角形をマウスドラッグ中に小さくすると黒い線がたくさんでてきますが、これはアプリケーションの仕様です) プロシージャソースは以下の通り。 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT ps; static POINT start, end; static bool push; switch(msg) { case WM_CREATE: push = false; break; case WM_LBUTTONDOWN: start.x = LOWORD(lParam); start.y = HIWORD(lParam); push = true; break; case WM_MOUSEMOVE: if(push){ end.x = LOWORD(lParam); end.y = HIWORD(lParam); InvalidateRect(hWnd, NULL, FALSE); } break; case WM_LBUTTONUP: end.x = LOWORD(lParam); end.y = HIWORD(lParam); push = false; InvalidateRect(hWnd, NULL, FALSE); break; case WM_PAINT: HBRUSH hBrush; hDC = BeginPaint(hWnd, &ps); hBrush = CreateHatchBrush(HS_VERTICAL, RGB(255, 0, 0)); SelectObject(hDC, hBrush); Rectangle(hDC, start.x, start.y, end.x, end.y); DeleteObject(hBrush); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } よろしくお願い致します。

  • ウィンドウをつまんで動かしたい

    POPUP,TOPMOST属性のウィンドウにボタンを貼り付けたタイマーを作っています。ボタン以外の場所をクリック&ドラッグすることでウィンドウを自由に移動できるようにしたくて以下の様にコードを書いたのですが上手く動きません。 case WM_LBUTTONDOWN: SetCapture(hwnd); mPrevXPos = LOWORD(lParam); mPrevYPos = HIWORD(lParam); return 0; case WM_LBUTTONUP: ReleaseCapture(); return 0; case WM_MOUSEMOVE: if(wParam & MK_LBUTTON) { MoveX = LOWORD(lParam)-mPrevXPos+wPrevXPos; MoveY = HIWORD(lParam)-mPrevYPos+wPrevYPos; if(MoveX<0) MoveX=0; if(MoveY<0) MoveY=0; MoveWindow(hwnd,MoveX,MoveY,WIHDOW_WIDTH,WINDOW_HEIGHT,TRUE); } return 0; case WM_MOVE: wPrevXPos = LOWORD(lParam); wPrevYPos = HIWORD(lParam); return 0; このようにしてウィンドウの左のほうを掴んで左方向にくいっと動かすとウィンドウが消滅してしまいます。MoveWindow関数はTRUEを返しています。SetCaptureを外すとウィンドウは消滅しなくなるので、マウス座標にマイナスの値が入るのがイケナイようなのですがどうすればよいのか分かりません。またMoveWindow関数にマイナスの座標が入ってもウィンドウが消えてしまうためスクリーンの左隅でストップするようにしてますが、この制約も取り除きたいのですがどうすればよいでしょう?

  • ウィンドウが表示されない

    あるサンプルプログラムを改造しようとしているのですが、g_hWnd=CreateWindow( _T(__FILE__),_T("シューティングゲーム"),WINDOW_STYLE, CW_USEDEFAULT,CW_USEDEFAULT,rc.right-rc.left,rc.bottom-rc.top, NULL,NULL,hInst,NULL);のところのWINDOW_STYLEをWS_OVERLAPPEDWINDOWに変えたらウィンドウが表示されません。どうしたら表示されるのでしょうか。わかる方いらいしたらご教授お願いします。多分ここだろうなというところのコードを載せます。 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_KEYDOWN: switch(wParam) { case VK_F1: ChangeDisplayMode(); return 0; case VK_ESCAPE: PostMessage(hWnd,WM_CLOSE,0,0); return 0; } return 0; case WM_DISPLAYCHANGE: // IDirect3DDevice9::Reset メソッドから Send される DisplayChange(); return 0; case WM_SIZE: if(g_bWndMode==false || wParam==SIZE_MINIMIZED) return 0; g_D3DPP.BackBufferWidth = LOWORD(lParam); g_D3DPP.BackBufferHeight = HIWORD(lParam); if(wParam==SIZE_MAXIMIZED || wParam==SIZE_RESTORED) ChangeWindowSize(); return 0; case WM_ACTIVATE: g_bActive=(LOWORD(wParam)!=WA_INACTIVE); return 0; case WM_DESTROY: CleanupD3DObject(); CleanupDXGraphics(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,msg,wParam,lParam); }

  • WM_NOTIFYのメッセージクラッカー

    Borland C++5.5 FreeVersion XP SP3の環境でAPIの練習中なのですが。 WM_NOTIFYのメッセージクラッカーってできるのでしょうか? windowsx.hのヘッダーを見ても見当たりません。 commctrl.hの中にそれらしきものがあるので試しに追加してもダメでした。 ---------------------------------------------------------------------------- //====== WM_NOTIFY Macros ===================================================== #define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \ (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam)) #define FORWARD_WM_NOTIFY(hwnd, idFrom, pnmhdr, fn) \ (LRESULT)(fn)((hwnd), WM_NOTIFY, (WPARAM)(int)(idFrom), (LPARAM)(NMHDR FAR*)(pnmhdr)) ---------------------------------------------------------------------------- とあるので、次のように宣言をしたのですが //プロトタイプ宣言 void Cls_OnTreeNotify(HWND,int,(NMHDR FAR*)); //メッセージクラッカー宣言 HANDLE_MSG(hWnd, WM_NOTIFY, Cls_OnTreeNotify); //実際の定義 void Cls_OnTreeNotify(HWND hwnd, int idFrom, (NMHDR FAR*)pnmhdr ) { } でコンパイルしたのですが、次のようなコンパイルエラーが発生します。 "未定義のシンボル HWND" 追加した部分(WM_NOTIFY)以外のメッセージクラッカーはWM_PAINT,WM_CREATEは正常にコンパイルできます。 WM_NOTIFYのメッセージクラッカーはできるのでしょうか。 ご教授お願いします。

  • VC++のLV_KEYDOWNについて

    キーボードのショートカット処理の関数を作成しているのですが、Ctrl + sでデフォルトの保存処理ではなく 別の処理を作成したいと考えております。 ですが下記のように実装してもCtrl + sを検出できません。(Ctrl + a)は検出するのですが。 何か原因があるのでしょうか? ご存知の方がいましたらご教授いただけないでしょうか? void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; SHORT nCtrl = 0; switch(pLVKeyDow->wVKey) { case 's': case 'S': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + sの処理 break; case 'a': case 'A': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + aの処理 break; } *pResult = 0; }

  • リストコントロールのデータの変更を検知したい

    リストコントロールのデータの変更時に呼び出されるイベントが分かりません、 OnLvnItemchangedList()であっているのでしょうか?もっと簡単に実現できるのなら、 教えてください。 VC++2010 MFC です。 削除のときは、条件なしに、OnLvnDeleteitemList()内でいいのですが、 追加も pNMLV->uChanged == 4 にすれば問題ないです。でもその他は、厳しくしすぎると クリックしただけで、データが変更されたと判断されたり、・・・でうまく行きません。 【リスト上のデータが変更されるケース】 データが変更される場合は、非選択状態から「すべてを置換」するケースや 一個一個 検索(選択)しながら、「置換」するケースがあります。 後は、リストコントロールにエディットボックスを張り付かせて、「編集」(エンターで確定) して、データを変更するケースがあります。 ただし、「すべてを置換」する場合でも、既に選択状態のデータを処理する場合もあり、困っています。 自分で作ったプログラムなのですから、各機能終了時に変更されたか?されてないか?は 分かっているのですが、勉強のため、質問をしました。 PreTranslateMessage()で出来るのでしょうか? (参考サイト: http://isobe.exblog.jp/996027/ ) 【目的】 起動時 から(前回保存時から)リストデータに変化がない場合、何もせずに終了したい 【やりたいこと】 リストの文字が変わったら、キャプションを FileListCreator(*) にすると ともに、ListDataNoChange_FLG = FALSE; にする。 保存ややリカバリ(復帰)を行ったら (*) を取って、 ListDataNoChange_FLG = TRUE; にする。 if ( ListDataNoChange_FLG == TRUE ) //保存処理をスキップする。 【できれば】 あとは、pNMLV->uChanged などの 4とか8とか、定数で記述したいです。 lParamが何を意味しているか?分からないです。教えて下さい。 void CFileListCreatorDlg::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   if (( pNMLV->uChanged == 4 && pNMLV->uNewState == 0 && pNMLV->uOldState == 0 ) //リストコントロールにアイテムが追加した時     || ( pNMLV->uChanged == 8 && pNMLV->uNewState == 3 && pNMLV->uOldState == 0)){ //「すべてを置換」「置換」ボタンを押した時 //「検索」ボタンで検索しただけでも選択状態になる     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 1 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 2 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 3 )){     ListDataNoChange_FLG = FALSE;//追加 2012.05.13          CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();     if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){       return;     }     m_Dlg->SetWindowText(_T("FileListCreator (*)"));   }   //CString tempStr;   //tempStr.Format(_T("OnLvnItemchangedList iItem: %d, lParam: %d, uChanged: %d, uNewState: %d, uOldState: %d\n"), pNMLV->iItem, pNMLV->lParam, pNMLV->uChanged, pNMLV->uNewState, pNMLV->uOldState);   //MessageBox(tempStr);   *pResult = 0; } void CFileListCreatorDlg::OnLvnDeleteitemList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   ListDataNoChange_FLG = FALSE;//追加 2012.05.13   CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();   if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){     return;   }   m_Dlg->SetWindowText(_T("FileListCreator(*)"));   *pResult = 0; } ご教授下さい。

  • インライン処理

    VS2008 MFC を使用して、CListCtrlの派生クラスを全てインラインで書きたいと思い、 ・追加->クラス->C++クラス->基本クラス"CListCtrl" + インラインオプションにチェック で作成したのですが、メッセージ処理を追加するとcppファイルが出来てしまいます。 利便性からヘッダファイル単体で使用したいのですが、cppの内容をヘッダに全て書き写し、cppファイルを削除することは出来ないのでしょうか? Ex. <クラス生成直後=ヘッダファイルのみ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } }; <メッセージ追加後=ヘッダ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } DECLARE_MESSAGE_MAP() afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult); }; <メッセージ追加後=cpp> #include "StdAfx.h" #include "Test01.h" BEGIN_MESSAGE_MAP(CTest01, CListCtrl) ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CTest01::OnLvnColumnclick) END_MESSAGE_MAP() void CTest01::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 *pResult = 0; } 上記の例でOnLvnColumnclickをヘッダファイルに記述することは可能でしたが、BEGIN_MESSAGE_MAPの辺りと、インクルードをヘッダに移動するとリンク時にエラーが出てしまいます。 メッセージ処理をする場合cppファイルは必須なのでしょうか? ・追加->クラス->MFCクラス->基本クラス"CListCtrl" で作成した場合、上記プラスIMPLEMENT_DYNAMICもインクルードファイル内に記述出来ずに困っています。 MFC初心者のため、いまいちBEGIN_MESSAGE_MAPやIMPLEMENT_DYNAMICの意味がわからず行き詰まっています。 なにかヒント等有りましたら、教えていただけないでしょうか? よろしくお願いいたします。

  • 時刻の日時指定コントロールで実行エラー

    時刻の日時指定コントロールで実行エラー MFCでwindowsアプリケーションを勉強しているものです。 OS : Vista Premium VS : 2008 Pro 日時指定コントロールで、日付や時刻を選択する参考書サンプルを動かそうとしています。 結果は、 時刻のDate Time Pickerのスピンコントロールを動かすとエラーが表示されます。 添付画像にあるエラー表示内の 'File: f:\dd\vctools\crt_bld\self_x86\crt\src\output.c ' というファイルは、 C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\ にあるoutput.cのことでしょうか? そうだとしても、今の私のスキルでは解読することができません。 この時刻のコントロールのプロパティは、以下のように設定しました。 ID : IDC_DATETIMEPICKER4 Format : 時刻 Use Spin Control : True ( 淡色表示になっている ) その他は、デフォルト値です。 このコントロールのイベントハンドラコード部分 void CDateTimeCtrlDialog::OnDtnDatetimechangeDatetimepicker4(NMHDR *pNMHDR, LRESULT *pResult) {     LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);     // TODO: ここにコントロール通知ハンドラ コードを追加します。     CTime ct;     m_MonthCal4.GetTime( ct );     m_strDate4.Format( L"%02d:%02d:%02" , ct.GetHour() , ct.GetMinute() , ct.GetSecond() );     UpdateData( false );     *pResult = 0; } どなたか教えてください。 お願いします。

  • リストビューで最下行から最上行にスクロールした際の描画問題

    VC++2005のMFC環境でプログラムを作成しています。 リストコントロールのイベント(LVN_KEYDOWN)よりハンドラを作成し、 下記のような実装を行い、最下行からさらに下キーを押下した際に、 最上行に選択フォーカスを移動させたいのですが、 青いフォーカスは上に移動しますが、点線のボックスが最下行に そのまま残ってしまい、その後もおかしな動きをしてしまいます。 何か実装で間違っている点があるのでしょうか? 解決策をご存知の方おられましたら、ご教示お願いいたします。 下記が問題のソースコードです。 void CtestListDlg::OnLvnKeydownList1(NMHDR *pNMHDR, LRESULT *pResult) { LV_KEYDOWN *pNMLV = reinterpret_cast<LV_KEYDOWN*>(pNMHDR); int ret = m_listTest.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); if(ret==-1) return; if(pNMLV->wVKey==VK_UP){ if(ret==0){ int count = m_listTest.GetItemCount(); m_listTest.SetItemState(count-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED); } else{ m_listTest.SetItemState(ret-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED); } } if(pNMLV->wVKey==VK_DOWN){ int count = m_listTest.GetItemCount(); if(ret==count-1){ m_listTest.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED); } else{ m_listTest.SetItemState(ret+1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED); } } *pResult = 0; }

  • マウス位置の色を得る

    マウス位置は lParam にあるらしいから  typedef struct tagPOINT {   LONG x_zahyo_long;   LONG y_zahyo_long;  }POINT;  POINT p;  char x_zahyo[5], y_zahyo[5]; として、  case WM_RBUTTONDOWN:   p.x_zahyo_long = LOWORD(lParam);   p.y_zahyo_long = HIWORD(lParam);   sprintf(x_zahyo,"%04d", p.x_zahyo_long);   sprintf(y_zahyo,"%04d", p.y_zahyo_long);   SetWindowText(hrs, x_zahyo);   SetWindowText(hrs, y_zahyo);  break; でやってたけど、得られた座標は常に 0001,0001 でした。 本題とは別だけど、4桁表示のやり方で、もっといいソースがあったら 教えてください。 bcc32 では lParam からマウス位置取得は無理ですか? lParam が使えなかったから、  POINT p = { 0,0 }; として、  GetCursorPos( &p ); で座標を得ました。 それで、ウインドウ上のマウスの位置の色を取得するにはどうしたら いいんですか? getPixel( ) の引数やソースの書式を教えてほしいです。