#include<Windows.h> LRESULT CALLBACK WndProc //处理发送到窗口的消息的应用程序定义的函数。wndproc类型定义指向此回调函数的指针。 //WindowProc是应用程序定义函数名的占位符。 //参考:https://msdn.microsoft.com/en-us/library/ms633573(v=VS.85).aspx ( HWND, //hwnd 窗口的句柄 UINT, //uMsg 消息。 有关系统提供的消息的列表,请参阅系统定义的消息。 WPARAM, //wParam 其余消息信息。 此参数的内容取决于uMsg参数的值。 LPARAM //lParam 其余消息信息。 此参数的内容取决于uMsg参数的值。 ); int WINAPI WinMain//用户提供的基于Windows的图形应用程序的入口点。 //WinMain是用于应用程序入口点的常规名称。 有关更多信息,请参阅备注。 //参考:https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-winmain ( HINSTANCE hInstance, //应用程序当前实例的句柄。 HINSTANCE hPrevInstance, //上一个应用程序实例的句柄。 //此参数始终为NULL。 //若是须要检测是否已存在其余实例,请使用CreateMutex函数建立惟一命名的互斥锁。 //即便互斥锁已经存在,CreateMutex也会成功,但该函数将返回ERROR_ALREADY_EXISTS。 //这表示您的应用程序的另外一个实例存在,由于它首先建立了互斥锁。 //可是,恶意用户能够在执行此操做以前建立此互斥锁,并阻止您的应用程序启动。 //要防止出现这种状况,请建立一个随机命名的互斥锁并存储该名称,以便只能由受权用户获取。 //或者,您可使用文件来实现此目的。 //要将应用程序限制为每一个用户一个实例,请在用户的配置文件目录中建立一个锁定文件。 PSTR szCmdLine, //应用程序的命令行,不包括程序名称。 要检索整个命令行,请使用GetCommandLine函数。 int iCmdshow //TBD ) { static TCHAR szAppName[] = TEXT("MyWindows"); HWND hwnd; MSG msg; WNDCLASS wndclass;//包含RegisterClass函数注册的窗口类属性。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagwndclassa wndclass.style = CS_HREDRAW| CS_VREDRAW;//调整窗口高度或宽度则重绘。 //参考:https://docs.microsoft.com/zh-cn/windows/desktop/winmsg/window-class-styles wndclass.lpfnWndProc = WndProc;//指向窗口过程的指针。 wndclass.cbClsExtra = 0;//在窗口类结构以后分配的额外字节数。 系统将字节初始化为零。 wndclass.cbWndExtra = 0;//窗口实例后要分配的额外字节数。 系统将字节初始化为零。 //若是应用程序使用WNDCLASS注册在资源文件中使用CLASS指令建立的对话框,则必须将此成员设置为DLGWINDOWEXTRA。 wndclass.hInstance = hInstance;//包含该类的窗口过程的实例的句柄。 wndclass.hIcon = //类图标的句柄。 该成员必须是图标资源的句柄。 //若是此成员为NULL,则系统提供默认图标。 LoadIcon(NULL, IDI_APPLICATION);//从与应用程序实例关联的可执行(.exe)文件加载指定的图标资源。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-loadicona wndclass.hCursor = //类游标的句柄。 该成员必须是游标资源的句柄。 //若是此成员为NULL,则只要鼠标移动到应用程序窗口,应用程序就必须显式设置光标形状。 LoadCursor(NULL, IDC_ARROW);//从与应用程序实例关联的可执行文件(.EXE)加载指定的游标资源。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-loadcursora wndclass.hbrBackground = //类背景画笔的句柄。 //该成员能够是用于绘制背景的物理画笔的句柄,也能够是颜色值。 (HBRUSH)GetStockObject(WHITE_BRUSH);//getstockobject函数检索库存笔、画笔、字体或调色板之一的句柄。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-getstockobject wndclass.lpszMenuName = NULL;//类菜单的资源名称,名称显示在资源文件中。 //若是使用整数来标识菜单,请使用MAKEINTRESOURCE宏。 //若是此成员为NULL,则属于此类的窗口没有默认菜单。 wndclass.lpszClassName = szAppName; //指向以null结尾的字符串或是atom的指针。 if (!RegisterClass(&wndclass))//注册一个窗口类,以便在调用CreateWindow或CreateWindowEx函数时使用。 { MessageBox(NULL, TEXT("This program needs to be executed on Windows NT."), szAppName, MB_OK| MB_ICONERROR); //显示模式对话框,其中包含系统图标,一组按钮和简要的特定于应用程序的消息,例如状态或错误信息。 //消息框返回一个整数值,指示用户单击的按钮。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-messagebox return 0; } else { hwnd = CreateWindow//建立重叠、弹出或子窗口。它指定窗口类、窗口标题、窗口样式和(可选)窗口的初始位置和大小。 //该函数还指定窗口的父级或全部者(若是有)以及窗口的菜单。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowa ( szAppName,//由之前调用RegisterClass或RegisterClassEx函数建立的以null结尾的字符串或类原子。 //原子必须在lpClassName的低位字中; 高阶词必须为零。 //若是lpClassName是字符串,则它指定窗口类名称。 //类名能够是使用RegisterClass或RegisterClassEx注册的任何名称,前提是注册该类的模块也是建立窗口的模块。 //类名也能够是任何预约义的系统类名。 有关系统类名称的列表,请参阅“备注”部分。 TEXT("My Window"), //窗口名称。 若是窗口样式指定标题栏,则lpWindowName指向的窗口标题将显示在标题栏中。 //使用CreateWindow建立控件(如按钮,复选框和静态控件)时,请使用lpWindowName指定控件的文本。 //使用SS_ICON样式建立静态控件时,请使用lpWindowName指定图标名称或标识符。 要指定标识符,请使用语法“#num”。 WS_OVERLAPPEDWINDOW,//正在建立窗口的样式。此参数能够是窗口样式值的组合,以及“备注”部分中指示的控件样式。 //参考:https://docs.microsoft.com/zh-cn/windows/desktop/winmsg/window-styles CW_USEDEFAULT,//窗口的初始水平位置。 //对于重叠或弹出窗口,x参数是窗口左上角的初始x坐标,以屏幕坐标表示。 //对于子窗口,x是窗口左上角相对于父窗口客户区左上角的x坐标。 //若是此参数设置为CW_USEDEFAULT,则系统选择窗口左上角的默认位置并忽略y参数。 //CW_USEDEFAULT仅对重叠窗口有效; 若是为弹出窗口或子窗口指定,则x和y参数设置为零。 CW_USEDEFAULT,//窗口的初始垂直位置。 //对于重叠或弹出窗口,y参数是窗口左上角的初始y坐标,以屏幕坐标表示。 //对于子窗口,y是子窗口左上角相对于父窗口客户区左上角的初始y坐标。 //对于列表框,y是列表框客户区左上角相对于父窗口客户区左上角的初始y坐标。 //若是使用WS_VISIBLE样式位设置建立重叠窗口而且x参数设置为CW_USEDEFAULT,则y参数肯定窗口的显示方式。 //若是y参数是CW_USEDEFAULT,则窗口管理器在建立窗口后使用SW_SHOW标志调用ShowWindow。 //若是y参数是某个其余值,则窗口管理器使用该值调用ShowWindow做为nCmdShow参数。 CW_USEDEFAULT,//窗口的宽度(以设备为单位)。 //对于重叠窗口,nWidth是窗口宽度,屏幕坐标或CW_USEDEFAULT。 //若是nWidth是CW_USEDEFAULT,则系统选择窗口的默认宽度和高度; //默认宽度从屏幕的初始x坐标延伸到右边缘,默认高度从初始y坐标延伸到图标区域的顶部。 //CW_USEDEFAULT仅对重叠窗口有效; 若是为弹出窗口或子窗口指定了CW_USEDEFAULT,则nWidth和nHeight设置为零。 CW_USEDEFAULT,//窗口的高度,以设备为单位。 //对于重叠窗口,nHeight是窗口坐标中窗口的高度。 //若是nWidth设置为CW_USEDEFAULT,则系统忽略nHeight。 NULL,//正在建立的窗口的父窗口或全部者窗口的句柄。要建立子窗口或拥有的窗口,请提供有效的窗口句柄。此参数对于弹出窗口是可选的。 //要建立仅消息窗口,请向现有仅消息窗口提供hwnd_消息或句柄。 NULL,//菜单的句柄,或根据窗口样式指定子窗口标识符。 //对于重叠窗口或弹出窗口,hmenu标识要与窗口一块儿使用的菜单;若是要使用类菜单,则能够为空。 //对于子窗口,hmenu指定子窗口标识符,该标识符是对话框控件用来通知其父窗口有关事件的整数值。 //应用程序肯定子窗口标识符;对于具备相同父窗口的全部子窗口,该标识符必须是惟一的。 hInstance,//与窗口关联的模块实例的句柄。 NULL//指向要经过createStruct结构(lpcreateParams成员)传递到窗口的值的指针,该结构由wm_create消息的lparam参数指向。 //此消息在返回以前由函数发送到建立的窗口。 //若是应用程序调用CreateWindow来建立MDI客户机窗口,lpparam应指向ClientCreateStruct结构。 //若是MDI客户机窗口调用CreateWindow来建立MDI子窗口,lpParam应该指向MDICreatestruct结构。若是不须要其余数据,lpparam可能为空。 ); ShowWindow(hwnd, iCmdshow);//设置指定窗口的显示状态。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-showwindow UpdateWindow(hwnd);//updateWindow函数经过向窗口发送wm_paint消息(若是窗口的更新区域不为空)来更新指定窗口的客户机区域。 //该函数将wm_paint消息直接发送到指定窗口的窗口过程,绕过应用程序队列。若是更新区域为空,则不发送消息。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-updatewindow while (GetMessage//从调用线程的消息队列中检索消息。该函数将发送传入的已发送消息,直到能够检索已发布的消息。 //与getmessage不一样,peekmessage函数不等待消息在返回以前发布。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage ( &msg, //指向从线程的消息队列接收消息信息的MSG结构的指针。 NULL, //要检索其消息的窗口的句柄。 //窗口必须属于当前线程。 //若是hwnd为空,getmessage将检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd值为空的任何消息(请参见msg结构)。 //所以,若是hwnd为空,则同时处理窗口消息和线程消息。 //若是hwnd为 - 1,则getmessage仅检索当前线程的消息队列中hwnd值为空的消息, //也就是说,由postmessage(当hwnd参数为空时)或postmthreadmessage发布的线程消息。 0, //要检索的最低消息值的整数值。 //使用wm_keyfirst(0x0100)指定第一个键盘消息,或使用wm_mouse first(0x0200)指定第一个鼠标消息。 //在这里和wmsgfiltermax中使用wm_input仅指定wm_输入消息。 //若是wmsgfiltermin和wmsgfiltermax都为零,则getmessage返回全部可用消息(即,不执行范围筛选)。 0//要检索的最高消息值的整数值。 //使用wm_keylast指定最后一条键盘消息,或使用wm_mouselast指定最后一条鼠标消息。 //在这里和wmsgfiltermin中使用wm_input仅指定wm_输入消息。 //若是wmsgfiltermin和wmsgfiltermax都为零,则getmessage返回全部可用消息(即,不执行范围筛选)。 )) { TranslateMessage(&msg);//将虚拟密钥消息转换为字符消息。 //字符消息被发送到调用线程的消息队列,以便下次线程调用getmessage或peekmessage函数时读取。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-translatemessage DispatchMessage(&msg);//将虚拟密钥消息转换为字符消息。 //字符消息被发送到调用线程的消息队列,以便下次线程调用getmessage或peekmessage函数时读取。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-dispatchmessage } return msg.wParam;//有关该消息的其余信息。 确切含义取决于消息成员的值。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmsg } } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps);//beginpaint函数准备用于绘制的指定窗口,并用有关绘制的信息填充paintstruct结构。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-beginpaint GetClientRect(hwnd, &rect);//检索富编辑控件的客户端矩形。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/tom/nf-tom-itextdocument2-getclientrect DrawText//drawtext函数在指定的矩形中绘制格式化文本。 //它根据指定的方法格式化文本(展开选项卡、调整字符、换行等)。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-drawtext ( hdc, //设备上下文的句柄 TEXT("Hello, this is my first window project."), //指向要指定要绘制的文本的字符串的指针。 //若是nCount参数为 - 1,则字符串必须以空值终止。 //若是uFormat包含DT_MODIFYSTRING,则该函数最多能够为该字符串添加四个附加字符。 //包含字符串的缓冲区应足够大以容纳这些额外字符。 -1, //字符串的长度(以字符为单位)。 //若是nCount为-1,则假定lpchText参数是指向以null结尾的字符串的指针,DrawText会自动计算字符计数。 &rect, //指向rect结构的指针,该结构包含要格式化文本的矩形(以逻辑坐标表示)。 DT_SINGLELINE| DT_CENTER| DT_VCENTER //格式化文本的方法。单行、水平中心、竖直中心。 ); EndPaint(hwnd, &ps);//EndPaint函数标记指定窗口中绘制的结束。 //每次调用BeginPaint函数都须要此函数,但仅在绘制完成后才须要此函数。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-endpaint return 0; case WM_DESTROY: PostQuitMessage(0);//向系统指示线程已请求终止(退出)。它一般用于响应wm_销毁消息。 return 0; } return DefWindowProc(hwnd, message, wParam, lParam); //调用默认窗口过程为应用程序不处理的任何窗口消息提供默认处理。 //此功能可确保处理每条消息。 //使用窗口过程接收的相同参数调用DefWindowProc。 //参考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-defwindowproca }