`
paulfzm
  • 浏览: 870994 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

窗口破坏过程与Windows消息循环

    博客分类:
  • vc++
阅读更多

从用户单击关闭按钮(标题栏最右边)或者用鼠标或鍵盘选择系统菜单的“关闭”选项,直到窗口消失,应用程序结束。这期间到底发生了什么呢?这曾经是我百思不得其解的问题,我想也会有很多人和我一样会碰到这个问题。所以我要把我的一些学习心得写出来,与大家共享:  
  1、首先会产生一个WM_SYSCOMMAND消息,如果程序员没有对此消息进行拦截,则由缺省的窗口函数DefWindowProc进行处理,如果表达式(LOWORD(wParam)&0xFFF0)==SC_CLOSE   成立,DefWindowProc发出一个WM_CLOSE消息。  
  2、同样,如果程序员没有对WM_CLOSE消息进行拦截,则还是由DefWindowProc进行处理,这次,她只简单的调用 DestroyWindow函数,DestroyWindow先把窗口破坏掉,使用户看不到窗口。但是窗口破坏后,应用程序并没有结束,于是 DestroyWindow再接再励,送出了一个WM_DESTROY消息。  
  3、这一次,WM_DESTROY被载获了,通常是会有这样的句子:  
  case   WM_DESTROY:  
  PostQuitMessage(0);  
  ...  
  这里PostQuitMessage函数很简单的发送一个WM_QUIT消息来响应WM_DESTROY  
  4、WM_QUIT消息非常特殊,她使GetMessage函数返回0,从而结束了消息循环,  
  应用程序从此结束。  
  下面我给出完整的证明程序,请大家一试:  
  #include   <Windows.h>  
  #include   <TCHAR.h>  
  LRESULT   CALLBACK   WndProc(HWND,UINT,WPARAM,LPARAM);  
          int   WINAPI   WinMain(HINSTANCE   hInstance,  
                                        HINSTANCE   hPrevInst,  
                                        LPSTR           lpszCmdLine,  
                                        int                 nCmdShow)  
  {  
          HWND   hwnd;  
          MSG   Msg;  
          WNDCLASS   wndclass;  
          char   lpszClassName[]="窗口";  
          char   lpszTitle[]="窗口示例";  
          wndclass.style=CS_HREDRAW   |   CS_VREDRAW;  
          wndclass.lpfnWndProc   =WndProc;  
          wndclass.cbWndExtra=0;  
          wndclass.cbClsExtra   =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;  
          if(!RegisterClass(&wndclass))  
          {  
                  MessageBeep(0);  
                  return   FALSE;  
          }  
          hwnd=CreateWindow(lpszClassName,  
                                      lpszTitle,  
                                      WS_OVERLAPPEDWINDOW,  
                                              CW_USEDEFAULT,  
                                      CW_USEDEFAULT,  
                                                      CW_USEDEFAULT,  
                                                      CW_USEDEFAULT,  
                              NULL,  
                              NULL,  
                              hInstance,  
                              NULL);  
          ShowWindow(hwnd,nCmdShow);  
          UpdateWindow(hwnd);  
          while(1)  
          {  
                  GetMessage(&Msg,NULL,0,0);  
                  if(Msg.message==WM_QUIT)  
                  {  
                          MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK);  
                          break;  
                  }  
                  TranslateMessage(&Msg);  
                  DispatchMessage(&Msg);  
          }  
                  MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK);  
          return   Msg.wParam;  
  }  
  LRESULT   CALLBACK   WndProc(  
                                                    HWND   hwnd,  
                                                    UINT   message,  
                                                    WPARAM   wParam,  
                                                    LPARAM   lParam)  
  {    
          switch(message)  
          {  
  case   WM_CLOSE:  
            MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用   DestroyWindow(hwnd);"),_T("注意了"),MB_OK);  
            DestroyWindow(hwnd);  
            break;          
  case   WM_DESTROY:  
                  MessageBox(NULL,_T("已调用过DestroyWindow(hwnd),看不到窗口了吧;"),_T("注意了"),MB_OK);  
          MessageBox(NULL,_T("以下处理WM_DESTROY"),_T("注意了"),MB_OK);  
          PostQuitMessage(0);  
          break;  
  case   WM_SYSCOMMAND:  
          if((LOWORD(wParam)&0xFFF0)==SC_CLOSE)  
          {  
                        MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK);  
                SendMessage(hwnd,WM_CLOSE,0,0);  
          }  
          //不要添加   break,否则不能响应其它WM_SYSCOMMAND消息  
  default:  
        return   DefWindowProc(hwnd,message,wParam,lParam);  
          }  
          return(0);  
  }  
   
  --------------------------------------------------------------------------------  
  窗口破坏过程与Windows消息循环的补充,增加了对WM_NCDESTROY的处理  
  /**  
  *         File   Name                 :         MessageTest.cpp  
  *         Version                 :         1.1  
  *         Project   Name         :         MessageTest  
  *         Project   Type         :         Win32  
  *         Author                 :       netcoder  
  *                 Addition                           :         此版本增加了对WM_NCDESTROY的处理,   感谢   lily311   的补充    
  */  
   
  #include   <windows.h>  
  #include   <tchar.h>  
   
   
  LRESULT   CALLBACK   WndProc(HWND,UINT,WPARAM,LPARAM);  
  int   WINAPI   WinMain(HINSTANCE   hInstance,HINSTANCE   hPrevInst,LPSTR   lpszCmdLine,int   nCmdShow)  
  {  
          HWND   hwnd;  
          MSG   Msg;  
          WNDCLASS   wndclass;  
          char   lpszClassName[]="窗口";  
          char   lpszTitle[]="窗口示例";  
          wndclass.style=CS_HREDRAW   |   CS_VREDRAW;  
          wndclass.lpfnWndProc   =WndProc;  
          wndclass.cbWndExtra=0;  
          wndclass.cbClsExtra   =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;  
          if(!RegisterClass(&wndclass))  
          {  
                  MessageBeep(0);  
                  return   FALSE;  
          }  
          hwnd=CreateWindow(lpszClassName,  
                                              lpszTitle,  
                                              WS_OVERLAPPEDWINDOW,  
                                              CW_USEDEFAULT,                              
                                              CW_USEDEFAULT,                                                
                                              CW_USEDEFAULT,                                                  
                                              CW_USEDEFAULT,  
                                              NULL,  
                                              NULL,  
                                              hInstance,  
                                              NULL);  
          ShowWindow(hwnd,nCmdShow);  
          UpdateWindow(hwnd);  
          while(1)  
          {  
                  GetMessage(&Msg,NULL,0,0);  
                  if(Msg.message==WM_QUIT)  
                  {  
                          MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK);  
                          break;  
                  }  
                  TranslateMessage(&Msg);  
                  DispatchMessage(&Msg);  
          }  
                  MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK);  
                  return   Msg.wParam;  
  }  
  LRESULT   CALLBACK   WndProc(                          
            HWND   hwnd,                          
            UINT   message,          
            WPARAM   wParam,                                          
            LPARAM   lParam)  
          {    
                  switch(message)  
                  {  
                  case   WM_CLOSE:  
                          MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用   DestroyWindow(hwnd);"),_T("注意了"),MB_OK);  
                          DestroyWindow(hwnd);  
                          break;  
   
                  case   WM_DESTROY:  
                          MessageBox(NULL,_T("已收到WM_DESTROY,看不到窗口了吧!"),_T("注意了"),MB_OK);  
                          break;  
   
                  case   WM_NCDESTROY:  
                          MessageBox(NULL,_T("收到WM_NCDESTROY!"),_T("注意了"),MB_OK);  
                          PostQuitMessage(0);  
                          break;  
   
                  case   WM_SYSCOMMAND:  
                          if((LOWORD(wParam)&0xFFF0)==SC_CLOSE)  
                          {  
                                  MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK);          
                                  SendMessage(hwnd,WM_CLOSE,0,0);  
                          }  
                          //不要添加   break,否则不能响应其它WM_SYSCOMMAND消息  
                  default:  
                          return           DefWindowProc(hwnd,message,wParam,lParam);  
                  }  
                  return(0);

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/azhang00000/archive/2009/03/05/3961231.aspx

 

LRESULT CMyDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
    switch(message)   
    {   
    case   WM_CLOSE:   
        MessageBox(_T("收到WM_CLOSE消息,即将调用   DestroyWindow(hwnd);"),_T("注意了"),MB_OK);   
        DestroyWindow();   
        break;   
    case   WM_DESTROY:   
        MessageBox(_T("已调用过DestroyWindow(hwnd),看不到窗口了吧;"),_T("注意了"),MB_OK);   
        MessageBox(_T("以下处理WM_DESTROY"),_T("注意了"),MB_OK);   
        PostQuitMessage(0);
        break;   
    case   WM_SYSCOMMAND:   
        if((LOWORD(wParam)&0xFFF0) == SC_CLOSE)   
        {    
            MessageBox(_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK);   
            SendMessage(WM_CLOSE,0,0);   
        }    
        //不要添加   break,否则不能响应其它WM_SYSCOMMAND消息 
    }     
    return CDialog::WindowProc(message, wParam, lParam);
}

 

分享到:
评论

相关推荐

    windowsnt 技术内幕

    调协系统管理告警(Administrative Alert) 向用户发送系统管理消息 远程关闭一台Windows NT计算机 使用Windows NT系统属性对话框 Windows NT诊断程序(Diagnostic)简介 使用Windows NT诊断程序打印一份报告 在Windows ...

    Windows 系统错误代码简单分析

     1002 窗口无法用来发送消息。  1003 无法完成此项功能。  1004 标志无效。  1005 卷不包含已识别的文件系统。请确认所有需要的文件系统驱动程序都已经加载,而且卷没有任何损坏。  1006 某文件的卷已...

    VC++ 专家指导.doc

    (21) 如何获取有关窗口正在处理的当前消息的信息 17 (22) 如何在代码中获取工具条和状态条的指针 18 (23) 如何使能和禁止工具条的工具提示 18 (24) 如何创建一个不规则形状的窗口 19 (25) 如何获取应用...

    20春学期《计算机应用基础》在线平时作业(2)-参考资料.docx

    20春学期《计算机应用基础》在线平时作业(2)-参考资料全文共6页,当前为第1页。20春学期《计算机应用基础》在线平时作业(2... A A 都具有破坏性 B 有些病毒无破坏性 C 都破坏EXE文件 D 不破坏数据,只破坏文件 17 在Wor

    【贵州电大】计算机应用基础-0028标准答案.doc

    " "在Windows中,当程序因某种原因陷入死循环,下列哪一个方法能较好地 " "结束该程序( )。 " "按[Ctrl]+[Alt]+[Del]键,然后选择"结束任务"结束该程序的运 " "行 " "按[Ctrl]+[Del]键,然后选择"结束任务"结束...

    华为编程开发规范与案例

    而pDBFat是数据库的起始地址,如果pSysHead-&gt;dbf_count值异常过大,将导致pDBFat值超过最大内存地址值,随后进行的内存操作将导致内存操作越界错误,因而在测试过程中数据库破坏后就出现了主机死机的现象。...

    LINUX安装与配置简明手册

    第12章 通过Samba服务与Windows网络 集成 152 12.1 概述 152 12.2 快速解决方案 154 12.2.1 获取Samba的最新版本 154 12.2.2 检查是否已经安装了Samba 154 12.2.3 从Red Hat发行版本的CD-ROM 光盘上安装Samba软件包 ...

    linux安装与配置简明手册

    第12章 通过Samba服务与Windows网络 集成 152 12.1 概述 152 12.2 快速解决方案 154 12.2.1 获取Samba的最新版本 154 12.2.2 检查是否已经安装了Samba 154 12.2.3 从Red Hat发行版本的CD-ROM 光盘上安装Samba...

    C++游戏编程快速入门视频教程 高清不加密

    3.3 绘制窗口 3.3.1 绘制文本 3.3.2 绘制图元 3.3.3 使用画笔和画刷 3.4 开发Crop Circles示例 3.4.1 编写程序代码 3.4.2 测试完成的程序 3.5 小结 3.6 亲身实践 第4章 绘制图形图像 4.1 位图图像的...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    作者通过总结各自多年的软件开发和教学培训经验,与大家分享了掌握Oracle SQL所独有的丰富功能的技巧所在,内容涵盖SQL执行、联结、集合、分析函数、子句、事务处理等多个方面。读者可以学习到以下几个方面的技巧:...

    仿世纪佳缘婚介交友系统5.3 ASP+SQL

    用途即为当该管理员是公司员工,那么可以把该管理员的IP添加为公司IP,那么该管理员到其它地方就无法登录后台,提高安全防止破坏。 (3)、编辑权限可以对各个管理员进行权限设置访问,可以分权。例如有些管理员...

    SUDT AccessPort PC机串口(RS232)调试、监控的软件。

    1.增加窗口记忆功能,自动保存窗口大小、位置。 2.增加流控制设置自动装载功能。 AccessPort 1.26 (2005.07.08) 1.Terminal模式增加自动应答功能,支持Hex,Text,Float等类型。 2.修正部分bug。 AccessPort 1.25 ...

Global site tag (gtag.js) - Google Analytics