Windows程序设计--创建第一个窗口

本篇文章讲如何创建一个基本的窗口。

MessageBox弹出来的消息框就是一个窗口,但是窗口是怎样创建的呢?其实很简单,只要几个固定的步骤就行。而只要我们的窗口创建出来之后,只要把需要的函数填进去就能得到一个有功能的窗口。所以我觉得学习Windows就是学习API函数而已,懂得如何调用,各个参数的意思就行。说到参数,其类型都是从C语言的基本数据类型演变而来的,并不难。

现在开始创建第一个窗口,该窗口并无功能,只是一个空的框架。

代码如下:

 #include <windows.h>

//声明窗口过程函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("MyClass") ;
     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, // 窗口类名
                          TEXT ("MyWin"), // 窗口标题 
                                             WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,//窗口风格
                          CW_USEDEFAULT,  // 窗口的x坐标,相对于屏幕左上角
                          CW_USEDEFAULT,  // 窗口的x坐标,相对于屏幕左上角
                          CW_USEDEFAULT,  // 窗口宽度(像素为单位)
                          CW_USEDEFAULT,  // 窗口高度(像素为单位)
                          NULL,          // 父窗口句柄
                          NULL,          // 窗口菜单
                          hInstance,    // 程序实例句柄
                          NULL) ;      // (请看注释1)

     //在屏幕上显示窗口
     ShowWindow (hwnd, iCmdShow) ;
     //指示窗口自我更新。
     UpdateWindow (hwnd) ;

            //从消息队列中取得消息
     while (GetMessage (&msg, NULL, 0, 0))
     {
         //转译某些键盘消息。
          TranslateMessage (&msg) ;
          //将消息发送给系统,系统再将消息发送给窗口过程处理消息。
          DispatchMessage (&msg) ;
     }
    // msg.wParam 来自一条表示退出的消息,返回这个值给系统,从而退出。
     return msg.wParam ;
}
//窗口过程函数 //窗口句柄 //窗口消息 //第一个额外附加消息 //第二个额外附加消息
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;//设备环境
     PAINTSTRUCT ps ;//绘画结构
     //通常定义为静态变量是为了在不断的调用这个函数时该值不会改变
     static int cxClient,cyClient;//客户区宽和高

     //筛选消息,如果没有需要关注的消息,则有系统自动处理
     switch (message)
     {
         //窗口创建消息,创建窗口时会有此消息
         //注:创建窗口之前还会有很多消息进来,可以自己在
         //switc中加断点调试看看有哪些消息进来
     case WM_CREATE:

          return 0;
          //当客户区改变的时候,也就是发生大小变化
          //就会传进来这个消息,然后两个参数会被改变
     case WM_SIZE:
           cxClient=LOWORD(lParam);
           cyClient=HIWORD(lParam);

           return 0;
          //垂直滚动条信息
           //记得在窗口风格中添加这两个风格
     case WM_VSCROLL:

         return 0 ;
          //水平滚动条信息
     case WM_HSCROLL:

           return 0;
          //重绘窗口消息
           //每当窗口改变大小或者移动时都会发送重绘
     case WM_PAINT:
          //开始绘制窗口。
          hdc = BeginPaint (hwnd, &ps) ;
          //获取设备环境的方法不只这一种

          //结束绘制窗口。
          EndPaint (hwnd, &ps) ;
          return 0 ;         
     case WM_DESTROY:
          //在消息队列中插入一个「退出程序」消息
         //该消息是WM_QUIT
          PostQuitMessage (0) ;
          return 0 ;
     }
            //除了需要关注的消息,其它消息都经由系统自动处理。
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

总结一下创建窗口的步骤:
1.创建并初始化窗口类
看过很多好文章,里面都会把创建窗口类比作一个品牌汽车的模板
2.注册窗口类
然后去为这个品牌注册登记
3.创建窗口
再然后用这个模板来创建同样品牌不同样式的汽车
4.显示、更新窗口
造好车后就要拿出去展示,并时不时的更新车辆信息
5.从消息循环队列中获取消息
把车卖出去后(显示窗口),会有客户把用户体验或者车辆问题反馈回来(消息),这肯定是需要排队的(队列),如果很紧急也可以插队。然后公司就会获取他们反馈的信息(系统),然后叫各种部门处理(窗口过程).
如此循环就是窗口了

HWND hwnd;//窗口句柄

UINT message;//一个无符号整形消息

WPARAM wParam;//16位(双字节(在16位系统的时间))的消息参数。
//值的款式和意思取决于重要的事件消息类型。
//注:在我的VS2008编译器中定义是64位的。

LPARAM lParam;//32位(长整型)的消息参数。这个参数的值和意思取决于主事件消息类型。
//注:在我的VS2008编译器中定义是64位的。

其在头文件中的定义如下:
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;

typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;

typedef _W64 long LONG_PTR, *PLONG_PTR;

DefWindowProc:(解释转自百科)

函数功能:该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口
消息提供缺省的处理。该函数确保每一个消息得到处理。
调用DefWindowProc函数时使用窗口过程接收的相同参数。

函数原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
  参数:
  hWnd:指向接收消息的窗口过程的句柄。
  Msg:指定消息类型。
  wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
  IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
  返回值:返回值就是消息处理结果,它与发送的消息有关。

现在窗口已经创建好了,骨架搭好了就剩下五脏六腑了,只要一步步完善这个骨架,最后就能写出一个界面程序了。
这里不详细解释每个结构体的参数是什么意思,因为没用到说了也白说,用了再去了解它,这样学习负担就不会很大。
看了这个那么长的代码也只是创建出一个空白的窗口,心里可能会有些失望,感觉好像很难,这是刚开始学习Windows程序设计都会遇到的坎坷。但是以后你写多了这个框架,你就会对里面各个参数有一点的理解,并且不之不觉中闭着眼睛都能写出这100多行代码。正所谓,都没有会走怎么可能会跑?所以还是慢慢走吧,总有一天会跑得飞起。

注释1:
lpParam:
指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。

你可能感兴趣的:(windows,api,函数,C语言,设计)