1、创建属于自己的窗口=创建窗口前的准备在创建窗口前我们先来熟悉几个名词, 这些名词现在可以暂时不去透彻的进行理解, 只需要印象中知道有这么回事就行。1. 窗口“窗口“这个我们都已经十分熟悉了, 在 Windows 中, 一个应用程序窗口上一般会在标题栏上显示程序的名称, 紧挨着标题栏的菜单栏, 或许还会有状态栏、滚动条等其他“装饰品“。2. 控件 在一些应用程序中, 我们经常可以在程序的界面上(窗口)看到一些按钮(Push Button)、文本框(Text Box)、列表框(List Box)、滚动条(Scroll Bar)等, 这些对象通常被称为控件, 在Windows程序设计一书中, 还被称
2、为“子窗口“、“控件窗口“或“子窗口控件“。3. 窗口类在建立一个窗口前, 我们必须首先注册一个“窗口类“(Windows Class), 接触过面向对象的朋友应该会首先想到面向对象当中的“类“, 但是, 这里“窗口类“中的“类“并不是指面向对象当中的那个“类“。在这里我们可以把“窗口类“理解为一个结构体, 结构体的成员就是窗口的一些属性, 例如窗口的标题是什么、窗口使用什么样的小图标以及窗口的风格之类的属性, 一个窗口就是一个结构体的对象, 结构体成员的属性决定着窗口的属性。4. 消息循环在 Windows 程序设计中, 消息循环是个不得不提的概念,Windows 操作系统是以消息驱动的,
3、消息队列是指在一个应用程序运行时, Windows 操作系统会为该应用程序建立一个“消息队列“,这个消息队列用来存放该程序可能创建的各种窗口的消息, 当用户对应用程序进行操作时, 例如点击一个按钮、调整下窗口的大小等,此时 Windows 会立即把这一消息告诉应用程序, 使应用程序能作出相应的动作。笔者觉得有比较强调一下上一段中的最后一句“此时 Windows 会立即把这一消息告诉应用程序, 使应用程序能作出相应的动作。“,我们在创建一个应用程序时, 不用想着什么时候才能从用户那得到指令, 因为操作系统会即时告诉我们用户此时是否对程序进行了操作, 对于没有接触过 Windows 编程的朋友们这
4、点可能有点难以理解,简单来说就是像如何获取一个按钮是否被单击, 或者如何获取用户此时是否在调整窗口大小之类的代码 Windows 已经帮我们完成了,我们只需要等待着 Windows 给我们发消息就行, 如何判断消息类型以及处理这些消息, 在代码上通常我们用 while 配合一个巨大的switch 来完成,。5. 窗口的过程函数当一个窗口建立之后, 就可以从 Windows 那里不断的接收到Windows 发来的消息, 接收到消息后我们就需要一个函数来处理这些消息, 可以简单的理解为, 这个用来处理接收到的消息的函数就称为窗口过程函数或者回调函数。下面我们来尝试着看一个创建一个基本窗口的代码。尝
5、试创建自己的窗口代码如下:#include LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; /声明用来处理消息的函数int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )static TCHAR szAppName = TEXT(“MyWindow“) ;HWND hwnd ;MSG msg ;WNDCLASS wndclass ; /声明一个窗口类对象/以下为窗口类对象 wndclass 的
6、属性wndclass.style = CS_HREDRAW | CS_VREDRAW ; /窗口样式wndclass.lpszClassName = szAppName ; /窗口类名wndclass.lpszMenuName = NULL ; /窗口菜单:无wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ; /窗口背景颜色wndclass.lpfnWndProc = WndProc ; /窗口处理函数wndclass.cbWndExtra = 0 ; /窗口实例扩展:无wndclass.cbClsExtra = 0
7、; /窗口类扩展:无wndclass.hInstance = hInstance ; /窗口实例句柄wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ; /窗口最小化图标:使用缺省图标wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; /窗口采用箭头光标if( !RegisterClass( return 0 ;hwnd = CreateWindow( /创建窗口szAppName, /窗口类名TEXT(“我的窗口“), /窗口标题WS_OVERLAPPEDWINDOW, /窗口的风格CW_U
8、SEDEFAULT, /窗口初始显示位置 x:使用缺省值CW_USEDEFAULT, /窗口初始显示位置 y:使用缺省值CW_USEDEFAULT, /窗口的宽度:使用缺省值CW_USEDEFAULT, /窗口的高度:使用缺省值NULL, /父窗口:无NULL, /子菜单:无hInstance, /该窗口应用程序的实例句柄 NULL /) ;ShowWindow( hwnd, iCmdShow ) ; /显示窗口UpdateWindow( hwnd ) ; /更新窗口while( GetMessage( /将虚拟键消息转换为字符消息DispatchMessage( /分发到回调函数(过程函数)
9、return msg.wParam ;LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )HDC hdc ; /设备环境句柄PAINTSTRUCT ps ; /绘制结构RECT rect; /矩形结构switch( message ) /处理得到的消息case WM_CREATE: /窗口创建完成时发来的消息MessageBox( hwnd, TEXT(“窗口已创建完成!“), TEXT(“我的窗口“), MB_OK | MB_ICONINFORMATION ) ;return 0;c
10、ase WM_PAINT: /处理窗口区域无效时发来的消息hdc = BeginPaint( hwnd, GetClientRect( hwnd, DrawText( hdc, TEXT( “Hello, 这是我自己的窗口!“ ), -1, EndPaint( hwnd, return 0 ;case WM_LBUTTONDOWN: /处理鼠标左键被按下的消息MessageBox( hwnd, TEXT(“鼠标左键被按下。“), TEXT(“单击“), MB_OK | MB_ICONINFORMATION ) ;return 0;case WM_DESTROY: /处理窗口关闭时的消息Mess
11、ageBox( hwnd, TEXT(“关闭程序!“), TEXT(“结束“), MB_OK | MB_ICONINFORMATION ) ;PostQuitMessage( 0 ) ;return 0;return DefWindowProc( hwnd, message, wParam, lParam ) ; /DefWindowProc 处理我们自定义的消息处理函数没有处理到的消息-先简单介绍这段代码, 在主函数 WinMain 中的窗口类对象wndclass 我们定义了窗口的相关属性, 尝试注册窗口类并调用CreateWindow 创建窗口, 创建完成后用 ShowWindow 让窗口
12、显示出来, 我们还使用了个 while 用来从消息队列里获取并分发消息给程序, 我们还定义了一个过程函数 WndProc 用来处理系统发来的消息。编译运行后, 如果没有错误将首先看到一个窗口建立成功与否的对话框, 当创建窗口失败时弹出一个错误对话框并关闭程序。当窗口被创建时首先 Windows 会发给我们一条创建完成的消息“WM_CREATE“, 在我们的消息处理函数 WinProc 中有 switch-case 语句对该消息进行了处理, 就是弹出一个窗口创建完成的对话框。同样, 我们还处理了当窗口的客户区(内容部分)被改变时发来的的“WM_PAINT“消息进行了处理, 让“Hello, 这是我创建的窗口!“始终显示在窗口中心。“WM_LBUTTONDOWN“消息是当用户在客户区按下鼠标左键时发来的消息, 我们作出相应的动作为弹出一个鼠标左键被按下的对话框。当用户点击窗口的关闭按钮时, “WM_DESTROY“消息就会发来, 我们作出的动作是弹出“关闭程序!“的对话框并且退出程序。