应用程序

Windows的应用程序一般包含窗口(Window),它主要为用户提供一种可视化的交互方式(窗口是由线程(Thread)创建的).Windows 系统通过消息机制来让系统和用户进行交互,用户通过触发事件来触发消息,消息(Message)被发送,保存,处理,一个线程会维护自己的一套消息队列(Message
Queue)[仅当线程有对应的创建窗口和处理窗口消息时候],在发生输入事件之后,Windows 系统将事件转换为一个消息并将消息放入程序的消息队列中.程序通过执行一块称之为「消息循环」的程序代码从消息队列中取出消息并调用窗体的回调函数处理消息,这样不仅保持线程间的独占性.而且队列的以先进先出方式处理消息来实现异步通信.

但是一般来说不是所有的消息都是需要程序处理的.而是针对其中某些特定的消息进行处理.即程序只关心自己想关心的问题而不会多去处理其他不必要的信息.但是系统并不会知道什么是程序所关心的消息,什么是程序不关心的消息,所以它会把所有的消息都发送给程序.那么程序便要从中塞选出自己想要处理的消息,然后把自己不想理会的消息过滤给系统,让系统去帮助处理这些不需要的消息(即系统提供的默认的窗口过程函数 DefWindowProc).那么一般程序的窗体过程具体流程如下:

上面可以看出窗体可以接收和处理消息的特性.然而控件其实也都是窗口.但是每个控件却不一定都具有接收和处理消息的功能.因为在系统中只有具有句柄(一个系统自动维护的32位的数值,是作为系统对象的简单的唯一性的标识)的窗口才具有处理消息的特性.因为只有具有句柄的窗口才能独立存在作为一窗体存在.作为其他控件的容器.而没有句柄的控件,如Label,是不能独立存在的,只能作为窗口控件的子控件,它不能绘制自身,只能依靠父窗体将它绘制来.

消息

  1. 消息载体

    消息由一个叫MSG的结构体定义,包括窗口句柄(HWND),消息ID(UINT),参数(WPARAM, LPARAM)等等:

    1 struct MSG
    2 {
    3 HWND hwnd;
    4 UINT message;
    5 WPARAM wParam;
    6 LPARAM lParam;
    7 DWORD time;
    8 POINT pt;
    9 };
  2. 消息的简单分类

    一般来说消息能够被分为「队列化的」和「非队列化的」.

    • 队列化的消息是由Windows放入程序消息队列中的.在程序的消息循环中,重新传回并分配给窗口消息处理程序.即把消息发送给程序的消息队列中,等带消息处理函数取出并处理消息.队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出.队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT).
    • 非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序.直接进行消息处理.非队列化消息则是其它消息.在许多情况下,非队列化消息来自呼叫特定的Windows函数.例如,当WinMain呼叫CreateWindow时,Windows将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE消息.当WinMain呼叫ShowWindow时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息.当WinMain呼叫UpdateWindow时,Windows将给窗口消息处理程序发送WM_PAINT消息.
    • 注意: 键盘或鼠标输入时发出的队列化消息信号,也能在非队列化消息中出现.例如,用键盘或鼠标选择了一个菜单项时,键盘或鼠标消息就是队列化的,而说明菜单项已选中的WM_COMMAND消息则可能就是非队列化的.
    • 任何情况下,窗口消息处理程序都将获得窗口所有的消息--包括队列化的和非队列化的
  3. 消息队列

    1. 系统队列

      当操作系统启动并初始化时,线程Raw Input Thread(RIT)就会启动,并创系统硬件输入队列(System Hardware Input Queue)(SHIQ). 对于外部的硬件事件(鼠标或者键盘),硬件驱动会将事件转换成消息,并存放到SHIQ中,而RIT线程就专门负责处理SHIQ中的消息,把消息分发到对应线程的消息队列里面.
    2. 线程队列

      而对于线程来说,每个线程可以拥有自己的消息队列,它和线程一一对应.在线程刚创建时,消息队列并不会被创建,而是当GDI的函数调用发生时,Windows系统才认为有必要为线程创建消息队列.系统会为其维护一个THREADINFO结构.

      消息队列包含在一个叫THREADINFO的结构中,有四个队列:

      • Sent Message Queue 发送消息队列 [该队列保存其他程序通过SendMessage给该线程发送的消息]
      • Posted Message Queue 登记消息队列 [该队列保存其他队列通过PostMessage给该线程发送的消息]
      • Visualized Input Queue 输入消息队列 [保存系统队列分发过来的消息,比如鼠标或者键盘的消息]
      • Reply Message Queue 响应消息队列 [保存向窗体发送消息后的结果,比如sendMessage操作结束后,接收消息方会发送一个Reply消息给发送方的Reply队列中,以唤醒发送队列]

      THREADINFO结构体定义如下图所示:

消息管理机制

  1. 消息源

    消息可以由Windows系统发送,也可以由应用程序本身;可以向线程内发送,也可以跨线程.主要是看发送函数的调用者.

  2. 附加参数:

    系统向窗口发送的消息通常包含3个参数,分别是:

    • 窗口句柄(a window handle):窗口句柄用来标识消息将要发送到的窗口对象,系统使用窗口句柄来确定哪一个窗口句柄应该接收该消息.
    • 消息标识符(a message identifier):消息标识符是用来区分不同消息的命名常量,当窗口过程接收到一个消息时,它使用消息标识符来确定如何处理该消息.例如,消息标识符WM_PAINT告诉窗口过程“窗口的客户区已经发生变化,窗口必须进行重新绘制”.
    • 消息参数(message parameters):消息参数用来表述窗口过程处理消息时所使用的数据或数据的位置,通常用一对参数表示(即2个长整型的参数:WPARAM, LPARAM).消息参数的意义和取值取决于消息.当不需要使用消息参数时,通常将其设置为NULL.窗口过程必须通过检查消息标识符来确定如何对消息参数进行解释.
  3. 传递过程:

    用户在操作程序时对电脑的操作这个事件将会被系统捕获到,然后把这个事件翻译成一个消息并且把消息投递到对应的消息队列中.而程序发现自己的消息队列中具有消息时它便会从自己的消息队列中取出消息并处理消息.直至消息队列为空为止.

  4. 三级结构

    Windows消息控制中心一般是三层结构,其顶端就是Windows内核.Windows内核维护着一个消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control).第二级控制中心一般是各Windows应用程序的Application对象.第三级控制中心就是Windows窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息.

总结

首先我们要了解 windows 系统下程序是以消息为基础,事件驱动之.首先用户出发事件,然后系统把事件转换为对应的消息,然后把消息投递到消息队列中.应用程序通过消息循环获得消息,然后把消息转交个系统,有系统再把消息交给对应的窗口回调函数(系统通过以注册的窗口类结构中的一个指向回调函数指针的成员找到窗体的回调函数,而这个窗体结构体是在窗体创建过程中设计窗体类时候通过定义一个 WNDCLASS 结构体设计窗体基本属性是定义的),通过窗口回调函数来处理消息,处理消息结束后,应用回调函数把权限在交还给系统然后,系统在执行权限交给应用程序.程序继续从消息队列中取出消息并按上述方法去处理消息之.流程如下:

转自:http://www.cnblogs.com/kzang/archive/2012/09/30/2709303.html



Windows 应用程序交互过程的更多相关文章

  1. JavaScript与C# Windows应用程序交互方法

    一.建立网页 <html> <head>       <meta http-equiv="Content-Language" content=&quo ...

  2. C# windows程序应用与JavaScript 程序交互实现例子

    C# windows程序应用与JavaScript 程序交互实现例子 最近项目中又遇到WinForm窗体内嵌入浏览器(webBrowser)的情况,而且涉及到C#与JavaScript的相互交互问题, ...

  3. Windows程序执行过程

    Windows应用程序: WinMain函数(入口函数): 1. 设计窗体类,注冊窗体类.WNDCLASS 2. 创建窗体,显示及更新窗体. 3. 消息循环. 窗体过程函数(回调函数):WindowP ...

  4. 【系统篇】从int 3探索Windows应用程序调试原理

    探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程 ...

  5. 升级Windows 10 正式版过程记录与经验

    升级Windows 10 正式版过程记录与经验 [多图预警]共50张,约4.6MB 系统概要: 预装Windows 8.1中文版 64位 C盘Users 文件夹已经挪动到D盘,并在原处建立了符号链接. ...

  6. 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离

        在某国外大型汽车公司BI项目中,有一个子项目,需要通过大屏幕展示销售报表,程序需要自动启动和关闭.开发人员在开发过程中,发现在Win7的service中不能直接操作UI进程,调查过程中,发现如 ...

  7. DirectShow程序运行过程简析

    这段时间一直在学习陆其明老师的<DirectShow开发指南>一书,书中对DirectShow的很多细节讲解清晰,但是却容易让人缺少对全局的把握.在学习过程中,整理了关于DirectSho ...

  8. windows进程/线程创建过程 --- windows操作系统学习

    有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...

  9. ASP.NET运行机制原理 ---浏览器与IIS的交互过程 自己学习 网上查了下别人写的总结的很好 就转过来了 和自己写的还好里嘻嘻

    一.浏览器和服务器的交互原理 (一).浏览器和服务器交互的简单描述: 1.通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去访问一台电脑上访问文件一样,只不过浏览器的访问请求是由被访问 ...

随机推荐

  1. IOS控件大全及控件大小

    一 视图UIView和UIWindow iphone视图的规则是:一个窗口,多个视图.UIWindow相当于电视机,UIViews相当于演员. 1.显示数据的视图 下面几个类可在屏幕上显示信息: UI ...

  2. xcode cocos2dx升级

    原文转自:http://www.codeo4.cn/archives/690 cocos2d-x的安装脚本里没有升级的脚本,我们如果在新版本安装的时候加上参数:-f 强制安装也没有能完全解决问题.新建 ...

  3. C#如何提取.txt文件中的每个字符串

    C#如何提取.txt文件中的每个字符串,并将其存放到一个类中. 将其中的编号 菜名 价格 分别存入不同的数组中. 注:在用ReadLine读取一行信息时为什么读取的中文字符变成了乱码. 20 满意答案 ...

  4. Kotlin Reference (十二) Extensions

    most from reference Kotlin与C#和Gosu类似,提供了扩展一个新功能的类,而不必继承类或使用任何类型的设计模式,如Decorator(装饰者模式).这是通过称为扩展的特殊声明 ...

  5. HDU 1501 Zipper(DFS)

    Problem Description Given three strings, you are to determine whether the third string can be formed ...

  6. sql,去重

    distinct SELECT distinct nf FROM BSHGJJK.T_JJ_NY_QSNCJBQK order by nf desc 来自为知笔记(Wiz)

  7. vue2.*初体验

    一. 推荐开发环境 二. 安装环境 安装 nvm :curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install. ...

  8. shell 脚本实战笔记(11)--Mysql在linux下的安装和简单运维

    前言: linux中安装mysql以及配置的管理, 基础的运维和管理还是需要会一些的. 这边作下笔记, 以求天天向上(^_^). 安装流程:*). 安装mysql-server1). 借助yum检索相 ...

  9. PDB调试模块

    这里主要是一些对于调试常用的命令:1.直接通过命令端输入进行调试 以pdb调试模式运行(主要用这个) python3 -m pdb file.py 2.在代码中导入pdb模块 import pdb 功 ...

  10. 在word文档里提取出所有的邮箱地址

    怎样在word文档里提取出所有的邮箱地址 文档内容太多,邮箱也有很多,一个个复制粘贴太浪费时间,怎样把这些邮箱简单的提取出来  答案:用查找功能. 查找目标:[A-z,0-9]{1,}\@[A-z,0 ...