1. 消息機(jī)制
windows操作系統(tǒng)最大的特色是良好的用戶交互性,這種交互性通過優(yōu)秀的圖形界面來實(shí)現(xiàn)
Windows操作系統(tǒng)將用戶對(duì)應(yīng)用程序窗口的所有操作(鍵盤按鍵、鼠標(biāo)點(diǎn)擊、窗口最大最小化等等)轉(zhuǎn)化為Windows消息并分發(fā)給應(yīng)用程序,應(yīng)用程序?qū)@些消息進(jìn)行響應(yīng),從而實(shí)現(xiàn)用戶對(duì)操作系統(tǒng)以及應(yīng)用程序的控制
這種產(chǎn)生消息、傳遞消息、處理消息的過程被稱為Windows消息機(jī)制 。
Windows操作系統(tǒng)為每一個(gè)正在運(yùn)行的應(yīng)用程序維護(hù)一個(gè)消息隊(duì)列。應(yīng)用程序的消息循環(huán)將接受和處理這些消息,從而對(duì)相關(guān)事件做出響應(yīng)。
1.1 得到消息
GetMessage(&msg, NULL, 0, 0);
從消息隊(duì)列取消息,如果消息隊(duì)列沒有消息時(shí),函數(shù)阻塞,等待消息,如果得到了消息,這個(gè)消息是wm_quit消息,立馬返回false,如果不是wm_quit消息,返回true
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
從消息隊(duì)列取消息,如果消息隊(duì)列有消息,且這個(gè)消息是任何消息,返回true,如果沒有消息返回false
1.2 發(fā)送消息
SendMessage(hWnd,WM_KEYDOWN,0,0);
可以理解為遞歸,直接把消息投遞給該窗口對(duì)應(yīng)的消息處理函數(shù)
PostMessage(hWnd, WM_KEYDOWN, 0, 0);
可以理解為排隊(duì),把消息投遞給這個(gè)窗口對(duì)應(yīng)的消息隊(duì)列,以供下一次去得到消息
2. 基本消息
windows程序模塊
WM_CREATE:
創(chuàng)建窗口時(shí)被發(fā)送給應(yīng)用程序,該消息只被發(fā)送一次。理解為類的構(gòu)造
WM_DESTROY:
當(dāng)關(guān)閉窗口時(shí)或者開發(fā)人員在程序中調(diào)用了DestroyWindow函數(shù)時(shí),WM_DESTROY消息會(huì)被發(fā)送給應(yīng)用程序。理解為類的析構(gòu)
WM_ACTIVATE:
該消息在以下3種情況時(shí)被發(fā)送:
- 鼠標(biāo)單擊激活。wParam參數(shù)被標(biāo)記為
WA_CLICKACTIVE
- 非鼠標(biāo)激活。wParam參數(shù)被標(biāo)記為
WA_ACTIVE
- 非激活。wParam參數(shù)被標(biāo)記為
WA_INACTIVE
系統(tǒng)命令消息
WM_SYSCOMMAND
在關(guān)閉、最大化、最小化、還原窗口時(shí)被發(fā)送給應(yīng)用程序。
- 當(dāng)wParam參數(shù)為
SC_CLOSE
時(shí)表示窗口進(jìn)行了關(guān)閉操作 - 當(dāng)wParam參數(shù)為
SC_MAXIMIZE
時(shí),表示窗口進(jìn)行了最大化操作 - 當(dāng)wParam參數(shù)為
SC_MINIMIZE
時(shí),表示窗口進(jìn)行了最小化操作 - 當(dāng)wParam參數(shù)為
SC_RESTORE
時(shí),表示窗口進(jìn)行了最小化操作
WM_COMMAND
當(dāng)用戶從菜單選中一個(gè)命令項(xiàng)目、當(dāng)一個(gè)控件發(fā)送通知消息給去父窗口或者按下一個(gè)快捷鍵將發(fā)送 WM_COMMAND
消息。
代碼示例
// 消息機(jī)制.cpp : 定義應(yīng)用程序的入口點(diǎn)。
//
#include "framework.h"
#include "消息機(jī)制.h"
#define MAX_LOADSTRING 100
// 全局變量:
HINSTANCE hInst; // 當(dāng)前實(shí)例
WCHAR szTitle[MAX_LOADSTRING]; // 標(biāo)題欄文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口類名
// 此代碼模塊中包含的函數(shù)的前向聲明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此處放置代碼。
// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 執(zhí)行應(yīng)用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));
MSG msg = { 0 };
// 主消息循環(huán):
//軟件,就用GetMessage
//第三個(gè)參數(shù)和第四個(gè)參數(shù),表示的是檢索范圍 0,0表示是所有的消息都要派發(fā)出來
/*while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}*/
//句柄:句柄實(shí)際上就是一個(gè)數(shù)字,用這個(gè)數(shù)字來表示這個(gè)窗口,每一個(gè)窗口都有一個(gè)唯一的句柄
while (msg.message != WM_QUIT)//先看是不是退出消息
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))//拿出消息放入msg
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return (int) msg.wParam;
}
//
// 函數(shù): MyRegisterClass()
//
// 目標(biāo): 注冊(cè)窗口類。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));
wcex.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_MY);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 函數(shù): InitInstance(HINSTANCE, int)
//
// 目標(biāo): 保存實(shí)例句柄并創(chuàng)建主窗口
//
// 注釋:
//
// 在此函數(shù)中,我們?cè)谌肿兞恐斜4鎸?shí)例句柄并
// 創(chuàng)建和顯示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 將實(shí)例句柄存儲(chǔ)在全局變量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函數(shù): WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目標(biāo): 處理主窗口的消息。
//
// WM_COMMAND - 處理應(yīng)用程序菜單
// WM_PAINT - 繪制主窗口
// WM_DESTROY - 發(fā)送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
/*case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_CLOSE:
MessageBox(0, 0, 0, 0);
break;
case SC_MINIMIZE:
break;
case SC_MAXIMIZE:
break;
}
DefWindowProc(hWnd, message, wParam, lParam);
}
break;*/
//case WM_ACTIVATE://激活消息
//{
// switch (wParam)//只要不是鼠標(biāo)消息,基本是wParam
// {
// case WA_CLICKACTIVE://鼠標(biāo)激活
// {
// static int j = 0;
// HDC hdc = GetDC(hWnd);
// TextOut(hdc, 110, j, _T("鼠標(biāo)激活"), 4);
// ReleaseDC(hWnd, hdc);
// j += 20;
// }
// break;
// case WA_ACTIVE://非鼠標(biāo)激活
// {
// static int j = 0;
// HDC hdc = GetDC(hWnd);
// TextOut(hdc, 210, j, _T("非鼠標(biāo)激活"), 5);
// ReleaseDC(hWnd, hdc);
// j += 20;
// }
// break;
// case WA_INACTIVE://非激活
// {
// static int j = 0;
// HDC hdc = GetDC(hWnd);
// TextOut(hdc, 310, j, _T("非激活"), 3);
// ReleaseDC(hWnd, hdc);
// j += 20;
// }
// break;
// }
//}
//break;
//case WM_CREATE://窗口創(chuàng)建消息
//{
// MessageBox(0, 0, 0, 0);//現(xiàn)有這個(gè)彈窗才有的主窗口
//}
//break;
//case WM_KEYDOWN://鍵盤按下
//{
// //第一個(gè)參:發(fā)送到那個(gè)窗口的句柄
// //第二個(gè)參:發(fā)送的什么消息
// //第三四個(gè)參:輔助消息 ,比如是鍵盤按鍵按下,是那個(gè)鍵按下
// //SendMessage(hWnd, WM_LBUTTONDOWN, 0, 0);
// //把這個(gè)消息放入消息隊(duì)列,馬上執(zhí)行,執(zhí)行完之后,再回來執(zhí)行剩下的,類似遞歸
// PostMessage(hWnd, WM_LBUTTONDOWN, 0, 0);
// static int j = 0;
// HDC hdc = GetDC(hWnd);
// TextOut(hdc, 110, j, _T("鍵盤按下"), 4);
// ReleaseDC(hWnd, hdc);
// j += 20;
// Sleep(1000);
// //把這個(gè)消息放入隊(duì)列,以供下次獲取
// //MessageBox(0, _T("鍵盤按下"), 0, 0);
//}
//break;
//case WM_LBUTTONDOWN://左鍵按下消息
//{
// //MessageBox(0, _T("左鍵按下"), 0, 0);
// static int j = 0;
// HDC hdc = GetDC(hWnd);
// TextOut(hdc, 210, j, _T("左鍵按下"), 4);
// ReleaseDC(hWnd, hdc);
// j += 20;
//}
//break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜單選擇:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_ASD_QWE:
MessageBox(0, 0, 0, 0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此處添加使用 hdc 的任何繪圖代碼...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY://銷毀消息
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);//窗口的系統(tǒng)消息處理函數(shù)
}
return 0;
}
// “關(guān)于”框的消息處理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}