利用PreTranslateMessage,响应按钮控件的按下(WM_LBUTTONDOWN)和松开(WM_LBUTTONUP)

 
VC的button控制只有两个事件,一个是单击事件,一个事双击事件。在这个方面VB就方便多了。但是我们有其他办法解决。首先我们先学一些基础知识。
 

1...关于PreTranslateMessage

PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当你需要在MFC之前处理某些消息时,常常要在这里添加代码.

2...关于MSG结构体
typedef struct tagMSG { // msg
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;

Members
hwnd
Handle to the window whose window procedure receives the message.
message
Specifies the message identifier. Applications can only use the low word; the high word is reserved by the system.
wParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
lParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
time
Specifies the time at which the message was posted.
pt
Specifies the cursor position, in screen coordinates, when the message was posted.

3...ID--HANDLE--HWND三者之间的互相转换
id->句柄、、、、、hWnd = ::GetDlgItem(hParentWnd,id);
id->指针、、、、、CWnd::GetDlgItem();
句柄->id、、、、、id = GetWindowLong(hWnd,GWL_ID);
句柄->指针、、、、CWnd *pWnd=CWnd::FromHandle(hWnd);
指针->ID、、、、、id = GetWindowLong(pWnd->GetSafeHwnd,GWL_ID);
指针->句柄、、、、hWnd=cWnd.GetSafeHandle() or mywnd->m_hWnd;

例程:

方法1:

BOOL AcameraCT::PreTranslateMessage(MSG* pMsg)
{
int buID;
buID= GetWindowLong(pMsg->hwnd,GWL_ID);//由窗口句柄获得ID号,GetWindowLong为获得窗口的ID号。
if(pMsg->message==WM_LBUTTONDOWN)
{
if(buID==IDC_BUTTON_CT1) //按下
{
//在这里添加单击按下事件的程序
}
}
if(pMsg->message==WM_LBUTTONUP)
{
if(buID==IDC_BUTTON_CT1)
{
//在这里添加单击松开事件的程序
}
}
return CDialog::PreTranslateMessage(pMsg);
}

方法2:

BOOL AcameraCT::PreTranslateMessage(MSG* pMsg)
{
int buID;
CWnd* pWnd=WindowFromPoint(pMsg->pt); //获得指定点句柄
buID=pWnd->GetDlgCtrlID();//获得该句柄的ID号。
if(pMsg->message==WM_LBUTTONDOWN)
{
if(buID==IDC_BUTTON_CT1) //按下
{
//在这里添加单击按下事件的程序
}
}
if(pMsg->message==WM_LBUTTONUP)
{
if(buID==IDC_BUTTON_CT1)
{
//在这里添加单击松开事件的程序
}
}
return CDialog::PreTranslateMessage(pMsg);

}

VC_HWND和CWND的概念以及转换

下面先说下HWMD的概念,我也不是很理解,应该是SDK接口的概念,并没有实际对象操作的地址空间。

它只是一个32bit的无符号整型数值,代表了句柄号handle

摘自网上的理论:

HWND是Windows系统中对所有窗口的一种标识,即窗口句柄。这是一个SDK概念。

CWnd是MFC类库中所有窗口类的基类。微软在MFC中将所有窗口的通用操作都封装到了这个类中,如:ShowWindow等等,同时它也封装了窗口句柄即m_hWnd成员。

由HWnd得到CWnd*:

CWnd wnd;

HWnd hWnd;

wnd.Attach(hWnd);

通常一个窗口资源已经和一个CWnd类的对象关联起来的,由于一般来说这个类是自己创建的,所以自然知道怎么得到指向这个类的指针。如果没有就创建一个CWnd对象,将这个对象与窗口资源的hWnd句柄关联起来。(如上边的语句)。如果用

static CWnd* CWnd::FromHandle(HWND hWnd) ;

则返回值是一个暂时的CWnd对象,并且我们确保返回值为非空,也就是hWnd是有效的。

static CWnd* CWnd::FromHandlePermanent(HWND hWnd) ;

返回的是一个永久的对象。只有在返回的CWnd在类表里已经存在是返回值为非空。

由CWnd获取HWnd就容易多了,因为它的一个成员m_hWnd就是所对应窗口的句柄。

wnd->m_hWnd。

——————————————————————————————————————————————————————————

CWnd* 和 HWND 差别很大

HWND 是 SDK 定义的类型, 是一个无确切意义的 32-bit 值,在调用 API 时用于指代窗体。

CWnd* 是一个有确切意义的指针,指向一个 MFC 窗体类 CWnd 的实例。因为 MFC 对 SDK 做了封装,大部分调用都可以用 CWnd* 作为参数,所以很容易混淆。从一个 CWnd* 获取句柄的方法是 pWnd->GetSafeHwnd(), 他比 pWnd->m_hWnd 安全,因为前者在 pWnd == NULL 的时候返回 NULL 而后者出现 access violation

从 hWnd 转换到 CWnd * 一个可以使用的方法是 CWnd::FromHandle

CWnd *pTempWnd = CWnd::FromHandle(hWnd); // 如果 hWnd 存在对应的 CWnd* ,则返回其指针,否则,创建一个 MFC 临时窗体并返回其指针。

注意这个函数会返回临时窗体的指针,如果需要更安全,调用 CWnd::FromHandlePermanent ,他在不存在对应的 CWnd* 时返回 NULL。

——————————————————————————————————————————————————————————

CWnd是MFC的窗口基类。 HWND是Windows窗口句柄。前者是一个C++对象,后者是一个类似于指针地址的数字型对象。

CWnd可以看成是对Windows窗口操作的封装,而封装的核心就是使用Windows窗口句柄(即HWND)来操作窗口.

CWnd可以通过CWnd::GetSafeHwnd()或成员变量m_hWnd来获得该窗口对象的HWND窗口句柄。

HWND可以通过CWnd的静态函数:CWnd::FromHandle()由句柄实例化一个CWnd对象出来。

以下是自己VC6.0上编译的情况,验证了以上的理论

CWnd* mark1;mark1=FindWindow(NULL,"TEST");//TEST是我的当前实例窗口的title

//从CWND*转换成HWND

HWND tmp=mark1->GetSafeHwnd(); //得到它的HWND

ID--HANDLE--HWND三者之间的互相转换的更多相关文章

  1. org.Hs.eg.db包简介(转换NCBI、ensemble等数据库中基因ID,symbol等之间的转换)

    1)安装载入 ------------------------------------------- if("org.Hs.eg.db" %in% rownames(install ...

  2. RDD、DataFrame、Dataset三者三者之间转换

    转化: RDD.DataFrame.Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换 DataFrame/Dataset转RDD: 这个转换很简单 val rdd1=testDF. ...

  3. 做筛选遍历时遇到的json字符串、json对象、json数组 三者之间的转换问题

    这个是后台对登录用户以及筛选条件的操作 @Override public List<SdSdPer> listResults(String sidx, String sord) { try ...

  4. [转]ExtJs基础--Html DOM、Ext Element及Component三者之间的区别

    要学习及应用好Ext框架,必须需要理解Html DOM.Ext Element及Component三者之间的区别. 每一个HTML页面都有一个层次分明的DOM树模型,浏览器中的所有内容都有相应的DOM ...

  5. keydown,keypress,keyup三者之间的区别

    最近看了Javascript高级教程中对过滤输入的介绍,想实现比如电话号码中不能包好非数值的字符,而相应文本中插入字符的操作是keypress事件,所以就想通过阻止这个事件的默认事件行为来阻止这个事件 ...

  6. CString string char* char 之间的字符转换(多种方法)

    在写程序的时候,我们经常遇到各种各样的类型转换,比如 char* CString string 之间的互相转换.首先解释下三者的含义. CString 是一种很有用的数据类型.它们很大程度上简化了MF ...

  7. <%@page include%>、<%@include%>、<jsp:include>三者之间的本质区别

    <%@page include%>.<%@include%>.<jsp:include>三者之间的本质区别 先从它的几个内置对象说起. application和se ...

  8. xsd与xml和类(class)对象之间的互相转换

    xsd与xml和类(class)对象之间的互相转换 . 第一:通过现有的已经写好的xsd来生成class(.cs)文件. 在您Visual Studio的安装目录下的SDKv2.0Bin中有个应用程序 ...

  9. JSP、servlet、SQL三者之间的数据传递

    JSP.servlet.SQL三者之间的数据传递 博客分类: web开发 JSPservletSQL数据库连接池web开发  前言: 最近一直在做WEB开发,现总结一下这一段时间的体会和感触. 切记, ...

随机推荐

  1. PTA 08-图9 关键活动 (30分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/719 假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它 ...

  2. iOS-APP图标和启动页的尺寸

    图标

  3. 【Luogu】P1155双栈排序(二分图)

    题目链接在此 此题一开始写了个深搜,过了30%的数据,也就是n<=10的那一段.... 然后看了题解发现这是个二分图的判断. 我们先举例子找到不能放进一个栈里的规律.设有数列[2,3,1,4] ...

  4. [BZOJ2342] [Shoi2011]双倍回文(manacher)

    传送门 manacher...... 先跑一边manacher是必须的 然后枚举双倍回文串的对称轴x 把这个双倍回文串分成4段,w wR w wR 发现,只有当 y <= x + p[x] / ...

  5. run as maven build时报错

    eclipse中使用maven插件的时候,运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery is ...

  6. 【Codeforces Round #504 (Div. 1 + Div. 2) 】

    A:https://www.cnblogs.com/myx12345/p/9843678.html B:https://www.cnblogs.com/myx12345/p/9843709.html ...

  7. 巧克力王国 BZOJ 2850

    巧克力王国 [问题描述] 巧克力王国里的巧克力都是由牛奶和可可做成的.但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力.对于每一块巧克力,我们设x和y为其牛奶和可可的含量.由于 ...

  8. R读数据stringsAsFactors=F,存数据时row.names = F

    stringsAsFactors=F   以前在r里读数据,经常把character读成factor,还得费半天劲把它转回来,尤其是把factor转成numeric还没有那么直接.例如: dat< ...

  9. VM虚拟机

    VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式).要想在网络管理和维护中合理应用它们,你就应该先了解一下这三种工作模式. 1 ...

  10. T1079 回家 codevs

    http://codevs.cn/problem/1079/ 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver~死坑 题目描述 Description 现在是晚 ...