Hook任务栏时钟窗口

用过一些日历软件的小伙伴应该都知道它们都实现了在时钟窗口上的Hook,也就是屏蔽了系统原有的功能,实现自己的功能

某日历软件Hook时钟窗口后的效果

#include <windows.h>
 
// 保存模块句柄,释放DLL时需要用到
static HMODULE gLibModule = 0;
 
// 用于保存时钟窗口原始处理过程,DLL卸载时应该还原
static LONG_PTR gOldWndProc = 0;
 
// 查找时钟窗口句柄
static HWND FindClockWindow()
{
    HWND h = FindWindow(TEXT("Shell_TrayWnd"), nullptr);
    if (IsWindow(h))
    {
        h = FindWindowEx(h, 0, TEXT("TrayNotifyWnd"), nullptr);
        if (IsWindow(h))
        {
            return FindWindowEx(h, 0, TEXT("TrayClockWClass"), nullptr);
        }
    }
    return 0;
}
 
static DWORD WINAPI FreeSelf(LPVOID param)
{
    FreeLibraryAndExitThread(gLibModule, EXIT_SUCCESS);
}
 
static void RestoreWndProc()
{
    if (gOldWndProc != 0)
        SetWindowLongPtr(FindClockWindow(), GWLP_WNDPROC, gOldWndProc);
}
 
// 新的窗口处理过程,核心工作都在这里
LRESULT CALLBACK ClockWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // 为了能收到鼠标左击右击的消息,必须让Windows以为我们"命中"了工作区
    if (uMsg == WM_NCHITTEST)
        return HTCLIENT;
 
    // 处理鼠标左击事件
    if (uMsg == WM_LBUTTONUP)
    {
        ShellExecute(0, TEXT("open"), TEXT("http://blog.csdn.net/aqtata"), nullptr, nullptr, SW_SHOW);
        return 0;
    }
 
    // 处理鼠标右击事件,这里我们卸载DLL(自身)
    if (uMsg == WM_RBUTTONUP)
    {
        RestoreWndProc();
        CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)FreeSelf, nullptr, 0, nullptr));
        return 0;
    }
 
    return WNDPROC(gOldWndProc)(hWnd, uMsg, wParam, lParam);
}
 
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        gLibModule = hModule;
        HWND hClock = FindClockWindow();
        if (IsWindow(hClock))
        {
            gLibModule = hModule;
            gOldWndProc = GetWindowLongPtr(hClock, GWLP_WNDPROC);
            if (gOldWndProc != 0)
            {
                SetWindowLongPtr(hClock, GWLP_WNDPROC, (LONG_PTR)&ClockWndProc);
            }
        }
        break;
    }
 
    case DLL_PROCESS_DETACH:
    {
        RestoreWndProc();
        break;
    }
    }
    return TRUE;
}
 

经过一番研究,发现原理其实很简单,就是注入DLL到时钟窗口进程(explorer.exe),然后接管窗口处理过程实现自己的功能

第一步是判断当前操作系统架构,是x86还是x64,你别指望一个x64的explorer.exe会加载你x86的DLL

第二步就是查找时钟窗口的进程(explorer.exe)

然后根据系统架构的不同注入不同架构的DLL,至于怎么注入我这里就不讲了,这个网上搜索一下有太多文章

 

下面直接给出DLL完整代码,VS2013 + Win7 x64 编译测试通过

 

 


以上代码实现了处理鼠标左击和右击的逻辑,为了展示实现原理所以没有实现复杂的功能,如果你愿意,可以在上面绘图、创建右键菜单甚至窗口等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值