茵蒂克絲
如何建立一個窗口
另一個再錄的 Windows SDK教程 裏面有講到快捷建立窗口的方式,不過這樣的話要分好幾個文件,感受有點混因此這裏就用原始的方式建立一個窗口。html
那麼,爲何講到 hook(鉤子)的時候要去建立窗口呢?其實這個問題提及來也不復雜,簡單點說,按博主這樣寫不用寫DLL也不用資源文件,其實是把問題簡化了一些。一般 hook 是用來監聽本身窗口上的鍵盤和鼠標輸入的,監聽全局的一般是設置一些全局的熱鍵(如QQ的 Ctrl+Alt+Z 調出QQ窗口),這些常見的功能也都是要依託窗口才能存在。因此咱們先來簡單說下手動創建一個窗口的流程。編程
手動建立窗口的流程
- 設置註冊窗口結構體
- 使用【窗口結構體】註冊窗口
- 建立窗口
- 顯示窗口
- 窗口過程處理
- 消息循環
實際代碼
這裏不會詳細講這個,有感興趣的能夠去追博主的 SDK教程 或者去搜 楊中科的《C語言也能幹大事》windows
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)
{
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;
}
|
由於是比較死的形式,以上代碼你們混個臉熟,大概知道各個部分的做用就好了,博主也歷來沒有專門記過。api
安裝鉤子 (Install hook)
簡介
窗口建好了以後就要開始轉到咱們的正題了,首先咱們須要明確的是,這個鉤子(hook)究竟是什麼,那麼博主這裏也不作太書面的解釋留下幾個連接:數組
百度百科:hook
MSDN: Hooks
博客園: Beginning HOOK網絡
各位能夠多多參考,那麼博主說下本身的理解:app
windows 系統中的【hook 機制】,就相似於一個【消息過濾網】,若是咱們向操做系統申請併成功對某個窗口安裝了一個【hook】指定了【回調函數】,那麼這個【回調函數】也就至關於咱們人爲對這個窗口添加了一個【消息過濾網】。此時當 windows 操做系統要對這個窗口發送任何消息的時候(例如按鍵、鼠標點擊等消息)操做系統會先調用咱們在【消息過濾網】中設置的【回調函數】去接受、處理、過濾等等,固然若是你在【回調函數】中拿到了數據卻沒有繼續傳遞給窗口的話,就至關於攔截了這些消息。wordpress
打個簡單的比方,若是你在系統全局安裝了一個【鍵盤消息】的鉤子,而且在其指定的【回調函數】中沒有把這個鍵盤消息繼續傳遞給系統上的窗口,那麼你的全部【鍵盤消息】都被這個【hook】也就咱們掛在這個【消息過濾網】上的【回調函數】給攔截了,這也意味着你的鍵盤會失靈。函數
SetWindowsHookEx 函數
那麼 SetWindowsHookEx 函數就是咱們用來在 windows 操做系統上安裝鉤子的函數,咱們簡單來看一下這個函數的原型:post
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)
{
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)
{
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;
}
|
上一講: Windows API 教程(六) 動態連接庫
下一講: Windows API 教程(八) 註冊快捷鍵