zoukankan      html  css  js  c++  java
  • 关于程序收到消息的顺序

    窗口过程收到消息是有一定顺序的,收到第一条消息并不是从消息循环开始以后,而是在CreateWindowEx 中就开始了,显示和刷新窗口的函数 ShowWindow 和 UpdateWindow 也向窗口过程发送消息。

    这一点并不奇怪,因为 Windows 在CreateWindowEx 前调用 RegisterClassEx 的时候就已经得到窗口过程的地址了。并且在建立窗口的过程中需要窗口过程的配合。
    调用 CreateWindowEx 时窗口过程收到的消息:

    调用ShowWindow时窗口过程收到的消息:

    然后程序执行 UpdateWindow,这个函数向窗口过程发送一条 WM_PAINT 消息,接着,主程序开始进入消息循环。
    在消息循环中,Windows 根据各种因素给窗口过程发送相应的消息,直到调用 DestroyWindows 为止。
    那么 DestoryWindow 向窗口过程发送的消息具体又是神马内容呢?
    请看大屏幕 ->>

    在所有这些阶段的消息中,大部分的消息都不需要程序自己关心,Windows 只是尽义务通知窗口过程而已,窗口过程转手就交给 DefWindowProc 去处理了。
    程序需要关心的消息有下面这些,可以根据需要选择使用:
    WM_CREATE -- 放置窗口初始化代码,如建立各种子窗口(状态栏和工具栏等)
    WM_SIZE -- 放置位置安排的代码,因为建立的子窗口可能需要随窗口大小的改变而移动位置
    WM_PAINT -- 如果需要自己绘制客户区,则在这里安排代码
    WM_CLOSE -- 向用户确认是否退出,如果退出则摧毁窗口并发送WM_QUIT消息
    WM_DESTROY -- 窗口摧毁,在这里放置释放资源等扫尾代码

    在例子程序中,我们处理了 WM_PAINT 消息来绘制客户区,功能就是在窗口的中间写上一行字:”Welcome to fishc.com!”
    过程是先通过 BeginPaint 获取窗口客户区的 ”设备环境” 句柄。
    然后通过 GetClientRect 获取客户区的大小。
    最后通过 DrawText 函数将字符串按照取得的屏幕大小居中写到 “设备环境” 中,也就是窗口上。
    如果不需要显示这个字符串,则连WM_PAINT消息也不用处理。


    消息默认处理机制 DefWindowProc
    Windows 预定义的消息范围是 0~03ffh,总共 1024 个消息,查看一下头文件Windows.inc,可以发现实际已定义的消息数目有几百个,这些消息中的大部分对于窗口的运行来说都是必需的。
    如果窗口过程要处理每一种消息,那么窗口过程中的 elseif 语句肯定就会绵延数千行,这显然很费劲,所以诞生了 DefWindowProc 函数。
    正是它用默认的方式处理了几百种消息,我们才能用区区百来行代码写出一个全功能的窗口。

    也正是所有的窗口都用DefWindowProc默认处理程序自己不处理的消息,才使它们的行为看上去大同小异,因为它们背后实际上是同一块代码在处理。

    这样子的话我们终于了解到为什么在 Windows 上很多窗口程序无论形状或者行为(拖动、最大化、最小化、关闭等)都大同小异。
    形状 – 窗口类
    行为 - DefWindowProc

    在窗口过程的分支语句中,用户处理所有需要个性化处理的消息,对于表现行为是默认行为的消息,在 else 分支中用 DefWindowProc 来处理。

    对于Windows来说,它并不关心消息在窗口过程中是程序用自己的代码处理的还是用DefWindowProc 处理的,它只看 eax 中的返回值来了解处理结果,所以不管消息是谁处理的,都必须在 eax 中返回正确的值。

    DefWindowProc 返回时 eax 中就是它对消息的处理结果,程序只要直接把 eax 传回给Windows 就行了,所以在例子程序中,DefWindowProc 后面直接用一句 ret 指令返回。

    下边给大家列出了 DefWindowProc 中对一些消息的处理方法,如果和用户期望的不同,就必须在窗口过程中自己处理。

    请看大屏幕 ->>

    从这些默认的处理方法可以看出,想要一个窗口和别的窗口看起来不一样。

    比如想要窗口看起来像苹果机的窗口一样,并且把关闭按钮移到标题栏最左边,那么可以自己处理 WM_NCPAINT 消息,把非客户区画成苹果机窗口的样子,并把关闭按钮画到标题栏左边。

    对别的消息的处理思路也可以按这种方法类推。

    另外,细心的鱼油会发现 DefWindowProc 对WM_CLOSE 的默认处理是调用 DestroyWindow摧毁窗口。
    DestroyWindow 会引发一个 WM_DESTROY消息, WM_DESTROY 和 WM_CLOSE 不同:
    WM_CLOSE 代表用户有关闭的意向,窗口过程有权”不服从”(如我们上节课对他进行修改)
    但收到 WM_DESTROY 的时候不管窗口过程愿不愿意,窗口的关闭已经是不可挽回的事。

  • 相关阅读:
    Java读书笔记(2)-输入输出
    Java读书笔记(1)-异常处理
    Photoshop自动导出各尺寸Android和Iphone图标,支持新版Android Studio
    【原创】我的研究生活
    [原创]使用Fiddler抓取手机APP流量--360WIFI
    Federa 7 配置yum 源
    开源自己写的刷票器软件(windows和Android)
    更新linux kernel到3.14.10 LTS版后,virt-manager无法识别qemu hypervisor的问题
    Net Core Identity 身份验证:注册、登录和注销 (简单示例)
    Net Core的API文档工具Swagger
  • 原文地址:https://www.cnblogs.com/poli/p/4856901.html
Copyright © 2011-2022 走看看