#include <Windows.h> #include "./resource.h" LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //回调函数是WNDCLASS窗体的消息处理函数 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstace, PSTR szCmdLine,int iCmdShow){ //主函数,入口函数.(参数1:该程序当前运行的实例的句柄 //参数2:当前实例的前一个实例的句柄,为NULL,无作用 //参数3:以空终止的字符串,指定传递给应用程序的命令行参数。 //参数4:定程序的窗口应该如何显示,最大化,最小化等 static TCHAR szAppName[] = TEXT("Hello Win"); // HWND hwnd;//句柄 MSG msg; //消息循环结构体 定义了一个消息名用以消息循环(指针) WNDCLASS wndclass;//窗口类结构,即窗口种类,只新建窗口种类才能创建一个或多个窗口 //新建窗口的信息从该结构中得到填充 wndclass.style = CS_HREDRAW | CS_VREDRAW;//窗口类的风格,有可重画等参数 wndclass.lpfnWndProc = WndProc ;//指向窗口过程函数的指针,指向回调函数 wndclass.cbClsExtra = 0; //窗口类附加数据,无扩展,无额外的字节 wndclass.cbWndExtra = 0; //窗口类附加数据 wndclass.hInstance = hInstance; //hInstance域标识应用程序的实例hInstance //即标识当前实例,可使windows连接到正确的程序 wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);//:成员hIcon被设置成应用程序所使用图标的句柄,图标是将应用程序最小化时 //出现在任务栏里的的图标,用以表示程序仍驻留在内存中 wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); // hCursor域定义该窗口产生的光标形状。LoadCursor可返回固有光标句柄或者应用程序定义的光标句柄。 //IDC_ARROW表示箭头光标. wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //wc.hbrBackground域决定Windows用于着色窗口背景的刷子颜色,函数GetStockObject返回窗口的颜色, wndclass.lpszMenuName = (LPCWSTR)IDR_MENU1; ;//在窗口类中定义菜单的字符串名 wndclass.lpszClassName = szAppName; //本窗口的类名指针 if(!RegisterClass (&wndclass)){//注册不成功 //注册窗口类 MessageBox(NULL ,TEXT("This program requires Windows NT"),TEXT("世界真大!"),MB_OK); //此处为注册窗口所提示的弹窗,MessageBox //参数1:该窗口的句柄 //参数2:消息框的内容 //参数3:消息框的标题内容 //参数4:含在消息内容中的标志集,就是按钮和图标,该句中的是OK按钮。 //图标按钮组合的话用“|”或 return 0; } hwnd = CreateWindow (szAppName, //1:登记的窗口类名,注册窗口时已定义 TEXT("欢迎你的到来!"),//2:窗口的标题 WS_OVERLAPPEDWINDOW,//3:用来表明窗口的风格,如有无最大化,最小化按纽 CW_USEDEFAULT,//4:用来表明程序运行后窗口在屏幕中的坐标值 CW_USEDEFAULT,//5:同4 CW_USEDEFAULT,//6:用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度 CW_USEDEFAULT,//7:同6 NULL, //8: 在创建窗口时可以指定其父窗口,这里没有父窗口则参数值为0。 NULL, //9:用以指明窗口的菜单 hInstance,//10:与该窗口相关联的模块实例的句柄 NULL);//11:附加数据 ShowWindow(hwnd,iCmdShow); //其第一个参数是窗口句柄,告诉ShowWindow()显示哪一个窗口,而第二个参数则告诉它如何显示这个窗口: //最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),还是最大化(SW_SHOWMAXIMIZED)。WinMain在创建完窗口后就调用ShowWindow函数, //并把iCmdShow参数传送给这个窗口。 UpdateWindow(hwnd); //把窗口显示了出来。调用函数UpdateWindow将产生一个WM_PAINT消息, //这个消息将使窗口重画,即使窗口得到更新 while(GetMessage(&msg ,NULL, 0,0)){ //取得消息 //参数1:要接收消息的MSG结构的地址 //参数2:表示窗口句柄,NULL则表示要获取该应用程序创建的所有窗口的消息 //参数3:指定消息范围 //参数4:指定消息范围 //后面三个参数被设置为默认值,这就是说你打算接收发送到属于这个应用程序的任何一个窗口的所有消息。 //在接收到除WM_QUIT之外的任何一个消息后,GetMessage()都返回TRUE。如果GetMessage收到一个WM_QUIT消息,则返回FALSE, //如收到其他消息,则返回TRUE。因此,在接收到WM_QUIT之前,带有GetMessage()的消息循环可以一直循环下去。 //只有当收到的消息是WM_QUIT时,GetMessage才返回FALSE,结束消息循环,从而终止应用程序。 均为NULL时就表示获取所有消息。 TranslateMessage(&msg); //翻译消息 //TranslateMessage()进行翻译,这个函数会转换成一些键盘消息,它检索匹配的WM_KEYDOWN和WM_KEYUP消息, //并为窗口产生相应的ASCII字符消息(WM_CHAR),它包含指定键的ANSI字符 DispatchMessage(&msg); //撤去消息 //调用DispatchMessage()要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程即WndProc回调函数来处理 //Windows会调用函数WindowsProc()来处理这个消息。在WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了一个消息循环。 } return msg.wParam;//表示从PostQuitMessage返回的值,检索WM_QUIT消息 } LRESULT CALLBACK WndProc(HWND hwnd ,UINT message,WPARAM wParam,LPARAM lParam){ //第一个为句柄,第二个为定义消息 //第三个为 第一条消息参数 //第四个为 第二条消息参数 HDC hdc; //用来存放调用 BeginPaint 返回的“设备环境”句柄 PAINTSTRUCT ps; //每个窗口要有一个PAINTSTRUCT结构来记录一些绘制信息,PAINTSTRUCT结构保存了窗口绘制客户区的一些信息, //例如,绘制客户区时是否要清除背景色,要更新的客户区的矩形区域的大小等等 //它由 Windows 传递给 BeginPaint,在结束绘制后再原封不动的传递给 EndPaint RECT rect ; //hdc ,psm,rect局部变量由处理 WM_PAINT 消息中的 GDI 函数调用 int wmpara; //第三个是提取出WM_COMMAND消息参数WPAPAM的低16位部分判断,用以判断用户选择了什么菜单 switch(message){ case WM_COMMAND: //消息循环中多了一个WM_COMMAND消息,它的作用是当用户 //点击菜单中的命令时发送这个消息 wmpara = LOWORD(wParam); //wParam参数包含32位的int型整数,低16位是窗口客户区长度,高16位是高度. //LOWORD 和 HIWORD是专门提取高低字位的宏 switch(wmpara){ case ID_EXIT: //当用户选择了文件中的退出后windows给程序发送的WM_COMMAND消 //息参数中的ID号 DestroyWindow(hwnd); return 0; case ID_DIS: //当用户选择了编辑中的显示后windows给程序发送 //的WM_COMMAND消息参数中的ID号 MessageBox(hwnd,TEXT("欢迎来到SDK"),TEXT("哈哈"),MB_OK); return 0; } case WM_PAINT: hdc = BeginPaint(hwnd ,&ps);//存放调用 BeginPaint 返回的“设备环境”句柄 //在处理 WM_PAINT 消息时,您调用BeginPaint函数,传给它一个窗口句柄和未初始化的 PAINTSTRUCT 型参数。 //调用成功后在 hDC中得到返回“设备环境”的句柄。下一次,调用 GetClientRect 以得到客户区的大小,大小放在 rect 中, //然后把它传给 DrawText GetClientRect(hwnd ,&rect); DrawText(hdc,TEXT("请使用菜单按钮!"),-1,&rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hwnd,&ps);//释放这个设备环境句柄 return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); } /* int DrawText( HDC hDC, // 设备描述表句柄 LPCTSTR lpString, // 将要绘制的字符串 int nCount, // 字符串的长度 LPRECT lpRect, // 指向矩形结构RECT的指针 UINT uFormat // 正文的绘制选项 ); DrawText是一个高层的调用函数。它能自动处理像换行、把文本放到客户区中间等这些杂事。所以您只管集中精力“绘制”字符串就可以了。我们会在下一课中讲解低一层的函数 TextOut,该函数在一个正方形区域中格式化一个文本串。它用当前选择的字体、颜色和背景色。它处理换行以适应正方形区域。它会返回以设备逻辑单位度量的文本的高度,我们这里的度量单位是像素点。让我们来看一看该函数的参数: hdc: “设备环境”的句柄。 lpString:要显示的文本串,该文本串要么以NULL结尾,要么在nCount中指出它的长短。 nCount:要输出的文本的长度。若以NULL结尾,该参数必须是-1。 lpRect: 指向要输出文本串的正方形区域的指针,该方形必须是一个裁剪区,也就是说超过该区域的字符将不能显示。 uFormat:指定如何显示。我们可以用 or 把以下标志或到一块: oDT_SINGLELINE:是否单行显示。 oDT_CENTER:是否水平居中。 oDT_VCENTER :是否垂直居中。 结束绘制后,必须调用 EndPaint 释放“设备环境”的句柄。 好了,现在我们把“绘制”文本串的要点总结如下: 1.必须在开始和结束处分别调用 BeginPaint 和 EndPaint; 2.在 BeginPaint 和 EndPaint 之间调用所有的绘制函数; 如果在其它的消息处理中重新绘制客户区,您可以有两种选择: (1)用GetDC和ReleaseDC代替BeginPaint和EndPaint; (2)调用InvalidateRect或UpdateWindow让客户区无效,这将迫使WINDOWS把WM_PAINT放入应用程序消息队列,从而使得客户区重绘。 */