Windows程序设计_学习总结(1)

很早之前就对windows程序设计的复杂性有所耳闻,总是听到同学这样描述windows编程——写一个很简单的窗口都要很长很长的代码。所以一直没有勇气去研究windows程序设计…

大二上,期末将至的时候,在图书馆里发现了《windows程序设计》这本书,而且还是全新的,挺厚的一本,我在书架前犹豫了一会后,终于下定决心把他借回去…

 

 

按照惯例,一本入门的编程书籍总是会介绍“hello world”。

 

这次让我兴奋的代码是这样的:

 

 

#include int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MessageBox (NULL, TEXT ("Hello, Windows 98!"), TEXT ("HelloMsg"), 0) ; return 0 ; }

 

和c语言相比,不过是头文件和入口函数不同罢了。

很简单的代码,不过当初我用VS2005写的时候,link的时候总是出错,后来才发现是入口函数没有调成WinMain,如果在VC6.0下,直接建立Win32 Application工程就行了。

 

看windows程序,常常会看到XX句柄,句柄无非就是一个数值,而且是可以标识某些东西的数值,就好比学号在学校里可以标识我们的身份。句柄参数名第一个字母都是”h”。

句柄的实际取值对我们来说并不重要,重要的是将句柄传递给我们所写的程序,让他们知道对哪个对象操作。而windows中有函数可以让我们很方便的获取句柄。

 

 

在windows.h中用define定义了大量的大写标识符,这些常量无需全部记住,不过记住他们的前缀我我们看懂windows程序设计十分重要。

CS            类风格选项

CW            创建窗口选项

DT            文本绘制选项

IDI           图标ID号

IDC           光标ID号

MB            消息框选项

SND           声音选项

WM            窗口消息

WS            窗口风格

变量的命名也很讲究,比如前缀i表示 int , 前缀sz表示 “以零结尾的字符串”…

 

在看windows程序时,会发现很多平常见不到的类型,有些类型不过是进行了同义转化,比如 UINT 实际上就是 unsigned int 类型,而有些类型不是,所以遇到陌生的类型,要查查帮助文档。

 

用C语言写一个窗口,代码真的很长很长,其实懂得了这些结构,看起来也不是那么的烦人。

 

创建一个窗口,首先要有窗口类,查查文档可以发现WNDCLASS有很多个字段,所以得一个一个的设置他们的属性。

接着是用RegisterClass注册窗口。注册失败返还0.

if (!RegisterClass (&wndclass)){

//错误处理代码

return 0;

}

 

注册完后用CreateWindow 创建窗口,该函数返回的是一个窗口句柄。这时窗口会在Windows内部被创建,即已经分配了一块内存来保存该窗口信息以及一些其他信息。

 

ShowWindow函数可以将该窗口显示出来。

UpdateWindow函数可以使传入句柄对应的窗口客户区重绘,而重绘是通过系统向窗口过程发送一条WM_PAINT信息完成的。

 

Windows为当前在其中运行的每一个Windows程序都维护了一个“消息队列”。当输入事件发生后,windows会自动将这些事件转换成“消息”,并将其放置在应用程序的消息队列中。

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

 

目前我看完本书的第五章,这段时间所接触到的windows程序中,以上的这些代码我都是copy的,真正让我写的就是窗口过程。

窗口过程的签名为:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,                                LPARAM lParam)

这里需要注意的是,窗口过程的函数名不一定是WndProc,但一定要和wndclass.lpfnWndProc 字段的值相同。

窗口过程几乎总是由Windows自身调用的。

 

在窗口过程中,我们可以处理很多消息,函数可以根据传入消息message的值来判断类型。常常用switch实现。消息有很多种,比如WM_CREATE WM_PAINT WM_DESTROY…

窗口过程对消息处理后应返回0。

 

如果传入的类型不在我处理范围内呢?想想我们在编码时,switch还跟一个default字段经常在一起使用,而这里使用的是DefWinProc函数来处理我们不想处理的消息,这对程序的正常运行很重要。

 

WM_PAINT消息很常见。

用记事本举个例子,当我们调整记事本的大小时,记事本中的文字会根据我们所作的调整进行重新排版。窗口过程收到了WM_PAINT ,然后进行了重绘。

在设置窗口属性时,wndclass.style = CS_HREDRAW | CS_VREDRAW ; 意思为当窗口横向或纵向发生变化时就进行重绘。

WM_PAINT消息的处理过程总是有以下代码:

hdc = BeginPaint (hwnd, &ps) ;  //hdc的类型是HDC

//重绘的代码…

EndPaint (hwnd, &ps) ;

 

上文提到的UpdateWindow就是指示窗口过程在窗口客户区进行绘制。

如果在case中有用到新的变量,应在switch外声明,我就有几次在case语句中声明变量然后出错都找不出来。

 

以下是书中的HELLOWIN.C,我常用他来做框架代码。

 

#include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } 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: return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, Windows 98!"), -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) ; }

你可能感兴趣的:(windows编程)