Eugie » 22 ноя 2004, 13:39
Вот пример, как это можно сделать (код для dll: когда она загружена, перехватывается обращение к пункту меню с именем "&About ...", вместо него вызывается MessageBox):
Код: Выделить всё
HHOOK hkMsg;
int nTargetCmdID;
// Searching for the main window of the current app.
BOOL CALLBACK EnumWindowsProc(
HWND hwnd, // handle to parent window
LPARAM lParam // application-defined value
)
{
DWORD dwPID, dwTID = GetWindowThreadProcessId(hwnd, &dwPID);
DWORD dwCurPID = GetCurrentProcessId();
BOOL bProceed = dwCurPID != dwPID;
if (!bProceed)
*(HWND*)lParam = hwnd;
return bProceed;
}
HWND GetAppTopWindow()
{
HWND hwnd = NULL;
EnumWindows(EnumWindowsProc, (LPARAM)&hwnd);
return hwnd;
}
int FindMenuItemID(HMENU hmMenu, LPCTSTR lpszMenuItemText)
{
int id = -1;
TCHAR buf[100];
MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING;
mii.dwTypeData = buf;
mii.cch = sizeof(buf)/sizeof(TCHAR);
for(int i = 0; i < GetMenuItemCount(hmMenu); i++)
{
GetMenuItemInfo(hmMenu, i, TRUE, &mii);
if (strcmp(mii.dwTypeData, lpszMenuItemText) == 0)
return GetMenuItemID(hmMenu, i);
mii.fMask = MIIM_SUBMENU;
GetMenuItemInfo(hmMenu, i, TRUE, &mii);
if (mii.hSubMenu)
id = FindMenuItemID(mii.hSubMenu, lpszMenuItemText);
}
return id;
}
int GetMenuCmdMsgID(LPCTSTR lpszMenuItemText)
{
HWND hwnd = GetAppTopWindow();
HMENU hmenu = GetMenu(hwnd);
return FindMenuItemID(hmenu, lpszMenuItemText);
}
LRESULT CALLBACK GetMsgProc(
int code, // hook code
WPARAM wParam, // removal option
LPARAM lParam // message
)
{
if (code == HC_ACTION)
{
MSG* pmsg = (MSG*)lParam;
wParam = PM_REMOVE;
nTargetCmdID = GetMenuCmdMsgID("&About ...");
if(pmsg->hwnd == GetAppTopWindow() &&
pmsg->message == WM_COMMAND &&
HIWORD(pmsg->wParam) == 0 &&
LOWORD(pmsg->wParam) == nTargetCmdID)
{
pmsg->wParam = -1; // to prevent passing to standard handler
MessageBox(NULL, "Target menu command called.", "Info", MB_OK);
return 0;
}
}
return CallNextHookEx(hkMsg, code, wParam, lParam);
}
void InstallHook()
{
hkMsg = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
}
void UninstallHook()
{
UnhookWindowsHookEx(hkMsg);
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
InstallHook();
break;
case DLL_PROCESS_DETACH:
UninstallHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
Вот пример, как это можно сделать (код для dll: когда она загружена, перехватывается обращение к пункту меню с именем "&About ...", вместо него вызывается MessageBox):
[code]
HHOOK hkMsg;
int nTargetCmdID;
// Searching for the main window of the current app.
BOOL CALLBACK EnumWindowsProc(
HWND hwnd, // handle to parent window
LPARAM lParam // application-defined value
)
{
DWORD dwPID, dwTID = GetWindowThreadProcessId(hwnd, &dwPID);
DWORD dwCurPID = GetCurrentProcessId();
BOOL bProceed = dwCurPID != dwPID;
if (!bProceed)
*(HWND*)lParam = hwnd;
return bProceed;
}
HWND GetAppTopWindow()
{
HWND hwnd = NULL;
EnumWindows(EnumWindowsProc, (LPARAM)&hwnd);
return hwnd;
}
int FindMenuItemID(HMENU hmMenu, LPCTSTR lpszMenuItemText)
{
int id = -1;
TCHAR buf[100];
MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING;
mii.dwTypeData = buf;
mii.cch = sizeof(buf)/sizeof(TCHAR);
for(int i = 0; i < GetMenuItemCount(hmMenu); i++)
{
GetMenuItemInfo(hmMenu, i, TRUE, &mii);
if (strcmp(mii.dwTypeData, lpszMenuItemText) == 0)
return GetMenuItemID(hmMenu, i);
mii.fMask = MIIM_SUBMENU;
GetMenuItemInfo(hmMenu, i, TRUE, &mii);
if (mii.hSubMenu)
id = FindMenuItemID(mii.hSubMenu, lpszMenuItemText);
}
return id;
}
int GetMenuCmdMsgID(LPCTSTR lpszMenuItemText)
{
HWND hwnd = GetAppTopWindow();
HMENU hmenu = GetMenu(hwnd);
return FindMenuItemID(hmenu, lpszMenuItemText);
}
LRESULT CALLBACK GetMsgProc(
int code, // hook code
WPARAM wParam, // removal option
LPARAM lParam // message
)
{
if (code == HC_ACTION)
{
MSG* pmsg = (MSG*)lParam;
wParam = PM_REMOVE;
nTargetCmdID = GetMenuCmdMsgID("&About ...");
if(pmsg->hwnd == GetAppTopWindow() &&
pmsg->message == WM_COMMAND &&
HIWORD(pmsg->wParam) == 0 &&
LOWORD(pmsg->wParam) == nTargetCmdID)
{
pmsg->wParam = -1; // to prevent passing to standard handler
MessageBox(NULL, "Target menu command called.", "Info", MB_OK);
return 0;
}
}
return CallNextHookEx(hkMsg, code, wParam, lParam);
}
void InstallHook()
{
hkMsg = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
}
void UninstallHook()
{
UnhookWindowsHookEx(hkMsg);
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
InstallHook();
break;
case DLL_PROCESS_DETACH:
UninstallHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
[/code]