MFC-鼠标相关操作_打开文件

鼠标事件:Windows中分为是三种,按下或释放鼠标、双击鼠标、移动鼠标;

上述三种鼠标实际那将触发鼠标消息,而鼠标消息分为两类,一类是客户区鼠标消息,另一类是非客户区鼠标消息,一般非客户区鼠标消息直接交由DefWindowProc处理;

客户区鼠标消息:

鼠标消息都属于窗口消息,因此消息ID的前缀都是WM_,根据鼠标左右中键的不同以及按下和释放这两个不同动作,鼠标消息的一般名称为WM_xBUTTONyyy;

前缀x有L、R、M分别表示鼠标左键、右键和中键,yyy有DOWN表示按下、UP表示释放、DBLCLK表示双击;

如果鼠标只有两个键(左右键)则应用程序不会收到中间消息,如果只有左键(单键鼠标,这种鼠标很少)则应用程序将不会收到右键消息,可以使用Win32 API函数GetSystemMetrics来查看鼠标有几个键

双击鼠标消息:消息ID是WM_xBUTTONDBLCLK,但要注意的是并不是双击只会产生一个DBLCLK消息,而是按顺序产生4个消息,以左键双击为例

WM_LBUTTONDOWN ; 第一次按下鼠标

WM_LBUTTONUP ; 第一次鼠标释放

WM_LBUTTONDBCLK ; 第二次按下鼠标,用DBLCLK替换了DOWN

WM_LBUTTONUP ; 第二次鼠标释放

在编程时要注意,不要让同一个键的连续单击和双击执行不同的任务,这样容易混淆导致混乱,原因就是上面的双击消息产生顺序,一般在双击的时候都是在第一次单击时选中目标,而在第二次按下(即DBLCLK消息产生后)才会执行一些特殊任务,比如Windows操作系统双击打开文件就是这样,第一次单击时选中文件并使图标变色,而在第二次按下时才打开文件;
窗口接受双击消息的前提:在注册窗口类时必须声明为CS_DBLCLKS,这在Win32中遇到过,但是MFC为框架窗口类注册是默认使用CS_DBLCLKS,因此MFC程序总能接受鼠标双击消息;

光标移动消息:消息ID是WM_MOUSEMOVE,接受该消息的对象是光标底下的窗口,窗口会接收到快速报告光标位置的消息,但是由于光标移动是频繁的,Windows并不是时时刻刻都报告光标移动消息,因为这样做的代价太大,很多其它消息会被光标移动消息淹没,并且时刻都报告光标移动消息会使程序效率降低,因此Windows并不报告所有的光标消息,而是每隔适当时间、适当位置报告一次,因此当光标在屏幕上快速划过时系统只会报告少数的几个消息,只有在光标缓慢滑动的时候才可能捕捉到精确的光标轨迹;

鼠标消息的处理:

1) 鼠标消息的消息ID、消息条目、响应函数的对应关系,所有鼠标消息的形式都是统一的:

WM_xBUTTONyyy ; 消息ID

ON_WM_xBUTTONyyy ; 消息条目

afx_msg void OnXButtonYYY(UINT nFlags, CPOINT point);

!还有一个鼠标移动消息也类同;

2) 鼠标消息处理函数的参数:

i. point:记录了鼠标被按下、释放时的客户区坐标(原点在客户区左上角),如果鼠标移动消息则该参数记录的是最近的光标位置;

ii. uFlags:记录了鼠标消息产生时的瞬时状态,里面有若干位标志,前缀MK_表示Mask Key,即掩码的意思;

MK_LBUTTON、MK_MBUTTON、MK_RBUTTON:表示鼠标的左、中、右键被按下

MK_CONTROL:Ctrl键被按下

MK_SHIFT:Shift键被按下

比如在检测操作鼠标的同时是否按下了Ctrl键则可以:if ( nFlags & MK_CONTROL ) { ... }

WM_LBUTTONDOWN鼠标左键按下消息

1.添加消息

在相应的控件上右击-->类向导

MFC-鼠标相关操作_右键_02

 

2.代码

void CMFCtestDlg::OnLButtonDown(UINT nFlags, CPoint point)  //鼠标左键按下消息函数
//uFlags:记录了鼠标消息产生时的瞬时状态,里面有若干位标志
//         MK_LBUTTON、MK_MBUTTON、MK_RBUTTON:表示鼠标的左、中、右键被按下
//         MK_CONTROL:Ctrl键被按下
//         MK_SHIFT:Shift键被按下
{
    
    if (nFlags & MK_CONTROL) 
        //如果同时按下CTRL键
    {
        AfxMessageBox(_T("同时按下CTRL键和鼠标左键"));
    }
    else
    {
        AfxMessageBox(_T("按下鼠标左键"));
    }

    CDialogEx::OnLButtonDown(nFlags, point);
}