文章目录
- 消息组成
- 消息的作用
- 获取消息
- 翻译消息
- 常见消息
- 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, //存取获取到的消息BUFF
	HWND hWnd, // 窗口句柄
	UINT wMsgFilterMin,//获取消息的最小ID
	UINT 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;//消息ID
	WPARAM 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/false
	LPCTSTR 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;
}


















![[发布]嵌入式系统远程测控软件-基于Qt](https://img-blog.csdnimg.cn/direct/ae576077ca3f40dfb7b12fcd2798a68c.png)
