Windows API 教程(七) hook 钩子监听

Windows API 教程(七) hook 钩子监听

Posted on 2013-08-15

茵蒂克丝

如何创建一个窗口

另外一个再录的 Windows SDK教程 里面有讲到快捷创建窗口的方式,不过这样的话要分好几个文件,感觉有点混所以这里就用原始的方式创建一个窗口。

那么,为什么讲到 hook(钩子)的时候要去创建窗口呢?其实这个问题说起来也不复杂,简单点说,按博主这样写不用写DLL也不用资源文件,实际上是把问题简化了一些。通常 hook 是用来监听自己窗口上的键盘和鼠标输入的,监听全局的通常是设置一些全局的热键(如QQ的 Ctrl+Alt+Z 调出QQ窗口),这些常见的功能也都是要依托窗口才能存在。所以我们先来简单说下手动建立一个窗口的流程。

手动创建窗口的流程

  1. 设置注册窗口结构体
  2. 使用【窗口结构体】注册窗口
  3. 创建窗口
  4. 显示窗口
  5. 窗口过程处理
  6. 消息循环

实际代码

这里不会详细讲这个,有感兴趣的可以去追博主的 SDK教程 或者去搜 杨中科的《C语言也能干大事》


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

#include <windows.h>

// 5. 窗口过程处理

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{  

    switch(msg)

    {

        case WM_CLOSE:

            DestroyWindow(hwnd);

        break;

        case WM_DESTROY:

            PostQuitMessage(0);

            break;

        default:

            return DefWindowProc(hwnd, msg, wParam, lParam);

    }

    return 0;

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPSTR lpCmdLine, int nCmdShow)

