MFC中,怎样在一个特定的控件里画图,比如picture control

基于CFormView的应用程序:

拖入了一个长方形的Picture类型控件,控件的ID为IDC_PIC1,type为Frame,(Type还有Rectange、BitMap等类型)

Sunken、Border为选中状态,

现在想在该控件中画图,

实现方法为,在OnDraw函数中加入以下代码:

CRect rect;

CWnd *pWin = GetDlgItem(IDC_PIC1);//获取该控件的指针,就可以对该控件直接操作了
pWin->GetClientRect(rect);//把控件的长宽、坐标等信息保存在rect里

int width=rect.Width();//可以获取宽和高
int height=rect.Height();

CString str;
str.Format("高度为:%d,宽度为:%d",height,width);

        AfxMessageBox(str,MB_YESNO|MB_ICONSTOP,0);


CDC *pDc = pWin->GetDC();//获取该控件的画布

        //有了画布,下面可以自由的画图了,想怎么画就怎么话,

pDc->Rectangle(rect);
CBrush myBrush;
myBrush.CreateSolidBrush(RGB(192,250,233));
pDc->FillRect(rect,&myBrush);

其实,实现起来很简单,关键语句就是加粗体的语句

即,要获取某个区域的指针,然后获取画布

基于对话框的程序:

实现功能:

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();这句,直接将前面绘好的图贴上来就是。
 

猜你喜欢

转载自blog.csdn.net/acoolgiser/article/details/87992597