【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646
本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数,来解释一般窗口消息的投递流程。 基于VS 2005
- BEGIN_MESSAGE_MAP(CMyView, CView)
- ON_WM_LBUTTONDBLCLK()
- END_MESSAGE_MAP()
- // ON_WM_LBUTTONDBLCLK宏展开
- #define ON_WM_LBUTTONDBLCLK() /
- { WM_LBUTTONDBLCLK, 0, 0, 0, AfxSig_vwp, /
- (AFX_PMSG)(AFX_PMSGW) /
- (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &ThisClass :: OnLButtonDblClk)) },
从上面的代码可以看出WM_LBUTTONCLICK消息的类型标签是AfxSig_vwp, 在afxmsg_.h中有一个枚举类型AfxSig,消息标签主要用于区分消息处理函数的类型。该类型中定义了AfxSig_vwp的值:
- enum AfxSig
- {
- //...
- AfxSig_vWp = AfxSig_v_W_p
- //...
- }
在AfxWndProc中,将消息中的句柄映射成窗口类指针,这个指针指向CMyView。AfxWndProc调用AfxCallWndProc,AfxCallWndProc调用CWnd::WindowProc,CWnd::WindowProc调用CWnd::OnWndMsg,CWnd::OnWndMsg完成对消息的处理。
- // wincore.cpp 1746
- BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- // ...
- // GetMessageMap是个虚函数,因为当前指针是指向CMyView,所以取到的是CMyView的消息映射表
- const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
- UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1);
- winMsgLock.Lock(CRIT_WINMSGCACHE);
- // 全局消息散列缓存,查找缓存
- AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
- const AFX_MSGMAP_ENTRY* lpEntry;
- if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
- {
- // cache hit
- lpEntry = pMsgCache->lpEntry;
- winMsgLock.Unlock();
- if (lpEntry == NULL)
- return FALSE;
- // cache hit, and it needs to be handled
- if (message < 0xC000)
- goto LDispatch; // 系统消息?
- else
- goto LDispatchRegistered; // 已注册消息?
- }
- else
- {
- // not in cache, look for it
- pMsgCache->nMsg = message;
- pMsgCache->pMessageMap = pMessageMap;
- for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL;
- pMessageMap = (*pMessageMap->pfnGetBaseMap)())
- {
- // Note: catch not so common but fatal mistake!!
- // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
- ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
- if (message < 0xC000)
- {
- // constant window message
- if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
- message, 0, 0)) != NULL)
- {
- pMsgCache->lpEntry = lpEntry;
- winMsgLock.Unlock();
- goto LDispatch;
- }
- }
- else
- {
- // registered windows message
- lpEntry = pMessageMap->lpEntries;
- while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
- {
- UINT* pnID = (UINT*)(lpEntry->nSig);
- ASSERT(*pnID >= 0xC000 || *pnID == 0);
- // must be successfully registered
- if (*pnID == message)
- {
- pMsgCache->lpEntry = lpEntry;
- winMsgLock.Unlock();
- goto LDispatchRegistered;
- }
- lpEntry++; // keep looking past this one
- }
- }
- }
- pMsgCache->lpEntry = NULL;
- winMsgLock.Unlock();
- return FALSE;
- }
- // ...
- LDispatch:
- mmf.pfn = lpEntry->pfn;
- switch (lpEntry->nSig)
- {
- //...
- case AfxSig_v_u_p: // 消息标签
- {
- CPoint point(lParam);
- (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
- }
- break;
- //...
- }
- //...
- LDispatchRegistered: // for registered windows messages
- ASSERT(message >= 0xC000);
- ASSERT(sizeof(mmf) == sizeof(mmf.pfn));
- mmf.pfn = lpEntry->pfn;
- lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
- }
- // 消息处理函数类型枚举
- union MessageMapFunctions
- {
- AFX_PMSG pfn; // generic member function pointer
- // ...
- LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM);
- };
【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)的更多相关文章
- 【转】Windows消息投递流程:WM_COMMAND消息流程
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182585 该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COM ...
- Windows窗口消息大全(转)
Windows窗口消息大全,全不全自己看 ////////////////////////////////////////////////////////////////////////// #inc ...
- Windows窗口消息大全
////////////////////////////////////////////////////////////////////////// #include "AFXPRIV.H& ...
- Windows程序设计--(三)窗口与消息
3.1 窗口的创建 3.1.1 系统结构概述 所谓「Windows给程序发送消息」,是指Windows呼叫程序中的一个函数,该函数的参数描述了这个特定消息.这种位于Windows程序中的函数称为「窗口 ...
- [8]windows内核情景分析--窗口消息
消息与钩子 众所周知,Windows系统是消息驱动的,现在我们就来看Windows的消息机制. 早期的Windows的窗口图形机制是在用户空间实现的,后来为了提高图形处理效率,将这部分移入内核空间,在 ...
- 关于 OnCloseQuery: 顺序、不能关机等(所有的windows的广播消息都是逐窗口传递的)——如果一个窗体的OnCloseQuery事件中如果写了代码那么WM_QUERYENDSESSION消息就传不过去了msg.result会返回0,关机事件也就停止了
系统关闭窗体的事件顺序为: OnCloseQuery ----> OnClose ----> OnDestroy 下面的代码说明问题: unit Unit3; interface uses ...
- 深刻:截获windows的消息并分析实例(DefWindowProc),以WM_NCHITTEST举例(Windows下每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息)
1,回调函数工作机制 回调函数由操作系统自动调用,回调函数的返回值当然也是返回给操作系统了. 2,截获操作系统发出的消息,截获到后,将另外一个消息返回给操作系统,已达到欺骗操作系统的目的. 下面还是以 ...
- Windows消息理解(系统消息队列,进程消息队列,非队列消息)
// ====================Windows消息分类==========================在Windows中,消息分为以下三类:标准消息——除WM_COMMAND之外,所 ...
- [转] C#中发送消息给指定的窗口,以及接收消息
原文C#中发送消息给指定的窗口,以及接收消息 public class Note { //声明 API 函数 [DllImport("User32.dll", EntryPoint ...
随机推荐
- React 根据 state 修改className
className={ this.state.isLike ? 'active iconfont icon-xihuan' : 'iconfont icon-xihuan1' }
- Git: A分支上的commit提交到B分支上
1. 执行git log -3 --graph A,查看A分支下的commit: 注:commit 后面的hash值代表某个commit,这里把”82f1fb7138c5860cc775b4b5ea7 ...
- nginx自动生成缩略图
网站上常常一张图片,多个地方需要使用不同的尺寸,一般的方案是上传的时候,根据不同的尺寸用程序生成多张图片. 这么做有两个缺点: 1.如果需要新的尺寸图片的话,只能遍历下数据库,重新生成一次图片. 2. ...
- tomcat_日志打印格式问题
1.需要在Catalina/conf/server.xml中设置一下:将文件中这一段的注释去掉(如下),然后将pattern的值改为combined ,这个模式下记录的日志比较详细. ...
- Python笔记 #13# Pandas: Viewing Data
感觉很详细:数据分析:pandas 基础 import pandas as pd import numpy as np import matplotlib.pyplot as plt dates = ...
- HDU 2848 Number Cutting Game(博弈思想 + dfs)题解
思路:dfs找先手必胜的情况是否存在 代码: #include<stack> #include<vector> #include<queue> #include&l ...
- POJ 1185 炮兵阵地(状压DP)题解
思路:和上一篇思路一样,但是这里要求最大能排几个,这里要开三维,记录上次和上上次的状态,再一一判定,状态转移方程为 dp[i][j][k] = max(dp[i][j][k],dp[i - 1][k] ...
- [问题解决]win10误删启动项(BCD)(HP电脑亲测,无需启动盘,并非重装系统)
昨天使用easyBCD软件,开始不太懂,手残把win10的引导删除了,后来发现电脑关机总是变成重启,无奈强制关机.今天重启了一下电脑,发现电脑已经无法打开了,这才明白昨天是误删了win10的BCD. ...
- springboot 日期类型处理
1. 日期类型输出参数处理 默认日期格式只支持:2017-07-01T10:10:01 修改为2017-07-01 10:10:01 只需要修改配置文件即可: spring: jackson: dat ...
- php 二维数组
<?php // 一个二维数组 $cars=array ( array(,), array(,), array(,) ); ?>