1 // Learn_01_CreateWindow.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 #include < windows.h> 6 #include "resource.h" 7 8 9 //-------------------------------------------------------------------------------------- 10 // 全局变量 11 //-------------------------------------------------------------------------------------- 12 13 //HINSTANCE 是“句柄型”数据类型。相当于装入到了内存的资源的ID。 14 //HINSTANCE对应的资源是instance.句柄实际上是一个无符号长整数。 15 //但它是“句柄型”,所以你不能把它当成真的无符号长整数,拿来派别的用处,例如,不能拿来做四则运算。 16 HINSTANCE g_hInst = NULL; 17 //h是类型描述,表示句柄(handle),Wnd 是变量对象描述,表示窗口,所以hWnd 表示窗口句柄 18 HWND g_hWnd = NULL; 19 20 21 //-------------------------------------------------------------------------------------- 22 // 函数声明 23 //-------------------------------------------------------------------------------------- 24 25 //HRESULT=h+result(句柄结果)。如果这个函数是执行完返回的话将包含具有实际意义的数据, 26 //如果立即返回则包含状态信息--发送成功与否,并不能说明执行的如何。 27 HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow); 28 //LRESULT就是longresult,也就是长整型 29 //之所以取名类LRESULT, 是因为L即long 30 //result表示结果, 说明这个函数的返回值是某个结果 31 //CALLBACK,回调函数就是一个通过函数指针调用的函数 32 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 33 34 35 //-------------------------------------------------------------------------------------- 36 // 程序入口。初始化,并进入消息循环。空闲时间用来绘制场景。 37 //-------------------------------------------------------------------------------------- 38 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 39 { 40 UNREFERENCED_PARAMETER(hPrevInstance);//UNREFERENCED_PARAMETER 未引用的参数 41 UNREFERENCED_PARAMETER(lpCmdLine); 42 43 if (FAILED(InitWindow(hInstance, nCmdShow))) //FAILED失败 44 return 0; 45 46 // 消息循环 47 48 /* 49 MSG是Windows程序中的结构体, 50 在Windows程序中,消息是由MSG结构体来表示的。MSG结构体的定义如下(参见MSDN): 51 typedef struct tagMSG { 52 HWND hwnd; //表示消息所属的窗口 53 UINT message; //制定了消息的标示符,在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。 54 //但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM是Windows message的缩写)的形式 55 //XXX对应某种消息的英文拼写的大写形式。例如,鼠标左键按下的消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN 56 //字符消息是WM_CHAR,等等。在程序中我们通常都是以WM_XXX宏的形式来使用消息的。 57 WPARAM wParam; 58 LPARAM lParam; //wParam和lParam,用于指定消息的附加信息。例如,当我们收到一个字符消息的时候,message成员变量的值就是WM_CHAR 59 //但是用户到底输入的是什么字符,那么就由wParam和lParam来说明。 60 DWORD time; 61 POINT pt; //time和pt分别表示消息投递到消息队列中的时间和鼠标的当前位置 62 } MSG; 63 */ 64 MSG msg = { 0 }; 65 while (GetMessage(&msg, NULL, 0, 0)) 66 { 67 TranslateMessage(&msg); //TranslateMessage将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里 68 //当下一次线程调用函数GetMessage或PeekMessage时被读出,函数原型BOOL TranslateMessage( CONST MSG*lpMsg ); 69 DispatchMessage(&msg); //DispatchMessage表示分发一个消息给窗口程序。通常消息从GetMessage函数获得。消息被分发到回调函数(过程函数) 70 //作用是消协传递给操作系统,然后操作系统去操作我们的回调函数,也就是说我们在窗体的过程中处理消息 71 } 72 73 return (int)msg.wParam; 74 } 75 76 77 //-------------------------------------------------------------------------------------- 78 // 注册窗口类并创建窗口 79 //-------------------------------------------------------------------------------------- 80 HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) 81 { 82 /* WNDCLASSEX的原型如下: 83 typedef struct WNDCLASSEX { 84 UINT cbSize; //WNDCLASSEX的大小,我们可以用sizeof(WNDCLASSEX)来获得准确的值 85 UINT style; //从这个窗口类派生的窗口具有的风格。可以用“or”操作符来把几个风格或到一起 86 WNDPROC lpfnWndProc; //窗口处理函数的指针,lpfn前缀表示该成员是一个指向函数的长指针 87 int cbClsExtra; //指定紧跟在窗口结构后的附加字节数 88 int cbWndExtra; //指定紧跟在窗口实例的附加字节数。如果一个应用程序在资源中用CLASS伪指令注册一个对话框类是, 89 //则必须把这个成员设成DLGWINDOWEXTRA 90 HINSTANCE hInstance; //本模块的实例句柄 91 HICON hIcon; //图标的句柄 92 HCURSOR hCursor; //光标的句柄 93 HBRUSH hbrBackground; //背景画刷的句柄 94 LPCTSTR lpszMenuName; //指向菜单的指针 95 LPCTSTR lpszClassName; /指向类名的指针 96 HICON hIconSm; //和窗口类关联的小图标。如果该值为MULL。则把hlcon中的图标转换成大小合适的小图标 97 } WNDCLASSEX, *PWNDCLASSEX; 98 */ 99 // 注册窗口类 100 WNDCLASSEX wcex; 101 wcex.cbSize = sizeof(WNDCLASSEX); //sizeof,判断数据类型长度符关键字,返回值为内存所占字节数 102 wcex.style = CS_HREDRAW | CS_VREDRAW; 103 wcex.lpfnWndProc = WndProc; 104 wcex.cbClsExtra = 0; 105 wcex.cbWndExtra = 0; 106 wcex.hInstance = hInstance; 107 wcex.hIcon = LoadIcon(hInstance, nullptr); 108 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 109 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 110 wcex.lpszMenuName = NULL; 111 wcex.lpszClassName = L"TutorialWindowClass"; 112 wcex.hIconSm = LoadIcon(wcex.hInstance, nullptr); 113 if (!RegisterClassEx(&wcex)) 114 return E_FAIL; 115 116 // 创建窗口 117 g_hInst = hInstance; 118 RECT rc = { 0, 0, 640, 480 }; //RECT用于储存成对出现的参数,原型为 typedef struct _RECT {LONG left;LONG top;LONG right;LONG bottom;} RECT, *PRECT 119 120 /*AdjustWindowRect依据所需客户矩形的大小,计算需要的窗口矩形的大小,计算出的窗口矩形随后可以传递给CreateWindows函数, 121 用于创建一个客户区所需大小的窗口 122 函数原型:BOOL AdjustWindowRect(LPRECT lpRect ,DWORD dwStyle,BOOL bMENU); 123 参数说明: 124 lpRect:指向RECT结构的指针,该结构包含所需客户区域的左上角和右下角的坐标。函数返回时,该结构容纳所需客户区域的窗口的左下角和右下角的坐标 125 dwStyle:指定将被计算尺寸的窗口的窗口风格 126 bMENU:指示窗口是否有菜单 127 */ 128 AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); 129 130 /*CreateWindow 131 HWND CreateWindow( 132 LPCTSTR lpClassName, //指向一个空结束的字符串或整型数atom。如果该参数是一个整型量, 133 //它是由此前调用theGlobalAddAtom函数产生的全局量。 134 //这个小于0xC000的16位数必须是lpClassName参数字的低16位,该参数的高位必须是0。 135 //如果lpClassName是一个字符串,它指定了窗口的类名。 136 //这个类名可以是任何用函数RegisterClass注册的类名,或是任何预定义的控制类名。 137 LPCTSTR lpWindowName,//指向一个指定窗口名的空结束的字符串指针。 138 //如果窗口风格指定了标题条,由lpWindowName指向的窗口标题将显示在标题条上。 139 //当使用Createwindow函数来创建控制例如按钮,选择框和静态控制时,可使用lpWindowName来指定控制文本。 140 141 DWORD dwStyle, //窗口的风格,如WS_BORDER:创建一个带边框的窗口,WS_HSCROLL:创建一个有水平滚动条的窗口。 142 int x, //指定窗口的初始水平位置,如果该参数被设为CW_USEDEFAULT则系统为窗口选择缺省的左上角坐标并忽略Y参数 143 int y, //指定窗口的初始垂直位置 144 int nWidth, //以设备单元指明窗口的宽度 145 int nHeight,//以设备单元指明窗口的高度 146 HWND hWndParent, //指向被创建窗口的父窗口或所有者窗口的句柄 147 HMENU hMenu, //菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口, 148 //hMenu指定窗口使用的菜单:如果使用了菜单类,则hMenu可以为NULL。 149 //对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。 150 //应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。 151 HANDLE hlnstance, //与窗口相关联的模块实例的句柄。 152 LPVOID lpParam //指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。 153 //如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。 154 ); 155 //返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。 156 */ 157 g_hWnd = CreateWindow(L"TutorialWindowClass", L"Direct3D Learning 01: Create Window", WS_OVERLAPPEDWINDOW, 158 CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, 159 NULL); 160 if (!g_hWnd) 161 return E_FAIL; 162 163 ShowWindow(g_hWnd, nCmdShow); 164 165 return S_OK; 166 } 167 168 169 //-------------------------------------------------------------------------------------- 170 // 每次当应用程序接收消息时调用这个方法 171 //-------------------------------------------------------------------------------------- 172 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 173 { 174 PAINTSTRUCT ps; //PAINTSTRUCT包含了某种应用程序用来绘制它所拥有的窗口客户区所需要的信息 175 HDC hdc; 176 177 switch (message) 178 { 179 case WM_PAINT: 180 hdc = BeginPaint(hWnd, &ps); 181 EndPaint(hWnd, &ps); 182 break; 183 184 case WM_DESTROY: 185 PostQuitMessage(0); 186 break; 187 188 default: 189 return DefWindowProc(hWnd, message, wParam, lParam); 190 } 191 192 return 0; 193 }