Win32程序的入口为WinMain`函数,是由操作系统调用的。和main()函数不同,WinMain有严格的原型定义,不能改变。其原型如下:

 

  1. int WINAPI WinMain( 
  2. INSTANCE    hInstance,      //当前实例句柄 
  3. HINSTANCE   hPrevInstance,      //前一个实例句柄 
  4. LPSTR       lpCmdLine,      //命令行参数 
  5. int         nCmdShow        //窗口显示方式,如SW_ SHOWNORMAL等 
  6. ); 

这里我们看到了一些不认识的大写字符,在此后的学习中,我们还会大量遇到这种情况。稍后我们会专门讲解。
Windows编程和DOS编程最大的不同之一就在于DOS是字符界面的,而Windows是图形界面的,因此Win32编程第一个重要的工作就是创建窗口。
创建一个Win32程序的典型步骤如下:
注册窗口类:RegisterClass()。定义窗口类,以指明窗口的外观和窗口回调函数等
创建窗口:CreateWindow()。创建一个窗口实例
显示窗口:ShowWindow()。显示刚刚创建的窗口
更新窗口:UpdateWindow()。更新窗口
消息循环:while (GetMessage(&msg, NULL, 0, 0))。进行消息循环,不断的处理消息。
实现回调函数:由系统调用,程序员负责代码实现,告诉系统如何响应消息。

创建一个简单的Win32应用程序MyWin
打开VS6.0,选择File菜单的New,在出现的对话框中,选择Projects栏目(新建工程),并点取其下的Win32 Application项,表示使用Win32环境创建应用程序。先在Locatin(路径)中选择要保存项目文件的路径,然后在Project Name(项目名称)中填入"MyWin",其它按照缺省设置)。单击OK按钮。代码如下:

 

  1. #include <windows.h> 
  2. #include <stdio.h> 
  3.  
  4. //声明窗口回调函数 
  5. LRESULT CALLBACK WinProc( 
  6.     HWND hwnd,      // 窗口句柄 
  7.     UINT uMsg,      // 消息ID 
  8.     WPARAM wParam,  // 第1个消息参数 
  9.     LPARAM lParam   // 第2个消息参数 
  10. ); 
  11.  
  12. //程序入口 
  13. int WINAPI WinMain( 
  14.   HINSTANCE hInstance,      // 当前实例句柄 
  15.   HINSTANCE hPrevInstance,  // 前一实例句柄 
  16.   LPSTR lpCmdLine,          // 命令行参数 
  17.   int nCmdShow              // 窗口显示方式 
  18.     //1. 注册窗口 
  19.     WNDCLASS wndcls;    //定义并填充窗口类 
  20.     wndcls.cbClsExtra = 0; 
  21.     wndcls.cbWndExtra = 0; 
  22.     wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
  23.     wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); 
  24.     wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
  25.     wndcls.hInstance = hInstance; 
  26.     wndcls.lpfnWndProc = WinProc;   //重点:指定回调函数 
  27.     wndcls.lpszClassName = "Itjob2010"
  28.     wndcls.lpszMenuName = NULL; 
  29.     wndcls.style = CS_HREDRAW | CS_VREDRAW; 
  30.     RegisterClass(&wndcls);     //注册窗口 
  31.  
  32.     //2. 创建窗口 
  33.     HWND hwnd; 
  34.     hwnd = CreateWindow( 
  35.         wndcls.lpszClassName,   //窗口类名称 
  36.         "一个简单的Win32程序"//窗口标题 
  37.         WS_OVERLAPPEDWINDOW,    //窗口风格,定义为普通型 
  38.         0,                      //窗口位置的x坐标 
  39.         0,                      //窗口位置的y坐标 
  40.         600,                    //窗口的宽度 
  41.         400,                    //窗口的高度 
  42.         NULL,                   //父窗口句柄 
  43.         NULL,                   //菜单句柄 
  44.         hInstance,              //应用程序实例句柄 
  45.         NULL);                  //窗口创建数据指针 
  46.  
  47.     //3. 显示窗口 
  48.     ShowWindow(hwnd, SW_SHOWNORMAL); 
  49.  
  50.     //4. 更新窗口 
  51.     UpdateWindow(hwnd); 
  52.  
  53.     //5. 消息循环 
  54.     MSG msg; 
  55.     while (GetMessage(&msg, NULL, 0, 0)) 
  56.     { 
  57.         TranslateMessage(&msg);     //把虚键消息翻译成字符消息(WM_CHAR), 
  58.                                     //再把它放回到应用程序的消息队列中去 
  59.         DispatchMessage(&msg);      //指示操作系统把这条消息发送到窗口 
  60.                                     //过程WinProc进行处理 
  61.     } 
  62.     return 0; 
  63.  
  64. //窗口回调函数,由操作系统调用,程序员 
  65. //不要调用,但程序员需要编写其实现代码 
  66. LRESULT CALLBACK WinProc( 
  67.     HWND hwnd,      // 窗口句柄 
  68.     UINT uMsg,      // 消息ID 
  69.     WPARAM wParam,  // 第1个消息参数 
  70.     LPARAM lParam   // 第2个消息参数 
  71.     switch (uMsg) 
  72.     { 
  73.     case WM_CHAR: 
  74.         sprintf(szChar, "你按下了%c键", (char)wParam); 
  75.         MessageBox(hwnd, szChar, "WM_CHAR", 0); 
  76.         break
  77.     case WM_LBUTTONDOWN: 
  78.         HDC hdc; 
  79.         hdc = GetDC(hwnd); 
  80.         TextOut(hdc, 0, 50, "计算机编程语言培训", strlen("计算机编程语言培训")); 
  81.         ReleaseDC(hwnd, hdc); 
  82.         break
  83.     case WM_PAINT: 
  84.         HDC hDC; 
  85.         PAINTSTRUCT ps; 
  86.         hDC = BeginPaint(hwnd, &ps); 
  87.         TextOut(hDC, 0, 0, "Hello, World!", strlen("Hello, World!")); 
  88.         EndPaint(hwnd, &ps); 
  89.         break
  90.     case WM_DESTROY: 
  91.         PostQuitMessage(0); 
  92.         break
  93.     default
  94.         return DefWindowProc(hwnd, uMsg, wParam, lParam); 
  95.     } 
  96.     return 0; 


编译,运行该程序。运行结果为出现一个简单的Windows窗口。在窗口空白区点击鼠标左键,会在屏幕上出现:计算机编程语言培训;按下a键,会提示:你按下了a键!
这是一个最简单的Win32应用程序,其他较复杂的Windows应用程序都是在这样的程序框架上扩展得到的。

下面对上述程序进行解释说明。
WinMain()函数
WinMain()函数是应用程序开始执行时的入口点,通常也是应用程序结束任务退出时的出口点。它与DOS程序的main()函数起同样的作用,有一点不同的是,WinMain()函数必须带有四个参数,它们是系统传递给它的。WinMain()函数的原型如下:

 

  1. int WINAPI WinMain( 
  2. INSTANCE    hInstance,      //当前实例句柄 
  3. HINSTANCE   hPrevInstance,      //前一个实例句柄 
  4. LPSTR       lpCmdLine,      //命令行参数 
  5. int         nCmdShow        //窗口显示方式,如SW_ SHOWNORMAL等 
  6. ); 

参数说明如下:
hInstance:是标识该应用程序当前的实例的句柄。它是HINSTANCE类型,HINSTANCE是Handle of Instance的缩写,表示实例的句柄。hInstance是一个很关键的数据,它唯一的代表该应用程序,在后面初始化程序主窗口的过程中需要用到这个 参数。这里有两个概念,一个是实例,一个是句柄。实例代表的是应用程序执行的整个过程和方法,一个应用程序如果没有被执行,只是存在于磁盘上,那么就说它是没有被实例化的;只要一执行,则说该程序的一个实例在运行。句柄,顾名思义,指的是一个对象的把柄。在Windows中,有各种各样的句柄,它们都是32位的指针变量,用来指向该对象所占据的内存区。句柄的使用,可以极大的方便Windows管理其内存中的各种对象。
hPrevInstance:它是用来标识该应用程序的前一个实例句柄。对于基于Win32的应用程序来说,这个参数总是NULL。这是因为在Win95操作系统中, 应用程序的每个实例都有各自独立的地址空间,即使同一个应用程序被执行了两次,在内存中也会为它们的每一个实例分配新的内存空间,所以一个应用程序被执行后,不会有前一个实例存在的可能。也就是说,hPrevInstance这个参数是完全没有必要的,只是为了提供与16位Windows的应用程序形式上 的兼容性,才保留了这个参数。在以前的16位Windows环境下(如Windows3.2),hPrevInstance用来标识与hInstance 相关的应用程序的前一个句柄。
lpCmdLine:是指向应用程序命令行参数字符串的指针。如在"开始"菜单中单击"运行",输入"WinMain.exe hello",则此参数指向的字符串为"hello"。
nCmdShow:是一个用来指定窗口显示方式的整数。这个整数值可以是SW_SHOW、SW_HIDE、SW_SHOWMAXIMIZED、SW_SHOWMINIMIZED等

注册窗口类
注册窗口类主要是对一个窗口类结构WNDCLASS的实例进行填充,然后调用RegisterClass()进行注册。每个窗口都有一些基本的属性,如窗口边框、窗口标题文字、窗口大小和位置、鼠标、背景色、处理窗口消息的回调函数的名称等等。注册的过程也就是将这些属性告诉系统,然后再调用CreateWindow()函数创建出窗口。

 

  1. typedef struct _WNDCLASS { 
  2. UINT style; //窗口风格,通常取值CS_HREDRAW|CS_VREDRAW 
  3. WNDPROC lpfnWndProc; //指定处理窗口消息的回调函数的远指针 
  4. int cbClsExtra; //指定分配给窗口类结构之后的额外字节数,0 
  5. int cbWndExtra; //指定分配给窗口实例之后的额外字节数,0 
  6. HANDLE hInstance; //指定窗口过程所对应的实例句柄 
  7. HICON hIcon; //指定窗口的图标,LoadIcon 
  8. HCURSOR hCursor; //指定窗口的鼠标,LoadCursor 
  9. HBRUSH hbrBackground; //指定窗口的背景画刷,CreateSolidBrush 
  10. LPCTSTR lpszMenuName; //窗口的菜单资源名称 
  11. LPCTSTR lpszClassName; //该窗口类的名称 
  12. } WNDCLASS; 

在这里提一下匈牙利表示法:其中的lpfn字首代表“指向函数的长指针”。cb字首代表“字节数”而且通常作为一个常数来表示一个字节的大小。h字首是一个句柄,而hbr字首代表“一个画刷的句柄”。lpsz字首代表“指向以0结尾字符串的指针”。
参数含义如下:
style:一般取值CS_VREDRAW|CS_HREDRAW,表示当窗口的水平方向或垂直方向的大小改变之后,窗口要全部重画。style窗口类型定义如下:

 

  1. #define     CS_VREDRAW          0x0001 
  2. #define     CS_HREDRAW              0x0002 
  3. #define     CS_KEYCVTWINDOW     0x0004 
  4. #define     CS_DBLCLKS              0x0008 
  5. #define     CS_OWNDC                0x0020 
  6.