{

    WNDCLASSEX wc;  // 更多详细都可以去百度的 http://baike.baidu.com/view/1750396.htm

    HWND hwnd;

    MSG Msg;

    char text[30];

    const char szClassName[] = "myWindowClass";

    // 1. 设置注册窗口结构体

    wc.cbSize        = sizeof(WNDCLASSEX);              // 注册窗口结构体的大小

    wc.style         = 0;                               // 窗口的样式

    wc.lpfnWndProc   = WndProc;                         // 指向窗口处理过程的函数指针

    wc.cbClsExtra    = 0;                               // 指定紧跟在窗口类结构后的附加字节数

    wc.cbWndExtra    = 0;                               // 指定紧跟在窗口事例后的附加字节数

    wc.hInstance     = hInstance;                       // 本模块的实例句柄

    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄

    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 光标的句柄

    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景画刷的句柄

    wc.lpszMenuName  = NULL;                            // 指向菜单的指针

    wc.lpszClassName = szClassName;                     // 指向类名称的指针

    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标

    // 2. 使用【窗口结构体】注册窗口

    if(!RegisterClassEx(&wc))

    {

        MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 3. 创建窗口

    hwnd = CreateWindowEx(

        WS_EX_CLIENTEDGE,       // 窗口的扩展风格

        szClassName,            // 指向注册类名的指针

        TEXT("窗口标题"),       // 指向窗口名称的指针

        WS_OVERLAPPEDWINDOW,    // 窗口风格

        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高

        NULL,                   // 父窗口的句柄

        NULL,                   // 菜单的句柄

        hInstance,              // 应用程序实例的句柄

        NULL                    // 指向窗口的创建数据

        );

    if(hwnd == NULL)

    {

        MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 4. 显示窗口

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    // 6. 消息循环

    while(GetMessage(&Msg, NULL, 0, 0) > 0)

    {

        TranslateMessage(&Msg);

        DispatchMessage(&Msg);

    }

    return Msg.wParam;

}

因为是比较死的形式,以上代码大家混个脸熟,大概知道各个部分的作用就行了,博主也从来没有专门记过。

安装钩子 (Install hook)

简介

窗口建好了之后就要开始转到我们的正题了,首先我们需要明确的是,这个钩子(hook)到底是什么,那么博主这里也不做太书面的解释留下几个链接:

百度百科:hook
MSDN: Hooks
博客园: Beginning HOOK

各位可以多多参考,那么博主说下自己的理解:

windows 系统中的【hook 机制】,就类似于一个【消息过滤网】,如果我们向操作系统申请并成功对某个窗口安装了一个【hook】指定了【回调函数】,那么这个【回调函数】也就相当于我们人为对这个窗口添加了一个【消息过滤网】。此时当 windows 操作系统要对这个窗口发送任何消息的时候(例如按键、鼠标点击等消息)操作系统会先调用我们在【消息过滤网】中设置的【回调函数】去接受、处理、过滤等等,当然如果你在【回调函数】中拿到了数据却没有继续传递给窗口的话,就相当于拦截了这些消息。

打个简单的比方,如果你在系统全局安装了一个【键盘消息】的钩子,并且在其指定的【回调函数】中没有把这个键盘消息继续传递给系统上的窗口,那么你的所有【键盘消息】都被这个【hook】也就我们挂在这个【消息过滤网】上的【回调函数】给拦截了,这也意味着你的键盘会失灵。

SetWindowsHookEx 函数

那么 SetWindowsHookEx 函数就是我们用来在 windows 操作系统上安装钩子的函数,我们简单来看一下这个函数的原型:


1

2

3

4

5

6

HHOOK WINAPI SetWindowsHookEx(

  _In_  int idHook,         // 安装的钩子类型

  _In_  HOOKPROC lpfn,      // 处理消息的回调函数

  _In_  HINSTANCE hMod,     // 当前实例句柄

  _In_  DWORD dwThreadId    // 线程ID

);

钩子类型有很多种,本页中留的大部分链接上都有讲到这里就不废话了,关于 hMod(当前实例句柄)和 dwThreadId(线程ID)之间的一些小九九博主这里也不多说,各位可以到下方的链接中去看看,博主这里就举一个容易实现的实例。

百度百科: SetWindowsHookEx
MSDN: SetWindowsHookEx

设置监听【键盘】消息

PKBDLLHOOKSTRUCT 是 WH_KEYBOARD_LL 方式中用来接收消息的结构体,大家可以到 WindUser.h 中多逛逛。

我们监听键盘的时候主要用的是该结构体的 vkCode(value code)和 scanCode 这两个字段。即键盘的【值码】和【扫描码】那么为什么判断一个按键要分成两个部分呢,原因是因为世界上的键盘有很多种,不同国家、不同厂商生产的键盘甚,至同一个键盘上【同样的键】不同的地方按下都可能会有差异。vkCode 是常见的一般都是公用的键盘值,而 scanCode 扫描码则是用来辅助区分的一个一个参数,例如同样是按下 ctrl 键,他们的 vkCode 是相同的但是 scanCode 却不同。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

#include <windows.h>

HHOOK myhook;   // 保存当前钩子句柄

/****************************************************************

  WH_KEYBOARD hook procedure

  鍵盤钩子处理过程

 ****************************************************************/

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)

{  

    char text[50], data[20];    // 输出字符串

    const char *info = NULL;    // 类型字符指针

    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; // 获取按键消息

    HDC hdc;    // 画图设备句柄

    // 判断是否收到键盘消息

    if (nCode >= 0)

    {

        // 判断消息类型

        if      (wParam == WM_KEYDOWN)      info = "普通按鍵抬起";

        else if (wParam == WM_KEYUP)        info = "普通按鍵按下";

        else if (wParam == WM_SYSKEYDOWN)   info = "系統按鍵抬起";

        else if (wParam == WM_SYSKEYUP)     info = "系統按鍵按下";

        // 初始化数组

        ZeroMemory(text, sizeof(text));

        ZeroMemory(data, sizeof(data));

        // 拼装字符串

        wsprintf(text, "%s - 键盘码 [%04d], 扫描码 [%04d]  ", info, p->vkCode, p->scanCode);

        wsprintf(data, "按鍵目测为: %c  ", p->vkCode);

        // 此处调用 GDI 画图函数来将截取到的内容画在窗口上

        hdc = GetDC(画图的窗口句柄);       // 获取要画图的设备句柄

        TextOut(hdc, 10, 10, text, strlen(text));   // 在窗口上画文字

        TextOut(hdc, 10, 30, data, strlen(data));   // 参数分别是 目标设备, x坐标, y坐标, 字符串内容, 字符串长度

        ReleaseDC(画图的窗口句柄, hdc);        // 释放设备句柄

    }

    // 将消息继续往下传递

    return CallNextHookEx(myhook, nCode, wParam, lParam);

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPSTR lpCmdLine, int nCmdShow)

{

    /* 其他代码 */

    // 设置键盘全局监听

    myhook = SetWindowsHookEx(

        WH_KEYBOARD_LL, // 监听类型【键盘消息】

        KeyboardProc,   // 处理函数

        hInstance,      // 当前实例句柄

        0               // 监听线程ID(NULL为全局监听)

    );

    // 判断是否成功

    if(myhook == NULL)

    {      

        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());

        MessageBox(hwnd, text, TEXT("错误"), MB_OK);

    }

    /* 其他代码 */

}

注:其中在输出按键的时候,直接用 %c 输出了 p->vkCode 部分,这个实际上不是很准确。

顺便提一句,各位也不要用这个功能去做什么坏事,比如去监听QQ窗口的键盘消息然后偷到密码盗别人号之类的, 博主已经试过了 这个本身有带防护的,用户在输密码的时候,会有干扰的键盘消息也一起冒出来所以没那么简单能到到别人输的密码。至于写个程序去拦截别人的键盘还有鼠标消息让别人的电脑不能用的情况,这个确实很容易做到,而且貌似杀毒软件都没办法防,只能自己在自己的电脑上留个后门,怎么写后门?后面的网络编程会说这个。

键盘监听完整代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

#include <windows.h>

HWND hgWnd;

HHOOK myhook;

/****************************************************************

  WH_KEYBOARD hook procedure

  鍵盤钩子处理过程

 ****************************************************************/

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)

{  

    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;

    const char *info = NULL;

    char text[50], data[20];

    PAINTSTRUCT ps;

    HDC hdc;

    if (nCode >= 0)

    {

        if      (wParam == WM_KEYDOWN)      info = "普通按鍵抬起";

        else if (wParam == WM_KEYUP)        info = "普通按鍵按下";

        else if (wParam == WM_SYSKEYDOWN)   info = "系統按鍵抬起";

        else if (wParam == WM_SYSKEYUP)     info = "系統按鍵按下";

        ZeroMemory(text, sizeof(text));

        ZeroMemory(data, sizeof(data));

        wsprintf(text, "%s - 键盘码 [%04d], 扫描码 [%04d]  ", info, p->vkCode, p->scanCode);

        wsprintf(data, "按鍵目測為: %c  ", p->vkCode);

        hdc = GetDC(hgWnd);        

        TextOut(hdc, 10, 10, text, strlen(text));

        TextOut(hdc, 10, 30, data, strlen(data));

        ReleaseDC(hgWnd,hdc);

    }

    

    return CallNextHookEx(myhook, nCode, wParam, lParam);

}

// 5. 窗口过程处理

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{  

    hgWnd = hwnd;

    switch(msg)

    {

        case WM_CLOSE:

            DestroyWindow(hwnd);

        break;

        case WM_DESTROY:

            PostQuitMessage(0);

            break;

        default:

            return DefWindowProc(hwnd, msg, wParam, lParam);

    }

    return 0;

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPSTR lpCmdLine, int nCmdShow)

