📄 hook.cpp
字号:
// 重绘按钮区域的桌面
R = ConfigButton->BoundsRect;
InvalidateRect(Window, &R, false);
// 成功处理此讯息
return 0;
}
}
}
}
return CallWindowProc((FARPROC)g_Data->OrigWndProc, Window, AMessage, WPARAM, LPARAM);
}
LRESULT _stdcall ParentWndProc(HWND Window, UINT AMessage, Longint WPARAM , Longint LPARAM)
{
PNMHdr NMHdr;
TRect RSrc, RDst;
switch (AMessage) {
case WM_NOTIFY:
NMHdr = PNMHdr(LPARAM);
switch (NMHdr->code) {
// ListView 视窗进行绘制时会先送给其父视窗 WM_NOTIFY 讯息
// 动作代码为 NM_CUSTOMDRAW
case NM_CUSTOMDRAW:
// 若矩形区域改变, 则变更 BackBits 大小
if (DynDisplay.BackBits->Width != DynDisplay.CurRect.Right - DynDisplay.CurRect.Left || DynDisplay.BackBits->Height != DynDisplay.CurRect.Bottom - DynDisplay.CurRect.Top) {
DynDisplay.BackBits->Width = DynDisplay.CurRect.Right - DynDisplay.CurRect.Left;
DynDisplay.BackBits->Height = DynDisplay.CurRect.Bottom - DynDisplay.CurRect.Top;
}
RSrc = Rect(0, 0, DynDisplay.BackBits->Width, DynDisplay.BackBits->Height);
if (g_Data->ShowDesktopWallPaper) { // 若要显示桌布
// 先将背景拷贝到 DynDisplay.BackBits
RDst = RSrc;
OffsetRect(&RDst, DynDisplay.Position.x + g_Data->WorkAreaRect.Left, DynDisplay.Position.y + g_Data->WorkAreaRect.Top);
DynDisplay.BackBits->Canvas->CopyRect(RSrc, DynDisplay.DesktopBits->Canvas, RDst);
}
// 若要显示桌布, 采透明贴字
if (g_Data->ShowDesktopWallPaper)
DynDisplay.BackBits->Canvas->Brush->Style = bsClear;
else {
// 否则将影像填满背景色
DynDisplay.BackBits->Canvas->Brush->Style = bsSolid;
DynDisplay.BackBits->Canvas->Brush->Color = clBackground;
}
// 先在 DynDisplay.BackBits 上绘出时间字串
DynDisplay.BackBits->Canvas->TextRect(RSrc, 0, 0, DynDisplay.DisplayString);
// 最後将 DynDisplay.BackBits 贴到桌面上
BitBlt(PNMLVCustomDraw(NMHdr)->nmcd.hdc, DynDisplay.Position.x, DynDisplay.Position.y, DynDisplay.BackBits->Width, DynDisplay.BackBits->Height,
DynDisplay.BackBits->Canvas->Handle, 0, 0, SRCCOPY);
// 进行正常的绘制动作
return CDRF_DODEFAULT;
}
break;
}
return CallWindowProc((FARPROC)g_Data->OrigParentWndProc, Window, AMessage, WPARAM, LPARAM);
}
LRESULT _stdcall GetMsgProc(int Code, Longint WPARAM , Longint LPARAM)
{
static bool bFirstCalled = true;
HANDLE hEvent;
if (Code == HC_ACTION) { // 动作代码为 HC_ACTION 时才处理
if (bFirstCalled) { // 第一次呼叫时进行 subclassing
bFirstCalled = false;
// subclass 背景视窗
g_Data->OrigWndProc = (WNDPROC)SetWindowLong(g_Data->Wnd, GWL_WNDPROC, (long)WndProc);
// subclass 背景视窗的父视窗
g_Data->ParentWnd = GetParent(g_Data->Wnd);
g_Data->OrigParentWndProc = (WNDPROC)SetWindowLong(g_Data->ParentWnd, GWL_WNDPROC, (long)ParentWndProc);
// 告知背景视窗, 已被 subclass
PostMessage(g_Data->Wnd, WM_SUBCLASSED, 0, 0);
InvalidateRect(g_Data->Wnd, NULL, true); // 重绘 ListView 视窗
// 告知 hook 程序完成
PostThreadMessage(PMsg(LPARAM)->wParam, WM_MYHOOK, 0, 0);
// 尝试开启保护 hook handle 的 event
hEvent = OpenEvent(SYNCHRONIZE, false, HOOK_EVENT_NAME);
if (hEvent) { // 如果开启成功, 表示 hook handle 尚未被写入
WaitForSingleObject(hEvent, INFINITE); // 等待 hook handle 确定下来
CloseHandle(hEvent); // 关闭 event
}
} else if (PMsg(LPARAM)->message == WM_MYHOOK) {
// 通知背景视窗, 将要 unsubclass
SendMessage(g_Data->Wnd, WM_BEFORE_UNSUBCLASS, 0, 0);
// unsubclass 背景视窗
SetWindowLong(g_Data->Wnd, GWL_WNDPROC, (long)g_Data->OrigWndProc);
// unsubclass 背景视窗的父视窗
SetWindowLong(g_Data->ParentWnd, GWL_WNDPROC, (long)g_Data->OrigParentWndProc);
InvalidateRect(g_Data->Wnd, NULL, true); // 重绘 ListView 视窗
// 告知 unhook 程序完成
PostThreadMessage(PMsg(LPARAM)->wParam, WM_MYHOOK, 0, 0);
}
}
// 呼叫下一个 hook 函式
return CallNextHookEx(g_Data->HHOOK, Code, WPARAM, LPARAM);
}
EXTERN bool _stdcall SetDeskHook(HWND Wnd)
{
DWORD ThreadId;
TMsg Msg;
HANDLE hEvent;
if (Wnd != 0) {
if (g_Data->HHOOK != 0) return false;
// 取得视窗的执行绪 ID
g_Data->Wnd = Wnd;
ThreadId = GetWindowThreadProcessId(g_Data->Wnd, NULL);
// 建立保护 hook handle 的 event
hEvent = CreateEvent(NULL, true, false, HOOK_EVENT_NAME);
// 安装 WH_GETMESSAGE hook
g_Data->HHOOK = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hinstDLL, ThreadId);
// 将 event 设为 signaled 状态, 若 hook 函式正在等待, 等於通知它,
// hook handle 已经 ready
SetEvent(hEvent);
// 关闭 event
CloseHandle(hEvent);
if (g_Data->HHOOK != 0) { // 若 hook 安装成功
// 丢一个无用讯息过去, 确认 hook 函式被呼叫
// 同时 subclass 背景视窗及其父视窗
PostThreadMessage(ThreadId, WM_NULL, GetCurrentThreadId(), 0);
// 等待 Hook 装设完成, 由 Hook 程序送回 WM_MYHOOK 讯息通知
do {
GetMessage(&Msg, 0, 0, 0);
} while (Msg.message != WM_MYHOOK);
return true;
}
} else {
if (g_Data->HHOOK != 0) {
ThreadId = GetWindowThreadProcessId(g_Data->Wnd, NULL);
// 告知 hook 函式, 请先 unsubclass, 准备要 unhook 了
PostThreadMessage(ThreadId, WM_MYHOOK, GetCurrentThreadId(), 0);
// 确定 GetMsgProc 已将背景视窗及其父视窗 unsubclassing 後..
do {
GetMessage(&Msg, 0, 0, 0);
} while (Msg.message != WM_MYHOOK);
// 取消 hook 函式
UnhookWindowsHookEx(g_Data->HHOOK);
g_Data->HHOOK = 0;
return true;
}
}
return true;
}
EXTERN void _stdcall SetMainWindow(HWND Wnd)
{
g_Data->MainWnd = Wnd;
}
EXTERN void _stdcall SetShowDesktopWallPaper(bool Value)
{
g_Data->ShowDesktopWallPaper = Value;
InvalidateRect(g_Data->Wnd, NULL, true);
}
EXTERN void _stdcall SetEssay(int index, char* Str)
{
if (index < MAX_ESSAY_LINE)
strncpy(g_Data->Essay[index], Str, MAX_ESSAY_CHAR - 1);
}
#define MIN(a,b) ((a)<(b)?(a):(b))
EXTERN void _stdcall SetEssayCount(int Count)
{
g_Data->Essay_LineCount = MIN(Count, MAX_ESSAY_LINE);
InvalidateRect(g_Data->Wnd, NULL, true);
}
EXTERN void _stdcall SetEssayFont(PLogFont LF)
{
memcpy(&g_Data->Essay_Font, LF, sizeof(TLogFont));
InvalidateRect(g_Data->Wnd, NULL, true);
}
void _stdcall SetEssayColor(COLORREF SepColor, COLORREF TextColor)
{
g_Data->SeperatorColor = SepColor;
g_Data->Essay_Color = TextColor;
InvalidateRect(g_Data->Wnd, NULL, true);
}
HANDLE MapGlobalData(const AnsiString MapName, int Size, LPVOID &P)
{
HANDLE ret = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, Size, MapName.c_str());
if (ret == 0) {
if (GetLastError() == ERROR_ALREADY_EXISTS) {
ret = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, MapName.c_str());
if (ret == 0) return ret;
} else
return ret;
}
P = (LPVOID)MapViewOfFile(ret, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (P == NULL) {
CloseHandle(ret);
ret = 0;
}
return ret;
}
void ReleaseGlobalData(HANDLE handle, void* &Ptr)
{
if (Ptr) {
UnmapViewOfFile(Ptr);
Ptr = NULL;
}
if (handle != 0) {
CloseHandle(handle);
handle = 0;
}
}
void DebugStr(AnsiString S)
{
S = S + "\n";
OutputDebugString(S.c_str());
}
#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
char buf[256];
GetModuleFileName(0, buf, sizeof(buf));
switch (fwdreason) {
case DLL_PROCESS_ATTACH:
g_hinstDLL = hinstDLL;
DebugStr(Format("DLL_PROCESS_ATTACH: %d %s", OPENARRAY(TVarRec, ((int)hinstDLL, buf))));
MapHandle = MapGlobalData(GLOBAL_DATA_MAPNAME, sizeof(TGlobalData), Pointer(g_Data));
break;
case DLL_PROCESS_DETACH:
DebugStr(Format("DLL_PROCESS_DETACH: %d %s", OPENARRAY(TVarRec, ((int)g_hinstDLL, buf))));
ReleaseGlobalData(MapHandle, Pointer(g_Data));
break;
case DLL_THREAD_ATTACH:;
break;
case DLL_THREAD_DETACH:;
break;
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -