WM_CLOSE、WM_DESTROY、WM_QUIT学习总结(点击关闭按钮会触发WM_CLOSE消息,DestroyWindow API会触发WM_DESTROY和WM_NCDESTROY消息,MSDN上写的很清楚)

WM_CLOSE:关闭应用程序窗口

WM_DESTROY:关闭应用程序

WM_QUIT:关闭消息循环

只有关闭了消息循环,应用程序的进程才真正退出(在任务管理器里消失)。

win32应用程序的完整退出过程:点击窗口右上角的关闭按钮,发送WM_CLOSE消息。此消息处理中调用DestroyWindow函数,发送WM_DESTROY消息。此消息处理中调用PostQuitMessage(0)函数,发送WM_QUIT消息到消息队列中。GetMessage捕获到WM_QUIT,返回0,退出循环(应用程序真正退出)。

tips:按照上述正常流程,WM_QUIT是不会到达窗口过程的。(因为在GetMessage截获了WM_QUIT消息之后,程序已经彻底退出了!)

MFC应用程序的完整退出过程:点击窗口右上角的关闭按钮,或选择【File/Close】,发出 WM_CLOSE消息。CMyFrameWnd 并没有设置WM_CLOSE 处理常式,于是交给预设之处理常式。预设函数对于WM_CLOSE 的处理方式是呼叫 ::DestroyWindow, 并因而发出WM_DESTROY。预设之WM_DESTROY 处理方式是呼叫::PostQuitMessage,因此发出WM_QUIT。CWinApp::Run 收到WM_QUIT 后会结束其内部之讯息回路, 然后呼叫ExitInstance,这是CWinApp 的?个虚拟函数。如果自己应用程序累CMyWinApp 改写了ExitInstance , 那么CWinApp::Run 所呼叫的就是CMyWinApp::ExitInstance,否则就是 CWinApp::ExitInstance。最后回到 AfxWinMain,执行 AfxWinTerm,结束程序。

附加:当调用DestroyWindow函数后,操作系统就会进行一系列的删除动作,先发送WM_DESTROY消息,接着发送WM_NCDESTROY消息。如果这个窗口还有子窗口或者是其它窗口的所有者,就需要给所有子窗口发送删除消息。

WM_QUIT是唯一可以使GetMessage(&msg,NULL,0,0)返回假值的消息.

相关代码分析:

//主函数中进入消息循环的代码片断
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg); //将消息进行处理一下
DispatchMessage(&msg); //再将消息变量msg传给windows,让windows来调用消息处理函数
}

如果把GetMessage(&msg,NULL,0,0)改为GetMessage(&msg,hWnd,0,0),则发现关闭应用程序后,任务管理器中仍有该程序的进程,且占用大量的内存,why?

msdn中的原因解释;对于GetMessage(&msg,hWnd,0,0),当第二个参数无效时,此函数返回值为-1。对于上述循环来说,此while条件为真,因此进入死循环,进程无法退出。

http://hhfighting.blog.163.com/blog/static/5570032320108215323797/

---------------------------------------------------------------------------------------------------------------

VCL里相应的代码:

procedure TCustomForm.WMClose(var Message: TWMClose);
begin
  Close;
end;

procedure TCustomForm.Close;
var
  CloseAction: TCloseAction;
begin
  if fsModal in FFormState then
    ModalResult := mrCancel
  else
    if CloseQuery then
    begin
      if FormStyle = fsMDIChild then
        if biMinimize in BorderIcons then
          CloseAction := caMinimize else
          CloseAction := caNone
      else
        CloseAction := caHide;
      DoClose(CloseAction);
      if CloseAction <> caNone then
        if Application.MainForm = Self then Application.Terminate
        else if CloseAction = caHide then Hide
        else if CloseAction = caMinimize then WindowState := wsMinimized
        else Release;
    end;
end;

procedure TCustomForm.WMDestroy(var Message: TWMDestroy);
begin
  if NewStyleControls then SendMessage(Handle, WM_SETICON, 1, 0);
  if (FMenu <> nil) and (FormStyle <> fsMDIChild) then
  begin
    Windows.SetMenu(Handle, 0);
    FMenu.WindowHandle := 0;
  end;
  inherited;
end;

还有:

function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
  Handled: Boolean;
begin
  Result := False;
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
  begin
    Result := True;
    if Msg.Message <> WM_QUIT then
    begin
      Handled := False;
      if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
      if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
        not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
    end
    else
      FTerminate := True;
  end;
end;

DestroyWindow函数来自这里(TApplication.Destroy里也调用了这个函数):

procedure TWinControl.DestroyWindowHandle;
begin
  Include(FControlState, csDestroyingHandle);
  try
    if not Windows.DestroyWindow(FHandle) then
      RaiseLastOSError;
  finally
    Exclude(FControlState, csDestroyingHandle);
  end;
  FHandle := 0;
end;

那难道每个TButton,每个TPanel,都会收到WM_DESTROY消息吗?

时间: 2024-10-12 08:16:10

WM_CLOSE、WM_DESTROY、WM_QUIT学习总结(点击关闭按钮会触发WM_CLOSE消息,DestroyWindow API会触发WM_DESTROY和WM_NCDESTROY消息,MSDN上写的很清楚)的相关文章

jQuery学习示例------点击红色方块实现左右晃动

<!DOCTYPE html> <html> <head> <title>test</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> <script type="text/javas

Robotium学习之点击没有ID的控件如何实现

---恢复内容开始--- 其实这篇文章写起来听费劲的,毕竟我自己也是刚刚解决这个问题..理解可能还是不太够,想说却也不知道从哪里说起比较好. UI自动化测试,我是以monkeyrunner入门的,这个工具,说实话入门真的很容易,sdk自带工具,环境不用花时间配置:脚本语言Python就我现在的理解看来也是一门非常实用并且简单的语言.但是原生的monkeyrunner几乎不能做任何复杂的事情,而大神们写的一些插件,也因为资料太少始终无法做的很好.所以怀着很复杂的心情,我放弃了monkeyrunne

解决点击关闭按钮,应用程序退出时,系统爆出“集合已修改,可能无法执行枚举操作”异常的相关思路

这两天在优化升级公司的一个业务系统时,更改了一下窗体关闭事件中的一句代码,由system.Enviromen.Exit(0)改为了Application.Exit();但是这时候问题就出现了,当点击系统右上角关闭按钮的时候,会爆出“集合已修改,可能无法执行枚举操作”的异常.如下图所示: 这是什么原因造成的呢?问了一下度娘,出现“集合已修改,可能无法执行枚举操作”这种异常大部分都是因为误用foreach语句引起的,foreach是取只读的,在取的时候数据不能变(包括修改,删除,添加等).要避免这个

CorePlot学习六---点击scatterPlot中的symbol点时弹出相应的注释

由于项目需要用到用户点击 symbol时,弹出相应的详细信息,发现国内讲解的比较少,经过一番搜索验证终于解决,先看效果图: 具体需要修改的代码如下: 首先要引用委托方法:CPTScatterPlotDelegate.CPTPlotSpaceDelegate 完成如下: #pragma mark - #pragma mark CPTPlotSpaceDelegate methods -(BOOL)plotSpace:(CPTPlotSpace *)space shouldHandlePointin

winfrom 捕获是否点击关闭按钮关闭的窗体

const int WM_SYSCOMMAND = 0x0112; const int SC_CLOSE = 0xF060; protected override void WndProc(ref Message msg) {                 if (msg.Msg == WM_SYSCOMMAND && ((int)msg.WParam == SC_CLOSE))          {                  // 点击winform右上关闭按钮        

点击事件里面的change事件,多次触发change事件

最近做个项目,在点击按钮后弹出一个层,里面有单选按钮,选中单选按钮时就可以动态添加到对应的地方了 $(".xinz").click(function(event){ event.stopPropagation(); radioBoxChange += 1; //clickChange = "shspClick"; var radioBox=$("#radioBox"); var hsBox=$(this).siblings(".deli

android 新手学习笔记 点击事件

//按钮点击事件 button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //代码实现 } });

IOS 手势学习(点击,长按,轻扫,拖拽,旋转,捏合缩放)

点击        UITapGestureRecognizer 长按        UILongPressGestureRecognizer 轻扫        UISwipeGestureRecognizer 拖拽        UIPanGestureRecognizer 旋转        UIRotationGestureRecognizer 捏合缩放 UIPinchGestureRecognizer 详细代码如下: #import "ViewController.h" @i

javascript学习代码--点击按钮显示内容

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-