MFC快捷菜单以及位图的加载和移动操作



功能要求:自行设计一个位图,然后令位图沿着直线和矩形的边界移动

一、效果:


(一)画直线

在这里插入图片描述

(二)画矩形

在这里插入图片描述

二、基本介绍

(一)功能实现用到的方法
  • MFC主边框的调整

  • 菜单栏的操作

  • 快捷菜单的操作

  • 计时器的基本使用

  • InvalidateRect(icon_rect,true);函数的使用

  • 位图的加载和使用

菜单栏的操作在我之前的一篇blog里,这里不再进行赘述

地址如下

MFC对话框、菜单栏、工具栏、控件的创建和基本使用

(二)环境描述

环境:visual studio 2010

三、实现过程


(一)主编框调整

首先是重设一下主边框

位置在CMainFrame.cpp里的CMainFrame::PreCreateWindow函数里

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: 在此处通过修改
    
	//  CREATESTRUCT cs 来修改窗口类或样式
	// 设置窗口大小
	cs.cx=800;
	cs.cy=600;
	// 将最小化按钮无效
	cs.style&=~WS_MINIMIZEBOX;
    //无法改变视窗尺寸
    // cs.style&=~WS_THICKFRAME;
	//最大化窗口按钮失效
	//cs.style&=~WS_MAXIMIZEBOX;
	return TRUE;
}

(二)快捷菜单的使用

1、添加快捷菜单资源

在这里插入图片描述

2、类向导里添加相应的消息处理函数

在类向导里添加WM_CONTEXTMENU消息的处理函数

在这里插入图片描述

3、为快捷菜单下的子菜单添加处理函数

在这里插入图片描述

4、快捷菜单加载
void Cthird4View::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
	// TODO: 在此处添加消息处理程序代码
	CMenu menu;
	// 加载快捷菜单
	menu.LoadMenuW(IDR_POPUP_MENU);
	CMenu *pMenu=menu.GetSubMenu(0);
	// 弹出快捷菜单
	pMenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);
}

5、画直线和矩形
void Cthird4View::OnPopupLine()
{
	// TODO: 在此添加命令处理程序代码
	CDC *pDC=GetDC();
	CRect rect;
	GetClientRect(&rect);
	pDC->MoveTo(rect.right/2-200,rect.bottom/2);
	pDC->LineTo(rect.right/2+200,rect.bottom/2);
	// 设置位图的初始位置
	icon_pos.x=rect.right/2-130;
	icon_pos.y=rect.bottom/2-3;
	// 设置icon周围的边框
	icon_rect.right=icon_pos.x+10;
	icon_rect.left=icon_pos.x-27.0;

	icon_rect.bottom=icon_pos.y+42;
	icon_rect.top=icon_pos.y+7;
	// 设置画线为type=0
	type=0;
}


void Cthird4View::OnPopupRect()
{
	// TODO: 在此添加命令处理程序代码
	CDC *pDC=GetDC();
	CRect rect;
	// 获得客户区的数据
	GetClientRect(&rect);
	// 选择透明画刷
	CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
	pDC->SelectObject(pBrush);
	pDC->Rectangle(rect.right/2-150,rect.bottom/2-150,rect.right/2+150,rect.bottom/2+150);

	// 设置位图的初始位置
	icon_pos.x=rect.right/2-176;
	icon_pos.y=rect.bottom/2-196;
	// 设置icon周围的边框
	icon_rect.right=icon_pos.x+4;
	icon_rect.left=icon_pos.x-21.0;

	icon_rect.bottom=icon_pos.y+42;
	icon_rect.top=icon_pos.y+7;
	// 设置画矩形为type=0
	type=1;
}

icon_posicon_rect是为之后的位图设定的参数

在类视图里直接添加变量即可

在这里插入图片描述

类型如下

CPoint icon_pos;
CRect icon_rect;

(三)位图的加载和使用

1、添加icon资源

在资源视图里为添加icon即可,工具栏在上方

在这里插入图片描述

2、Timer计时器

类视图里的WM_TIMER是计时器的消息

在这里插入图片描述

OnBeginMove()OnStopMove()函数是菜单栏里计时器的处理函数

在这里插入图片描述
其代码如下

void Cthird4View::OnBeginMove()
{
	// TODO: 在此添加命令处理程序代码
	//设为70时比较流畅
	SetTimer(1,70,NULL);
}


void Cthird4View::OnStopMove()
{
	// TODO: 在此添加命令处理程序代码
	KillTimer(1);
}

3、InvalidateRect(icon_rect,true);函数

接下就是位图移动的重点动作了

这个时候需要先介绍InvalidateRect(icon_rect,true);函数

