MFC菜单工具栏以及状态栏编程

1、 创建“图形”、“颜色”、“线的类型”、“线宽度”子菜单。
(1) 在新建的工程中“ResourceView”中打开Menu选项,在空白中添加这几项。
(2) 在“图形”下拉菜单中依次添加“椭圆”、“矩形”、“曲线”,并且依次设置ID分别为:ID_ELLIPSE,ID_RECTANGLE,ID_CURVES。
(3) 在“颜色”下拉菜单中依次添加“红色”,“绿色”,“蓝色”,“白色”和“黑色”。并设置其ID分别为ID_COLORRED,ID_COLORGREEN,ID_COLORBLUE,ID_COLORBLACK,ID_COLORWHITE。
(4) 在“线的类型”下拉菜单中依次添加“实线”和“虚线”。其ID分别是ID_LINESOLID,ID_LINEDOT
(5) 在“线宽度”下拉菜单中创建“1”和“2”,其ID分别设为ID_LINEWIDE1,ID_LINEWIDE2。
编译,运行后效果如下:










2、 响应菜单栏中的“图形”下拉子菜单的消息
响应椭圆(ID_ELLIPSE)矩形(ID_RECTANGLE)
(1)、首先在view类中添加变量
BOOL m_ISPointup;  //鼠标左键弹起
							
BOOL m_ISPointdown; //鼠标左键按下
						
CPoint m_pointup;   //鼠标左键弹起的位置
						
CPoint m_pointdown;  //鼠标左键按下的位置

BOOL m_ClickRectangle; //判断是否画矩形
							BOOL m_ClickEllipse;   //判断是否画椭圆
							    Int flage;//菜单选项被标记的标志


(2)、在view类中对这些变量初始化
m_pointdown = 0;  //原点
m_pointup = 0;
m_ISPointup = FALSE; //未按下
m_ISPointdown = FALSE;
flag = 0;


(3)、响应ID_ELLIPSE和ID_RECTANGLE的command和update消息
void CYangwei20090810229View::OnEllipse() 
{
	// TODO: Add your command handler code here
	flag++;
	m_ClickEllipse = TRUE;
	m_ClickRectangle = FALSE;
	m_ClickCurves = FALSE;
}
void CYangwei20090810229View::OnRectangle() 
{
	// TODO: Add your command handler code here
	flag++;
	m_ClickEllipse = FALSE;
	m_ClickRectangle = TRUE;
	m_ClickCurves = FALSE;
}
void CYangwei20090810229View::OnUpdateEllipse(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(flag%2==0);
	if(255 == flag)
	{
		flag = 1;
}

void CYangwei20090810229View::OnUpdateRectangle(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(flag%2==1);
}


(3)、响应WM_LBUTTONDOWN消息,此时记下该点位置,并表示按下状态,添加代码:
void CYangwei20090810229View::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_pointdown = point;
	m_ISPointdown = TRUE;
	m_ISPointup = FALSE;
	CView::OnLButtonDown(nFlags, point);
}
(4)、响应WM_LBUTTONUP消息记下此点位置,虽然在此程序中未用到改点。
	void CYangwei20090810229View::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_pointup = point;
	CDC *pDC=GetDC();
	CBrush *pnew = CBrush::FromHandle((HBRUSH)GetStockObject(HOLLOW_BRUSH));//获得空画刷
	CBrush *pold = pDC->SelectObject(pnew); //选择新建画刷

	CPen newpen(m_penstyle,m_linewide,RGB(m_pen.red,m_pen.green,m_pen.blue));//创建自定义的画笔,这里的m_pen是自己写的结构
	CPen *poldpen = pDC->SelectObject(&newpen);     //选择自定义的画笔
	if(m_ClickEllipse)
	{
		pDC->Ellipse(m_pointdown.x,m_pointdown.y,point.x,point.y);	
	}
	if(m_ClickRectangle)
	{
		pDC->Rectangle(m_pointdown.x,m_pointdown.y,point.x,point.y);
	}
	pDC->SelectObject(poldpen);
	pDC->SelectObject(pold);
	m_ISPointup = TRUE;
	m_ISPointdown = FALSE;
	
	CView::OnLButtonUp(nFlags, point);
}


