hook给应用程序窗口加边框

hook dll

// FrameHook.h

#pragma once

#ifdef FRAMEHOOK_EXPORTS
#define FRAMEHOOK_API __declspec(dllexport)
#else
#define FRAMEHOOK_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

FRAMEHOOK_API BOOL InstallHook(HWND hwnd, PTCHAR procName = NULL);
FRAMEHOOK_API BOOL UnInstallHook();

#ifdef __cplusplus
}
#endif

// FrameHook.cpp

// FrameHook.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "FrameHook.h"
#include "resource.h"
#include <process.h>
#include <Tlhelp32.h>
#include <string>
#include <tchar.h>
#include <sstream>

#pragma data_seg("Segment")
HINSTANCE g_hInst;					// 载入dll的应用程序实例
HWND g_hApp = NULL;					// 被hook的应用程序句柄
HWND g_hDlg = NULL;					// 应用程序边框句柄
HHOOK g_cbtHook = NULL;				// WH_CBT
HHOOK g_callWndProcHook = NULL;		// WH_CALLWNDPROC
const UINT g_space = 15;			// 边框宽度
const UINT g_millisecond = 300;		// 边框异步显示间隔
#pragma data_seg()
#pragma comment(linker, "/SECTION:Segment,RWS")

static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);

#define WM_CREATE_FRAME_DIALOG (WM_USER + 123)

inline void DebugLog(const char *msg, ...)
{
	char buf[1024] = {0};
	va_list ap;
	va_start(ap, msg);
	vsprintf_s(buf, sizeof(buf), msg, ap);
	va_end(ap);
	OutputDebugStringA(buf);
}

void ShowFrameDlg();
void HideFrameDlg();
void ShowAutoSizeFrameDlg();
void MoveFrameDlg(RECT rc);
void AsyncShowFrameDlg(UINT milliseconds, BOOL isNormal = TRUE);
void SetAppFocus();
BOOL IsScreenRect(RECT rc);

FRAMEHOOK_API BOOL InstallHook(HWND hwnd, PTCHAR procName)
{
	g_hApp = hwnd;
	DWORD pid = GetWindowThreadProcessId(hwnd, NULL);
	g_cbtHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProc, g_hInst, pid);
	g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hInst, pid);

	if (NULL==g_cbtHook || NULL==g_callWndProcHook) {
		DebugLog("SetWindowsHookEx error, errcode:%d\n", GetLastError());
		return FALSE;
	}
	
	SendMessage(g_hApp, WM_CREATE_FRAME_DIALOG, 0, 0);
	DebugLog("FrameHook install success\n");
	return TRUE;
}

FRAMEHOOK_API BOOL UnInstallHook()
{
	if (g_hDlg) {
		SendMessage(g_hDlg, WM_CLOSE, 0, 0);
		DebugLog("DestroyWindow, errcode:%d\n", GetLastError());
	}

	if (g_cbtHook) {
		if (!UnhookWindowsHookEx(g_cbtHook)) {
			DebugLog("UnhookWindowsHookEx error, CBTHOOK, errcode:%d\n", GetLastError());
		}
	}

	if (g_callWndProcHook) {
		if (!UnhookWindowsHookEx(g_callWndProcHook)) {
			DebugLog("UnhookWindowsHookEx error, WNDPROCHOOK, errcode:%d\n", GetLastError());
		}
	}

	return TRUE;
}

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if ((nCode < 0) || ((HWND)wParam != g_hApp)) {
		return CallNextHookEx(g_cbtHook, nCode, wParam, lParam);
	}

	switch (nCode)
	{
	case HCBT_ACTIVATE:
		{
			if (IsWindowVisible(g_hDlg)) {
				LPCBTACTIVATESTRUCT p = (LPCBTACTIVATESTRUCT)lParam;
				if (g_hDlg == p->hWndActive) {
					//ShowAutoSizeFrameDlg();
					//if (g_hApp != GetFocus()) {
					//	SetAppFocus();
					//}
				} else if (0==p->hWndActive) {
					ShowAutoSizeFrameDlg();
					if (g_hApp != GetFocus()) {
						SetAppFocus();
					}
				}
			}
		}
		break;
	case HCBT_MINMAX:
		{
			DebugLog("CBTProc, HCBT_MINMAX\n");
			SetWindowPos(g_hDlg, g_hApp, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
			UINT sw = LOWORD(lParam);
			DebugLog("CBTProc, HCBT_MINMAX, %d\n", sw);
			if (sw == SW_RESTORE) {
				if (IsZoomed(g_hApp)) {
					AsyncShowFrameDlg(g_millisecond, FALSE);
				} else {
					AsyncShowFrameDlg(g_millisecond);
				}
			} else if (sw == SW_MAXIMIZE) {
				HideFrameDlg();
			}
		}
		break;
	case HCBT_MOVESIZE:
		{
			PRECT p = (PRECT)lParam;
			MoveFrameDlg(*p);
		}
		break;
	case HCBT_DESTROYWND:
		DebugLog("CBTProc, HCBT_DESTROYWND\n");
		HideFrameDlg();
		break;
	}

	return CallNextHookEx(g_cbtHook, nCode, wParam, lParam);
}

INT_PTR CALLBACK FrameDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CTLCOLORDLG:
		{
			static HBRUSH bkBrush = CreateSolidBrush(RGB(181, 230, 29));
			return INT_PTR(bkBrush);
		}
	case WM_CLOSE:
		DebugLog("FrameDlgProc, WM_CLOSE\n");
		DestroyWindow(hwndDlg);
		break;
	}
	return 0;
}

LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode < 0) {
		return CallNextHookEx(g_callWndProcHook, nCode, wParam, lParam);
	}

	PCWPSTRUCT p = (PCWPSTRUCT)lParam;
	if (g_hApp == p->hwnd) {
		switch (p->message)
		{
		case WM_CREATE_FRAME_DIALOG:
			{
				g_hDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_FRAMEDLG), 0, FrameDlgProc);
				ShowAutoSizeFrameDlg();
				SetAppFocus();
				DebugLog("AppHandle:0x%x, FrameHandle:0x%x\n", g_hApp, g_hDlg);
			}
			break;
		case WM_MOVING:
		case WM_SIZING:
			HideFrameDlg();
			break;
		case WM_CLOSE:
			DebugLog("CallWndProc, WM_CLOSE\n");
			HideFrameDlg();
		case WM_DESTROY:
			DebugLog("CallWndProc, WM_DESTROY\n");
			HideFrameDlg();
			break;

		default:
			break;
		}
	}
	return CallNextHookEx(g_callWndProcHook, nCode, wParam, lParam);
}

void ShowFrameDlg()
{
	ShowWindow(g_hDlg, SW_SHOW);
}

void HideFrameDlg()
{
	ShowWindow(g_hDlg, SW_HIDE);
}

void ShowAutoSizeFrameDlg()
{
	RECT appRect;
	GetWindowRect(g_hApp, &appRect);
	if (IsScreenRect(appRect)) {
		return;
	}

	RECT dlgRect;
	dlgRect.left = appRect.left - g_space;
	dlgRect.top = appRect.top - g_space;
	dlgRect.right = appRect.right + g_space;
	dlgRect.bottom = appRect.bottom + g_space;

	SetWindowPos(g_hDlg, HWND_TOP, dlgRect.left, dlgRect.top,
		dlgRect.right-dlgRect.left, dlgRect.bottom-dlgRect.top, SWP_SHOWWINDOW | SWP_NOZORDER);
}

void MoveFrameDlg(RECT dstRect)
{
	if (IsScreenRect(dstRect)) {
		return;
	}

	RECT dlgRect;
	dlgRect.left = dstRect.left - g_space;
	dlgRect.top = dstRect.top - g_space;
	dlgRect.right = dstRect.right + g_space;
	dlgRect.bottom = dstRect.bottom + g_space;
	
	SetWindowPos(g_hDlg, HWND_TOP, dlgRect.left, dlgRect.top,
		dlgRect.right-dlgRect.left, dlgRect.bottom-dlgRect.top, SWP_SHOWWINDOW); 
}

typedef struct tagThreadParam
{
	UINT times;
	BOOL isNormal;
}ThreadParam, *PThreadParam;

UINT WINAPI AsyncShowFrameDlgProc(void *data)
{
	PThreadParam p = (PThreadParam)data;
	Sleep(p->times);
	if (p->isNormal) {
		ShowFrameDlg();
	} else {
		ShowAutoSizeFrameDlg();
	}
	return 0;
}

void AsyncShowFrameDlg(UINT milliseconds, BOOL isNormal)
{
	static ThreadParam tp;
	tp.times = milliseconds;
	tp.isNormal = isNormal;
	HANDLE h = (HANDLE)_beginthreadex(NULL, 0, AsyncShowFrameDlgProc, (PThreadParam)&tp, 0, NULL);
	CloseHandle(h);
}

void SetAppFocus()
{
	SetFocus(g_hApp);
}

BOOL IsScreenRect(RECT rc)
{
	RECT screenRect;
	SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
	if (rc.left==screenRect.left && rc.right==screenRect.right &&
		rc.top==screenRect.top && rc.bottom==screenRect.bottom) {
			return TRUE;
	}
	return FALSE;
}

使用hook dll,显示载入:

class FHookLauncher
{
public:
	FHookLauncher()
		: m_hModule(NULL)
		, m_installHookFunc(NULL)
		, m_uninstallHookFunc(NULL)
	{
		const TCHAR name[] = TEXT("FrameHook64.dll");
		m_hModule = LoadLibrary(name);
		if (m_hModule) {
			m_installHookFunc = (InstallHookFunc)GetProcAddress(m_hModule, "InstallHook");
			m_uninstallHookFunc = (UnInstallHookFunc)GetProcAddress(m_hModule, "UnInstallHook");
		}
	}

	~FHookLauncher()
	{
		if (m_hModule) {
			FreeLibrary(m_hModule);
			m_hModule = NULL;
		}
	}

	void Install(HWND hwnd)
	{
		if (m_installHookFunc) {
			m_installHookFunc(hwnd, NULL);
		}
	}

	void Uninstall()
	{
		if (m_uninstallHookFunc) {
			m_uninstallHookFunc();
		}
	}

private:
	FHookLauncher(const FHookLauncher&);
	FHookLauncher& operator=(const FHookLauncher&);

private:
	HMODULE m_hModule;
	typedef BOOL (*InstallHookFunc)(HWND hwnd, PTCHAR procName);
	typedef BOOL (*UnInstallHookFunc)();
	InstallHookFunc m_installHookFunc;
	UnInstallHookFunc m_uninstallHookFunc;
};

需要注意的是32位的dll只能给32位应用程序加边框,对于64位应用程序需要一个64位版本的dll,

如果只有一个32位程序我怎样才能让这个64位hook dll给64位的应用程序加边框呢?

方法是:增加一个中间层64位程序,用这个程序来加载64位hook dll,而我们的32位应用程序可以通过窗口句柄发消息给64位中间程序

来控制64位hook dll的加载和卸载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值