在MFC中用双缓冲绘制橡皮线,新画的总是覆盖了原来画的(就是一新画的时候原来的就消失了)
下面是我写的简易代码这个鼠标移动的主要就是给OnDraw函数传坐标void CTwoBufferView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (chek)//鼠标按下的时候开始作图
{
cend=point;
Invalidate(false);
}
CView::OnMouseMove(nFlags, point);}这是OnDraw函数的代码void CTwoBufferView::OnDraw(CDC* pDC)
{
CTwoBufferDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
//创建画笔
CPen m_pen;
m_pen.CreatePen(PS_SOLID, 5, RGB(0,123,0));
SelectObject(memDc,m_pen);
//开始画图
memDc.MoveTo(cbgin);
memDc.LineTo(cend);
//将内存设备环境上的图拷贝到屏幕上显示
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDc, 0, 0, SRCCOPY);
//绘图完成后清理
memBmp.DeleteObject();
memDc.DeleteDC();
}
//都是全局变量
CBitmap memBmp;
CDC memDc;高手请给解答。。是不是要用个数组把画过的保存起来 然后在循环的输出?
下面是我写的简易代码这个鼠标移动的主要就是给OnDraw函数传坐标void CTwoBufferView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (chek)//鼠标按下的时候开始作图
{
cend=point;
Invalidate(false);
}
CView::OnMouseMove(nFlags, point);}这是OnDraw函数的代码void CTwoBufferView::OnDraw(CDC* pDC)
{
CTwoBufferDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
//创建画笔
CPen m_pen;
m_pen.CreatePen(PS_SOLID, 5, RGB(0,123,0));
SelectObject(memDc,m_pen);
//开始画图
memDc.MoveTo(cbgin);
memDc.LineTo(cend);
//将内存设备环境上的图拷贝到屏幕上显示
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDc, 0, 0, SRCCOPY);
//绘图完成后清理
memBmp.DeleteObject();
memDc.DeleteDC();
}
//都是全局变量
CBitmap memBmp;
CDC memDc;高手请给解答。。是不是要用个数组把画过的保存起来 然后在循环的输出?
新绘制后进入OnDraw()函数后坐标参数都改变了
可以把以前的坐标保存起来
可以参考下思路:typedef struct
{
CPoint begin;
CPoint end;
}POINTS;
#define MAX_NUM 100//最大数目自己定义
POINTS pt[MAX_NUM];
int count;//记录已经绘制了多少个矩形,初始化时count=0;
鼠标点击时:pt[count].begin=?;pt[count].end=?;count++;
绘制时:用一个循环来for(int i=0;i<count;i++){……}
大致思路就是这样,自己写吧
OnDraw中只做一件事,BitBlt,就是拷贝内存dc到屏幕dc上去,
绘图操作(不在Ondraw中)都画在内存DC上。
//鼠标左键按下的时候
void CTwoBufferView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
pt[count].begin=point;
pt[count].cend=point;
count++;
chek=true;//鼠标按下
CView::OnLButtonDown(nFlags, point);
}
鼠标移动的时候void CTwoBufferView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (chek)//鼠标按下的时候开始作图
{
pt[count].cend=point;
count++;
Invalidate(false);
}
CView::OnMouseMove(nFlags, point);
}OnDraw函数void CTwoBufferView::OnDraw(CDC* pDC)
{
CTwoBufferDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
//创建一画笔
CPen m_pen;
m_pen.CreatePen(PS_SOLID, 1, RGB(255,0,0));
SelectObject(memDc,m_pen);
for(int i=0;i<count;i++)
{
memDc.MoveTo(pt[count].begin);
memDc.LineTo(pt[count].cend);
}
//将内存设备环境上的图拷贝到屏幕上显示
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDc, 0, 0, SRCCOPY);
//绘图完成后的清理
memBmp.DeleteObject();
memDc.DeleteDC();
}
没有效果你看怎么回事?。
count是记录绘制矩形的个数
在绘制一个矩形时鼠标一直在移动count一直在加
自己好好理解下这个过程
看代码:// 1View.h : CMy1View 类的接口
//
#pragma once
typedef struct
{
CPoint begin;
CPoint end;
}PTS;
#define MAX 100
class CMy1View : public CView
{
protected: // 仅从序列化创建
CMy1View();
DECLARE_DYNCREATE(CMy1View)// 属性
public:
CMy1Doc* GetDocument() const;// 操作
public:// 重写
public:
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);// 实现
public:
virtual ~CMy1View();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endifprotected:// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
private:
PTS pt[MAX];
int count;
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
private:
BOOL m_IsLButtonDown;
};#ifndef _DEBUG // 1View.cpp 中的调试版本
inline CMy1Doc* CMy1View::GetDocument() const
{ return reinterpret_cast<CMy1Doc*>(m_pDocument); }
#endif
// 1View.cpp : CMy1View 类的实现
//#include "stdafx.h"
#include "1.h"#include "1Doc.h"
#include "1View.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMy1ViewIMPLEMENT_DYNCREATE(CMy1View, CView)BEGIN_MESSAGE_MAP(CMy1View, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()// CMy1View 构造/析构CMy1View::CMy1View()
: m_IsLButtonDown(FALSE)
{
// TODO: 在此处添加构造代码
count=0;}CMy1View::~CMy1View()
{
}BOOL CMy1View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式 return CView::PreCreateWindow(cs);
}// CMy1View 绘制void CMy1View::OnDraw(CDC* pDC)
{
CMy1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
for(int i=0;i<count;i++)
{
//MessageBox(_T("HHH"));
pDC->MoveTo(pt[i].begin);
pDC->LineTo(pt[i].end);
}
// TODO: 在此处为本机数据添加绘制代码
}
// CMy1View 打印BOOL CMy1View::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}void CMy1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}void CMy1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
// CMy1View 诊断#ifdef _DEBUG
void CMy1View::AssertValid() const
{
CView::AssertValid();
}void CMy1View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}CMy1Doc* CMy1View::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy1Doc)));
return (CMy1Doc*)m_pDocument;
}
#endif //_DEBUG
// CMy1View 消息处理程序int CMy1View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1; // TODO: 在此添加您专用的创建代
return 0;
}void CMy1View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
this->m_IsLButtonDown=TRUE;
pt[count].begin=point; CView::OnLButtonDown(nFlags, point);
}void CMy1View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
count++;
this->m_IsLButtonDown=FALSE;
CView::OnLButtonUp(nFlags, point);
}void CMy1View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_IsLButtonDown)
{
pt[count].end=point;
Invalidate();
}
CView::OnMouseMove(nFlags, point);
}
不知道是不是这样的简单画线
小修改了下代码已经可以画来了。。但是线条粗的时候拖动鼠标效果不是很理想。线条会有点闪、拖动鼠标时两条线的交叉会有白色点。。
代码如下:鼠标移动 ---void CTwoBufferView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (chek)//鼠标按下的时候开始作图
{
CClientDC pDC(this);
int nOldDrawMode = pDC.SetROP2(R2_NOTXORPEN);/*R2_NOT*//*R2_XORPEN*/
CPen cpen(PS_SOLID, 5, RGB(0,123,0));
pDC.SelectObject(&cpen);
pDC.MoveTo(cbgin);
pDC.LineTo(cend);
cend=point;
pDC.MoveTo(cbgin);
pDC.LineTo(cend);
pDC.SelectObject(&cpen);
pt[count].cend=point;
}
CView::OnMouseMove(nFlags, point);
}
//鼠标左键按下的时候
void CTwoBufferView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
pt[count].begin=point;
pt[count].cend=point;
cbgin=point;//原点坐标
cend=point;//当前坐标
chek=true;//鼠标按下
CView::OnLButtonDown(nFlags, point);
}
//鼠标左键弹起了的时候
void CTwoBufferView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
chek=false;
Invalidate(false); //刷新
count++; //弹起来的时候数量加一 表明已经画好一个线段
CView::OnLButtonUp(nFlags, point);
}void CTwoBufferView::OnDraw(CDC* pDC)
{
CTwoBufferDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
MyDraw(pDC); //调用自定义函数
}
void CTwoBufferView::MyDraw(CDC *pDC)
{
CRect rect;
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
//创建一画笔
CPen m_pen;
m_pen.CreatePen(PS_SOLID, 5, RGB(0,123,0));
SelectObject(memDc,m_pen);
for(int i=0;i<count;i++)
{
memDc.MoveTo(pt[i].begin);
memDc.LineTo(pt[i].cend);
}
//将内存设备环境上的图拷贝到屏幕上显示
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDc, 0, 0, SRCCOPY);
//绘图完成后的清理
memBmp.DeleteObject();
memDc.DeleteDC();
}
//定义的结构体等。。
#define MAX_NUM 100
typedef struct POINTS
{
CPoint begin;
CPoint cend;
};
POINTS pt[MAX_NUM];
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
1.在 OnDraw/OnPaint 等函数中使用双缓冲的方式绘制全部数据,这是为了保证被别的窗体挡住或从最小化恢复后能正确显示。
2.在 MouseMove 等函数中只绘制真正需要的数据,而不要通过调用 Invalidate 全部重绘的方式。这样代码虽然简单,但往往会出现闪烁或效率低。 另外,微软的 AllVCLanguageSamples.zip 例子程序里有个叫 drawcli 的,是一个简单的绘图程序,可以参考做为例子。
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CRect rect;
GetClientRect(&rect);
//创建一个用于绘图的内存设备环境
memDc.CreateCompatibleDC(&pDC);
//建立一个与屏幕显示兼容的位图,
memBmp.CreateCompatibleBitmap(&pDC, rect.Width(), rect.Height());
CBitmap *pOldBit= memDc.SelectObject(&memBmp);
memDc.FillSolidRect(0,0,rect.Width(), rect.Height(),RGB(255,255,255));
return 0;
}
void CTwoBufferView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (chek)//鼠标按下的时候开始作图
{
pt[count].cend=point;
Invalidate();
}
CView::OnMouseMove(nFlags, point);
}void CTwoBufferView::OnDraw(CDC* pDC)
{
CTwoBufferDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
MyDraw(pDC);
}
void CTwoBufferView::MyDraw(CDC *pDC)
{
CRect rect;
GetClientRect(&rect);
//创建一画笔
CPen m_pen;
m_pen.CreatePen(PS_SOLID,5, RGB(123,255,0));
SelectObject(memDc,m_pen);
for(int i=0;i<count;i++)
{
memDc.MoveTo(pt[i].begin);
memDc.LineTo(pt[i].cend);
}
//将内存设备环境上的图拷贝到屏幕上显示
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDc, 0, 0, SRCCOPY);
//绘图完成后的清理在析构函数
}
CTwoBufferView::~CTwoBufferView()
{
memBmp.DeleteObject();
memDc.DeleteDC();
}