しばらくブログはお休みモード.今,TreeView を持つアプリを書いているのですが,TreeView のアイテムの名前を変更しようとしたときに,Enter キーを押すと OK ボタンにフォーカスを奪われてしまい意図した動きにならない(「名前の変更」の終了ではなく,ダイアログ自体が終了しています)と言う問題が発生しました.
この問題をどうやって回避するのかなぁと Web を漁っていると,どうやら「コントロールのサブクラス化」と呼ばれる方法で回避するようです.
static WNDPROC DefaultTreeViewEditProc; // サブクラス化する前のデフォルトのウィンドウプロシージャ static LRESULT CALLBACK TreeViewEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_GETDLGCODE: return DLGC_WANTALLKEYS; // Enter, Esc キーなどの処理を行った事を通知 default: break; } return CallWindowProc(reinterpret_cast<WNDPROC>(DefaultTreeViewEditProc), hWnd, msg, wParam, lParam); } static LRESULT CALLBACK DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_NOTIFY: { LPNMHDR header = reinterpret_cast<LPNMHDR>(lp); if (header->code == TVN_BEGINLABELEDIT) { HWND edit = (HWND)SendMessage(tree_view_handle, GWLP_WNDPROC, TVM_GETEDITCONTROL, 0, 0); DefaultTreeViewEditProc = (WNDPROC)SetWindowLongPtr(edit, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&EditProc)); } break; } default: break; } return FALSE; }
この方法を知る前は,キーボードのメッセージをフックして無理やり処理するなどしていたのですが,サブクラス化する事でだいぶスマートに処理できるようになりました.