程序最重要的部分之一是对鼠标和键盘操作的响应。
一.了解鼠标事件。以前,对鼠标事件的理解仅限于控件的单击和双击事件。但是实际的鼠标操作包括很多。在这里,我们将使用一个用于绘制图片的小程序来说明对鼠标的响应。
首先创建一个新的MFC程序,选择对话框类型,然后将Mouse设置为程序标题。创建程序框架后,删除对话框窗口中的所有控件。这样,整个对话框都可以用于绘图。
然后在对话框窗口右下角的属性窗口中选择消息选项,将列出一系列事件消息。例如,WM_LBUTONDOWN(按下鼠标左键),WM_LBUTTONUP(按下鼠标左键),WM_MOUSEMOVE(鼠标在应用程序窗口空间中移动)。绘制程序主要通过mousemove事件实现。选择事件以添加功能。将以下代码添加到entry函数的实现中。
void CMouseDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //检查鼠标左键是否被按下 if ((nFlags&MK_LBUTTON) == MK_LBUTTON){ //获取设备上下文 CClientDC dc(this); //画出像素 dc.SetPixel(point.x, point.y, RGB(100, 100, 250)); } CDialogEx::OnMouseMove(nFlags, point); }
然后您可以运行该程序,但是此绘图程序与我们通常的不同。稍后再说。
让我们先看一下这段代码。有两个参数传递给该函数。第一个参数是一组标记,用于确定按下哪个鼠标按钮。判断if的前半部分是按位与,过滤器是被按下的左按钮的标记,然后与后半部分匹配;第二个参数是当前鼠标的位置,即鼠标在对话框窗口中的坐标,它包含两个成员:x,y;然后您可以使用此信息在窗口上画一个点。
在绘制点之前,我们还需要获取对话框窗口的设备上下文。也就是说,CClientDC dc(this);这个说法。这是通过声明CClientDC类的新实例以及该参数是当前窗口的指针来完成的。此类封装设备上下文以及可以在其上执行的大多数操作,包括所有屏幕绘制操作。可以理解,设备上下文是一个画布,您可以在其上绘制程序。
下一个句子是绘制一个点,您可以控制该点的颜色。颜色控制由RGB值控制。
然后讨论该程序的问题。运行该程序时,您会发现,如果移动得太快,它将不是一条实线,而是一个点。这取决于我们计算机每隔一段的程序的性质。是时候检查鼠标的位置并绘制一个点了。如果运动缓慢,则仍然可以实现。如果速度太快,它将变为虚线。那我们怎么解决呢?很简单,在由鼠标确定的两点之间连接一条直线。请按照以下步骤实现:
首先将两个成员变量添加到我们的对话框类-CMouseDlg类中,即m_iPrevX,m_iPrevY,类型为int,属性为private。用于保存上一点的数据。连接起来很方便。
然后对上一个功能进行一些更改。
void CMouseDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //检查鼠标左键是否被按下 if ((nFlags&MK_LBUTTON) == MK_LBUTTON){ //获取设备上下文 CClientDC dc(this); //从从前一点到当前点画一条线 dc.MoveTo(m_iPrevX, m_iPrevY); dc.LineTo(point.x, point.y); //把当前点作为前一点保存 m_iPrevX = point.x; m_iPrevY = point.y; } CDialogEx::OnMouseMove(nFlags, point); }
dc.MoveTo(m_iPrevX,m_iPrevY); dc.LineTo(point.x,point.y);这两个回合是用来连接的,您首先需要移动到第一个位置,然后画一条线到第二个位置,这是非常重要的一步。没有此步骤,Windows将不知道从哪里开始绘制。这时,运行程序会更好,并且不会出现虚线,但是存在一个新问题。每次按下鼠标左键按下键时,它会立即连接到最后一个点。
现在,为了进行最后的改进,该程序被完善为:当按下鼠标左键时,当前位置将用于初始化前一个位置的位置变量。
首先在消息模式下将功能添加到对话框对象的WM_LBUTTONDOWN消息中。该函数的内容如下:
void CMouseDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_iPrevX = point.x; m_iPrevY = point.y; CDialogEx::OnLButtonDown(nFlags, point); }
当我们再次运行它时,程序将达到所需的功能。
二.对键盘的响应。
获取键盘事件与获取鼠标事件非常相似。但是键盘事件远少于鼠标事件。
WM_KEYDOWN按下了一个键
WM_KEYUP释放了一个键
按下WM_SYSKEYDOWNF10或同时按下Alt和另一个键
释放WM_SYSKEYUPF10或同时释放Alt和另一个键
这些事件消息可用于对话框窗口对象,并且仅当窗口中没有启用的控件时才会触发。
我们在上述绘图程序中添加了一个小功能,当按下一个键时,光标的形状就会改变。 A更改为默认光标; B变为I形垂直线; C更改为沙漏型; X退出程序
首先选择WM_KEYDOWN消息以添加功能。代码如下:
void CMouseDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: 在此添加消息处理程序代码和/或调用默认值 char cChar;//当前被按下的字符 HCURSOR hCursor = 0;//显示光标句柄 HCURSOR hPrevCursor = 0;//以前的光标句柄 cChar = char(nChar);//将按下的键转换为字符 if (cChar == 'A'){ //加载箭头光标 hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); } if (cChar == 'B'){ //加载箭头光标 hCursor = AfxGetApp()->LoadStandardCursor(IDC_IBEAM); } if (cChar == 'C'){ //加载箭头光标 hCursor = AfxGetApp()->LoadStandardCursor(IDC_WAIT); } if (cChar == 'X'){ hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); hPrevCursor = SetCursor(hCursor); if (hPrevCursor) DestroyCursor(hPrevCursor); OnOK();//退出应用 } else{ if (hCursor){ hPrevCursor = SetCursor(hCursor); if (hPrevCursor) DestroyCursor(hPrevCursor); } } CDialogEx::OnKeyDown(nChar, nRepCnt, nFlags); }
此功能具有三个参数。第一个nChar是按下的键,这是字符的字符代码,需要将其转换为代码第一行中的字符。然后可以直接比较;第二个参数nRepCnt是按键的时间。通常在按下时会释放它。该值为1.如果按住该键,则该值将增加。该值告诉您Windows认为已按下此键的次数。第三个参数nFlags是标志的组合,可以确定在按下该键的同时按下Alt键还是扩展键。
更改光标的过程是:第一步是通过LoadStandardCursor(IDC_ARROW)将光标转移到内存中。然后,将游标的句柄传递给SetCursor函数,此函数将游标转换为与该句柄相对应的游标,并返回上一个游标的句柄。 DestroyCursor(hPrevCursor)可用于销毁上一个光标。
注意:当鼠标移动时,光标将切换到默认箭头。
AfxGetApp函数:上面的LoadStandardCursor由AfxGetApp调用。此函数是一个全局函数,它返回当前应用程序类的实例。应用程序类是当前应用程序中CWinApp的后代。给我们写的程序是CMouseApp类。当我们需要访问封装在CWinApp类或当前派生类中的函数时,可以使用AfxGetApp函数获取指向它的指针。如果您不熟悉继承和派生,请回过头来仔细阅读c ++书。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-344769-1.html
甲午战争前
咋回去呢