上一课笨笨给大家介绍的是在普通窗口上多区域绘图,本课将介绍对话框下的情形。由于对话框的消息循环和普通窗口有一些区别,所以在具体操作上略有不同,下面的处理过程可以供大家参考。
第一步,打开VC,建立一个基于MFC AppWizard(exe)向导的项目LessonA07。向导中选择Dialog Based,其它不做任何更改,直接点Finish。
第二步,拷贝库文件到LessonA07文件夹中,
第三步,在VC界面的资源编辑器中,删除掉对话框中间的“TODO: 在这里设置对话控制。”这个标签,然后再对话框中放置两个Picture控件,并把这两个控件的ID设置为ID_CHART1和ID_CHART2。
第四步,在VC中打开LessonA07Dlg.h文件,在其头部加入CChart头文件和库文件的引用。
第五步,在LessonA07Dlg.h文件中给CLessonA07Dlg类添加CChart类型和CWnd*类型的成员变量。
CChart m_Chart[2];
CWnd *m_pWnd[2];
注意这里笨笨用的是数组,其实像上一课那样不用数组也是OK的,只是因为笨笨懒惯了,用数组可以写循环,提升键盘的使用寿命
第六步,在LessonA07Dlg.h文件的OnInitDialog函数中编写如下的初始化代码。
// 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_Chart[0].SetBkgndColor(GetSysColor(COLOR_3DFACE));
// chart 2
m_Chart[1].SetType(kTypePie);
m_Chart[1].AddPie(2, _T("刘岩"));
m_Chart[1].AddPie(2, _T("瞿颖"));
m_Chart[1].AddPie(4, _T("周迅"));
m_Chart[1].AddPie(8, _T("王菲"));
m_pWnd[1] = GetDlgItem(IDC_CHART2);
第七步,在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);
m_Chart[i].OnLButtonDownR(pWnd->m_hWnd, pt, 0);
}
}
}
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);
m_Chart[i].OnLButtonUpR(pWnd->m_hWnd, pt, 0);
}
}
}
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);
m_Chart[i].OnLButtonDblClkR(pWnd->m_hWnd, pt, 0);
}
}
}
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);
m_Chart[i].OnMouseMoveR(pWnd->m_hWnd, pt, 0);
}
}
}
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);
m_Chart[i].OnContextMenuR(NULL, pWnd->m_hWnd, pt);
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
注意到这里处理消息的位置是在PreTranslateMessage中,原因就是由于对话框消息处理的特殊性。此外,在具体的处理过程中没有响应WM_CONTEXTMENU,而是用WM_RBUTTONDOWN代替,也是出于这个原因。
好了,这一课也结束了,希望这一课的内容能对大家有所参考。