這是最簡單的例子,我可以開發:
你需要的Visual Studio,加2項目的解決方案:
![enter image description here](https://i.stack.imgur.com/q6w1H.jpg)
第一個項目(HookDLL)是一個dll項目,第二(運行程序)是一個Win32控制檯項目
在main.cpp中
(在項目運行的應用程序)補充一點:
__declspec(dllimport) void RunHook();
int _tmain(int argc, _TCHAR* argv[])
{
RunHook();
return 0;
}
在dllmain按鈕中。CPP(在HookDLL項目)添加以下代碼:
#include <Windows.h>
#include <stdio.h>
HINSTANCE hinstDLL;
HHOOK hhook_wndproc;
HWND b = NULL;
HBRUSH blue_brush = NULL, yellow_brush, red_brush;
int button_status = 0;
LRESULT CALLBACK DefaultWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
if(!blue_brush)
{
blue_brush = CreateSolidBrush(RGB(0, 0, 255));
yellow_brush = CreateSolidBrush(RGB(255, 255, 0));
red_brush = CreateSolidBrush(RGB(255, 0, 0));
}
break;
case WM_PAINT:
{
HBRUSH b;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
switch(button_status)
{
case 0:
b = blue_brush;
break;
case 1:
b = yellow_brush;
break;
default:
b = red_brush;
}
FillRect(hdc, &ps.rcPaint, b);
EndPaint(hwnd, &ps);
}
return 0;
case WM_MOUSEMOVE:
if(button_status == 0)
{
SetTimer(hwnd, 1, 100, NULL);
button_status = 1;
InvalidateRect(hwnd, NULL, false);
}
return 0;
case WM_TIMER:
{
POINT pt;
GetCursorPos(&pt);
if(button_status == 1 && WindowFromPoint(pt) != hwnd)
{
KillTimer(hwnd, 1);
button_status = 0;
InvalidateRect(hwnd, NULL, false);
}
}
return 0;
case WM_MOUSELEAVE:
button_status = 0;
InvalidateRect(hwnd, NULL, false);
return 0;
case WM_LBUTTONDOWN:
button_status = 2;
InvalidateRect(hwnd, NULL, false);
return 0;
case WM_LBUTTONUP:
if(button_status == 2) MessageBox(GetParent(hwnd), "teamviewer like button clicked", "Message", MB_OK);
button_status = 1;
InvalidateRect(hwnd, NULL, false);
return 0;
}
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
void InitButton(HWND parent, int xPos, int yPos)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = DefaultWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstDLL;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "DEFAULT_CLASS";
RegisterClass(&wc);
b = CreateWindowEx(WS_EX_TOOLWINDOW, "DEFAULT_CLASS", NULL, WS_BORDER | WS_POPUP | WS_VISIBLE, xPos, yPos, 20, 20, parent, NULL, hinstDLL, NULL);
}
LRESULT WINAPI HookCallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode >= 0 && lParam != 0)
{
CWPRETSTRUCT *msg = (CWPRETSTRUCT*)lParam;
if(!IsWindow(msg->hwnd) || (GetWindowLong(msg->hwnd, GWL_STYLE) & WS_CHILD) != 0) return CallNextHookEx(hhook_wndproc, nCode, wParam, lParam);
switch(msg->message)
{
case WM_SHOWWINDOW:
if(!b && msg->wParam != 0)
{
b = (HWND)1;// see NOTES 5
RECT a;
GetWindowRect(msg->hwnd, &a);
InitButton(msg->hwnd, a.right - 150, a.top);
}
break;
case WM_SIZE:
if(GetParent(b) == msg->hwnd)
{
RECT a;
GetWindowRect(msg->hwnd, &a);
SetWindowPos(b, 0, a.right - 150, a.top, 0, 0, SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
break;
case WM_SIZING:
case WM_MOVING:
if(GetParent(b) == msg->hwnd)
{
RECT* lprc = (LPRECT) msg->lParam;
SetWindowPos(b, 0, lprc->right - 150, lprc->top, 0, 0, SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
}
return CallNextHookEx(hhook_wndproc, nCode, wParam, lParam);
}
__declspec(dllexport) void RunHook()
{
hhook_wndproc = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallWndProc, hinstDLL, 0);
char aux[10];
gets_s(aux);
UnhookWindowsHookEx(hhook_wndproc);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hinstDLL = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
現在,使項目爲正在運行的應用項目>項目依賴的DLL項目depedent:
![enter image description here](https://i.stack.imgur.com/ZMFVL.jpg)
注: 1)我不使用NC畫圖代碼,因爲並不總是有效,如果Windows緩衝非客戶區域,則會擦除自定義的NC畫圖按鈕
2)在64位環境中,您需要爲32位應用程序運行32位掛鉤,64位應用程式
3),你不能調試鉤子,在連接到另一個PROCCESS,我建議你在你的應用程序和線程窗口調試它,而在另一個proccess後期測試時,工作
4)我使用一個按鈕狀的方式爲簡單起見
5)這一行
b = (HWND)1;
我用它來「解決」一個多線程的問題,我建議你做出更好的代碼(同步化)這種情況下
是如何工作的:
- 運行應用程序
- ,當它開始安裝一個掛鉤
- 打開任何其他應用程序(同32/64位,見注2)
- 你必須在標題欄左側看到一個藍色按鈕
- 單擊它並看到一個消息框
- 對於完成掛鉤:只需在控制檯窗口按ENTER鍵
代碼流:
- 運行的應用程序只是調用RunHook()在DLL程序和DLL做的DLL工作
- RunHook()開始鉤HookCallWndProc(全球)
- HookCallWndProc捕獲所需的消息並使用InitButton()過程創建窗口按鈕
- DefaultWindowProc處理按鈕消息