{

    WNDCLASSEX wc;  // http://baike.baidu.com/view/1750396.htm

    HWND hwnd;

    MSG Msg;

    char text[30];

    const char szClassName[] = "myWindowClass";

    // 1. 设置注册窗口结构体

    wc.cbSize        = sizeof(WNDCLASSEX);              // 注册窗口结构体的大小

    wc.style         = 0;                               // 窗口的样式

    wc.lpfnWndProc   = WndProc;                         // 指向窗口处理过程的函数指针

    wc.cbClsExtra    = 0;                               // 指定紧跟在窗口类结构后的附加字节数

    wc.cbWndExtra    = 0;                               // 指定紧跟在窗口事例后的附加字节数

    wc.hInstance     = hInstance;                       // 本模块的实例句柄

    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄

    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 光标的句柄

    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景画刷的句柄

    wc.lpszMenuName  = NULL;                            // 指向菜单的指针

    wc.lpszClassName = szClassName;                     // 指向类名称的指针

    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标

    // 2. 使用【窗口结构体】注册窗口

    if(!RegisterClassEx(&wc))

    {

        MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 3. 创建窗口

    hwnd = CreateWindowEx(

        WS_EX_CLIENTEDGE,       // 窗口的扩展风格

        szClassName,            // 指向注册类名的指针

        TEXT("窗口标题"),       // 指向窗口名称的指针

        WS_OVERLAPPEDWINDOW,    // 窗口风格

        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高

        NULL,                   // 父窗口的句柄

        NULL,                   // 菜单的句柄

        hInstance,              // 应用程序实例的句柄

        NULL                    // 指向窗口的创建数据

        );

    if(hwnd == NULL)

    {

        MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 4. 显示窗口

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    // 设置键盘全局监听

    myhook = SetWindowsHookEx(

        WH_KEYBOARD_LL, // 监听类型【键盘】

        KeyboardProc,   // 处理函数

        hInstance,      // 当前实例句柄

        0               // 监听窗口句柄(NULL为全局监听)

    );

    if(myhook == NULL)

    {      

        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());

        MessageBox(hwnd, text, TEXT("错误"), MB_OK);

    }

    // 5. 消息循环

    while(GetMessage(&Msg, NULL, 0, 0) > 0)

    {

        TranslateMessage(&Msg);

        DispatchMessage(&Msg);

    }

    return Msg.wParam;

}

运行截图

设置监听【鼠标】消息

与键盘监听类似,各位直接看代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

#include <windows.h>

HWND hgWnd;

HHOOK myhook;

/****************************************************************

  WH_KEYBOARD hook procedure

  鍵盤钩子处理过程

 ****************************************************************/

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)

{  

    LPMSLLHOOKSTRUCT p = (LPMSLLHOOKSTRUCT)lParam;

    POINT   pt = p->pt;

    DWORD   mouseData = p->mouseData;

    const char *info = NULL;

    char text[60], pData[50], mData[50];

    PAINTSTRUCT ps;

    HDC hdc;

    if (nCode >= 0)

    {

        if   (wParam == WM_MOUSEMOVE)       info = "鼠标移动    ";

        else if(wParam == WM_LBUTTONDOWN)   info = "鼠标【左键】按下";

        else if(wParam == WM_LBUTTONUP)     info = "鼠标【左键】抬起";

        else if(wParam == WM_LBUTTONDBLCLK) info = "鼠标【左键】双击";

        else if(wParam == WM_RBUTTONDOWN)   info = "鼠标【右键】按下";

        else if(wParam == WM_RBUTTONUP)     info = "鼠标【右键】抬起";

        else if(wParam == WM_RBUTTONDBLCLK) info = "鼠标【右键】双击";

        else if(wParam == WM_MBUTTONDOWN)   info = "鼠标【滚轮】按下";

        else if(wParam == WM_MBUTTONUP)     info = "鼠标【滚轮】抬起";

        else if(wParam == WM_MBUTTONDBLCLK) info = "鼠标【滚轮】双击";

        else if(wParam == WM_MOUSEWHEEL)    info = "鼠标【滚轮】滚动";

        ZeroMemory(text, sizeof(text));

        ZeroMemory(pData, sizeof(pData));

        ZeroMemory(mData, sizeof(mData));

        wsprintf( text, "当前状态: %10s   ", info);

        wsprintf(pData, "0x%x - X: [%04d], Y: [%04d]  ", wParam, pt.x, pt.y);

        wsprintf(mData, "附带数据: %16u   ", mouseData);

        hdc = GetDC(hgWnd);        

        TextOut(hdc, 10, 10,  text, strlen(text));

        TextOut(hdc, 10, 30, pData, strlen(pData));

        TextOut(hdc, 10, 50, mData, strlen(mData));

        ReleaseDC(hgWnd,hdc);

    }

    

    return CallNextHookEx(myhook, nCode, wParam, lParam);

}