简单来说就是调用这个函数之后,会用背景色填充icon_rect所表示的矩形区域

更加详细的原理分析和其他问题网上相关文章较多
请读者自行查找
这里列出几篇不错的文章
https://blog.csdn.net/u011580175/article/details/56354223
https://blog.csdn.net/harvic880925/article/details/8963711?locationNum=11

4、位图移动核心代码:
void Cthird4View::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(nIDEvent==1){
		//如果要沿矩形移动
		if(type==1){
			CDC *pDC=GetDC();
			// 加载位图
			HICON icon;
			icon=AfxGetApp()->LoadIconW(IDI_MYICON);
			
			CRect rect,newRect;
			// 获取客户区数据
			GetClientRect(&rect);
			newRect=icon_rect;
			// 矩形的上边界
			if(icon_pos.x>rect.right/2-229&&icon_pos.x<rect.right/2+166&&icon_pos.y<=rect.bottom/2-196){
				if(flag==0){
				// newRect向右移动
				newRect.right+=offset;
				newRect.left+=offset;
				// 重绘icon_rect区域
				InvalidateRect(icon_rect,true);
				// 绘制位图
				pDC->DrawIcon(icon_pos,icon);
				// icon向右移动
				icon_pos.x+=offset;
				}
				else{
					newRect.right+=offset;
					newRect.left+=offset;
					// 重绘icon_rect区域
					InvalidateRect(icon_rect,true);
					// icon向右移动
					icon_pos.x+=offset;
					// 绘制位图
					pDC->DrawIcon(icon_pos,icon);
				}
				// 更新icon_rect 区域
				icon_rect=newRect;
			}// 矩形的右边界
			else if(icon_pos.x>=rect.right/2+150&&icon_pos.y>=rect.bottom/2-196&&icon_pos.y<=rect.bottom/2+126){
				// 重绘newRect区域
				InvalidateRect(newRect,true);
				// 设置转向
				if(flag==0){
					// newRect向右移动
					newRect.right+=offset;
					newRect.left+=offset;
					flag=1;
				}
				else{
					// newRect向下移动
					newRect.top+=offset;
					newRect.bottom+=offset;
					// icon向下移动
					icon_pos.y+=offset;
				}
				// 绘制位图
				pDC->DrawIcon(icon_pos,icon);
				// 更新icon_rect 区域
				icon_rect=newRect;
			}// 矩形的下边界
			else if(icon_pos.x>=rect.right/2-190&&icon_pos.x<=rect.right/2+226&&icon_pos.y>=rect.bottom/2+104){
				// newRect向左移动
				newRect.right-=offset;
				newRect.left-=offset;
				// 重绘icon_rect区域
				InvalidateRect(icon_rect,true);
				// icon向左移动
				icon_pos.x-=offset;
				// 绘制位图
				pDC->DrawIcon(icon_pos,icon);
				// 更新icon_rect 区域
				icon_rect=newRect;
			}// 矩形的左边界
			else if(icon_pos.x<=rect.right/2+150&&icon_pos.y>=rect.bottom/2-176&&icon_pos.y<=rect.bottom/2+166){
				// newRect向上移动
				newRect.top-=offset;
				newRect.bottom-=offset;
				// 重绘icon_rect区域
				InvalidateRect(icon_rect,true);
				// icon向上移动
				icon_pos.y-=offset;
				// 绘制位图
				pDC->DrawIcon(icon_pos,icon);
				// 更新icon_rect 区域
				icon_rect=newRect;
			}
			
			
		}
		//如果要沿直线移动
		if(type==0){
			CDC *pDC=GetDC();
			//加载位图
			HICON icon;
			icon=AfxGetApp()->LoadIconW(IDI_MYICON);
			pDC->DrawIcon(icon_pos,icon);
			// 获得客户区的数据
			CRect rect,newRect;
			GetClientRect(&rect);
			// newRect区域移动
			newRect=icon_rect;
			newRect.right+=offset;
			newRect.left+=offset;
			// 到边界时反向
			if(icon_pos.x<rect.right/2-190||icon_pos.x>rect.right/2+150)
				offset=-offset;
			// 重绘icon_rect区域
			InvalidateRect(icon_rect,true);
			// 更新icon_rect
			icon_rect=newRect;
			// icon向左移动
			icon_pos.x+=offset;
			
			}
		}
	CView::OnTimer(nIDEvent);
}

其中的flag参数也是添加的变量,类型为bool

四、总结

本章节重点讲述了快捷菜单和位图的相关操作


如果本文对老铁们有帮助的话请给个三连叭~~
在这里插入图片描述

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joshua_yi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值