上一课笨笨给大家介绍的是在普通窗口上多区域绘图,本课将介绍对话框下的情形。由于对话框的消息循环和普通窗口有一些区别,所以在具体操作上略有不同,下面的处理过程可以供大家参考。
第一步,打开VC,建立一个基于MFC AppWizard(exe)向导的项目LessonA07。向导中选择Dialog Based,其它不做任何更改,直接点Finish。
第二步,拷贝库文件到LessonA07文件夹中,
第三步,在VC界面的资源编辑器中,删除掉对话框中间的“TODO: 在这里设置对话控制。”这个标签,然后再对话框中放置两个Picture控件,并把这两个控件的ID设置为ID_CHART1和ID_CHART2。
第四步,在VC中打开LessonA07文件,在其头部加入CChart头文件和库文件的引用。
第五步,在LessonA07Dlg.h文件中给CLessonA07Dlg类添加CChart类型和CWnd*类型的成员变量。
CChart m_Chart[2]; CWnd *m_pWnd[2];
注意这里笨笨用的是数组,其实像上一课那样不用数组也是OK的,只是因为笨笨懒惯了,用数组可以写循环,提升键盘的使用寿命
第六步,在LessonA07Dlg.h文件的OnInitDialog函数中编写如下的初始化代码。
CRect rt; // chart 1 m_Chart[0].SetType(kTypeXY); for(int i=-10; i<=10; i++) { m_Chart[0].AddPoint2D(i, i*i); } m_pWnd[0] = GetDlgItem(IDC_CHART1); m_pWnd[0]->GetClientRect(&rt); m_Chart[0].SetConfineRect(rt); m_Chart[0].SetBkgndColor(GetSysColor(COLOR_3DFACE)); // chart 2 m_Chart[1].SetType(kTypePie); m_Chart[1].AddPie(2, "刘岩"); m_Chart[1].AddPie(2, "瞿颖"); m_Chart[1].AddPie(4, "周迅"); m_Chart[1].AddPie(8, "王菲"); m_pWnd[1] = GetDlgItem(IDC_CHART2); m_pWnd[1]->GetClientRect(&rt); m_Chart[1].SetConfineRect(rt);
注意这里和以前一样,利用SetConfineRect确定各个Chart的绘图目标区域。
第七步,在LessonA07Dlg.h文件的OnPaint函数的最前面,添加如下代码。
for(int i=0; i<2; i++) { m_Chart[i].OnDraw(m_pWnd[i]->m_hWnd); }
现在可以运行了,效果如下。
第八步,添加消息处理例程。由于对话框的消息循环比较特殊,这里我们在PreTranslateMessage中处理。首先需要重载这个函数,然后改写如下。
BOOL CLessonA07Dlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class CRect rect; CPoint pt; CWnd *pWnd; int i; if(pMsg->message==WM_LBUTTONDOWN) { for(i=0; i<2; i++) { pWnd=m_pWnd[i]; pWnd->GetWindowRect(&rect); if (rect.PtInRect(pMsg->pt)) { pt = pMsg->pt; pWnd->ScreenToClient(&pt); if(m_Chart[i].OnLButtonDown(pWnd->m_hWnd, pt, 0)) { m_Chart[i].OnDraw(pWnd->m_hWnd); } } } } else if(pMsg->message==WM_LBUTTONUP) { for(i=0; i<2; i++) { pWnd=m_pWnd[i]; pWnd->GetWindowRect(&rect); if (rect.PtInRect(pMsg->pt)) { pt = pMsg->pt; pWnd->ScreenToClient(&pt); if(m_Chart[i].OnLButtonUp(pWnd->m_hWnd, pt, 0)) m_Chart[i].OnDraw(pWnd->m_hWnd); } } } else if(pMsg->message==WM_LBUTTONDBLCLK) { for(i=0; i<2; i++) { pWnd=m_pWnd[i]; pWnd->GetWindowRect(&rect); if (rect.PtInRect(pMsg->pt)) { pt = pMsg->pt; pWnd->ScreenToClient(&pt); if(m_Chart[i].OnLButtonDblClk(pWnd->m_hWnd, pt, 0)) m_Chart[i].OnDraw(pWnd->m_hWnd); } } } else if(pMsg->message==WM_MOUSEMOVE) { for(i=0; i<2; i++) { pWnd=m_pWnd[i]; pWnd->GetWindowRect(&rect); if (rect.PtInRect(pMsg->pt)) { pt = pMsg->pt; pWnd->ScreenToClient(&pt); if(m_Chart[i].OnMouseMove(pWnd->m_hWnd, pt, 0)) m_Chart[i].OnDraw(pWnd->m_hWnd); } } } else if(pMsg->message==WM_RBUTTONDOWN) {// for(i=0; i<2; i++) { pWnd=m_pWnd[i]; pWnd->GetWindowRect(&rect); if (rect.PtInRect(pMsg->pt)) { pt = pMsg->pt; // pWnd->ScreenToClient(&pt); if(m_Chart[i].OnContextMenu(NULL, pWnd->m_hWnd, pt)) m_Chart[i].OnDraw(pWnd->m_hWnd); } } } return CDialog::PreTranslateMessage(pMsg); }
注意到这里处理消息的位置是在PreTranslateMessage中,原因就是由于对话框消息处理的特殊性。此外,在具体的处理过程中没有响应WM_CONTEXTMENU,而是用WM_RBUTTONDOWN代替,也是出于这个原因。
好了,这一课也结束了,希望这一课的内容能对大家有所参考。
版权声明:本文为博主原创文章,未经博主允许不得转载。