// 5. 窗口过程处理

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{  

    hgWnd = hwnd;

    switch(msg)

    {

        case WM_CLOSE:

            DestroyWindow(hwnd);

        break;

        case WM_DESTROY:

            PostQuitMessage(0);

            break;

        default:

            return DefWindowProc(hwnd, msg, wParam, lParam);

    }

    return 0;

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPSTR lpCmdLine, int nCmdShow)

{

    WNDCLASSEX wc;  // http://baike.baidu.com/view/1750396.htm

    HWND hwnd;

    MSG Msg;

    char text[30];

    const char szClassName[] = "myWindowClass";

    // 1. 设置注册窗口结构体

    wc.cbSize        = sizeof(WNDCLASSEX);              // 注册窗口结构体的大小

    wc.style         = 0;                               // 窗口的样式

    wc.lpfnWndProc   = WndProc;                         // 指向窗口处理过程的函数指针

    wc.cbClsExtra    = 0;                               // 指定紧跟在窗口类结构后的附加字节数

    wc.cbWndExtra    = 0;                               // 指定紧跟在窗口事例后的附加字节数

    wc.hInstance     = hInstance;                       // 本模块的实例句柄

    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄

    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 光标的句柄

    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景画刷的句柄

    wc.lpszMenuName  = NULL;                            // 指向菜单的指针

    wc.lpszClassName = szClassName;                     // 指向类名称的指针

    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标

    // 2. 使用【窗口结构体】注册窗口

    if(!RegisterClassEx(&wc))

    {

        MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 3. 创建窗口

    hwnd = CreateWindowEx(

        WS_EX_CLIENTEDGE,       // 窗口的扩展风格

        szClassName,            // 指向注册类名的指针

        TEXT("窗口标题"),       // 指向窗口名称的指针

        WS_OVERLAPPEDWINDOW,    // 窗口风格

        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高

        NULL,                   // 父窗口的句柄

        NULL,                   // 菜单的句柄

        hInstance,              // 应用程序实例的句柄

        NULL                    // 指向窗口的创建数据

        );

    if(hwnd == NULL)

    {

        MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK);

        return 0;

    }

    // 4. 显示窗口

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    // 设置鼠标全局监听

    myhook = SetWindowsHookEx(

        WH_MOUSE_LL,    // 监听类型【鼠标】

        MouseProc,  // 处理函数

        hInstance,      // 当前实例句柄

        0               // 监听窗口句柄(NULL为全局监听)

    );

    if(myhook == NULL)

    {      

        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());

        MessageBox(hwnd, text, TEXT("错误"), MB_OK);

    }

    // 5. 消息循环

    while(GetMessage(&Msg, NULL, 0, 0) > 0)

    {

        TranslateMessage(&Msg);

        DispatchMessage(&Msg);

    }

    return Msg.wParam;

}

https://lellansin.wordpress.com/2013/08/15/windows-api-%E6%95%99%E7%A8%8B%EF%BC%88%E4%B8%83%EF%BC%89-hook-%E9%92%A9%E5%AD%90%E7%9B%91%E5%90%AC%EF%BC%88%E7%BC%96%E5%86%99%E4%B8%AD%EF%BC%89/

时间: 2024-12-24 02:17:10

Windows API 教程(七) hook 钩子监听的相关文章

Windows API教程文件系统

本篇文章主要介绍了"Windows API教程文件系统",主要涉及到Windows API教程文件系统方面的内容,对于Windows API教程文件系统感兴趣的同学可以参考一下. 索引 概念简介 文件对象 文件流 文件句柄 文件指针 文件系统操作 常见 API 高级文件操作 本讲程序功能列表 CreateFile 具体参数 返回值 DeleteFile 参数 返回值 CopyFile.MoveFile.FindFirstFile ReadFile GetCurrentDirectory

