#define UNICODE #define _UNICODE #include <windows.h> #include <tchar.h> const TCHAR CLSNAME[] = TEXT("helloworldWClass"); LRESULT CALLBACK winproc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp); int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PTSTR cmdline, int cmdshow) { WNDCLASSEX wc = { }; MSG msg; HWND hwnd; wc.cbSize = sizeof (wc); wc.style = 0; wc.lpfnWndProc = winproc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName= CLSNAME; wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION); if (!RegisterClassEx(&wc)) { MessageBox(NULL, TEXT("Could not register window class"), NULL, MB_ICONERROR); return 0; } hwnd = CreateWindowEx(WS_EX_LEFT, CLSNAME, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL); if (!hwnd) { MessageBox(NULL, TEXT("Could not create window"), NULL, MB_ICONERROR); return 0; } ShowWindow(hwnd, cmdshow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK winproc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) { return DefWindowProc(hwnd, wm, wp, lp); }
看到的第一件事是两个宏定义UNICODE和_UNICODE。这些宏使我们的程序理解宽字符串(wchar_t[n]),而不是普通的窄字符串(char[n])。结果,所有字符串文字必须包装在TEXT(宏中。Win32字符串的通用字符类型为TCHAR,其定义取决于是否UNICODE定义。包含一个新的标头:<tchar.h>包含的声明TCHAR。
窗口由所谓的窗口类组成。这描述了有关在窗口实例之间共享的窗口信息,例如图标,光标和其他。窗口类由窗口类名称标识,该名称CLSNAME在此示例中的全局变量中给出。的第一步WinMain是填写窗口类结构WNDCLASSEX wc。成员是:
cbSize:结构的大小(以字节为单位)
style:窗口类的样式。现在是0。
lpfnWndProc:这是更重要的字段之一。它存储窗口过程的地址。窗口过程是处理作为该窗口类实例的所有窗口的事件的函数。
cbClsExtra:为窗口类分配的额外字节数。在大多数情况下,该成员为0。
cbWndExtra:为每个单独的窗口分配的额外字节数。不要将此与混淆cbClsExtra,这在所有实例中都是常见的。通常为0。
hInstance:实例句柄。只需将hInst参数分配WinMain给该字段即可。
hIcon:窗口类的图标句柄。LoadIcon(NULL, IDI_APPLICATION)加载默认的应用程序图标。
hCursor:窗口类的光标句柄。LoadCursor(NULL, IDC_ARROW)加载默认光标。
hbrBackground:背景画笔的句柄。GetStockObject (WHITE_BRUSH)给白色画笔一个句柄。由于必须GetStockObject返回通用对象,因此必须强制转换返回值。
lpszMenuName:要使用的菜单栏的资源名称。如果不需要菜单栏,则此字段可以为NULL。
lpszClassName:标识此窗口类结构的类名称。在此示例中,CLSNAME全局变量存储窗口类名称。
hIconSm:小类图标的句柄。
初始化此结构后,将RegisterClassEx调用该函数。这将导致窗口类在Windows中注册,从而使应用程序知道该窗口类。失败时返回0。
现在已经注册了窗口类,我们可以使用显示窗口CreateWindowEx。参数为:
stylesex:扩展的窗口样式。缺省值为WS_EX_LEFT。
clsname:类名
cap:窗口标题或标题。在这种情况下,标题会显示在窗口的标题栏中。
样式:窗口样式。如果要创建像这样的顶级(父)窗口,则要传入的标志是WS_OVERLAPPEDWINDOW。
x:窗口左上角的x坐标。
y:窗口左上角的y坐标
cx:窗口的宽度
cy:窗口的高度
hwndParent:父窗口的句柄。由于此窗口本身是父窗口,因此此参数为NULL。
hMenuOrID:如果正在创建的窗口是父窗口,则此参数是窗口菜单的句柄。请勿将其与类菜单混淆WNDCLASSEX::lpszClassName。类菜单对于具有相同类名称的所有Windows实例都是通用的。但是,此参数仅适用于此实例。如果正在创建的窗口是子窗口,则这是子窗口的ID。在这种情况下,我们将创建一个没有菜单的父窗口,因此将传递NULL。
hInst:应用程序实例的句柄。
等:传递给窗口的窗口过程的额外信息。如果没有其他信息要传输,则传递NULL。
如果xory或cxorcy为CW_USEDEFAULT,则该参数的值将由Windows确定。这就是本例中所做的。
CreateWindowEx将句柄返回到新创建的窗口。如果窗口创建失败,则返回NULL。
然后,我们通过调用显示窗口ShowWindow。该函数的第一个参数是窗口的句柄。第二个参数是显示样式,它指示如何显示窗口。大多数应用程序只是传递传入的cmdshow参数WinMain。显示该窗口后,必须通过调用来更新它UpdateWindow。它导致将更新消息发送到窗口。我们将在另一个教程中了解这意味着什么。
现在是应用程序的核心:消息泵。它抽取操作系统发送给该应用程序的消息,并将消息分派到窗口过程。的GetMessage,直到应用程序receieves导致它退出一个消息,在这种情况下返回0的是涉及的是指向一个的唯一参数调用返回非零MSG,将在与有关邮件的信息被填充结构。其他参数均为0。
在消息循环内,TranslateMessage将虚拟键消息转换为字符消息。同样,这对我们来说并不重要。它需要一个指向MSG结构的指针。直接在其后面的调用DispatchMessage将其参数所指向的消息调度到窗口的窗口过程。最后WinMain要做的就是返回状态码。结构的wParam成员MSG包含此返回值,因此将其返回。
但这仅用于WinMain功能。另一个功能是winproc窗口程序。它将处理Windows发送给该窗口的消息。的签名winproc是:
hwnd:正在处理其消息的窗口的句柄。
wm:窗口消息标识符
wp:消息信息参数之一。这取决于wm论点
lp:消息信息参数之一。这取决于wm论点。此参数通常用于传输指针或句柄
在这个简单的程序中,我们自己不会处理任何消息。但这并不意味着Windows也不会。这就是为什么必须调用的原因DefWindowProc,其中包含默认的窗口处理代码。必须在每个窗口过程的末尾调用此函数。
甲手柄是代表一个唯一的对象的数据类型。它们是指针,但指向操作系统维护的秘密数据结构。这些结构的细节与我们无关。用户所需要做的就是简单地使用API调用创建/获取句柄,并将其传递给采用该句柄类型的其他API调用。我们使用的唯一句柄类型是的HWND返回CreateWindowEx。
在此示例中,我们遇到了几个常量,它们全部用大写字母开头,并以2或3个字母开头。(Windows类型也全部大写)
IDI_APPLICATION:包含默认应用程序图标的资源名称。与LoadIcon或LoadImage(在此示例中为LoadIcon)一起使用。
IDC_ARROW:包含默认应用程序游标的资源名称。与LoadIcon或LoadImage(在此示例中为LoadIcon)一起使用。
WHITE_BRUSH:股票对象的名称。该备用对象是白色画笔。
MB_ICONERROR:用于MessageBox显示错误图标的标志。
WS_EX_LEFT:默认的扩展窗口样式。这将导致窗口具有左对齐的属性。
WS_OVERLAPPEDWINDOW:一种窗口样式,指示该窗口应该是具有标题栏,大小框和其他顶级窗口典型元素的父窗口。
CW_USEDEFAULT:使用CreateWindowEx的x,y,cx,或cy争论。使WindowsCW_USEDEFAULT为传递的参数选择有效值。
当为Windows编程时,您将不得不习惯Win32类型,它们是内置类型的别名。这些类型大写。该程序中使用的别名类型为:
TCHAR:通用字符类型。如果UNICODE已定义,则为wchar_t。另外,它是一个char。
UINT:无符号整数。用于表示窗口过程和其他目的中的消息标识符。
WPARAM:在Win16中,这是一个WORD参数(因此带有W前缀)。但是,随着Win32的引入,它现在是一个UINT_PTR。这说明了这些Windows别名的要点。他们在那里是为了保护程序免受更改。
LPARAM:这是一个LONG参数(LONG_PTR在Win64中)。
PTSTR:P均值指针。该T指一般的性格和STR手段字符串。因此,这是指向TCHAR字符串的指针。其他字符串类型包括:
LPTSTR:与 PTSTR
LPCTSTR:均值 const TCHAR *
PCTSTR:与 LPCTSTR
LPWSTR:宽字符串(wchar_t *)
LPCWSTR:均值 const wchar_t *
PWSTR:与 LPWSTR
以及更多正如您所看到的,Win32类型可能很难理解,尤其是对于这么多同义类型,这是Win16的产物。
LRESULT:此类型用于表示窗口过程的返回值。通常是LONG(因此L)。