【计算机图形学课程】二.MFC鼠标响应函数模拟画图软件

2023-11-14

        上一篇文章我们讲述MFC绘制图形的基本函数,包括绘制直线、绘制矩形、绘制椭圆及绘制文字,同时通过绕圆旋转和矩形平移简单的理解了图形学知识。这篇文章我将介绍鼠标响应和键盘响应,通过这些事件让学生实现一个类似画图的简单软件,同时充分发挥学生想象,自己创作东西。
        前文:
       【计算机图形学课程】一.MFC基本绘图函数使用方法

 

一. MFC工程创建及鼠标响应

        新建一个MFC 单文档的应用程序"MousePic"。

        然后,选择"View(视图)"->"建立类向导",快键键是Ctrl+W。这是MFC非常重要的一个知识点,对话框或单文档设置按钮操作、响应函数都是通过该操作实现。

        在MFC ClassWizard中选择创建工程的"CMousePicView"类名,然后再"Message"中选择"WM_LBUTTONDOWN",鼠标左键按下响应操作。同时,双击它添加函数OnLButtonDown()。

        鼠标常见消息响应:
        WM_LBUTTONDBCLK 双击鼠标左键
        WM_LBUTTONDOWN 按下鼠标左键
        WM_LBUTTONUP 释放鼠标左键
        WM_MOUSEMOVE 在客户区移动鼠标
        WM_RBUTTONDBCLK 双击鼠标右键
        WM_RBUTTONDOWN 按下鼠标右键
        WM_RBUTTONUP 释放鼠标右键
        

二. MFC实现鼠标响应操作

        1.鼠标左键按下
        双击函数会定位到"MousePicView.cpp"文件,现在可以对OnLButtonDown()函数进行编辑。其中CPoint point参数记录当前鼠标左键按下的位置,nFlags表示掩码。

        然后添加代码如下:

//定义一个点类型的变量,用来保存当用户点击界面时点击的位置
CPoint m_point;

//鼠标左键按下
void CMousePicView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	//把当前点击的点的位置赋给点m_point
	m_point = point;
	CView::OnLButtonDown(nFlags, point);
}

        2.鼠标左键释放
        通过同样的方法在"类向导"中实现鼠标左键释放函数,如下图所示。

        添加代码主要是鼠标释放(弹起):

//鼠标释放:记录当前坐标
void CMousePicView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	//绘制图形
	CDC *p = GetDC();
	p->MoveTo(m_point);    //鼠标移动到左键按下点
	p->LineTo(point);      //绘制一条直线 终点为鼠标释放点
	CView::OnLButtonUp(nFlags, point);
}

        此时鼠标绘制图形如下所示,但是存在两个问题:绘制过程中不可见、绘制结果只是直线。

        所以,需要借助鼠标移动函数实现,在鼠标移动过程中就进行绘制,同时引入bool类型的变量,判断鼠标按下或释放,按下的时候进行绘制操作。

        3.鼠标左键移动
        通过同样的方法在"类向导"中实现鼠标左键释放函数。

        完整代码如下所示:

//定义一个点类型的变量,用来保存当用户点击界面时点击的位置
CPoint m_point;

//定义布尔型变量 m_click=true表示鼠标点击 false表示鼠标释放
bool m_click;

//鼠标左键按下
void CMousePicView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	//把当前点击的点的位置赋给点m_point
	m_point = point;
	m_click = true;
	CView::OnLButtonDown(nFlags, point);
}


//鼠标释放:记录当前坐标
void CMousePicView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	//绘制图形
	/*
	CDC *p = GetDC();
	p->MoveTo(m_point);    //鼠标移动到左键按下点
	p->LineTo(point);      //绘制一条直线 终点为鼠标释放点
	*/
	m_click = false;
	CView::OnLButtonUp(nFlags, point);
}

//鼠标移动绘制图形
void CMousePicView::OnMouseMove(UINT nFlags, CPoint point) 
{
	//定义画笔并选择
	CDC *p=GetDC();
	CPen pen(PS_SOLID, 4, RGB(255,0,0));
	p->SelectObject(pen);

	//鼠标按下进行绘制
	if(m_click==true) {
		p->MoveTo(m_point);
		p->LineTo(point);
		m_point = point;
	}
	CView::OnMouseMove(nFlags, point);
}

        绘制结果如下所示,相当于一个简单的画图软件。

        4.补充知识
        如果在OnMouseMove()鼠标移动函数if判断中缺少代码m_point = point,它会出现意想不到的效果,因为你需要每次绘制,鼠标移动当前点坐标point都需要赋值给下次绘制的起始坐标,供p->MoveTo(m_point)使用。

        同时,你可以绘制圆形、矩形等相关形状,不仅仅限定于直线。

