//注意messagebox函数窗口名字必须使用TEXT函数包含
//句柄:返回标识资源的标志号
//常见句柄:窗口句柄(HWND) 图标句柄(HICON),光标句柄(HCURSOR),画刷句柄(HBRUSH)
//CS 窗口类别 CW建立窗口 DT 绘制文字 IDI图示ID IDC 游标ID MB 消息框 SND 声音 WM 窗口消息 WS窗口样式
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance,//应用程序的实例句柄
HINSTANCE hPrevInstance, //该应用程序前一个实例的句柄
PSTR szCmdLine, //命令行参数串
int iCmdShow) //程序在初始化时如何显示窗口
{ static TCHAR szAppName[] = TEXT("HelloWin"); //定义字符串
WNDCLASS wndclass; //定义一个wndclass窗口类对象
wndclass.style = CS_HREDRAW| CS_VREDRAW; //指定窗口类型样式
/*CS_HREDRAW 为宽度变化 CS_VREDRAW 为高度变化 CS_NOCLOSE 禁用系统菜单的close命令 CS_DBLCLKS 向窗口发送鼠标双击消息 我们想要去掉该变量具有的某个样式,那么可以先对该样式标识符进行取反(~)操作, 然后再和这个变量进行与(&)操作即可实现。例如,要去掉先前的style 变量所具有的 CS_VREDRAW 样式,可以编写代码:style=style & ~ CS_VREDRAW。 */
wndclass.lpfnWndProc = WndProc; //指向窗口过程函数 //lpfnWndProc为一个函数指针,指向窗口函数本例
wndclass.cbClsExtra = 0; //类变量占用的存储空间 wndclass.cbWndExtra = 0; //实例变量占用的存储空间 //默认设置为0
wndclass.hInstance = hInstance; //包含窗口过程的程序的实例句柄 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //指定窗口类光标句柄
/*1.可以加载windows系统提供的标准图标,也可以加载用户自己制作的图标,并返回系统分配的句柄。 2.如果加载系统图标,那么第一参数设置为NULL,第二参数为图标资源 3.设定资源为ID,其中IDM_为菜单资源, IDI_为图标资源 IDB_为按钮资源 */
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //指定窗口类图标句柄,调用方法同上
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); //指定窗口类画刷句柄
/*1.HBRUSH为类型转换 2.WHITE_BRUSH为白色画刷,也有BLACK_BRUSH为黑色画刷 */
wndclass.lpszMenuName = NULL; //指定菜单资源名字
wndclass.lpszClassName = szAppName; //指定窗口类名字
//注册窗口 // 该函数只有一个参数,即上一步骤中所设计的窗口类对象的指针。
//如果函数成功,返回值是唯一标识已注册的类的一个原子;如果函数失败,返回值为0
if (!RegisterClass(&wndclass)){ MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);//可省略 return 0; }
//如果窗口创建成功,CreateWindow 函数将返回系统为该窗口分配的句柄,否则,返回NULL。
//注意,在创建窗口之前应先定义一个窗口句柄变量来接收创建窗口之后返回的句柄值
HWND hwnd; //定义句柄变量
hwnd = CreateWindow //创建窗口
(szAppName, //类名,指定该窗口所属的类
TEXT("The Hello Program"), //窗口的名字
WS_OVERLAPPEDWINDOW, //窗口的风格
CW_USEDEFAULT, //窗口左上角相对于屏幕左上角的初始x坐标
CW_USEDEFAULT, //Y
CW_USEDEFAULT, //窗口的宽度
CW_USEDEFAULT, //窗口的高度
NULL, //一个子窗口的父窗口的句柄
NULL, //菜单句柄
hInstance, //创建窗口对象的应用程序的实例句柄
NULL); //创建窗口指定的额外参数
ShowWindow(hwnd, iCmdShow);//显示窗口
/*调用函数ShowWindow 来显示窗口,该函数的原型声明如下所示: BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow // show state); ShowWindow 函数有两个参数,第一个参数hWnd 就是在上一步骤中成功创建窗口后返回的那个窗口句柄; 第二个参数nCmdShow 指定了窗口显示的状态,常用的有以下几种。 n SW_HIDE:隐藏窗口并激活其他窗口。 n SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。 n SW_SHOWMAXIMIZED:激活窗口并将其最大化显示。 n SW_SHOWMINIMIZED:激活窗口并将其最小化显示。 n SW_SHOWNORMAL:激活并显示窗口。如果窗口是最小化或最大化的状态,系统将其恢复到原来的尺寸和大小。 应用程序在第一次显示窗口的时候应该指定此标志 */
UpdateWindow(hwnd);//更新窗口
MSG msg;//定义消息结构体变量
//GetMessage函数只有接收到WM_QUIT消息时,返回0,才会退出
while (GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
//TranslateMessage将虚拟键消息转换为字符消息,字符消息被投递到调用线程的消息队列中
DispatchMessage(&msg);
//DispathMessage函数实际上将消息回传到操作系统,由操作系统调用函数过程函数对消息进行处理 }
/* 在创建窗口、显示窗口、更新窗口后,我们需要编写一个消息循环,不断地从消息队列中取出消息, 并进行响应。要从消息队列中取出消息,我们需要调用GetMessage()函数,
该函数的原型声明如下:
BOOL GetMessage(
LPMSG lpMsg, // address of structure with message
HWND hWnd, // handle of window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message);
参数 lpMsg 指向一个消息(MSG)结构体,GetMessage 从线程的消息队列中取出的消息信息将保存在该结构体对象中。 参数 hWnd 指定接收属于哪一个窗口的消息。通常我们将其设置为NULL,用于接收属于调用线程的所有窗口的窗口消息。 参数 wMsgFilterMin 指定要获取的消息的最小值,通常设置为0。 参数 wMsgFilterMax 指定要获取的消息的最大值。如果wMsgFilterMin 和wMsgFilterMax 都设置为0,则接收所有消息。 */
return msg.wParam;
//PostQuitMessage函数的参数值(见代码,通常是0)将作为WM_QUIT 消息的wParam 参数(见注释⑦),
//此时参数wParam为0。收到WM_QUIT 消息消息循环自然终止,然后程序执行下面的语句:
//return msg.wParam; 即返回0值正常退出WinMain并终止程序。
}
LRESULT CALLBACK WndProc
(HWND hwnd, //窗口句柄 UINT
message, //消息代码
WPARAM wParam, //消息代码的两个附加参数
LPARAM lParam){
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message){
case WM_CREATE://创建过程
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("Hello, Windows 98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE://关闭状态
if (IDYES == MessageBox(hwnd, TEXT("是否真的结束?"), TEXT("message"), MB_YESNO))
{ DestroyWindow(hwnd); }
/*1.int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT UType); hwnd表示拥有的窗口,第二个为显示消息内容,第三个为对话框标题,第四个位按钮类型 IDABORT:Abort 按钮被选中。IDCANCEL:Cancel按钮被选中。IDIGNORE:Ignore按钮被选中。 IDNO:NO按钮被选中。IDOK:OK按钮被选中。IDRETRY:RETRY按钮被选中。 IDYES:YES按钮被选中。 */
return 0;
case WM_DESTROY://销毁
PostQuitMessage(0);
return 0; }
return DefWindowProc(hwnd, message, wParam, lParam);
}
/*进队消息与不进队消息(了解): 进队消息和不进队消息 其实在Windows中消息能够被分为“进队的”和“不进队的”。进队的的消息是由Windows放入程序消息队列中的 在程序的消息循环中,重新返回并分配给窗口过程。不进队的的消息在Windows调用窗口时直接送给窗口过程。 也就是说,进队的消息被“发送”给消息队列,而不进队的的消息则直接“发送”给窗口过程。任何情况下, 窗口过程都将获得窗口所有的消息--包括进队的和不进队的。窗口过程是窗口的“消息中心”。 进队消息基本上是用户输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、 鼠标移动(WM_MOUSEMOVE)和鼠标键(WM_LBUTTONDOWN)的形式给出。进队消息还包含时钟消息(WM_TIMER)、 刷新消息(WM_PAINT)和退出消息(WM_QUIT)。不进队消息则是其它消息。在许多情况下,不进队消息来自 调用特定的Windows函数。例如,当WinMain调用CreateWindow时,Windows将创建窗口并在处理中给窗口过程 发送一个WM_CREATE消息。当WinMain调用ShowWindow时,Windows将给窗口过程发送WM_SIZE和WM_SHOWWINDOW消息。 当WinMain调用UpdateWindow时,Windows将给窗口过程发送WM_PAINT消息。键盘或鼠标输入时发出的进队消息信号 ,也能在不进队消息中出现。例如,用键盘或鼠标选择了一个菜单项时,键盘或鼠标消息就是进队的,而说明菜单 项已选中的WM_COMMAND消息则可能就是不进队的 */