键和Ctrl键的组合状态。nFlag参数取值范围:
(1) MK_LBUTTON:鼠标左键被按下; (2) MK_RBUTTON:鼠标右键被按下; (3) MK_MBUTTON:鼠标中键被按下; (4) MK_SHIFT:键盘上的Shift键被按下; (5) MK_CONTROL:键盘上的Ctrl键被按下;
如果想知道某个键是否被按下,可用对应的位屏蔽值与nFlags参数作按位逻辑“与”运算,所的结果若为非零值,则表示该按钮被按下,例如:
if (nFlags & LBUTTON)
AfxMessageBox(“LButton is pressed down!”) Else
AfxMessageBox(“LButton is pressed Up!”); 如何区分两次单击和一次双击,这取决于两次按下按钮之间的时间间隔,只有当时间间隔小于一定值时才被认为是一次双击。Windows默认的时间为500ms。可以用SetDoubleClickTime()函数来重新设置时间间隔值。
若要使窗口函数能接收到鼠标双击产生的消息,在注册窗口类时,必须指明该窗口具有CS_DBLCLKS风格,否则,即使进行了双击操作,该窗口也只能收到两条“WM_LBUTTONDOWN”和“WM_LBUTTONUP”消息,例如:
wndclass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
3.3.2 捕捉鼠标
在交互式图形程序设计中,经常要使用鼠标的位置拾取、拖动或拖放,这些动作必须进行鼠标的捕捉。
鼠标捕捉只需要调用CWnd::SetCapture()函数。用户完成鼠标捕捉工作后一般是响应一个鼠标按下信息,要释放鼠标捕捉则是调用CWnd::ReleaseCapture()函数。释放被捕捉鼠标的最好时间是在响应鼠标弹起的时候(WM_LBUTTON)。
3.3.3 鼠标编程综合示例
示例1:在窗口中以文本的形式给出鼠标的状态,即当鼠标移动时,给出鼠标的位置;当鼠标按下鼠标左、右键时显示出鼠标按键状态。例如,当鼠标左键按下时,显示“LBUTTON DOWN!”。
第一步:建立一个myMouse工程文件; 第二步:添加鼠标事件处理函数
鼠标右击视图类(如CmyMouseView),选择“add windows message handler…”,弹出事件处理函数列表窗口,如图3-11所示
-- 21
图3-11 Windows事件处理函数列表窗口 从左边事件消息列表中选择“WM_LBUTTONDOWN”,然后单击“Add and Edit”按钮,即加入鼠标左键按下事件函数,并要求编辑事件处理程序。 第三步:输入事件处理程序
void CMymouseView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //获得pDC
CDC* pDC=GetDC();
pDC->TextOut(20,40,”LBUTTONDOWM!”); // 输出显示信息 CView::OnLButtonDown(nFlags, point); }
其中,阴影部分是用户输入的程序,其它内容都是自动生成的内容。
第四步:重复第二步和第三步,分别添加WM_LBUTTONUP,WM_MOUSEMOVE,WM_RBUTTONDOWN,WM_RBUTTONUP,WM_LBUTTONDBCLK, WM_RBUTTONDBCLK鼠标事件,并输入以下程序:
void CMouseView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default
CDC *pDC=GetDC();
pDC->TextOut(20,40,\ CView::OnLButtonUp(nFlags, point); }
void CMouseView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
pDC->TextOut(20,60,\
-- 22
CView::OnRButtonDown(nFlags, point); }
void CMouseView::OnRButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
pDC->TextOut(20,40,\ CView::OnRButtonUp(nFlags, point); }
void CMouseView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC(); char tbuf[80]; sprintf(tbuf,\ // 输出鼠标当前位置
pDC->TextOut(20,20,tbuf); CView::OnMouseMove(nFlags, point); }
void CMouseView::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
pDC->TextOut(20,80,\ CView::OnLButtonDblClk(nFlags, point); }
void CMouseView::OnRButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
pDC->TextOut(20,80,\ CView::OnRButtonDblClk(nFlags, point); }
第五步:编译程序,并验证执行结果。
示例2:采用鼠标橡皮筋技术画圆
鼠标橡皮筋技术画圆就是采用圆心和圆周上任一点画圆技术(简称C+P方法),首先用鼠标左击选择圆心位置,然后移动鼠标,圆随鼠标移动而扩大或缩小,当再次单击鼠标左键时,确定圆周上的一点,从而画出相应的圆。直线、矩形等基本图形都可以采用橡皮筋技术。
第一步:建立MouseSpring工程文件;
-- 23
第二步:向视图类中添加自定义的成员变量
用鼠标右键单击视图类,选择“Add Member Variable…”,添加下面三个成员变量。 proctected :
CPoint m_bO; // 圆心 CPoint m_bR; //圆上的点
int m_ist; //圆心与圆周上点的区别,m_ist=0,表示鼠标左击点为圆心, //m_ist=1,表示鼠标左击点为圆周上的点 操作方法如图3-13所示,分别添加上述三个成员变量。
图3-13 添加成员变量
第三步:向视图类中添加自定义的成员函数原型: public:
void DrawCircle(CDC* pDC, CPoint cenp, CPoint ardp); int ComputeRadius(CPoint cenp,CPoint ardp);
具体操作方法:用鼠标右键单击视图类,选择“Add Member Function…”,如图3-14所示。分别添加上述两个成员函数,分别用于画圆和计算圆的半径。
图3-14 添加成员函数
第三步:在视图类CPP文件的构造函数中初始化成员变量。
视图类的构造函数名与该视图类的名字相同。在视图类中选择构造函数,如:CMouseSpringView(),用鼠标左键双击,输入下面程序代码:
CMouseSpringView:: CMouseSpringView() {
//TODO: add construction code here m_bO.x=0; m_bO.y=0; //圆心
-- 24
m_bR.x=0; m_bR.y=0; //圆上的点 m_ist=0; //圆心与圆上的点区别 }
第四步:在视图类的OnDraw()函数中加入下列代码,实现视图绘图。 void CMouseSpringView::OnDraw(CDC* pDC) { CMouseSpringDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->SelectStockObject(NULL_BRUSH); DrawCircle(pDC,m_bO,m_bR); // 调用自定义的成员函数画圆 }
第五步:向视图类中添加两个鼠标消息响应函数,并输入鼠标处理程序代码。
具体操作方法与鼠标示例1方法相同。一个是OnLButtonDown()函数,另一个是OnMouseMove()函数。程序如下:
void CMouseSpringView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
pDC->SelectStockObject(NULL_BRUSH); if (!m_ist) //绘制圆 { m_bO=m_bR=point; //纪录第一次单击鼠标位置,定圆心 m_ist++; } else { m_bR=point; //记录第二次单击鼠标的位置,定圆周上的点 m_ist--; // 为新绘图作准备 DrawCircle(pDC,m_bO,m_bR); //绘制新圆 } ReleaseDC(pDC); //释放设备环境 CView::OnLButtonDown(nFlags, point); }
void CMouseSpringView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();
int nDrawmode=pDC->SetROP2(R2_NOT); //设置异或绘图模式,并保存原来绘图模式 pDC->SelectStockObject(NULL_BRUSH); if(m_ist==1)
-- 25