#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WinSunProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASS wndcls;
wndcls.cbClsExtra=0;
wndcls.cbWndExtra=0;
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
wndcls.hInstance=hInstance;
wndcls.lpfnWndProc=WinSunProc;//回调函数,自己编写,用于处理消息
wndcls.lpszClassName="Weixin2003";//窗口类的名字
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls);
HWND hwnd;
hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,
0,0,600,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinSunProc(
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 szChar[20];
sprintf(szChar,"char is %d",wParam);
MessageBox(hwnd,szChar,"weixin",0);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse clicked","weixin",0);
HDC hdc;
hdc=GetDC(hwnd);
TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训"));
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT:
HDC hDC;
PAINTSTRUCT ps;
hDC=BeginPaint(hwnd,&ps);
TextOut(hDC,0,0,"维新培训",strlen("维新培训"));
EndPaint(hwnd,&ps);
break;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
以下是程序解读
typedef struct tagMSG
{
HWND hwnd; //窗口句柄(句柄HANDLE:资源标识)
UINT message; //UNIT:unsinged int;消息以整型的方式表示
//实际中,用大量的宏(WM:window message)来表示,方便记忆
//例如:WM_LBUTTONDOWN表示鼠标左键按下,为一个十六进制数
WPARAM wPaream; //整数,消息的附加信息,例如:WM_CHAR 表示按下一个字母,其附加信息中的WPARAM为该字母的ASCII
LPARAM lParam; //整数,消息的附加信息
DWORD time; //WORD:十六位整数,D:double,即32位,表示消息的传递时间
POINT pt; //POINT:结构体,点的坐标,表示当消息被投递的时候光标的位置
}MSG, *PMSG;
//WinMain函数,Windows程序入口函数
int WINAPI WinMain(
HINSTANCE hInstance, //当前实例句柄,(实例:当前运行的程序)
HINSTANCE HPreInstance,//先前实例句柄,一般为NULL,不需要
LPSTR lpCmdLine, //命令行参数,LP:long pointer,STR :string
int nCmdShow //显示状态:最大/小化,隐藏
);
//WinMain 函数在程序启动是由操作系统调用,参数也是由操作系统进行赋值
//窗口的创建步骤
//1.设计窗口类;2.注册窗口类;3.创建窗口;4.显示及更新窗口
//1.设计窗口类,对窗口类的各个成员变量进行赋值
typedef struct _WNDCLASS
{
UINT style; //窗口类的类型,也是大量的宏定义,以 CS_ 开头
//例如:wndcls.style=CS_HREDRAW | CS_VREDRAW
//代表当窗口的水平坐标或垂直坐标发生变化时,窗口要发生重画
WNDPROC lpfnWndProc; //指定该类型窗口的过程函数,也称回调函数。
//当应用程序接受到消息时, 需调用某一函数来处理该消息
//这个调用函数的过程由操作系统完成,
//但是对消息进行处理的函数的代码要由我们编写
//所需要调用的函数就是由lpfnWndProc成员指定的
int cbClsExtra; //类附加内存,一般为0
int cbWndExtra; //窗口附加内存,一般为0
HANDLE hInsatance; //实例句柄
HICON hIcon; //图标句柄, 用LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName)进行赋值
//当采用由微软提供的标准图标(如:IDI_ERROR)时,hInstance 为NULL
HCURSOR hCursor; //光标句柄,用LoadCursor(HINSTANCE hInstance,LPCTSTR lpCursorName)进行赋值
//当采用由微软提供的标准光标(如:IDC_ARROW)时,hInstance 为NULL
HBRUSH hbrBackground; //画刷句柄,用GetStockObject(int fnObject),其返回值为画刷、笔等的句柄(HGDIOBJ)
//但是和HBRUSH不同,所以要加上强制类型转换,
LPCTSTR lpszMenuName; //32位指针,指向常量字符串(CT:const),用于设定菜单的名字,没有为NULL
LPCTSTR lpszClassName; //窗口类的实例的名字
}WNDCLASS; //窗口类的名字
//2.注册窗口类
//使用RegisterClass(CONST WNDCLASS *lpWndClass)
//其中lpWndClass为要被注册的窗口类的指针
RegisterClass(&wndclass);
//其中,wndclass为WNDCLASS结构体变量,就是已经定义好的窗口类
//3.创建窗口
HWND hwnd; //窗口句柄,保存新创建的窗口标识
//创建窗口的函数定义如下:
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类的实例的名字,在设计窗口类时已经指定,即lpszClassName
//Attention:必须一样,否则不会产生窗口,只会运行程序
//因为该名字的窗口类并没有定义
LPCTSTR lpWindowName, //窗口的名字,位于窗口左上角
DWORD dwStyle, //窗口的类型,(用WS_...表示)注意区别于类的类型
int x, //窗口的水平坐标,一般为CW_USEDEFAULT
int y, //窗口的垂直坐标,左上角为坐标原点,向右为x轴,向下为y轴
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND HWndParent, //父窗口的句柄,没有为NULL
HMENU hMenu, //菜单的句柄,没有为NULL
HINSTANCE hInstance, //当前实例的句柄
LPVOID lpParam //指针,暂时用不上,设为NULL
);
//4.显示窗口
BOOL ShowWindow( //指定窗口的显示状态
HWND hWnd, //句柄,要显示的窗口的句柄
int nCmdShow //显示状态,如SW_SHOWMAXIMIZED,最大化显示
);
//5.更新窗口
UpdateWindow(hwnd); //可有可无
//6.消息循环
MSG msg
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//函数说明:
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd, //获取消息的窗口,为NULL时,获取所有窗口的消息
UINT wMsgFilterMin, //消息的最小值,为0时,返回所有的消息
UINT wMsgFilterMax //消息的最大值,为0时,返回所有的消息
);
//返回值:如果没有收到WM_QUIT,返回值非零,否则为零
TranslateMessage() //转换消息
DispatchMessage() //将消息传给回调函数
//至此窗口创建的过程基本完成,还缺一个函数,要由我们自己来编写,即回调函数
LRESULT CALLBACK WindoWProc( //CALLBACK会在后面进行介绍
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
//以上为窗口过程函数的定义和基本格式,函数的名字可以更改
int MessageBox(
HWND hWnd,
LPCTSTR lpText, //消息显示的文本
LPCTSTR lpCaption,//标题
UINT uType //消息框的类型,如:MB_YESNO,为宏定义
);
//返回值为:IDOK,IDNO,IDYES,IDRETRY等等
HDC :句柄
//DC:Device Context 设备上下文或设别描述表或设备环境,一种数据结构
//作用:用于应用程序和物理设备之间进行交互,从而提供了应用程序设计的平台无关性
//访问:只能由各种相关的API函数通过HDC访问该结构,如GetDC(hwnd)和ReleaseDC(hwnd,hDC)要搭配使用
BOOL TextOut(
HDC hDC,
int nXStart, //输出文本的开始坐标
int nYStart,
LPCTSTR lpString, //输出的文本内容
int cbString //文本字符数
);
WM_PAINT:窗口重绘;
BeginPaint()和EndPaint()搭配使用,且只能用于相应WM_PAINT的消息响应
HDC BeginPaint(
HWND hwnd, //窗口句柄
LPPAINTSTRUCT lpPaint//结构体指针,由PAINTSTRUCT定义
);
BOOL DestroyWindow( //调用函数时会发送WM_DESTROY消息,并销毁窗口,但是它并不负责退出程序,即终止while循环
HWND hwnd
);
VOID PostQuitMessage(int nExitCode)
//会发送WM_QUIT消息到消息队列,于是GetMessage得到WM_QUIT
//退出while循环的过程分析:
//1).通过GetMessage得到WM_CLOSE,不是WM_QUIT,返回值非零,循环继续,由DispatchMessage传递给回调函数
//2).选择IDYES——>DestroyWindow,同时发送WM_DESTROY到消息队列中
//3).再次经过步骤1),回到函数收到WM_DESTROY,发送WM_QUIT到消息队列
//4).此时GetMessage收到WM_QUIT,返回值为零,while循环结束,退出WinMain。
消息缺省处理:Default
//DefWindowProc(hwnd,uMsg,wParam,lParam) ,参数与回调函数的参数一致。
对回调函数中 CALLBACK 的解释:
//#define CALLBACK __stdcall 标准调用约定
对于上面的理解,还有两个问题
Question1:窗口的名字和窗口类的名字辨析??
Question2:hWnd 和 hInstanced 有什么区别???
在另外两篇文章中有解释。