1、MSG结构体(消息)
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
句柄(HANDLE),资源的标识。
操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。按资源的类型,又可将句柄细分为图标句柄(HICON),光标句柄(HCURSOR),窗口句柄(HWND),应用程序实例句柄(HINSTANCE)等等各种类型的句柄。操作系统给每一个窗口制定一个唯一的标识号,即窗口句柄。
UINT:unsigned int 也就是说 message存放的是一些无符号整形变量。例如,我们按下鼠标,就会产生一个UINT数给message。这些数字是很不好记的。微软给这些UINT定义成了一些宏。这些宏是以WM_开头的。比如,按下鼠标左键为WM_LBOTTONDOWN。
WPARAM:也是一种整数类型的数据。wParam存放的是message的附加参数,比如,我们按下A键,产生一个WM_CHAR消息,但是不知道按下的是哪个按键,所以,可以将A的ASCII码放在wParam中去。
LPARAM:和WPARAM的意思一样,作用不同。
DWORD:32位无符号整数,time指定消息发布的时间
POINT:结构体,代码如下。表示了坐标值。pt指示一个光标的位置
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT;
2、入口函数
int WINAPI WinMain(
HINSTANCE hInstance, // 当前应用程序实例句炳
HINSTANCE hPrevInstance, // 指向前一个运行的应用程序实例的句柄。永远为NULL
LPSTR lpCmdLine, // LP:长指针类型。LPWSTR:一个指向字符串的长指针。lpCmdLine是命令行的参数command line
int nCmdShow // 窗口显示时的状态,来决定你的应用程序是最小化还是最大化,还是关闭窗口
);
//WinMain函数是操作系统调用的,里面的参数都是操作系统自动给的。
3、设计一个窗口类
typedef struct _WNDCLASS {
UINT style; //窗口类样式
WNDPROC lpfnWndProc; //用来接收一个函数指针。当窗口产生一个消息,需要一个回调函数来处理这个消息,这个处理消息的函数就是用lpfnWndProc来指定
int cbClsExtra; //窗口类附加内存字节数,通常为0
int cbWndExtra; //窗口附加内存字节数,通常为0
HANDLE hInstance; //应用程序实例句柄
HICON hIcon; //标题栏图标
HCURSOR hCursor; //光标
HBRUSH hbrBackground; //画刷的句柄,可以设置窗口背景颜色
LPCTSTR lpszMenuName; //long pointer const string,设置菜单资源名称
LPCTSTR lpszClassName; //设置窗口类名称
} WNDCLASS;
4、注册窗口类
用RegisterClass();
ATOM RegisterClass(
CONST WNDCLASS *lpWndClass //class data
)
//typedef WORD ATOM;
//typedef unsigned short WORD;
//所以说ATOM应该是无符号短整型
例如,上面我们实例化一个类对象 WNDCLASS wndclass;
设置好各种参数后,再RegisterClass(&wndclass);
就行了。
5、创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, // 已注册的窗口类名称
LPCTSTR lpWindowName, // 窗口的名字
DWORD dwStyle, // 窗口样式
int x, // 窗口的水平坐标
int y, // 垂直坐标
int nWidth, // 宽度
int nHeight, // 高度
HWND hWndParent, // 父窗口句柄
HMENU hMenu, // 菜单句柄
HINSTANCE hInstance, // 应用程序实例句柄
LPVOID lpParam // long point void,没有类型的指针,用于多文档程序的附加参数,单文档为NULL
);
6、显示及更新窗口
BOOL ShowWindow(
HWND hWnd,
int nCmdShow //show state 可以设置最大化显示,最小化显示
);
然后要调用UpdateWindow(hwnd);
刷新窗口
7、消息循环与发送消息
MSG msg;
while (GetMessage(&msg,NULL,0,0)) //从消息队列获取消息并在消息队列删除该消息(除WM_PAINT)
{ //第二个参数设置为NULL是为了捕获任何窗口消息,如果设置为hwnd,则只会接收来自该窗口的消息
TranslateMessage(&msg); //消息解释
DispatchMessage(&msg); //将消息发送到“窗口过程”
}
GetMessage函数体如下:
BOOL GetMessage(
LPMSG lpMsg, // 消息结构体指针,返回消息信息
HWND hWnd, // 窗口句柄 ,通常设为NULL
UINT wMsgFilterMin, // 消息过滤最小值
UINT wMsgFilterMax // 消息过滤最大值,如果都设置为0,函数将获取所有范围的消息。即取所有消息队列
);
GetMessage函数只有在接收到WM_QUIT消息时,才返回0。-1,获取消息失败。其他,获取成功。
消息队列为空时,GetMessage会一直等待。
8、窗口过程与响应消息
LRESULT CALLBACK MyWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
//LRESULT:从窗口程序或者回调函数返回的32位值
{
switch (uMsg)
{
case WM_PAINT: //WndProc处理的第二个消息为WM_PAINT。当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时,将由这个消息通知程序
//如,有两个窗口:A和B,B在A的上面,并遮住了A的一部分,那么A的被遮住的这部分就叫做A的无效区域,这种情况是由于有个实际存在的窗口遮住产生了无效区域
//但有的时候没有实际窗口,但为了重绘就手动使某区域无效,也就是InvalidiRect(),这便是“使窗口无效”的概念
case WM_KEYDOWN: //按键消息
case WM_LBUTTONDOWN: //该消息当用户在window客户区域点击鼠标左键的时候发送
…
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
//将不感兴趣的、不需要我们处理的消息,交还给Windows操作系统为我们处理
}
return 0;
}
9、MessageBox
显示一个消息对话框,消息框返回一个整数值,该值指示用户单击了哪个按钮
int WINAPI MessageBox(
HWND hWnd,
LPCSTR lpText, //指向消息消息框内容
LPCSTR lpCaption, //指向消息框标题
UINT uType); //指定一个决定对话框的内容和行为的位标志集,此参数可以为下列标志组中标志的组合。指定下列标志中的一个来显示消息框中的按钮以及图标
按钮:
图标:
形态:
其他:
10、win32 application实例
#include<stdio.h>
#include<windows.h>
//------------------------------------------------------------
LRESULT CALLBACK MyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);//回调函数声明
//------------------------------------------------------------
int WINAPI WinMain(
HINSTANCE hInstance, // 当前应用程序实例句柄
HINSTANCE hPrevInstance, // 永远为NULL
LPSTR lpCmdLine, // 命令行参数
int nCmdShow) // 窗口显示时的状态
{
//MessageBox(NULL,lpCmdLine,"命令行参数",0);//MessageBox 弹出窗口展示消息
WNDCLASS MyWnd;
MyWnd.style=CS_HREDRAW|CS_VREDRAW;
//CS_HREDRAW:当窗口水平方向的宽度变化时重绘整个窗口。CS_VREDRAW:当窗口垂直方向的宽度变化时重绘整个窗口
MyWnd.cbClsExtra=NULL;
MyWnd.cbWndExtra=NULL;
MyWnd.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//返回系统常用画刷,黑色画刷
MyWnd.hCursor=LoadCursor(NULL,IDC_CROSS);//十字光标
MyWnd.hIcon=LoadIcon(NULL,IDI_QUESTION);//加载问号图标
MyWnd.hInstance=hInstance;
MyWnd.lpfnWndProc=MyWndProc;
MyWnd.lpszClassName="Hello";
MyWnd.lpszMenuName=NULL;
//对设计好的窗口类进行注册
RegisterClass(&MyWnd);
//创建窗口
HWND hWnd;
hWnd=CreateWindow("Hello","Window编程",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
//WS_OVERLAPPEDWINDOW:创建一个拥有各种窗口风格的窗体,包括标题,系统菜单,边框,最小化和最大化按钮等
//CW_USEDEFAULT:设置窗口大小,位置为默认值
//显示及其更新窗口
ShowWindow(hWnd,SW_SHOW);//显示,SW_HIDE为隐藏
UpdateWindow(hWnd);
//消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))//从消息队列中获取消息
{
TranslateMessage(&msg);//消息解释
DispatchMessage(&msg);//将消息发送到“窗口过程”
}
return 0;
}//winmain结束
//回调函数
LRESULT CALLBACK MyWndProc(
HWND hwnd,//handle to window
UINT uMsg,//message identifier
WPARAM wParam,//first message parameter
LPARAM lParam)//second message parameter
{
switch(uMsg)
{
case WM_CHAR:
char name[20];
sprintf(name,"Char is %d",wParam);
MessageBox(hwnd,name,"weixin2013",0);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"Mouse Click","weixin2013",0);
HDC hdc;//设备描述表句柄
hdc = GetDC(hwnd);//获取一个设备描述表
TextOut(hdc,0,50,"计算机编程语言学习",strlen("计算机编程语言学习"));
//0,50是x,y坐标,即设定要显示的文本在窗口中的位置
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT: //窗口初始化、最小化、最大化、移动窗口、改变窗口尺寸、某些API函数、窗口无效等等
HDC hDC;
PAINTSTRUCT ps; //PAINTSTRUCT:结构体,包含了用于绘制窗口客户区的信息
hDC = BeginPaint(hwnd,&ps);//获取一个设备描述表,重绘窗口
TextOut(hDC,0,0,"计算机编程",strlen("计算机编程"));
EndPaint(hwnd,&ps);//将窗口状态重置为有效;删除消息队列中的WM_PAINT消息
break;
case WM_CLOSE:
if(IDYES == MessageBox(hwnd,"是否要关闭?","weixin2013",MB_YESNO))
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_RBUTTONDOWN:
SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)"hello!");//改变窗口标题名称
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}