windows 应用程序窗口的创建

 很多人都认为windows 程序设计很难,会有一种闻声丧胆的感觉,我个人认为那只不过是一种错觉,那是因为你没有深入的去了解windows 程序设计,只要你坚持了,深入了解了,你将发现windows 程序设计是很有意思的,也不是许多人所说的那般神秘,你会慢慢喜欢上她。


    要创建一个windows 应用程序并不是那么困难,一般步骤如下:

一、创建一个windows 窗口类,并初始化要创建窗口的一些信息
   设置要创建窗口的属性,定义在WNDCLASSEX结构中
   typedef struct_WNDCLASSEX
   {
       UNIT cbSize;               //WNDCLASSEX  结构的大小
       UNIT style;                //从这个窗口派生的窗口具有的风格
       WNDPROC lpfnWndProc;       //即 window procedure,窗口消息处理函数指针
       int cbClsExtra;            //指定紧跟在窗口类结构后的附加字节数
       int cbWndExtra;            //指定紧跟在窗口事例后的附加字节数
       HANDLE hInstance;          //本模块的实例句柄
       HICON hIcon;               //窗口左上角的句柄
       HCURSOR  hCursor;          //光标的句柄
       HBRUSH hbrBackground;      //背景画刷的句柄
       LPCTSTR lpszMenuName;      //菜单名
       LPCTSTR lpszClassName;     //该窗口类的名称
       HICON hIconSm;             //小图标句柄
    }WNDCLASSEX;
这一步就是根据所要创建的窗口,设置WNDCLASSEX 结构
   事例如下:
    WNDCLASSEX MyWindow;
    MyWindow.cbSize             =      sizeof(MyWindow);            //结构的大小
    MyWindow.style              =      CS_HREDRAW|CS_VREDRAW;       //指定如果窗口大小改变就重画
    MyWindow.lpfnWndProc        =      MainWndProc;                 //窗口函数指针
    MyWindow.cbClsExtra         =      0;                           //没有额外的类内存
    MyWindow.cbWndExtra         =      0;                           //没有额外的窗口内存
    MyWindow.hInstance          =      hInstance;                   //实例句柄
    MyWindow.hIcon              =      ::LoadIcon(NULL,IDI_APPLICATION);  //使用预定义的图标
    MyWindow.hCursor            =      ::LoadCursor(NULL,IDC_ARROW);      //使用预定义的光标
    MyWindow.hbrBackground      =      (HBRUSH)::GetStockObject(WHITE_BRUSH); //使用白色背景画刷
    MyWindow.lpszMenuName       =      NULL;                        //不指定菜单
    MyWindow.lpszClassName      =      szClassName;                 //窗口类的名称
    MyWindow.hIconSm            =      NULL;                        //没有类的小图标
    
   其中有一个窗口函数指针,在程序前应该先声明该窗口的消息处理函数
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
当然在程序中,还要实现消息处理函数,使其能够处理相应的消息

二、设置好要创建的窗口的属性后,就可以注册要创建的窗口了
   注册窗口类用API 函数RegisterClassEx,如果函数成功,返回值是唯一识别被注册类的一个原子;如果函数失败,返回值为0。
  函数原型:ATON RegisterClassEX(CONST WNDCLASSEX * Ipwcx);

   注册上面设置的窗口如下:
        ::RegisterClassEx(&MyWindow);

三、注册窗口后,接下来就是创建注册的窗口
   创建窗口用API 函数CreateWindowEx,创建窗口成功的话,该函数返回创建窗口的句柄,否则返回false
    函数原型:
             HWND CreateWindowEx(
                      DWORD    dwExStle,       //指定窗口的扩展风格
                      LPCTSTR  IpClassName,    //指向一个空结束的字符串或整型数atom
                      LPCTSTR  lpWindowName,   //指向一个指定窗口名的空结束的字符串指针
                      DWORD    dwStyle,        //指定创建窗口的风格
                      int      x,              //初始化X坐标
                      int      y,               //初始化Y坐标
                      int      nWidth,         //初始化窗口宽度
                      int      nHeight,        //初始化窗口高度
                      HWND     hWndParent,     //指定父窗口句柄,没有的话,为NULL
                      HMENU    hMenu,          //菜单句柄,或依据窗口风格指明一个子窗口标识
                      HANDLE   hlnstance,      //与窗口相关联的模块事例的句柄
                      LPVOID   lpParam          //指向一个值的指针,该值传递给窗口 WM_CREATE消息
                                   );

   创建上面注册的窗口类如下:
        HWND m_hWnd  =  ::CreateWindowEx(
             0,
             szClassName,
             "My first Window",
             WS_OVERLAPPEDWINDOW,
             200,
             100,
             600,
             450,
             NULL,
             NULL,
             hInstance,
             NULL);

四、创建窗口成功的话,创建的窗口还没有显示出来,这些需要调用ShowWindow函数把窗口显示出来并更新窗口
    函数原型:BOOL ShowWindow(HWND hWnd,int nCmdShow);
    函数原型:BOOL UpdateWindow(HWND hWnd);
   
    显示上面创建的窗口:
     ::ShowWindow(m_hWnd,nCmdShow);
    接下来则是更新窗口
     ::UpdateWindow(m_hWnd);

