您的位置:首页 > 其它

MFC对话框绘图

2014-04-05 00:28 225 查看
实现功能:

1、在对话框上的一块区域绘制彩色线条。

2、窗口被覆盖后恢复时,图像自动重绘。

3、改变按钮颜色。

操作:

根据向导建立一个对话框程序。在资源中添加一个静态文本框,其ID为IDC_STATIC。

在DialogXXXDlg.h 中加入如下内容

CBrush m_brush;//用于自定义颜色

CDC m_memDC;//屏幕DC兼容的内存DC

CBitmap m_Bmp;//位图

CWnd* m_pDrawWnd;//用于保存静态文本框的对象指针

//

// 初始化和双缓冲相关的数据

void InitialDBB();

//双缓冲内存上绘图

void DrawOnMem();

//在静态区域画图

void DrawOnStaticArea();

//更改颜色的消息响应函数

afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);

在DialogXXXDlg.cpp 中加入如下内容

1、添加消息映射

ON_WM_CTLCOLOR()

2、OnInitDialog()中添加初始化代码

// TODO: 在此添加额外的初始化代码

m_brush.CreateSolidBrush(RGB(255,0,0));//初始化画刷

m_pDrawWnd = GetDlgItem(IDC_STATIC);//获得静态窗口对象指针

InitialDBB();// 初始化双缓冲相关的数据

3、重写函数OnCtlColor()

//改变按钮颜色

HBRUSH CDialogDrawDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)

{

HBRUSH hbr=CDialog::OnCtlColor(pDC,pWnd,nCtlColor);

//

if(pWnd->GetDlgCtrlID()==IDOK || pWnd->GetDlgCtrlID()==IDCANCEL)

{

pDC->SetTextColor(RGB(255,0,0));//设置文本颜色

pDC->SetBkMode(TRANSPARENT);//文字背景设为透明

pDC->SetBkColor(RGB(255,0,0));//设置背景色

return m_brush;

}

//

return hbr;//m_brush;///hbr

}

4、添加头文件中声明的函数的定义代码

// 初始化和双缓冲相关的要素

void CDialogDrawDlg::InitialDBB()

{

CRect rt;

m_pDrawWnd->GetClientRect(&rt);

CDC* sDC = m_pDrawWnd->GetDC();

// 为屏幕DC创建兼容的内存DC

if(!m_memDC.CreateCompatibleDC(sDC))//

{

::PostQuitMessage(0);

}

// 创建位图,不能是m_memDC,否则无颜色

m_Bmp.CreateCompatibleBitmap(sDC, rt.Width(), rt.Height());//m_memDC

// 相当于选择画布,m_pDrawWnd->

::SelectObject(m_memDC.GetSafeHdc(), m_Bmp);

m_pDrawWnd->ReleaseDC(sDC);

}

//双缓冲内存上绘图

void CDialogDrawDlg::DrawOnMem()

{

CRect rect;

m_pDrawWnd->GetClientRect(&rect);

//COLORREF crl = GetSysColor(COLOR_3DFACE);

//m_memDC.FillSolidRect(rect, crl);

//m_memDC.FillSolidRect(&rect, 0x00FFFFFF);// 白色填充, 注意,这次是画在内存设备环境上

CPen pen(PS_SOLID,1,RGB(255,0,0));

m_memDC.SelectObject(&pen);

//画图部分

m_memDC.MoveTo(rect.right,rect.bottom);

m_memDC.LineTo(rect.left,rect.top);

}

//

//在静态区域画图

void CDialogDrawDlg::DrawOnStaticArea()

{

CWnd* pWnd = GetDlgItem(IDC_STATIC);//获得静态文本框的窗口对象

CRect rect;

pWnd->GetClientRect(&rect);

//

CDC* pDC = pWnd->GetDC();//

//

DrawOnMem();

// 一次性的将内存设备环境上绘制完毕的图形"贴"到屏幕上

pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_memDC, 0, 0, SRCCOPY);

pWnd->ReleaseDC(pDC);//

//

}

5、OnPaint()函数中添加绘图代码(红色部分为添加内容)

void CDialogDrawDlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // 用于绘制的设备上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 使图标在工作区矩形中居中

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width() - cxIcon + 1) / 2;

int y = (rect.Height() - cyIcon + 1) / 2;

// 绘制图标

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CDialog::OnPaint();

//重绘图像区域

PAINTSTRUCT ps;

CRect rt;

m_pDrawWnd->GetClientRect(&rt);

CDC* pDC=m_pDrawWnd->BeginPaint(&ps);

DrawOnMem();

pDC->BitBlt(0, 0, rt.Width(), rt.Height(), &m_memDC, 0, 0, SRCCOPY);

m_pDrawWnd->EndPaint(&ps);

}

}

这里需要用BeginPaint() 和 EndPaint()函数获得DC。原因是主窗体在处理WM_PAINT消息的时候也需要绘制发送消息给各个控件有机会绘制自己;如果不用BeginPaint() 和 EndPaint()函数获得控件DC,该控件的消息队列中的WM_PAINT消息就不会被删除,控件就还会调用其自身的OnPaint()函数重绘控件,从而我们绘制的图像会被覆盖。

说明:这里的DrawOnStaticArea()没有用到。这是用作扩展时在该区域绘图的,写在这里是方便日后扩展。如果这样的话,OnPaint()中就不需要DrawOnMem();这句,直接将前面绘好的图贴上来就是。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: