• 締切済み

ウィンドウ非表示に時に表示したポップアップメニューを閉じるには?

質問させて頂きます。 現在C++にてWin32SDKを使用し開発を行っております そこで、メインウィンドウが非表示の時にポップアップメニューを表示するようにしているのですが 非表示の際、ホットキーを起因にポップアップメニューを表示すると ポップアップメニュー以外をクリックしても消えますが WM_TIMER等、一定時間経過時に表示した場合 ポップアップメニュー以外をクリックしても消えません 下記が一部コードを抜粋した物です case WM_CREATE: hMenu = CreatePopupMenu( ); AppendMenu( hMenu, MF_STRING, 0x01, TEXT("HOGE1") ); AppendMenu( hMenu, MF_STRING, 0x02, TEXT("HOGE2") ); return 0; case WM_HOTKEY: GetCursorPos( &pos ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); return 0; case WM_TIMER: GetCursorPos( &pos ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); return 0; ホットキーの設定と、タイマーの設定の処理を付随しておりませんが ホットキー、タイマーの処理は同じものです ポップアップメニューを表示の際、WM_INITMENUPOPUPからポップアップメニューをサブクラス化し WM_KILLFOCUS等のメッセージが来た際に破棄する処理を試しても上手く行きません この場合、マウスをグローバルフックしなければならないでしょうか? 極力フックは避けて解決したいと思っております。 ご教授の程よろしくお願いします。

みんなの回答

回答No.1

 こんにちは。  DirectInputとスレッドで出来ると言えば出来ます。ただ、マウスもキーボードもするとなるとグローバルフックの方が楽かもしれません。  以下はマウスだけですが、ポップアップは確かに消えます。ただ、大分アラもあるとは思うので、参考程度でお願いします。 #define DIRECTINPUT_VERSION 0x0800 #include<windows.h> #include<dinput.h> #include<commctrl.h> #include"resource.h" #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dxguid.lib") const DWORD dwTIMER_OPEN = 1000; LPDIRECTINPUT8 g_pDI; LPDIRECTINPUTDEVICE8 g_pMouse; //スレッド DWORD WINAPI ThreadProc(LPVOID p) { HWND hWnd = (HWND)p; while(::IsWindow(hWnd)) { DIMOUSESTATE2 dims; HRESULT hr = g_pMouse->GetDeviceState(sizeof(DIMOUSESTATE2), &dims); if(SUCCEEDED(hr)) { //マウス左or中央or右クリック if(dims.rgbButtons[0] || dims.rgbButtons[1] || dims.rgbButtons[2]) { //ポップアップがあれば消す HWND hWndPopup = FindWindow("#32768", NULL); if(hWndPopup && IsWindowVisible( hWndPopup ) ) { SendMessage(hWndPopup, WM_KEYDOWN, VK_ESCAPE, 0); } } } } return 0; } //DirectInput初期化 static BOOL DI_Init(HWND hWnd, HINSTANCE hInst) { HRESULT hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_pDI, NULL); if(FAILED(hr)) return FALSE; hr = g_pDI->CreateDevice(GUID_SysMouse, &g_pMouse, NULL); if(FAILED(hr)) return FALSE; hr = g_pMouse->SetDataFormat(&c_dfDIMouse2); if(FAILED(hr)) return FALSE; //バックグラウンドモードで全てのマウスを拾う hr = g_pMouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); if(FAILED(hr)) return FALSE; //軸モードを設定(相対値モードに設定) DIPROPDWORD diprop = {sizeof(DIPROPDWORD)}; diprop.diph.dwHeaderSize= sizeof(diprop.diph); diprop.diph.dwObj = 0; diprop.diph.dwHow = DIPH_DEVICE; diprop.dwData = DIPROPAXISMODE_REL; g_pMouse->SetProperty(DIPROP_AXISMODE, &diprop.diph); return SUCCEEDED(hr); } //ウィンドウクラス登録 static ATOM Regist(LPCTSTR szClassName, WNDPROC wndProc) { WNDCLASSEX wndclass = {sizeof(wndclass)}; wndclass.hCursor = ::LoadCursor(NULL,IDC_ARROW); wndclass.hIcon = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szClassName; wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); wndclass.hInstance = ::GetModuleHandle(NULL); wndclass.style = 0; wndclass.lpfnWndProc = wndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; return ::RegisterClassEx(&wndclass); } //ウィンドウを作成して開く static HWND OpenWindow(LPCTSTR szClassName, LPCTSTR szTitleName, INT w, INT h) { HINSTANCE hInst = ::GetModuleHandle(NULL); HWND hWnd = ::CreateWindowEx(WS_EX_TOOLWINDOW, szClassName, szTitleName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT, w, h, NULL, NULL, hInst, NULL); return hWnd; } LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HMENU hMenu = CreatePopupMenu(); POINT pos; switch(uMsg) { case WM_CREATE: AppendMenu( hMenu, MF_STRING, 0x01, TEXT("HOGE1") ); AppendMenu( hMenu, MF_STRING, 0x02, TEXT("HOGE2") ); SetTimer(hWnd, dwTIMER_OPEN, 1000, NULL); ::DI_Init(hWnd, ::GetModuleHandle(NULL)); g_pMouse->Acquire(); break; case WM_HOTKEY: GetCursorPos( &pos ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); break; case WM_CLOSE: ::DestroyWindow(hWnd); break; case WM_NCDESTROY: ::PostQuitMessage(0); break; case WM_COMMAND: switch(LOWORD(wParam)) { case 0x01: ::MessageBox(hWnd, "0x01", "0x01", IDOK); break; case 0x02: ::MessageBox(hWnd, "0x02", "0x02", IDOK); break; } break; case WM_TIMER: switch(wParam) { case dwTIMER_OPEN: KillTimer(hWnd, wParam); GetCursorPos( &pos ); SetActiveWindow( hWnd ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); SetTimer(hWnd, wParam, 1000, NULL); break; } break; } return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR lpCmdLine, int nShowCmd) { MSG msg; const TCHAR tstrClassName[] = TEXT("test resize frame"); const TCHAR tstrTitleName[] = TEXT("title"); ::InitCommonControls(); //ウィンドウクラスの登録 ::Regist(tstrClassName, &::WndProc); //ウィンドウを作成して開く HWND hWnd = ::OpenWindow(tstrClassName, tstrTitleName, 800, 600); //ウィンドウの表示 ::ShowWindow(hWnd, SW_SHOW); //スレッドを回す DWORD id = 0; HANDLE hThread = ::CreateThread(NULL, 0, ThreadProc, hWnd, 0, &id); ::SetThreadPriority(hThread, THREAD_PRIORITY_LOWEST); //メッセージ回転 while(::GetMessage(&msg, NULL, 0, 0) == TRUE) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } //到着を待つ ::WaitForSingleObject(hThread, INFINITE); ::CloseHandle(hThread); //DirectInputの解放 g_pMouse->Release(); g_pDI->Release(); //終了 return msg.wParam; }

minomino_a
質問者

お礼

machongola様 ソース迄載せて頂き、丁寧なご回答有難うございます。 DirectInputで監視出来る事は知りませんでしたので DirectInputを調べて試して見たいと思います。 本当に有難うございました。

関連するQ&A