功能要求:自行设计一个位图,然后令位图沿着直线和矩形的边界移动
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;
}
在类向导里添加WM_CONTEXTMENU
消息的处理函数
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);
}
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_pos
和icon_rect
是为之后的位图设定的参数
在类视图里直接添加变量即可
类型如下
CPoint icon_pos;
CRect icon_rect;
在资源视图里为添加icon即可,工具栏在上方
类视图里的WM_TIMER
是计时器的消息
OnBeginMove()
和OnStopMove()
函数是菜单栏里计时器的处理函数
void Cthird4View::OnBeginMove()
{
// TODO: 在此添加命令处理程序代码
//设为70时比较流畅
SetTimer(1,70,NULL);
}
void Cthird4View::OnStopMove()
{
// TODO: 在此添加命令处理程序代码
KillTimer(1);
}
接下就是位图移动的重点动作了
这个时候需要先介绍InvalidateRect(icon_rect,true);
函数
简单来说就是调用这个函数之后,会用背景色填充icon_rect
所表示的矩形区域
更加详细的原理分析和其他问题网上相关文章较多
请读者自行查找
这里列出几篇不错的文章
https://blog.csdn.net/u011580175/article/details/56354223
https://blog.csdn.net/harvic880925/article/details/8963711?locationNum=11
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
本章节重点讲述了快捷菜单和位图的相关操作
如果本文对老铁们有帮助的话请给个三连叭~~