利用PreTranslateMessage,响应按钮控件的按下(WM_LBUTTONDOWN)和
松开(WM_LBUTTONUP)
VC的button控制只有两个事件:单击事件,双击事件。
1...关于PreTranslateMessage
PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里。当你需要在MFC之前处理某些消息时,常常要在这里添加处理代码。
2...关于MSG结构体
typedef struct tagMSG{// msg
HWNDhwnd;
UINTmessage;
WPARAMwParam;
LPARAMlParam;
DWORD time;
POINT pt;
} MSG;
3...控件ID--HANDLE--HWND三者之间的互相转换
控件ID-> 句柄: hWnd =::GetDlgItem(hParentWnd, IDXX);
控件ID->指针: CWnd::GetDlgItem();
句柄 -> 控件ID:id = GetWindowLong(hWnd,GWL_ID);
句柄 -> 指针: CWnd*pWnd = CWnd::FromHandle(hWnd);
指针 -> 控件ID:ID=GetWindowLong(pWnd->GetSafeHwnd, GWL_ID);
指针 -> 句柄: hWnd= pWnd->GetSafeHandle();
实例:
方法1:
BOOLXXXXX::PreTranslateMessage(MSG* pMsg)
{
UINT btnID;
//由窗口句柄获得控件ID号,GetWindowLong为获得窗口的ID号。
btnID=GetWindowLong(pMsg->hwnd,GWL_ID);
if(pMsg->message== WM_LBUTTONDOWN)
{
if( btnID==IDC_BTN_MYBUTTON) // 自定义的button被按下
{
// 在这里添加button被按下事件的处理
}
}
//
if(pMsg->message ==WM_LBUTTONUP)
{
if(btnID ==IDC_BTN_MYBUTTON)
{
//在这里添加鼠标松开事件的处理
}
}
//其他消息,我们仍然使用默认处理
returnCDialog::PreTranslateMessage(pMsg);
}
方法2:
BOOLXXXXXX::PreTranslateMessage(MSG* pMsg)
{
UINT btnID;
CWnd* pWnd =WindowFromPoint(pMsg->pt); // 获得指定点的窗体句柄
btnID=pWnd->GetDlgCtrlID(); // 获得该窗体句柄的ID
if(pMsg->message== WM_LBUTTONDOWN)
{
if(btnID==IDC_BTN_MYBUTTON) // 自定义的button被按下
{
// 在这里添加button被按下事件的处理
}
}
//
if(pMsg->message ==WM_LBUTTONUP)
{
if(btnID==IDC_BTN_MYBUTTON)
{
//在这里添加鼠标松开事件的处理
}
}
}
—————————————————————————————————————————————————————
VC中HWND和CWND的概念以及转换:
HWND是Windows系统中对所有窗口的一种标识,即窗口句柄。这是一个SDK概念。
CWnd是MFC类库中所有窗口类的基类。微软在MFC中将所有窗口的通用操作都封装到了这个类中,如:ShowWindow等等,同时它也封装了窗口句柄即m_hWnd成员。
由HWnd得到CWnd*:
CWndwnd;
HWndhWnd;
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。// 但是建议不要这样来使用
//建议获取方式
HWND hWnd =pWnd-> GetSafeHwnd();
CWnd* 和 HWND差别很大:
HWND 是 SDK 定义的类型,是一个无确切意义的 32-bit 值,在调用 API 时用于指代窗体。
CWnd*是一个有确切意义的指针,指向一个 MFC 窗体类 CWnd 的实例。因为 MFC 对 SDK 做了封装,大部分调用都可以用 CWnd*作为参数,所以很容易混淆。从一个 CWnd* 获取句柄的方法是 pWnd->GetSafeHwnd(),他比 pWnd->m_hWnd 更安全(因为 pWnd->GetSafeHwnd()在pWnd == NULL 的时候返回 NULL ,而 pWnd->m_hWnd会出现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对象出来。