zoukankan      html  css  js  c++  java
  • 《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制

    (金光鳞闪影若茫)

    窗口四步走:

      设计窗口类

      注册窗口类

      创建窗口

      显示更新窗口

    最后创建消息循环和响应函数

    设计窗口类:

     typedef struct {
         UINT style;//窗口类型 
         WNDPROC lpfnWndProc;//窗口处理函数
         int cbClsExtra;//窗口扩展
         int cbWndExtra;//窗口实例扩展
         HINSTANCE hInstance;//实例句柄
         HICON hIcon;//窗口的最小化图标
         HCURSOR hCursor;//窗口鼠标光标
         HBRUSH hbrBackground;//窗口背景色
         LPCTSTR lpszMenuName;//窗口菜单
         LPCTSTR lpszClassName;// 窗口类名
    } WNDCLASS, *LPWNDCLASS

    说明:

    举例:

    WNDCLASS wndclass;
      char lpszClassName[]="窗口"; //窗口类名
      char lpszTitle[]="测试窗口";  //窗口标题名
      //窗口类定义,窗口类定义了窗口的形式与功能,窗口类定义通过给窗口类数据结构WNDCLASS赋值完成
      //该数据结构中包含窗口类的各种属性
      wndclass.style =0; // 窗口类型为缺省类型CS_     Class Style
      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=lpszClassName; //窗口类名为“窗口”

    注册窗口类:

    //以下是窗口类的注册-----------Windows系统本身提供部分预定义的窗口类,程序员也可以自定义窗口类,窗口类必须先注册后使用。
    if(!RegisterClass(&wndclass)) //如果注册失败 发出警告
      {MessageBeep(0); return FALSE;}
    说明:注册内容为窗口类对象指针(服务消息处理)

     创建窗口:

    //创建窗口创建一个窗口的实例由函数CreateWindow()实现
    CreateWindow(lpszClassName, //窗口类名,创建窗口时一定要基于我们已经注册过的窗口类名,即"窗口"。
               lpszTitle, //窗口标题名
              WS_OVERLAPPEDWINDOW, //窗口的风格 WS_ Windows Style
              CW_USEDEFAULT, //窗口左上角坐标值为缺省值 CW_  Create Wndow
               CW_USEDEFAULT,
               CW_USEDEFAULT, //窗口的高和宽为缺省值
                CW_USEDEFAULT,
                 NULL, //此窗口无父窗口
                 NULL, //此窗口无子菜单
                 hInstance, //创建此窗口的应用程序的当前句柄
                 NULL //不使用该值
    );

    说明:创建方式应为 HWND hwnd = CreateWindow(...);

    hwnd值为NULL(创建失败)或者窗口句柄(创建成功)

    显示更新窗口:

    显示窗口:

    //显示窗口

    ShowWindow(hwnd,nCmdShow);

    窗口句柄以及指定显示状态

    更新窗口:

    //绘制用户区,在显示后必须需要

    UpdateWindow(hwnd);

    循环及响应:

     消息循环:

    BOOL GetMessage(
        LPMSG lpMsg,//指向 MSG 结构的指针,用于存放获取到的消息
        HWND hWnd,//当其值是 NULL 时,将获取所有的当前线程的窗口消息和线程消;当其值是 -1 时,只获取当前线程消息
        UINT wMsgFilterMin,//指定被可以被获取的消息值的最小整数(消息其实就是一个被定义的整数)
        UINT wMsgFilterMax,//指定被可以被获取的消息值的最大整数
    );

    说明:Min和Max都设置为0时接收所有消息;返回值都为非零值(除了WM_QUIT)错误返回值为-1;

       消息循环一条线程一个,是保证windows消息响应模式就基础,而非一个窗口一个;

    举例:

    //消息循环
    while(GetMessage(&Msg,NULL,0,0))  
    {
     TranslateMessage(&Msg);//对"消息对"的转化,如对键盘的WM_KEYDOWN和WM_KEYUP消息对转化为WM_CHAR消息,并且将转换后的新消息投递到我们的消息队列中去,
                   //这个转化操作不会影响原来的消息,只会产生一个新的消息。
     DispatchMessage(&Msg);//DispatchMessage()函数是将我们取出的消息传到窗口的回调函数去处理;可以理解为该函数将取出的消息路由给操作系统,然后操作系统去调用我们的窗口回调函数对这个消息进行处理。 }

    窗口过程函数:

    LRESULT CALLBACK WindowProc
    (
    HWND hwnd, // 消息句柄
    UINT uMsg, // 消息代码
    WPARAM wParam, // first message parameter
    LPARAM lParam // second message parameter
    ); 

    说明:

    函数名随意但要对应设计时的名称,一个窗口对应一个过程函数

    过程函数配合switch/case处理窗口中其他控件消息

    举例:

    long CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                          LPARAM lParam)
    {
      switch(message)
      {
        case WM_DESTROY:
          PostQuitMessage(0);
        default: //缺省时采用系统消息缺省处理函数
          return DefWindowProc(hwnd,message,wParam,lParam);
      }
      return (0);
    }

     说明:其中message 通过translatemessage()将事件转化而来

    综合:

    long CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//声明
    //WinMain函数是所有Windows应用程序的入口,类似c语言中的main函数其功能是完成//一系列的定义和初始化,并产生消息循环。函数说明:
    int WINAPI WinMain(HINSTANCE hInstance,       // handle to current instance
                                HINSTANCE hPrevInstance, // handle to previous instance
                                LPSTR lpCmdLine,              // command line
                                  int nCmdShow                     // show state
    )
    {
           //初始化,初始化包括窗口类的定义、注册、创建窗口实例和显示窗口四部分
      HWND hwnd;
      MSG Msg;
      WNDCLASS wndclass;
      char lpszClassName[]="窗口"; //窗口类名
      char lpszTitle[]="测试窗口";  //窗口标题名
      //窗口类定义,窗口类定义了窗口的形式与功能,窗口类定义通过给窗口类数据结构WNDCLASS赋值完成
      //该数据结构中包含窗口类的各种属性
      wndclass.style =0; // 窗口类型为缺省类型CS_     Class Style
      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=lpszClassName; //窗口类名为“窗口”
      //以下是窗口类的注册-----------Windows系统本身提供部分预定义的窗口类,程序员也可以自定义窗口类,窗口类必须先注册后使用。
      if(!RegisterClass(&wndclass)) //如果注册失败 发出警告
           {MessageBeep(0); return FALSE;}
      //创建窗口创建一个窗口的实例由函数CreateWindow()实现
      hwnd=CreateWindow( lpszClassName, //窗口类名,创建窗口时一定要基于我们已经注册过的窗口类名,即"窗口"。
                                         lpszTitle, //窗口标题名
                                         WS_OVERLAPPEDWINDOW, //窗口的风格 WS_ Windows Style
                                         CW_USEDEFAULT, //窗口左上角坐标值为缺省值 CW_  Create Wndow
                                         CW_USEDEFAULT,
                                         CW_USEDEFAULT, //窗口的高和宽为缺省值
                                          CW_USEDEFAULT,
                                         NULL, //此窗口无父窗口
                                         NULL, //此窗口无子菜单
                                         hInstance, //创建此窗口的应用程序的当前句柄
                                         NULL //不使用该值
      );
      //显示窗口
      ShowWindow(hwnd,nCmdShow);
      //绘制用户区
      UpdateWindow(hwnd);
      //消息循环
      while(GetMessage(&Msg,NULL,0,0))  //GetMessage()函数是从调用线程的消息队列中取出一条消息;对于每一个应用程序窗口线程,操作系统都会为其建立一个消息队列,
    当我们的窗口有消息时(即所有与这个窗口线程相关的消息),操纵系统会把这个消息放到该线程的消息队列当中,我们的窗口程序就通过这个GetMessage()函数从自己的消息队列中取出一条一条具体的消息并进行响应操作。
      {   TranslateMessage(&Msg);//对"消息对"的转化,如对键盘的WM_KEYDOWN和WM_KEYUP消息对转化为WM_CHAR消息,并且将转换后的新消息投递到我们的消息队列中去,
    这个转化操作不会影响原来的消息,只会产生一个新的消息。
      DispatchMessage(&Msg);//DispatchMessage()函数是将我们取出的消息传到窗口的回调函数去处理;可以理解为该函数将取出的消息路由给操作系统,然后操作系统去调用我们的窗口回调函数对这个消息进行处理。 }   return Msg.wParam; //消息循环结束 即程序结束时 将信息返回系统 } //窗口函数,窗口函数定义了应用程序对接收到的不同消息的响应,其中包含了应用程序对各种可能接受到的消息的处理过程,时消息处理分支控制语句的集合 long CALLBACK WndProc(HWND hwnd,    UINT message,   WPARAM wParam, LPARAM lParam) {   switch(message)   {     case WM_DESTROY:       PostQuitMessage(0);     default: //缺省时采用系统消息缺省处理函数       return DefWindowProc(hwnd,message,wParam,lParam);   }   return (0); } 注:窗口回调函数的函数指针定义typedef LRESULT CALLBACK (* WNDPROC)(HWND, UINT, WPARAM, LPARAM); WNDPROC OldWndProc; LRESULT CALLBACK NewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (Msg) { ...... } return CallWindowProc(OldWndProc,g_Wnd,Msg,wParam,lParam); } OldWndProc = (WNDPROC)GetWindowLong(g_Wnd,GWL_WNDPROC); SetWindowLong(hwnd, GWL_WNDPROC,(LPARAM)(WNDPROC)NewWndProc); 通过调用SetWindowLong函数可以修改该窗体类的回调函数。
  • 相关阅读:
    微信小程序之自定义模态弹窗(带动画)实例
    微信小程序 tab切换内容及分页
    Django实现标签联动以及xadmin中实现标签联动
    小程序跨页面数据传递与事件响应
    django admin显示多对多字段ManyToManyField
    【pycharm】Unable to save settings: Failed to save settings. Please restart PyCharm解决
    django-xadmin自定义widget插件(自定义详情页字段的显示样式)
    django 做 migrate 时 表已存在的处理
    感悟|再谈数学知识的积累
    欣赏|最新技术显示的试卷
  • 原文地址:https://www.cnblogs.com/sepmaple/p/9321732.html
Copyright © 2011-2022 走看看