//鼠标移动绘制图形
void CMousePicView::OnMouseMove(UINT nFlags, CPoint point) 
{
	//定义画笔并选择
	CDC *p=GetDC();
	CPen pen(PS_SOLID, 1, RGB(255,0,0));
	p->SelectObject(pen);

	//鼠标按下进行绘制
	if(m_click==true) {
		p->MoveTo(m_point);
		//p->LineTo(point);
		p->Rectangle(point.x, point.y,point.x+20, point.y+30);
		m_point = point;
	}
	CView::OnMouseMove(nFlags, point);
}

        输出如下所示:


        绘制中,定义了画笔Pen,正确的方法需要在绘制完成后,进行释放该画笔。核心代码如下:

	//定义画笔绘制矩形  
    CPen MyPen, *OldPen;   
    MyPen.CreatePen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝色  
    OldPen = pDC->SelectObject(&MyPen);        //旧画笔赋值  

	//绘制图形


	//清除  
    pDC->SelectObject(OldPen);  
    MyPen.DeleteObject();  

 

三. MFC键盘响应函数

        1.基础知识
        Windows对每个按键定义了与设备无关的编码,这种编码叫做虚拟码。有了这个虚拟码,Windwos程序员可以使用该虚拟码进行编程。其中键盘上部分按键的虚拟码如下图所示:

        Windows按键消息常见如下:
        WM_CHAR 敲击键盘上的字符键时,产生该消息
        WM_KEYDOWN 任意键(包括字符键)被按下时都产生该消息,如果被按下的是字符键,在产生消息的同时还产生字符消息
        WM_KEYUP 任意角(包括字符键)被释放都产生该消息 
        WM_SYSKEYDOWN F10被按下或者Alt与另一个键被同时按下
        WM_SYSKEYUP F10被释放或者Alt与另一个键被同时释放

        2.按键响应操作
        同样,通过类向导建立按键按下函数。

        然后添加如下代码,按下任意一个键,绘制的矩形向右平移40距离。

//鼠标按键
void CMousePicView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	CDC *p = GetDC();
	p->MoveTo(m_point);       //键盘按下
	m_point.x += 40;          //水平平移40
	p->Rectangle(m_point.x, m_point.y, m_point.x+20, m_point.y+30);
	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

        绘制图形如下所示:

        3.响应不同键盘的操作
        需要将UINT nChar转换为Char字符型,然后进行盘,WASD进行上下左右移动绘制椭圆。

//鼠标按键
void CMousePicView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	CDC *p = GetDC();
	char cChar;               //当前被按下的字符
    cChar = char(nChar);      //将按下的键转换为字符

	//定义画笔  
    CPen MyPen, *OldPen;   
    MyPen.CreatePen(PS_DASH, 2, RGB(0,0,255));  //虚线 粗2 蓝色  
    OldPen = p->SelectObject(&MyPen);           //旧画笔赋值  
  
    //画刷  
    CBrush MyBrush, *OldBrush;  
    MyBrush.CreateSolidBrush(RGB(0,255,0));  
    OldBrush = p->SelectObject(&MyBrush);  


    if (cChar == 'D') {
		p->MoveTo(m_point);       //D键按下
		m_point.x += 40;          //水平向右平移40
		p->Ellipse(m_point.x, m_point.y, m_point.x+20, m_point.y+40);
	}
	if (cChar == 'A') {
		p->MoveTo(m_point);       //A键按下
		m_point.x -= 40;          //水平向左平移40
		p->Ellipse(m_point.x, m_point.y, m_point.x+20, m_point.y+40);
	}
	if (cChar == 'S') {
		p->MoveTo(m_point);       //S键按下
		m_point.y += 50;          //竖直向下平移50
		p->Ellipse(m_point.x, m_point.y, m_point.x+20, m_point.y+40);
	}
	if (cChar == 'W') {
		p->MoveTo(m_point);       //W键按下
		m_point.y -= 50;          //竖直向上平移50
		p->Ellipse(m_point.x, m_point.y, m_point.x+20, m_point.y+40);
	}
	

	//清除  
    p->SelectObject(OldPen);  
    MyPen.DeleteObject();  
    p->SelectObject(OldBrush);  
    MyBrush.DeleteObject(); 

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

        绘制如下图所示:


        4.按键光标选择