响应曲线(ID_CURVES)
(1)、响应ID_CURVES的command消息
void CYangwei20090810229View::OnCurves() 
{
	// TODO: Add your command handler code here
	m_ClickCurves = TRUE;   //代表曲线被选择
	m_ClickEllipse = FALSE; 
	m_ClickRectangle = FALSE;
}
响应WM_MOUSEMOVE消息
void CYangwei20090810229View::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(m_ISPointdown && m_ClickCurves)
	{
		CClientDC dc(this);
		CPen pen(m_penstyle,m_linewide,RGB(m_pen.red,m_pen.green,m_pen.blue));
		CPen *pold = dc.SelectObject(&pen);
		dc.MoveTo(m_pointdown);
		dc.LineTo(point);
		m_pointdown = point;
		dc.SelectObject(pold);
	}
	CView::OnMouseMove(nFlags, point);
}


对于颜色菜单,首先在view类中的头文件中定义一个结构体
struct myColor
{
	int red;//红色
	int green;//绿色
	int blue;//蓝色
};


向view类中添加myColor m_pen; //画笔的颜色
初始化黑色
m_pen.red = 0;
m_pen.green = 0;
m_pen.blue = 0;

响应红色ID_COLORRED的command消息
void CYangwei20090810229View::OnColorred() 
{
	// TODO: Add your command handler code here
	m_pen.red = 255;
	m_pen.green = 0;
	m_pen.blue = 0;
}


其他的颜色道理一样,只要知道各种颜色的三原色各自的值并且赋给他们即可,不再详述

对于线的类型:
在view类中添加变量m_penstyle并在构造函数中初始化
	
m_penstyle =PS_SOLID;//线类型实线

然后响应实线ID_LINESOLID的command消息
void CYangwei20090810229View::OnLinesolid() 
{
	// TODO: Add your command handler code here
	m_penstyle = PS_SOLID;
}
对于虚线响应ID_LINEDOT消息
void CYangwei20090810229View::OnLinedot() 
{
	// TODO: Add your command handler code here
	m_penstyle = PS_DOT;
}

对于线宽 1,2分别响应ID_LINEWIDE1和ID_LINEWIDE2的command消息
void CYangwei20090810229View::OnLinewide1() 
{
	// TODO: Add your command handler code here
	m_linewide = 1;//线宽1
}

void CYangwei20090810229View::OnLinewide2() 
{
	// TODO: Add your command handler code here
	m_linewide = 2;//线宽2
}



3、 响应工具栏的的各种图形消息
如椭圆
在ResourceView页面中,双击Toolbar文件夹,可以看到有一个ID位ID_MAINFRAME的工具栏。双击ID_MAINFRAME工具栏,在工具栏编辑框中出现如下图所示的工具栏。

在工具栏的最右边有一空白按钮,双击该按钮,弹出对话框如下图,其中ID选择ID_ELLIPSE,即“椭圆”按钮。该按钮显示在编辑窗口中,可以通过Graphics和Colors工具箱及鼠标画自己的图标。(矩形工具栏图标同椭圆方法)

MFC菜单工具栏以及状态栏编程_第1张图片
其他图形一样。

4、 响应右击菜单消息
a) 在工作区的ResourceView选项卡中,右击Menu文件夹,在弹出菜单中选择插入菜单便可创建一个新的菜单资源,其ID为IDR_MENU1。右击IDR_MENU1,在弹出菜单中选择属性,修改其ID为IDR_POPMENU。双击IDR_POPMENU资源进入编辑对话框,对弹出式菜单进行编辑,,完成后的菜单资源如图:

