大家好,我想在对话框中插入位图,然后通过按键的形式,按下对话框的一个按钮就会再位图的指定位置画出一个圆,下面是我的程序,显示结果是只有位图,并没有画出圆,请大家帮我修改修改,谢谢啦!void CmapDlg::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
{
// CDialogEx::OnPaint();
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐标
CDC dcMem;
dcMem.CreateCompatibleDC(&dc); //创建兼容DC
CBitmap bmBackGround;
bmBackGround.LoadBitmap(IDB_BITMAP1); //载入位图
BITMAP bitmap;
bmBackGround.GetBitmap(&bitmap); //获取位图信息
CBitmap *pbitold=dcMem.SelectObject(&bmBackGround); //将位图选入DC中
SetStretchBltMode(dc, HALFTONE);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),
&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); //以stretchBlt的方式添加位图到相应区域
dcMem.SelectObject(pbitold);
}
}
void CmapDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐
CBrush brush;
brush.CreateSolidBrush(RGB(255, 0, 0));
dc.SelectObject(brush);
dc.Ellipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
}
按键画图
{
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
{
// CDialogEx::OnPaint();
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐标
CDC dcMem;
dcMem.CreateCompatibleDC(&dc); //创建兼容DC
CBitmap bmBackGround;
bmBackGround.LoadBitmap(IDB_BITMAP1); //载入位图
BITMAP bitmap;
bmBackGround.GetBitmap(&bitmap); //获取位图信息
CBitmap *pbitold=dcMem.SelectObject(&bmBackGround); //将位图选入DC中
SetStretchBltMode(dc, HALFTONE);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),
&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); //以stretchBlt的方式添加位图到相应区域
dcMem.SelectObject(pbitold);
}
}
void CmapDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐
CBrush brush;
brush.CreateSolidBrush(RGB(255, 0, 0));
dc.SelectObject(brush);
dc.Ellipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
}
按键画图
或者就是声明一些存储空间,保存你需要绘制圆形图的数据,然后点击按钮时就增加数据,调用Invalidata,在OnPaint中就调用这些存储空间的数据进行图形绘制
定义成员变量:BOOL m_bDraw; 并初始化为FALSE
然后:void CmapDlg::OnPaint()
{
//.................
else
{
// CDialogEx::OnPaint();
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐标CDC dcMem;
dcMem.CreateCompatibleDC(&dc); //创建兼容DC
CBitmap bmBackGround;
bmBackGround.LoadBitmap(IDB_BITMAP1); //载入位图
BITMAP bitmap;
bmBackGround.GetBitmap(&bitmap); //获取位图信息
CBitmap *pbitold=dcMem.SelectObject(&bmBackGround); //将位图选入DC中
SetStretchBltMode(dc, HALFTONE);
if(m_bDraw)//-----------画椭圆
{
CBrush brush;
brush.CreateSolidBrush(RGB(255, 0, 0));
dcMem.SelectObject(brush);
dcMem.Ellipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
}
//------------------end draw Ellipse
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),
&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); //以stretchBlt的方式添加位图到相应区域
dcMem.SelectObject(pbitold);
}
}
然后在OnBnClickedButton1()中:void CmapDlg::OnBnClickedButton1()
{
m_bDraw = TRUE;
Invalidate();
}
圆实际也可以考虑弄到第二个缓冲DC里面 dcMemEllipse,然后再往位图上面贴,dcMemEllipse要SetBkMode(TRANSPARENT)。这个主要是在如果你画的不是圆而是更大的图的时候的区别,画圆很快所以也没有什么必要。
另外
1.CPaintDC只能在OnPaint里面才可以用,所以你那个在CLICK事件时候用是不对的。
2.可以考虑所有的绘画在OnEraseBkgnd事件里面执行,而且要用InvalidateRect,指定区域刷新。主要是你这个对话框里面啥也没有所以不会觉得,如果有很多东西,即使用了缓冲DC但在Invalidate后也会闪一大下子。
定义成员变量:BOOL m_bDraw; 并初始化为FALSE
然后:void CmapDlg::OnPaint()
{
//.................
else
{
// CDialogEx::OnPaint();
CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐标CDC dcMem;
dcMem.CreateCompatibleDC(&dc); //创建兼容DC
CBitmap bmBackGround;
bmBackGround.LoadBitmap(IDB_BITMAP1); //载入位图
BITMAP bitmap;
bmBackGround.GetBitmap(&bitmap); //获取位图信息
CBitmap *pbitold=dcMem.SelectObject(&bmBackGround); //将位图选入DC中
SetStretchBltMode(dc, HALFTONE);
if(m_bDraw)//-----------画椭圆
{
CBrush brush;
brush.CreateSolidBrush(RGB(255, 0, 0));
dcMem.SelectObject(brush);
dcMem.Ellipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
}
//------------------end draw Ellipse
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),
&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); //以stretchBlt的方式添加位图到相应区域
dcMem.SelectObject(pbitold);
}
}
然后在OnBnClickedButton1()中:void CmapDlg::OnBnClickedButton1()
{
m_bDraw = TRUE;
Invalidate();
}
恩,谢谢,就是用Invalidate函数会产生闪烁,还需要解决闪烁问题。
然后
void CmapDlg::OnBnClickedButton1()
{
m_bDraw = TRUE;
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect);
ScreenToClient(rect);
CRect rectEllipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
InvalidateRect(rectEllipse);}
您说的第一种方法我没有理解,不知道怎么做,我试了您说的第二种方法,是能成功的,但是图形重绘的时候有闪烁,请问这怎样消除。
双缓存
这是我根据以上几位提出的建议更改的程序,用于消除重绘时的闪烁,可是程序编译没问题,运行产生中断。请帮我看看程序哪里有问题?我已经把bmBackGround和dcMem声明成了成员变量。CPaintDC dc(this);
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect); //这里的IDC_STATIC_NAME是你要添加位图的范围
ScreenToClient(rect); //将屏幕坐标转换成客户区坐标 dcMem.CreateCompatibleDC(&dc); //创建兼容DC
BITMAP bitmap;
bmBackGround.GetBitmap(&bitmap); //获取位图信息
bmBackGround.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图
CBitmap *pbitold=dcMem.SelectObject(&bmBackGround); //将位图选入DC中
// dcMem.FillSolidRect(rect,dc.GetBkColor());//按原来背景填充客户区,不然会是黑色
SetStretchBltMode(dc, HALFTONE);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),
&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); //以stretchBlt的方式添加位图到相应区域
dcMem.SelectObject(pbitold);
dc.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC(); //删除DC
// bmBackGround.DeleteObject(); //删除位图
CBrush brush;
brush.CreateSolidBrush(RGB(255, 0, 0));
dc.SelectObject(brush);
if (m_draw)
{
dc.Ellipse(rect.left+m_x-5, rect.top+m_y-5, rect.left+m_x+5, rect.top+m_y+5);
}
m_draw=false;
bmBackGround.CreateCompatibleBitmap而且既然都声明成了成员变量,为什么还非得在OnPaint里面反复的Create , delete?
ON_WM_erasebkgnd
然后
void CmapDlg::OnBnClickedButton1()
{
m_bDraw = TRUE;
CRect rect;
GetDlgItem(IDC_MAP)->GetWindowRect(rect);
ScreenToClient(rect);
CRect rectEllipse(rect.left+485, rect.top+153, rect.left+495, rect.top+163);
InvalidateRect(rectEllipse);
}这样就只有圆的部分闪一下,Invalidate会使整个对话框重绘。