//鼠标按键
void CMousePicView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	//光标操作
    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);
    }
    else{
        if (hCursor){
            hPrevCursor = SetCursor(hCursor);
            if (hPrevCursor)
                DestroyCursor(hPrevCursor);
        }
    }

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

 

四. MFC鼠标绘制-学生作业展示

        最后展示学生做的成果,虽然代码非常简单,原理也很简单,但是学生做得真的挺好的,原来编程还可以这样上啊,一方面提升学生的学习兴趣,另一方面增加他们的编程能力。

  

 

 

 

  

 

 

   

        还是那句话,非常佩服学生的创造力及想象力吧!而且编程课原来可以这么进行,提升学生的编程能力的同时也培养了学生的兴趣。希望文章对你有所帮助~
        (By:Eastmount 2016-11-20 半夜2点半 http://blog.csdn.net/eastmount/ )

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【计算机图形学课程】二.MFC鼠标响应函数模拟画图软件 的相关文章

  • 菜单被裁剪

    我有一个MFC项目 它支持 40 多种语言 我的电脑上有两个显示器 它们都是不同尺寸的显示器和不同的分辨率 如果我将应用程序移至较小的显示器上 则不会显示完整的语言菜单 我知道它会显示滚动条 为什么不是呢 我的菜单是标准菜单 没有什么花哨
  • 如何显示非模式对话框并立即在其中显示信息?

    我想在屏幕上显示一个无模式对话框并在其中显示一些信息 但是 如果我按照以下方式使用它 则会出现一些问题 function showdialog XXX heavy work update the dialog heavy work upda
  • CloseWindow和WM_CLOSE有什么关系

    我现在有点困惑 是吗 WM CLOSE http msdn microsoft com en us library windows desktop ms632617 28v vs 85 29 aspx and CloseWindow htt
  • 如何最好地避免 C++/CLI 本机类型中的双重转换

    传统上 我一直使用 MFC 扩展 dll 并使用 dllimport dllexport 导入 导出 但是 当 dll 更改为使用 clr 时 此方法的成本会变得很高 因为调用可能会导致双重转换 我现在的性能受到了巨大的打击 需要停止双重重
  • 使用 CSplitterWnd 在 CChildFrame 中创建多个视图

    我正在使用 MFC MDI 我需要创建如下视图 我的 ChildWnd 分为两部分 它们是LeftView CView 和RightView CScrollView LeftView 分为两部分 TreeView 和 FormView 我怎
  • 如何在 MFC 中创建 GUI

    我需要能够即时创建指南 MFC中有没有办法做到这一点 我了解了如何在 net 中做到这一点 但我们还没有做到这一点 如果没有 您是否有一些我可以使用的代码的指针 don t forget to add Rpcrt4 lib to your
  • 跨平台 Windows / OS X 开发,具有大量现有代码库

    对于使用 MFC 和 WinAPI 用 C 编写的复杂应用程序 有大量现有代码库 需要将其移植到 Mac OS X 理想的解决方案是在不同平台之间拥有尽可能多的通用代码 尤其是诸如业务之类的代码逻辑 GUI 可能会有所不同 具体取决于跨平台
  • 创建非托管常规 MFC DLL 并从托管 C++ .NET 应用程序调用它时出现问题

    我有几个关于 DLL 的问题 我尝试了很多 但无法获得完整的图片 大多数示例都是用 C 等编写的 使用 VS2005 中的向导 我创建了一个非托管 MFC 常规 DLL 由于剩余代码 必须是 MFC 然后我尝试将其导入 VS2005 管理的
  • 如何发光最小。最大和关闭按钮?

    我按照以下指南使用 DWM API 创建自定义 Aero 框架 My work void CMainFrame OnActivate UINT nState CWnd pWndOther BOOL bMinimized CFrameWnd
  • MFC:如何在一个函数中捕获对话框每个控件的设置焦点

    我有 n 个对话框 它们具有相同的基本对话框 每个对话框都有自己的控件 编辑框 组合框 列表控件 etc 在基本对话框中 如何设置每个控件的焦点消息 例如 给出一个消息框 text Hello I got focus my ID is d
  • 如何调整 CWnd 内 WPF 控件的大小?

    我正在托管 WPFUserControlMFC 内部CWnd 它工作得很好 我现在需要弄清楚如何与其父控件一起调整控件的大小 我已经迷上了OnSize我正在打电话GetWindowRect并将结果设置为我的控件 如下所示 void CChi
  • 禁用/启用 MFC 功能包的功能区按钮

    我正在使用 MFC 功能包 并且功能区栏上有一些按钮 即 CMFCRibbonButton 的实例 问题是我想在某些条件下启用和禁用其中一些 但在运行时 我怎样才能做到这一点 因为没有具体的方法 我听说解决方案是在运行时附加 分离事件处理程
  • 获取正在运行的程序的属性

    我想开发一个程序 其 ID 是一张牌 因为它在另一个正在运行的程序 例如扑克或红心游戏或其他程序 中播放 我首先尝试获取有关已运行的游戏程序的所需信息 但我从一开始就遇到了问题 我正在运行 MSVC 2013 并开发 MFC 应用程序 现在
  • 捕获由纯 C++ dll 中的 MFC 应用程序生成的 Windows 消息

    首先 这可能吗 我有一个与某些硬件接口的第三方 dll 它是用MFC编写的 我 从 dll 供应商处 收到了一个示例 Visual Studio 2010 解决方案 该解决方案只有一个项目 调用相关第三方 dll 的 MFC 应用程序 ex
  • .NET(或 MFC)的高速图形控件?

    我需要编写一个数字示波器类型的应用程序 有很多很棒的静态绘图控件 但我需要一些可以绘制每秒处理 4000 个样本的 16 条轨迹的东西 有人知道 NET 的高速图形控件吗 我什至会选择 MFC 因为它可以封装到 NET 控件中 谢谢您的帮助
  • MFC编辑控件更新

    我尝试使用它添加的变量来更新编辑控件的文本 这是一个CString但我失败了 m sNrAuto some text UpdateData TRUE 我也尝试过使用UpdateWindow 但编辑控件仍为空白 我知道我可以使用SetWind
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 支持 ARM 上的 Windows 10 桌面应用程序 - MFC 和 COM 以及 OPOS 可以工作吗?

    我试图了解将在 x86 Windows 10 上运行的 C MFC 应用程序移植到具有 Qualcomm Snapdragon 处理器的 ARM Windows 10 设备的障碍 32位应用程序具有以下特点 MFC 与 C 用于用户界面 C
  • 如何将tchar指针转换为char指针

    我想将 tchar 转换为 char 这可能吗 如果是的话该怎么做 我使用unicode设置 A TCHAR要么是一个普通的char or a wchar t取决于您的项目的设置 如果是后者 您需要使用WideCharToMultiByte

随机推荐

  • [代码调试]SPHP代码调试误入的坑

    SPHP论文下载链接 今天在找SPHP论文的代码时 发现谷歌上有一位兄弟上传了 说是作者上传的源码 以为很快就可以将论文中的结果复现出来 却没想到折腾了一晚上毫无进展 下面我把我的错误经验分享给大家 SPHP代码下载链接 当我们下载完这个代
  • 编程实战(3)——python绘制极坐标雷达图

    编程实战 3 python绘制极坐标雷达图 文章目录 编程实战 3 python绘制极坐标雷达图 综述 绘图代码和解析 绘制一张多主体雷达图 预处理 封闭雷达图 绘制图像 绘制多张单主体雷达图 建立子图 循环遍历画每个子图 综述 pytho
  • java远程连接linux并发送命令,两种方案比较Jsch与ganymed-ssh2

    通过Jsch连接 step 1引入jar包
  • k8s之ReplicaSet

    我们在定义pod资源时 可以直接创建一个kind Pod类型的自主式pod 但是这存在一个问题 假如pod被删除了 那这个pod就不能自我恢复 就会彻底被删除 线上这种情况非常危险 所以今天就给大家讲解下pod的控制器 所谓控制器就是能够管
  • Log4cpp:为中小型C++项目加上log支持

    对于一个上点规模的C 项目而言 Log的作用是毋庸置疑的 出问题的时候 看了Log 常见的问题处理起来自是方便不过 即使遇到麻烦的问题 也可以从 总发现不少蛛丝马迹 因此一个严肃的项目应该从一开始就好好考虑如何打Log 便于分析 维护 现实
  • Selenium3自动化测试【6】浏览器driver的安装(FireFox)

    Selenium支持各种浏览器 读者可以在不同的浏览器中开展自动化测试 它支持的浏览器包括IE FireFox Chrome Opera Safari等 本讲就围绕常用的FireFox Chrome与Selenium的结合进行讲解 由于Se
  • 遥测终端机RTU助力城市内涝监测系统

    一 背景概述 2023年第5号台风 杜苏芮 周末登陆福建晋江 一波未平一波又起 卡努台风也进入了48小时警戒线 台风侵袭给城市基础设施和居民生活带来了严重的影响 后面第11号台风 海葵 号随之带来了更多城市内涝问题 且难以一下子解决 为了有
  • iOS 开发之CocoaPods常用第三方框架导入

    1 使用终端打开文件 假设项目放在桌面上 cd Desktop cd 项目名称 2 创建Podfile文件 命令如下 vim Podfile 3 输入 i 进入编辑模式并copy下面的这段代码 platform ios 8 0 target
  • C语言比较两个字符串是否相等的案例讲解

    思路分析 比较两个字符串是否相等要看两个字符串的长度和内容是否一样 如果长度和内容有一个不一样那么这两个字符串不相等 方法1 strcmp函数可以比较2个字符串的大小和内容是否一样 我们可以使用这个函数来进行判断 知识补充 strcmp函数
  • Node.js——回调函数及事件处理机制

    目录 回调函数 定义 理解 事件处理机制 补充 回调函数 定义 什么是回调函数呢 通俗的讲 将一个函数A作为参数传递给函数B 在函数B内对函数A进行调用 函数A就是回调函数 Node js 异步编程的直接体现就是回调 回调函数在完成任务后就
  • VM虚拟机安装Ubantu18.04【踩坑无数】【指路合集】

    写在前面 因为自己最近正在学习 作为一个小白 也遇到了很多问题 这里一起记录一下给大家遇到相同问题的指指路 其实内容多难倒也没有 跟着教程走也不会有什么难度 只希望能减少遇到同样问题的人search有效信息的来解决自己问题的时间 安装教程指
  • git warning: LF will be replaced by CRLF in package.json解决办法

    在修改了package json文件之后 使用git add 提交代码出现以下报错 warning LF will be replaced by CRLF in package json The file will have its ori
  • JVM线上故障排查的基本操作

    前言 线上经常会遇到各种各样的问题 CPU 飚高 内存溢出 频繁 GC 总的来说 基本上就是cpu 磁盘 内存以及网络等相关问题 所以进行排查时候尽量四个方面依次排查一遍 同时例如jstack jmap等工具也是不囿于一个方面的问题的 基本
  • [Python] 转贴:anaconda 下多版本Python 安装说明(win10)

    anaconda 下多版本Python 安装说明 转贴再补充 原帖见 https blog csdn net soloyuyang article details 75807425在原帖基础上补充了图 但是主要工作还是原帖的 win10系统
  • android 串口开发

    FT312D有参考
  • AD批量隐藏元件注释(Comment)

    步骤 1 右击元件注释在菜单中选中 Find Similar Objects 查找相似元件 2 在弹出来的菜单中 在Part comment 后面的下拉框中选择Same 即设定筛选条件为筛选所有相同comment的元件 然后点击OK 最后点
  • HttpComponents入门解析

    1 简介 超文本传输协议 http 是目前互联网上极其普遍的传输协议 它为构建功能丰富 绚丽多彩的网页提供了强大的支持 构建一个网站 通常无需直接操作http协议 目前流行的WEB框架已经透明的将这些底层功能封装的很好了 如常见的J2EE
  • java 关于锁常见面试题

    1 synchronized作用于静态方法和非静态方法的区别 非静态方法 给对象加锁 可以理解为给这个对象的内存上锁 注意 只是这块内存 其他同类对象都会有各自的内存锁 这时候在其他一个以上线程中执行该对象的这个同步方法 注意 是该对象 就
  • 「考生说」双非考生依旧可以成为“天选之子”

    随着2022年考研复试季的结束 微博热搜开始被 六战法考最终上岸的北大物业小哥刘政 中专生考进清华 等词条刷屏 大批网友也开启了他们 夸夸 能力 在这大量的评论中依旧有着众多让人鼓舞的金句产出 你不需要很厉害才能开始 但你需要开始才能很厉害
  • 【计算机图形学课程】二.MFC鼠标响应函数模拟画图软件

    上一篇文章我们讲述MFC绘制图形的基本函数 包括绘制直线 绘制矩形 绘制椭圆及绘制文字 同时通过绕圆旋转和矩形平移简单的理解了图形学知识 这篇文章我将介绍鼠标响应和键盘响应 通过这些事件让学生实现一个类似画图的简单软件 同时充分发挥学生想象