MFC菜单工具栏以及状态栏编程_第2张图片
b) 添加代码,实现鼠标右键单击时显示弹出式菜单。在查看菜单项中选择建立类向导来添加右键单击弹出式菜单WM_CONTEXTMENU及消息处理函数,这时MFC会发现创建了一个新资源,将询问是否创建一个新类,取消后,弹出下图对话框,选择ID为CExyangwei20090810229View,Messages为WM_CONTEXTMENU,双击该消息或单击Add Function按钮,将为该消息添加默认处理函数,单击Edit Code按钮进入OnContextMenu()函数,对其进行编辑。
MFC菜单工具栏以及状态栏编程_第3张图片
void CYangwei20090810229View::OnContextMenu(CWnd*, CPoint point)
{

	// CG: This block was added by the Pop-up Menu component
	{
		if (point.x == -1 && point.y == -1){
			//keystroke invocation
			CRect rect;
			GetClientRect(rect);
			ClientToScreen(rect);

			point = rect.TopLeft();
			point.Offset(5, 5);
		}

		CMenu menu;
		VERIFY(menu.LoadMenu(CG_IDR_POPUP_YANGWEI20090810229_VIEW));

		CMenu* pPopup = menu.GetSubMenu(0);
		ASSERT(pPopup != NULL);
		CWnd* pWndPopupOwner = this;

		while (pWndPopupOwner->GetStyle() & WS_CHILD)
			pWndPopupOwner = pWndPopupOwner->GetParent();

		pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
			pWndPopupOwner);
	}
}


其中响应画各种图形的方法与工具栏中的做法差不多
对于清空消息ID_UPDATE
void CYangwei20090810229View::OnUpdate() 
{
	// TODO: Add your command handler code here
	Invalidate();
	UpdateWindow();
}


5、 下面美化状态栏
(1)、将状态栏的提示器改成自己的东西,在这里我改成了作者和日期
  即2011-4-2 made by Veiker.其实就是在ResourseView中的StringTable中找到
AFX_IDS_IDLEMESSAGE 将其属性改下
(2)、修改状态栏中的提示器
  让状态栏显示鼠标箭头的位置,CTRL键是否按下,时间、进度条
A、 在Stringtable中添加对应的ID
B、 在Frame类构造函数中的indicators数组中添加ID(对应ID如下显示)
static UINT indicators[] =
{
	ID_SEPARATOR,  // status line indicator
	ID_XY,         //显示鼠标位置
	    ID_INDICATOR_CTRL,//显示CTRL键是否按下
	    ID_INDICATOR_TIME,//显示时间
	ID_INDICATOR_PROG,//显示进度条
				ID_INDICATOR_NUM,//显示数字
};


显示鼠标位置:
响应WM_MOUSEMOVE 由于前面响应过这里只要向里面添加代码
CString str;
str.Format("x=%d,y=%d",point.x,point.y);
CMainFrame*pMainFrame=(CMainFrame*)(AfxGetApp()->GetMainWnd());
pMainFrame->m_wndStatusBar.SetPaneText(1,str);


注意:包含MainFrm.h
显示CTRL键是否按下在View类中的消息注释宏中添加
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CTRL,OnUpdateKeyCtrl)
然后响应函数
void CYangwei20090810229View::OnUpdateKeyCtrl(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(::GetKeyState(VK_CONTROL)<0);  //更新状态指示器
}


显示时间
在frame类中OnCreate()中添加
SetTimer(1,1000,NULL);
CTime time = CTime::GetCurrentTime();
CString str = time.Format("%H:%M:%S");
m_wndStatusBar.SetPaneText(3,str);

响应WM_TIMER消息
void CMainFrame::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 CTime time = CTime::GetCurrentTime();
 CString str = time.Format("%H:%M:%S");
 m_wndStatusBar.SetPaneText(3,str);
  CFrameWnd::OnTimer(nIDEvent);
}


显示进度条:
在frame类中添加变量CProgressCtrl m_Process;
响应WM_PAINT消息
void CMainFrame::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	CRect rect;
	m_wndStatusBar.GetItemRect(4,&rect);
	if(m_Process.m_hWnd)
	{
m_Process.SetWindowPos(NULL,rect.left,rect.top,rect.Width(),rect.Height(),SWP_NOZORDER);
	}
	else{
     m_Process.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,111);
	}
 // Do not call CFrameWnd::OnPaint() for painting messages
}


向OnTimer()中添加m_Process.StepIt();
三、 运行后总体效果:

MFC菜单工具栏以及状态栏编程_第4张图片
源代码:见附件

你可能感兴趣的:(编程,C++,c,ITeye,mfc)