プロが教える店舗&オフィスのセキュリティ対策術

質問させて頂きます。

現在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等のメッセージが来た際に破棄する処理を試しても上手く行きません

この場合、マウスをグローバルフックしなければならないでしょうか?
極力フックは避けて解決したいと思っております。
ご教授の程よろしくお願いします。

A 回答 (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;

LPDIRECTINPUT8g_pDI;
LPDIRECTINPUTDEVICE8g_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;
}
    • good
    • 0
この回答へのお礼

machongola様

ソース迄載せて頂き、丁寧なご回答有難うございます。

DirectInputで監視出来る事は知りませんでしたので
DirectInputを調べて試して見たいと思います。

本当に有難うございました。

お礼日時:2009/06/13 14:28

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!