• Hook任务栏时钟窗口(原理其实很简单,就是注入DLL到时钟窗口进程(explorer.exe))


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

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

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

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

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

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

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

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #include <windows.h>  
    2.   
    3. // 保存模块句柄,释放DLL时需要用到  
    4. static HMODULE gLibModule = 0;  
    5.   
    6. // 用于保存时钟窗口原始处理过程,DLL卸载时应该还原  
    7. static LONG_PTR gOldWndProc = 0;  
    8.   
    9. // 查找时钟窗口句柄  
    10. static HWND FindClockWindow()  
    11. {  
    12.     HWND h = FindWindow(TEXT("Shell_TrayWnd"), nullptr);  
    13.     if (IsWindow(h))  
    14.     {  
    15.         h = FindWindowEx(h, 0, TEXT("TrayNotifyWnd"), nullptr);  
    16.         if (IsWindow(h))  
    17.         {  
    18.             return FindWindowEx(h, 0, TEXT("TrayClockWClass"), nullptr);  
    19.         }  
    20.     }  
    21.     return 0;  
    22. }  
    23.   
    24. static DWORD WINAPI FreeSelf(LPVOID param)  
    25. {  
    26.     FreeLibraryAndExitThread(gLibModule, EXIT_SUCCESS);  
    27. }  
    28.   
    29. static void RestoreWndProc()  
    30. {  
    31.     if (gOldWndProc != 0)  
    32.         SetWindowLongPtr(FindClockWindow(), GWLP_WNDPROC, gOldWndProc);  
    33. }  
    34.   
    35. // 新的窗口处理过程,核心工作都在这里  
    36. LRESULT CALLBACK ClockWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
    37. {  
    38.     // 为了能收到鼠标左击右击的消息,必须让Windows以为我们"命中"了工作区  
    39.     if (uMsg == WM_NCHITTEST)  
    40.         return HTCLIENT;  
    41.   
    42.     // 处理鼠标左击事件  
    43.     if (uMsg == WM_LBUTTONUP)  
    44.     {  
    45.         ShellExecute(0, TEXT("open"), TEXT("http://blog.csdn.net/aqtata"), nullptr, nullptr, SW_SHOW);  
    46.         return 0;  
    47.     }  
    48.   
    49.     // 处理鼠标右击事件,这里我们卸载DLL(自身)  
    50.     if (uMsg == WM_RBUTTONUP)  
    51.     {  
    52.         RestoreWndProc();  
    53.         CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)FreeSelf, nullptr, 0, nullptr));  
    54.         return 0;  
    55.     }  
    56.   
    57.     return WNDPROC(gOldWndProc)(hWnd, uMsg, wParam, lParam);  
    58. }  
    59.   
    60. BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)  
    61. {  
    62.     switch (ul_reason_for_call)  
    63.     {  
    64.     case DLL_PROCESS_ATTACH:  
    65.     {  
    66.         gLibModule = hModule;  
    67.         HWND hClock = FindClockWindow();  
    68.         if (IsWindow(hClock))  
    69.         {  
    70.             gLibModule = hModule;  
    71.             gOldWndProc = GetWindowLongPtr(hClock, GWLP_WNDPROC);  
    72.             if (gOldWndProc != 0)  
    73.             {  
    74.                 SetWindowLongPtr(hClock, GWLP_WNDPROC, (LONG_PTR)&ClockWndProc);  
    75.             }  
    76.         }  
    77.         break;  
    78.     }  
    79.   
    80.     case DLL_PROCESS_DETACH:  
    81.     {  
    82.         RestoreWndProc();  
    83.         break;  
    84.     }  
    85.     }  
    86.     return TRUE;  
    87. }  


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

    http://blog.csdn.net/aqtata/article/details/23883699

  • 相关阅读:
    uniapp
    uniapp
    uniapp
    偶然发现的一天
    了不起的麦瑟尔夫人第三季
    女性长期没有"恩爱",会出现这4个后果?提醒:频率最好能在这个数
    IntelliJ IDEA live template 方法配置
    使用MHA实现MySQL主从复制高可用
    Linux 常用命令介绍
    开源堡垒机
  • 原文地址:https://www.cnblogs.com/findumars/p/5277591.html
Copyright © 2020-2023  润新知