Windows环境下修改Oracle实例监听IP地址

Windows环境下修改Oracle实例监听IP地址. 配置文件路径:<ORACLE_HOME>\NETWORK\ADMIN 如:C:\Oracle11gR2\product\11.2.0\dbhome_1\NETWORK\ADMIN 一.修改配置文件:listener.ora # listener.ora Network Configuration File: D:\Oracle11gR2\product\11.2.0\dbhome_1\network\admin\listener.ora

Node.js 教程 05 - EventEmitter(事件监听/发射器 )

目录: 前言 Node.js事件驱动介绍 Node.js事件 注册并发射自定义Node.js事件 EventEmitter介绍 EventEmitter常用的API error事件 继承EventEmitter 前言: 今天事儿太多了,没有发太多的东西.不好意思了各位. 本篇主要介绍Node.js中的事件驱动,至于Node.js事件概念的东西,太多了. 本系列课程主要抱着的理念就是,让大家慢慢的入门,我也尽量写的简单一点. 所以呢,本文事件驱动,大家的目标应该是:理解Node.js的事件驱动.会

Android基础入门教程——3.1 基于监听的事件处理机制

Android基础入门教程--3.1.1 基于监听的事件处理机制 标签(空格分隔): Android基础入门教程 本节引言: 第二章我们学习的是Android的UI控件,我们可以利用这些控件构成一个精美的界面,但是仅仅是界面而已:下一步就要开始学习逻辑与业务实现了,本章节讲解的是Android的事件处理机制!何为事件处理机制?举个 简单的例子,比如点击一个按钮,我们向服务器发送登陆请求!当然,Android中的事件处理机制不止这一种, 比如屏幕发生选择,我们点击了屏幕上某个区域-简单点说,事件处

迷你MVVM框架 avalonjs 学习教程15、属性监听与模块通信

avalon的ViewModel对象从其内部EventManager里继承了三个方法,$watch.$unwatch.$fire三个方法,它们就是我们本节的主题. 词如其名,非常直白,一看就知道做什么.我们先从$watch方法说起,它能监听当前的VM第一层的监控属性 与 计算属性,如果某属性是一个对象,想监控其子孙属性,就需要定位到此对象上使用$watch回调了.$watch回调会默认传入先后两个属性值. <!DOCTYPE html> <html> <head> &l

Windows平台下Oracle 11g R2监听文件日志过大,造成客户端无法连接的问题处理

近期部署在生产环境的应用突然无法访问,查看应用日志发现无法获取数据库连接. SystemErr R Caused by: oracle.net.ns.NetException: The Network Adapter could not establish the connection SystemErr R at oracle.net.nt.ConnStrategy.execute(ConnStrategy.java:359) SystemErr R at oracle.net.resolve

C#全局键盘监听(Hook)的使用

一.为什么需要全局键盘监听? 在某些情况下应用程序需要实现快捷键执行特定功能,例如大家熟知的QQ截图功能Ctrl+Alt+A快捷键,只要QQ程序在运行(无论是拥有焦点还是处于后台运行状态),都可以按下快捷键使用此功能... 这个时候在程序中添加键盘监听肯定不能满足需求了,当用户焦点不在App上时(如最小化,或者用户在处理其它事物等等)键盘监听就失效了 二.怎样才能实现全局键盘监听? 这里需要用到Windows API,源码如下:(可以作为一个工具类[KeyboardHook.cs]收藏起来) u

【转】【C#】全局键盘监听

using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Reflection; namespace 梦琪动漫屋 { /// <summary> /// 键盘钩子/// </summary> class KeyboardHook { public ev

【转】Hook钩子C#实例

[转]Hook钩子C#实例 转过来的文章,出处已经不知道了,但只这篇步骤比较清晰,就贴出来了. 一.写在最前 本文的内容只想以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx 二.了解一下钩子 从字面上理解,钩子就是想钩住些东西,在程序里可以利用钩子提前处理些Windows消息. 例子:有一个Form,Fo