至此,一个简单的window 应用程序窗口已经呈现在你的面前了

五、接下来就是让窗口可对不同的消息才去不同的操作

    达到这个目的,即让窗口进入无限的消息循环:

      MSG msg;
      while(::GetMessage(&msg,nCmdShow))
      {
          //转化键盘消息
          ::TranslateMessage(&msg);
          //将消息发送相应的窗口函数
          ::DispatchMessage(&msg);
      }

Windows 为每个线程维护了一个消息队列,每当有一个输入发生,Windows 就把用户的输入翻译成消息放在消息队列中。利用GetMessage函数可以从调用线程的消息队列中取出一个消息来填充MSG结构。

  ::GetMessae(&msg,NULL,0,0);
如果消息队列中没有消息(既没有用户输入),这个函数会一直等待下去,直到有消息进入消息队列为止。如果从消息队列中取得消息不是WM_QUIT,则返回非零值,一个WM_QUIT消息会促使GetMessage函数返回0,从而结束消息循环。

msg是MSG结构类型的一个变量,这个结构定义了消息的所有属性。
      typedef struct tagMSG
      {
          HWND     hwnd;            //消息要发送的窗口句柄
          UINT     message;         //消息标示符,一WM_开头的预定义值(意为window  message)
          WPARAM   wParam;          //消息的参数之一
          LPARAM   lParam;          //消息的参数之二
          DWORD    time;            //消息放入消息队列的时间       
          POINT    pt;              //这是一个POINT结构,表示消息放入消息队列是的鼠标位置
       }MSG,*PMSG;


windows 应用程序简单窗口的创建实现代码

#include "stdafx.h"

// 窗口函数的消息处理函数原形声明
LRESULT  CALLBACK MainWProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
             int       nCmdShow)
{
    char szClassName[] = "MainWClass";   
    WNDCLASSEX wndclass;
   
    // 用描述主窗口的参数填充WNDCLASSEX结构
    wndclass.cbSize = sizeof(wndclass);                          // 结构的大小
    wndclass.style = CS_HREDRAW|CS_VREDRAW;                      // 指定如果大小改变就重画
    wndclass.lpfnWndProc = MainWProc;                            // 窗口函数指针
    wndclass.cbClsExtra = 0;                                     // 没有额外的类内存
    wndclass.cbWndExtra = 0;                                     // 没有额外的窗口内存
    wndclass.hInstance = hInstance;                              // 实例句柄
    wndclass.hIcon = ::LoadIcon(NULL,IDI_APPLICATION);           // 使用预定义图标
    wndclass.hCursor = ::LoadCursor(NULL,(LPSTR)IDC_ARROW);      // 使用预定义的光标
    wndclass.hbrBackground = (HBRUSH)
        ::GetStockObject(WHITE_BRUSH);                           // 使用白色背景画刷
    wndclass.lpszMenuName = NULL;                                // 不指定菜单
    wndclass.lpszClassName = szClassName ;                       // 窗口类的名称   
    wndclass.hIconSm = NULL;                                     // 没有类的小图标
   
    // 注册这个窗口类
    ::RegisterClassEx(&wndclass);
       
    // 创建主窗口
    HWND hwnd = ::CreateWindowEx(
        0,                      // dwExStyle,扩展样式   
        szClassName,            // lpClassName,类名           
        "贴心小闹钟",           // lpWindowName,标题       
        WS_OVERLAPPEDWINDOW,    // dwStyle,窗口风格   
        200,                    // X,初始 X 坐标       
        100,                    // Y,初始 Y 坐标       
        600,                    // nWidth,宽度           
        450,                    // nHeight,高度           
        NULL,                   // hWndParent,父窗口句柄           
        NULL,                   // hMenu,菜单句柄       
        hInstance,              // hlnstance,程序实例句柄       
        NULL) ;                 // lpParam,用户数据           

    if(hwnd == NULL)
    {
        ::MessageBox(NULL, "创建窗口出错!", "error", MB_OK);
        return -1;
    }

    // 显示窗口,刷新窗口客户区
    ::ShowWindow(hwnd, nCmdShow);
    ::UpdateWindow(hwnd);
   
    // 从消息堆中取出消息
    MSG msg;   
    while(::GetMessage(&msg, NULL, 0, 0))
    {
        // 转化键盘消息
        ::TranslateMessage(&msg);
        // 将消息发送到相应的窗口函数
        ::DispatchMessage(&msg);
    }

    // 当GetMessage返回0时程序结束
    return msg.wParam;
}


LRESULT CALLBACK MainWProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    char szText[] = "贴心小闹钟";
    switch (message)
    {        
    case WM_PAINT: // 窗口客户区需要重画
        {
            HDC hdc;
            PAINTSTRUCT ps;

            // 使无效的客户区变的有效,并取得设备环境句柄
            hdc = ::BeginPaint (hwnd, &ps) ;   
            // 显示文字
            ::TextOut(hdc, 250, 10, szText, strlen(szText));
            ::EndPaint(hwnd, &ps);
            return 0;
        }   
    case WM_DESTROY: // 正在销毁窗口

        // 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
        ::PostQuitMessage(0) ;
        return 0 ;
    }

    // 将我们不处理的消息交给系统做默认处理
    return ::DefWindowProc(hwnd, message, wParam, lParam);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值