文章目录
- 消息组成
- 消息的作用
- 获取消息
- 翻译消息
- 常见消息
- 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;
}