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

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

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

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

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

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

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

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

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

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

Hook任务栏时钟窗口(原理其实很简单,就是注入DLL到时钟窗口进程(explorer.exe))的更多相关文章

  1. 这么说吧,java线程池的实现原理其实很简单

    好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...

  2. CSS浮动属性,知道原理就很简单,灵活控制块级元素在一行内显示

    在页面布局中,有两个非常常用的CSS属性.它们巧妙的控制着块级元素们之间的位置,灵活的让块级元素在一行内显示或者另起一行.说到这里,相信大家已经猜出来了,这两个属性就是控制块级元素浮动的属性.整个页面 ...

  3. 很简单的Java断点续传实现原理

    原理解析 在开发当中,"断点续传"这种功能很实用和常见,听上去也是比较有"逼格"的感觉.所以通常我们都有兴趣去研究研究这种功能是如何实现的? 以Java来说,网 ...

  4. 模态窗口原理及注意事项--http://www.alisdn.com/wordpress/?p=53

    前言 在开发Windows引用程序的时候,在一些需要用户确认,或者提示用户注意的场合,经常使用模态对话框,或者叫模态窗口.在绝大多数情况下,模态窗口给开发人员带来了极大的便利,并且在某些应用上有不可替 ...

  5. TCP面试题之滑动窗口原理

    TCP 滑动窗口 作用: 1. 提供TCP可靠性:对发送的数据进行确认 2. 流量控制:窗口大小随链路变化 一.TCP窗口机制 TCP中窗口大小是指tcp协议一次传输多少个数据.因为TCP是一个面向连 ...

  6. extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

    extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

  7. TCP 拥塞窗口原理

    学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度. 拥塞 ...

  8. TCP之拥塞窗口原理

    学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度. 拥塞 ...

  9. 微信 电脑版 HOOK(WeChat PC Hook)- 远程线程注入dll原理

    Windows加载dll的特性 1.Windows系统中,每个exe软件运行的时候,会加载系统模块kernel32.dll 2.所有加载进exe软件的系统模块kernel32.dll,内存地址都是一样 ...

随机推荐

  1. 【笨木头Lua专栏】基础补充08:协同程序之resume-yield间的数据返回

    这次要介绍几个事实上非常easy,可是一定要小心的返回值规则. 笨木头花心贡献,哈?花心?不,是用心~ 转载请注明.原文地址: http://www.benmutou.com/archives/173 ...

  2. RequiredFieldValidator控件--必填验证控件

    RequiredFieldValidator控件: ·RequiredFieldValidator控件也被称之为必填验证控件,顾名思义,也就是与RequiredFieldValidator控件关联的控 ...

  3. 04-IOSCore - User Defaults、Archive、存储总结

    一. User Defaults 1. 是什么? 是一个特殊的plist文件 2. 干什么? 用于保存应用的配置信息 3. 存什么信息? 信息:欢迎界面有没有被打开过 目的:欢迎界面只显示一次 信息: ...

  4. cocos2d-x游戏开发系列教程-中国象棋05-开始游戏

    前情回顾 通过CCMainMenu的init函数,已经把所有的按钮,棋子都摆放完毕了,但是这个时候,棋子是不能走动的,只有在开始游戏之后才能移动棋子. 点击

  5. opencv视频播放

    在一个界面上显示一张图片.是一件非常easy的事情,但说到要显示视频.刚開始学习的人可能不知道怎么处理,事实上,一般来说能够理解为视频就是图片以人眼察觉不到的速度高速更新. 曾经用摄像头採集视频显示在 ...

  6. SignalR 聊天室实例详解(服务器端推送版)

    翻译自:http://www.codeproject.com/Articles/562023/Asp-Net-SignalR-Chat-Room  (在这里可以下载到实例的源码) Asp.Net Si ...

  7. C#面向对象2 静态类、静态成员的理解

    理解:静态成员属于类所有,为各个类的实例所公用,与实例无关,需要全局共享的属性或者方法定义成静态的 C#静态成员:  1.静态成员属于类所有,故用类名调用,非静态成员属于类的实例所有,用实例名调用  ...

  8. boost::property_tree读取解析ini文件--推荐

    boost::property_tree读取解析ini文件 #include "stdafx.h" #include <iostream> #include <b ...

  9. qt之正则表达式

    原地址:http://blog.csdn.net/phay/article/details/7304455 QRegExp是Qt的正则表达式类.Qt中有两个不同类的正则表达式.第一类为元字符.它表示一 ...

  10. 【Demo 0007】Android 信使(Intent)

    本章学习要点:       1.  了解Intent功能作用:       2.  掌握Intent在显示和隐示基本使用方法及规则: