Win32消息机制

    过程驱动:程序是依照我们预先定义好的顺序运行。每运行一步,下一步都已经依照预定的顺序 继续运行,直至程序结束。

    事件驱动:程序的运行顺序是无序的。某个时间点所运行的代码。是由外界 通知。因为我们无法决定程序运行顺序。所以代码的运行也是无序的。

  Win32基本消息

   WM_DESTROY:
      窗体销毁时的消息。能够做退出或善后处理

  WM_CREATE:
      窗体创建消息,是在窗体创建后,窗体处理函数收到的第一条消息
  能够在这个消息内,做初始化或者穿件子窗体
  WPARAM wParam - 不使用
  LPARAM lParam - CREATESTRUCT指针
   WM_SIZE:
      当窗体大小发生改变时,会收到这个消息。
  能够在这个消息中调整窗体的布局
 WM_SYSCOMMAND:
      系统命令消息,当点击系统菜单和按钮时会收到
  能够在这个消息中,提示用户保存数据等
 WM_PAINT:
      画图消息
      键盘消息:
 鼠标消息
 WM_TIME:定时器消息 

 消息的获取和发送

     获取GetMessage/PeekMessage
         GetMessage 获取消息。堵塞函数
         PeekMessage 获取消息,非堵塞函数
     发送SendMessage/PostMessage
         SendMessage 发送消息并等候消息处理结束才返回。

 
         PostMessage 发送消息后马上返回,不关心消息处理的结果。 

LRESULT SendMessage/PostMessage(
HWND hWnd, //处理消息窗体
UINT Msg, //消息的ID
WPARAM wParam, //消息的參数
LPARAM lParam );//消息的參数

 3 消息组成和分类
   3.1 消息组成
      窗体句柄/消息ID/消息參数(WPARAM.LPARAM)
   3.2 消息分类
      3.2.1 系统消息 - 由系统定义和使用的消息
         比如:WM_CREATE/WM_SIZE
         消息ID范围为: 0 - 0x03FF(WM_USER-1)
      3.2.2 用户定义消息 - 应用程序能够自定义和使用的消息, WM_USER(0x0400)
         从WM_USER的ID開始,到0x7FFF,是用户能够定义使用的消息.
      3.2.3 其它消息范围
         WM_APP(0x8000)-0xBFFF:应用程序訪问窗体的消息ID
         0xC000-0xFFFF: 应用程序訪问消息,使用字符串注冊系统产生对应消息ID
      3.2.4 用户定义消息的使用
         1)定义自定义消息ID:

 #define   WM_FIRSTMSG  (WM_USER+1)

         2)在窗体处理函数中,响应消息

 switch( nMsg )
{
case WM_FIRSTMSG:
//处理函数
break;
}

         3)SendMessage/PostMessage发送消息

    SendMessage( hWnd, WM_FIRSTMSG, 0, 0 );

  4 消息队列
    4.1 消息队列 - 用于存储消息的内存空间,消息在队列中是先入先出.
    4.2 消息队列的分类
      4.2.1 系统消息队列 - 由系统维护的消息队列. 
      4.2.2 应用程序消息队列(线程消息对列) -属于每一个线程的各自拥有的消息队列.
  
  5 消息和消息队列
    5.1 依据消息和消息队列关系,将消息分成两种:
      队列消息 - 能够存放在消息队列中的消息.
      非队列消息 - 发送时不进入消息队列.
    5.2 队列消息
      首先存放到消息队列其中,然后由GetMessage/PeekMessage取出,然后进行处理.
      比如: 鼠标消息/键盘消息/WM_PAINT/WM_QUIT/M_TIMER消息
    5.3 非队列消息
      消息发送直接发送给指定的窗体,查找窗体的处理函数,返回处理结果.
 
 6 消息的获取   
    6.1 消息循环
      6.1.1 GetMesssage从队列中获取消息,推断是否是WM_QUIT消息,假设发现是WM_QUIT消息,消息循环结束,否则继续下一步.
      6.1.2 TranslateMessage 翻译按键消息,假设发现有按键消息,产生字符消息放入消息对列, 继续下一步
      6.1.3 DispatchMessage 找到消息所发窗体的处理函数,处理消息.处理完毕后,返回6.1.1.
    6.2 GetMesssage和PeekMessage
      6.2.1 从线程消息队列中获取消息,假设找到消息,就返回消息,进行消息处理. 假设未找到消息,运行6.2.2
      6.2.2 查找系统消息队列.通过向系统消息队列查询,假设找到消息,获取消息并返回,进行消息处理.假设未找到消息,运行6.2.3
      6.2.3 检查窗体须要又一次绘制的范围,假设发现存在又一次绘制的范围,会产生WM_PAINT消息.然后进行消息处理, 假设未找,运行6.2.4
      6.2.4 检查WM_TIMER定时器消息,假设发现存在已经到时的定时器,会产生WM_TIMER消息.进行消息处理. 假设未找,运行6.2.5
      6.2.5 运行内存管理工作.
      6.2.6 依据函数不同,处理结果不同:
        GetMesssage - 堵塞,等候下一条消息
        PeekMessage - 让出控制权,交给后面的代码运行.
        
  7 消息发送  
    7.1 消息发送分两种
       发送(Send)消息 - 直接发送给指定的窗体,并等候结果.
       投递(Post)消息 - 发送到消息队列其中,立马返回,由消息循环处理.
    7.2 PostMessage和SendMessage
      PostMessage产生队列消息,因为发送后不等候消息处理结果,所以不能确定消息是否被处理成功.
      SendMessage产生非队列消息,能够确定消息是否成功. 

看以下的代码演示样例:

 

/*File : message.cpp
*Auth : sjin
*Date : 20140519
*Mail : 413977243@qq.com
*/ #include <iostream>
#include <Windows.h>
#include <stdio.h> HINSTANCE g_hInst = NULL;
HWND g_button = NULL; LRESULT CALLBACK WndProc(HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam); /*注冊窗体*/
BOOL RegisterWnd(LPSTR pszClassName)
{
WNDCLASSEX wce = {0};
wce.cbClsExtra = 0;
wce.cbSize = sizeof(wce);
wce.cbWndExtra = 0;
wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
wce.hCursor = NULL;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hInstance = g_hInst;
wce.lpfnWndProc = WndProc;
wce.lpszClassName = pszClassName;
wce.lpszMenuName = NULL;
wce.style = CS_HREDRAW|CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce);
if(0 == nAtom)
return FALSE;
return TRUE;
} /*创建窗体*/
HWND CreateWnd(LPSTR pszClassName)
{
HWND hWnd = CreateWindowEx(0, pszClassName,
"MyWnd", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,g_hInst,NULL);
return hWnd;
} /*显示窗体*/
void DisplayWnd(HWND hWnd)
{
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
} void wm_create(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
LPCREATESTRUCT pCreateStruct = LPCREATESTRUCT(lParam);
/*打印窗体的名字
先弹出这个对话框,点击OK后弹出窗体
*/
//MessageBox(NULL, pCreateStruct->lpszName,"WM_CREATE",MB_OK); /*创建一个子窗体*/
g_button = CreateWindowEx(0, "BUTTON",
"BUTTON", WS_CHILD|WS_VISIBLE, 30,
20,100,50,
hWnd,NULL,g_hInst,NULL); } void wm_size(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
INT nWidth = LOWORD(lParam);
INT nHeight = HIWORD(lParam);
CHAR szText[256] = {'\0'};
sprintf(szText,"W:%d;H:%d",nWidth,nHeight);
//MessageBox(NULL, szText,"WM_SIZE",MB_OK); if(NULL != g_button)
{
int nX = (nWidth - 100)/2;
int nY = (nHeight - 100)/2;
MoveWindow(g_button, nX, nY, 100, 100, TRUE);
}
} /*运行系统命令函数处理*/
BOOL wm_syscommand(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
switch(wParam){
case SC_CLOSE:
if(IDOK == MessageBox(NULL,"是否将文件存盘","提示",MB_OKCANCEL|MB_ICONWARNING)){
return TRUE;
} else {
return FALSE;
}
break;
default:
break;
} return FALSE;
} /*消息处理函数*/
LRESULT CALLBACK WndProc(HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam)
{
switch(nMsg){
/*Win 32 基本消息
WM_DESTROY:
窗体销毁时的消息,能够做退出或善后处理
WM_CREATE:
窗体创建消息。是在窗体创建后。窗体处理函数收到的第一条消息
能够在这个消息内,做初始化或者穿件子窗体
WPARAM wParam - 不使用
LPARAM lParam - CREATESTRUCT指针
WM_SIZE:
当窗体大小发生改变时。会收到这个消息。
能够在这个消息中调整窗体的布局
WM_SYSCOMMAND:
系统命令消息,当点击系统菜单和按钮时会收到
能够在这个消息中。提示用户保存数据等
WM_PAINT:
画图消息
键盘消息:
鼠标消息
WM_TIME:定时器消息
*/
case WM_DESTROY://窗体销毁时的消息
/*向窗体发送WM_QUIT 消息*/
//SendMessage(hWnd, WM_QUIT, 0, 0);/*发送消息并等候消息处理结束才返回*/
PostMessage(hWnd, WM_QUIT, 0, 0);/*发送消息后马上返回,不关心消息处理的结果*/
//PostQuitMessage(0);
return 0;
case WM_CREATE:/*创建窗体*/
wm_create(hWnd,nMsg,wParam,lParam);
break; case WM_SIZE:/*窗体拖动*/
wm_size(hWnd,nMsg,wParam,lParam);
break;
case WM_SYSCOMMAND:/*运行系统命令*/
if(!wm_syscommand(hWnd,nMsg,wParam,lParam)){
return 0;
}
break; }
return DefWindowProc(hWnd, nMsg, wParam, lParam);
} /*消息循环*/
void Message()
{
/* MSG 结构体參数描写叙述
typedef struct tagMSG { // msg
HWND hwnd; //消息窗体句柄
UINT message;//消息标示
WPARAM wParam;//消息的參数
LPARAM lParam;//消息的參数
DWORD time;//消息的时间
POINT pt;//消息产生时。鼠标的位置
} MSG;
*/ MSG msg = {0}; /*
BOOL GetMessage(
LPMSG lpMsg,//存放获取到的消息数据 由系统填写关于消息的參数
HWND hWnd,//获取消息的窗体句柄。可接受指定窗体消息
UINT wMsgFilterMin,//消息过滤的起始消息
UINT wMsgFilterMax //消息过滤的终止消息
);
return :
TRUE :成功获取消息。FALSE:获取到WM_QUIT消息时。 能够使用PostQuitMessage向窗体发送WM_QUIT消息
GetMessage:获取消息。堵塞函数
PeekMessage:获取消息,非堵塞函数
*/
while(GetMessage(&msg, NULL, 0, 0))
{
/*TranslateMessage:
就是将键盘的消息转换成字符消息
1、首先检查是否是键盘消息
2、假设发现是按键消息,将依据按键,产生字符消息
在下一个GetMessage运行时,收到这个消息
3、假设未发现按键消息,未做不论什么处理
*/
TranslateMessage(&msg);
/*DispatchMessage
依据消息数据内窗体句柄,找到这个窗体的窗体处理函数, 调用处理函数。进行消息处理。
假设MSG中。HWND窗体句柄为空,DispatchMessage不做不论什么处理。
*/
DispatchMessage(&msg);
}
} int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
RegisterWnd("MyWnd");
HWND hWnd = CreateWnd("MyWnd");
DisplayWnd(hWnd);
Message();
return 0;
}

走进windows编程的世界-----消息处理函数(1)的更多相关文章

  1. 走进windows编程的世界-----消息处理函数(2)

    一 WM_PAINT消息 1 WM_PAINT的产生   因为窗体的互相覆盖等,产生须要绘制的区域,那么会产生WM_PAINT消息.   普通情况下,不直接发送WM_PAINT消息,通过API声明须要 ...

  2. 走进windows编程的世界-----消息处理函数(3)

    二 定时器消息 1 定时器消息 WM_TIMER   依照定时器设置时间段,自己主动向窗体发送一个定时器消息WM_TIMER. 优先级比較低.   定时器精度比較低,毫秒级别.消息产生时间也精度比較低 ...

  3. 走进windows编程的世界-----入门篇

    1   Windows编程基础 1.1Win32应用程序基本类型 1)  控制台程序 不须要完好的windows窗体,能够使用DOS窗体方式显示 2)  Win32窗体程序 包括窗体的程序,能够通过窗 ...

  4. 走进windows编程的世界-----画图相关

    Windows画图 1 图形绘制      1.1 图形绘制的方式      获取到画图句柄-设备描写叙述表(DC),使用对应的画图的API,在设备上绘制图形.          1.2 颜色     ...

  5. 走进windows编程的世界-----对话框、文本框、button

    1 对话框的分类  2 对话框的基本使用方式  3 对话框资源  4 有模式对话框的使用 int DialogBox( HINSTANCE hInstance, LPCTSTR lpTemplate, ...

  6. 走进windows编程的世界-----窗体的注冊及创建

    1   窗体注冊和创建 1.1WIN32 窗体程序创建步骤 1.WinMain入口函数的定义 2.WindowProc函数的定义 3.注冊窗体类 RegisterClass.RegisterClass ...

  7. 走进windows编程的世界-----windows进程

    Windows进程  1 Windows进程    进程是一个容器,包括了一个应用程序实例的各种资源.Windows多任务的操作系统,因此能够同一时候运行多个进程.      2 Windows进程的 ...

  8. [C#] 走进异步编程的世界 - 在 GUI 中执行异步操作

    走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5877042.html 序 这是继<开始接 ...

  9. 走进异步编程的世界 - 在 GUI 中执行异步操作

    转载:https://www.cnblogs.com/liqingwen/p/5877042.html 走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://w ...

随机推荐

  1. 『Json』常用方法记录

    json模块可以把字典结构改写为string然后保存,并可以反向读取字典 pickle模块则可以持久化任意数据结构 但是即使同样是字典数据结构,两个包也是有差别的, json字典value不支持其他对 ...

  2. MVC 模式——第3章

    在深入到 ASP.NET MVC 框架的细节之间,最好熟悉 MVC 的设计模式及其背后的思想.良好地理解 MVC 背后的内容,有助于在阅读本书的过程中将该框架的特性放到相关的情境之中. 3.2 理解 ...

  3. python daal test

    import os import sys from daal.algorithms import low_order_moments from daal.data_management import ...

  4. spark collect获取所有元素

    from pyspark import SparkConf, SparkContext conf = SparkConf().setMaster("local").setAppNa ...

  5. spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战

    SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...

  6. ArrayList与List<T>笔记

    ArrayList与List<T>笔记 ArrayList是在System.Collections命名空间的一个类, 通过Add的方法添加一个项, 当进到这个类的元数据时, 可以看到这个方 ...

  7. MySQL 5.7 分区表性能下降的案例分析

    转载自:https://mp.weixin.qq.com/s/K3RpSBAIWFwGCIWyfF0QPA 前言:希望通过本文,使MySQL5.7.18的使用者知晓分区表使用中存在的陷阱,避免在该版本 ...

  8. hpu 1267 Cafeteria (01背包)

    1267: Cafeteria [DP] 时间限制: 1 Sec 内存限制: 128 MB提交: 76 解决: 31 统计 题目描述 Nanae把饥肠辘辘的josnch带去一家自助餐厅,面对面前眼花缭 ...

  9. HTTPS工作原理和TCP握手机制

    1.HTTPS的工作原理 HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手, 在握手过程中将确立双方加密传输数据的密码信息. TLS/SSL协议不仅仅是一套加密传输的协议, ...

  10. python3.6 ubuntu

    apt-get install python3.6-dev 安装 pip install mysqlclient 必备