文章目录
- 消息组成
- 消息的作用
- 获取消息
- 翻译消息
- 常见消息
- WM_DESTROY
- WM_SYSCOMMAND
- 消息循环的阻塞
- 发送消息
- 字符串资源
- 加速键资源
- GDI绘图对象-画笔
- 位图绘制
- 文本绘制
- 字体
- 模式对话框
- 动态库特点
- 线程
- 创建线程
- 互斥
- 事件
- 信号量
消息组成
- 窗口句柄
- 消息ID
- 消息的两个参数
- 消息产生的时间
- 消息产生时的鼠标位置
消息的作用
- 当系统通知窗口工作时,就采用消息的方式派发给窗口
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);
}
return 0;
获取消息
BOOL GetMessage(LPMSG lpMsg, //存取获取到的消息BUFFHWND hWnd, // 窗口句柄UINT wMsgFilterMin,//获取消息的最小IDUINT wMsgFilterMax,//获取消息的最大ID)
- lpMsg–当获取到的消息后,将消息的参数存放到MSG结构中
- hWnd–获取到hWnd所指定窗口的消息
- wMsgFilterMin和wMsgFilterMsx—只能获取到由他们指定的消息,如果都为0,则表示没有范围
翻译消息
TranslateMessage–翻译消息,按键消息,翻译成字符消息
BOOL TranslateMessage{CONST MSG * lpMsg;//要翻译的消息地址
}
- 检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。
常见消息
WM_DESTROY
- 产生时间:窗口被销毁时的消息
- 附带信息:wParam为0 lParam 为0
- 一般用法:常用于在窗口被销毁之前,做相应的善后处理,例如资源、内存等
WM_SYSCOMMAND
- 产生时间:当点击窗口的最大化,最小化,关闭等
- 附带消息:wParam:具体点击的位置,例如关闭SC_CLOSE等 lParam:鼠标光标的位置,LOWORD(lParam);//水平位置 HIWORD(lParam);//垂直位置
- 一般用法:常用在窗口关闭时,提示用户处理
消息循环的阻塞
while(1){if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){if(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DisPatchMessage(&nMsg);}}
}
发送消息
- SendMessage–发送消息,会等候消息处理的结果
- PostMessage–投递消息,消息发出后立刻返回并不会等候消息执行结果
BOOL SendMessage/PostMessage{HWND hWnd;//消息发送的目的窗口UINT msg;//消息IDWPARAM wParam;//消息参数LPARAM lParam;//消息参数
}
自定义消息:
- 系统消息:0x000-0x03ff 由系统定义好的消息,可以在程序中直接使用
- 用户自定义消息–ID范围(0x0400-0x7fff) 由用户自己定义,满足用户自己的需求,由用户自己发出消息,并相应处理
#define WM_USER 0X0400+1
SendMessage(hWnd,msg,1,2);
字符串资源
- 添加字符串资源:添加字符串表,在表中增加字符串
- 字符串资源的使用
int LoadString(HINSTANCE hInstance;UINT uID,LPTSTR lpBuffer,int nBufferMax
);成功返回字符串长度,失败0
加速键资源
GDI绘图对象-画笔
- 画笔作用:线的颜色、线型、线粗;HPEN-画笔句柄
- 画笔使用:创建画笔
HPEN CreatePen(int fnPenStyle, //画笔的样式int nWidth, //画笔的粗细COLORREF crColor //画笔的颜色
)创建成功返回句柄
- 其他:可以使用GetStockObject函数获取系统维护的画刷、画笔等,如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的GetStockObject返回的画刷不需要DeleteObject
HANDLE g_hOutput = 0;
void DrawPit(HDC hdc) {for (int i = 0; i < 256; i++) {for (int j = 0; j < 256; j++) {SetPixel(hdc, i, j, RGB(i, j, 0));}}
}void DrawLine(HDC hdc) {MoveToEx(hdc, 100, 100, NULL);LineTo(hdc, 300, 300);
}void DrawRect(HDC hdc) {Rectangle(hdc, 100, 100, 300, 300);
}
void DrawEll(HDC hdc) {Ellipse(hdc, 100, 100, 300, 300);
}
void OnPaint(HWND hWnd) {PAINTSTRUCT ps = { 0 };HDC hdc = BeginPaint(hWnd, &ps);//DrawPit(hdc);//DrawLine(hdc);//DrawRect(hdc);HPEN hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));HGDIOBJ nOldPen = SelectObject(hdc, hPen);//HBRUSH hBrush = CreateSolidBrush(RGB(0, 255, 0));HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);//透明颜色HGDIOBJ nOldBrush = SelectObject(hdc, hBrush);DrawEll(hdc);//DeleteObject(hBrush);SelectObject(hdc, nOldBrush);//SelectObject(hdc, nOldPen);//DeleteObject(hPen);EndPaint(hWnd, &ps);
}
位图绘制
void DrawBmp(HDC hdc) {//添加位图资源(不需要代码)HBITMAP hBmp = LoadBitmap(g_hInstance, (char *)IDB_BITMAP1);HDC hMemdc = CreateCompatibleDC(hdc);//创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中绘图HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp);//将位图数据送给内存DC,内存DC在虚拟区域中将位图绘制出来BitBlt(hdc, 100, 100, 48, 48, hMemdc, 0, 0, SRCCOPY);//将虚拟区域中绘制好的图像城成像到窗口中StretchBlt(hdc, 200, 200, 24, 24, hMemdc, 0, 0, 48, 48, SRCCOPY);//缩放成像SelectObject(hMemdc, nOldBmp);DeleteObject(hBmp);DeleteDC(hMemdc);
}
文本绘制
void OnPaint(HWND hWnd) {PAINTSTRUCT ps = { 0 };HDC hdc = BeginPaint(hWnd, &ps);char szText[] = "hello txt";SetTextColor(hdc, RGB(255, 0, 0));SetBkColor(hdc, RGB(0, 255, 0));SetBkMode(hdc, TRANSPARENT);TextOut(hdc, 100, 100, szText, strlen(szText));RECT rc;rc.left = 100;rc.top = 150;rc.right = 200;rc.bottom = 200;Rectangle(hdc, 100, 150, 200, 200);DrawText(hdc, szText, strlen(szText), &rc, DT_LEFT | DT_TOP | DT_WORDBREAK);EndPaint(hWnd, &ps);
}
字体
void OnPaint(HWND hWnd) {PAINTSTRUCT ps = { 0 };HDC hdc = BeginPaint(hWnd, &ps);SetTextColor(hdc, RGB(255, 0, 0));SetBkColor(hdc, RGB(0, 255, 0));SetBkMode(hdc, TRANSPARENT);HFONT hFont = CreateFont(30, 0, 45, 0, 900, 1, 1, 1, GB2312_CHARSET, 0, 0, 0, 0, "黑体");HGDIOBJ nOldFont = SelectObject(hdc, hFont);char szText[] = "hello txt";TextOut(hdc, 100, 100, szText, strlen(szText));RECT rc;rc.left = 100;rc.top = 150;rc.right = 200;rc.bottom = 200;Rectangle(hdc, 100, 150, 200, 200);DrawText(hdc, szText, strlen(szText), &rc, DT_LEFT | DT_TOP | DT_WORDBREAK);SelectObject(hdc, nOldFont);DeleteObject(hFont);EndPaint(hWnd, &ps);
}
模式对话框
HINSTANCE g_hInstance = 0;
void OnCommand(HWND hWnd,WPARAM wParam){switch(LOWORD(wParam)){case ID_MODEL:{DialogBox(g_hInstance,(char*)IDD_DIALOG1,hWnd,DlgProc);}}
}INT CALLBACK DlgProc(HWND hwndlg,UINT msgID, WPARAM wParam,LPARAM lParam){if(wParam == SC_CLOSE){EndDialog(hwndlg,100);}break;return FALSE;
}
动态库特点
动态库特点
- 运行时独立存在
- 源码不会连接到执行程序
- 使用时加载(使用动态库必须动态库执行)
与静态库比较:
- 由于静态库是将代码嵌入
线程
创建线程
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,//安全属性SIZE_T dwStackSize, //线程栈的大小LPTHREAD_START_ROUTINE lpStartAddress, //线程处理函数的函数地址LPVOID lpParameter, //传递给线程处理函数的参数DWORD dwCreationFlags, //线程的创建方式LPDWORD lpThread //创建成功,返回线程的ID
);创建成功,返回线程句柄
定义线程处理函数
DWORD WINAPI ThreadProc(LPVOID lpParameter //创建线程时,传递给线程的参数
)
互斥
相关的问题:
多线程下代码或资源的贡献使用
互斥的使用:
1、创建互斥
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,//安全属性BOOL bInitialOwner, //初始的拥有者 true/falseLPCTSTR lpName //命名
);创建成功或返回互斥句柄
2、等候互斥
WaitFor… 互斥的等候遵循谁先等候谁先获取
3、释放互斥
BOOL ReleaseMutex(HANDLE hMutex //handle to mutex
);
3、关闭互斥句柄
#include<Windows.h>
#include<stdio.h>HANDLE g_hMutex;
DWORD CALLBACK TestProc(LPVOID pParam) {char* pszText = (char *)pParam;while (1) {WaitForSingleObject(g_hMutex, INFINITE);for (int i = 0; i < strlen(pszText); i++) {printf("%c", pszText[i]);Sleep(125);}printf("\n");ReleaseMutex(g_hMutex);}return 0;
}
DWORD CALLBACK TestProc2(LPVOID pParam) {char* pszText = (char *)pParam;while (1) {WaitForSingleObject(g_hMutex, INFINITE);for (int i = 0; i < strlen(pszText); i++) {printf("%c", pszText[i]);Sleep(125);}printf("\n");ReleaseMutex(g_hMutex);}return 0;
}
int main() {g_hMutex = CreateMutex(NULL, FALSE, NULL);DWORD nID = 0;char *pszText = "**********";HANDLE hThread = CreateThread(NULL, 0, TestProc, pszText, 0, &nID);char *pszText2 = "----------";HANDLE hThread2 = CreateThread(NULL, 0, TestProc2, pszText2, 0, &nID);getchar();getchar();return 0;}
事件
相关问题:
程序之间的通知的问题
事件的使用
1、创建事件
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,//安全属性BOOL bManualReset,//事件重置方式,true手动,false自动BOOL bInitialState, //事件初始状态,true有信号LPCTSTR lpName //事件命名
);创建成功返回事件句柄
2、等候事件
WaitForSingleObject/WaitForMUltipleObjects
3、触发事件(将事件设置成有信号状态)
BOOL SetEvent(HANDLE hEvent //handle to event
);
4、复位事件(将事件设置成无信号状态)
BOOL ResetEvent(HANDLE hEvent //handle to evnet
);
5、关闭事件 CloseHandle
小心事件的死锁
#include<Windows.h>
#include<stdio.h>
HANDLE g_hEvent = 0;
DWORD CALLBACK PrintProc(LPVOID pParam) {while (1) {WaitForSingleObject(g_hEvent, INFINITE);ResetEvent(g_hEvent);printf("********\n");}
}
DWORD CALLBACK CtrlProc(LPVOID pParam) {while (1) {Sleep(1000);SetEvent(g_hEvent);}
}
int main() {g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);DWORD nID = 0;HANDLE hThread[2] = { 0 };hThread[0] = CreateThread(NULL, 0, PrintProc, NULL, 0, &nID);hThread[1] = CreateThread(NULL, 0, CtrlProc, NULL, 0, &nID);WaitForMultipleObjects(2, hThread,TRUE, INFINITE);CloseHandle(g_hEvent);return 0;
}