MFC双缓冲绘图问题

志雄阿三 2015-07-15 11:38:15
先上图:


问题是这样的:
我想用双缓冲技术画一个坐标系,并在坐标系上画3个点。目标效果就是实现中间那个小的坐标系的效果(这个坐标系不是用双缓冲画的)。
绘制小的坐标系时,我用的SetMapMode( MM_TWIPS )模式,并将CClientDC *pDC = new CClientDC( this )转化为逻辑模式,
pDC->DpToLp();并设置了坐标原点。

而当我使用双缓冲的时候,
1、SetMapMode( MM_TWIPS )根本什么都不能显示出来;
2、SetMapMode( MM_TEXT )时,可以显示如图,可以看到点非常大。
3、MemDC.DpToLp()似乎没什么效果。

由于我的作图空间很小,而且坐标系是X+指右,Y+指上。请问有没有什么办法可以解决这个问题?
...全文
340 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
cppabc 2016-02-20
  • 打赏
  • 举报
回复
引用 6 楼 pcradio 的回复:
[quote=引用 5 楼 y330197352 的回复:] [quote=引用 3 楼 pcradio 的回复:] 我的映射模式是MM_ISOTROPIC,这个模式,逻辑坐标和设备坐标的长度比例我是可以自由设置的,逻辑坐标系方向也可以自由设置,已经设置为x正方向为右,y正方向为上了,你的代码有问题,因为没有贴全,我估计是你在把位图bitblt的时候没有把映射模式设回去或者你的视口原点坐标有问题
我按照您的代码改了改,真的成功了!!哈哈,太感谢了! 首先我的代码顺序很乱,我按照您的改了下代码顺序,这样即使是MM_TWIPS也可以显示出图像了(虽然不是我要的结果); 然后,我添加了int nOldMode = memDC.SaveDC();和memDC.RestoreDC(nOldMode);就OK了。 我现在还没明白为什么这么改就成功了,我还要在理解理解,太感谢了~![/quote] 你的映射模式和我的只是映射时长度映射的不一样,我的是1 logic unit == 1 device pixel 你的模式MM_TWIPS是 1 logic unit==1/1440 inch 逻辑坐标系的xy正方向是与你的一致的,之所以要RestoreDC是因为双缓冲绘图时,内容是绘在了视口原点发生了变化的 位图上的,也就是说位图的视口原点已经不是(0,0)了,最后你需要把位图BitBlt到窗口的视口坐标系中,这时依旧会从当前位图 的视口坐标系原点开始复制,这样就会导致你不能把整个位图都复制过去,所以你必须在BitBlt前把位图的视口原点还原到初始状态,也就是位图左上角,与位图窗口坐标原点重合,RestoreDC就是做这个的[/quote] 我也遇到了同样的问题,为什么用你的方法显示不出来呢,显示是只是显示一个黑色的背景: GetClientRect(&rect); CDC dcMem; dcMem.CreateCompatibleDC(pDC); //创建与视图的设备相兼容的内存设备 CBitmap bmp; bmp.CreateCompatibleBitmap(pDC,rect.right,rect.bottom); //创建一个与视图兼容的位图 CBitmap* pOldBmp=dcMem.SelectObject(&bmp); //选择位图 CFont font; int nOldMode = dcMem.SaveDC(); dcMem.SetMapMode(MM_LOENGLISH); dcMem.FillSolidRect(&rect,pDC->GetBkColor()); dcMem.MoveTo(20,-20); dcMem.LineTo(40,-100); dcMem.LineTo(50,-200); dcMem.LineTo(200,-500); dcMem.RestoreDC(nOldMode); pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); //将在内存中绘制好的图像重新显示到视图中 dcMem.SelectObject(pOldBmp); dcMem.SelectObject(pOldBmp);
阿源是少年 2015-07-16
  • 打赏
  • 举报
回复
引用 5 楼 y330197352 的回复:
[quote=引用 3 楼 pcradio 的回复:] 我的映射模式是MM_ISOTROPIC,这个模式,逻辑坐标和设备坐标的长度比例我是可以自由设置的,逻辑坐标系方向也可以自由设置,已经设置为x正方向为右,y正方向为上了,你的代码有问题,因为没有贴全,我估计是你在把位图bitblt的时候没有把映射模式设回去或者你的视口原点坐标有问题
我按照您的代码改了改,真的成功了!!哈哈,太感谢了! 首先我的代码顺序很乱,我按照您的改了下代码顺序,这样即使是MM_TWIPS也可以显示出图像了(虽然不是我要的结果); 然后,我添加了int nOldMode = memDC.SaveDC();和memDC.RestoreDC(nOldMode);就OK了。 我现在还没明白为什么这么改就成功了,我还要在理解理解,太感谢了~![/quote] 你的映射模式和我的只是映射时长度映射的不一样,我的是1 logic unit == 1 device pixel 你的模式MM_TWIPS是 1 logic unit==1/1440 inch 逻辑坐标系的xy正方向是与你的一致的,之所以要RestoreDC是因为双缓冲绘图时,内容是绘在了视口原点发生了变化的 位图上的,也就是说位图的视口原点已经不是(0,0)了,最后你需要把位图BitBlt到窗口的视口坐标系中,这时依旧会从当前位图 的视口坐标系原点开始复制,这样就会导致你不能把整个位图都复制过去,所以你必须在BitBlt前把位图的视口原点还原到初始状态,也就是位图左上角,与位图窗口坐标原点重合,RestoreDC就是做这个的
志雄阿三 2015-07-16
  • 打赏
  • 举报
回复
引用 3 楼 pcradio 的回复:
我的映射模式是MM_ISOTROPIC,这个模式,逻辑坐标和设备坐标的长度比例我是可以自由设置的,逻辑坐标系方向也可以自由设置,已经设置为x正方向为右,y正方向为上了,你的代码有问题,因为没有贴全,我估计是你在把位图bitblt的时候没有把映射模式设回去或者你的视口原点坐标有问题
我按照您的代码改了改,真的成功了!!哈哈,太感谢了! 首先我的代码顺序很乱,我按照您的改了下代码顺序,这样即使是MM_TWIPS也可以显示出图像了(虽然不是我要的结果); 然后,我添加了int nOldMode = memDC.SaveDC();和memDC.RestoreDC(nOldMode);就OK了。 我现在还没明白为什么这么改就成功了,我还要在理解理解,太感谢了~!
赵4老师 2015-07-15
  • 打赏
  • 举报
回复
Coordinate Space and Transformation Functions The following functions are used with coordinate spaces and transformations. ClientToScreen CombineTransform DPtoLP GetCurrentPositionEx GetGraphicsMode GetMapMode GetViewportExtEx GetViewportOrgEx GetWindowExtEx GetWindowOrgEx GetWorldTransform LPtoDP MapWindowPoints ModifyWorldTransform OffsetViewportOrgEx OffsetWindowOrgEx ScaleViewportExtEx ScaleWindowExtEx ScreenToClient SetGraphicsMode SetMapMode SetViewportExtEx SetViewportOrgEx SetWindowExtEx SetWindowOrgEx SetWorldTransform
阿源是少年 2015-07-15
  • 打赏
  • 举报
回复
我的映射模式是MM_ISOTROPIC,这个模式,逻辑坐标和设备坐标的长度比例我是可以自由设置的,逻辑坐标系方向也可以自由设置,已经设置为x正方向为右,y正方向为上了,你的代码有问题,因为没有贴全,我估计是你在把位图bitblt的时候没有把映射模式设回去或者你的视口原点坐标有问题
阿源是少年 2015-07-15
  • 打赏
  • 举报
回复
我在对话框OnPaint画的,核心代码如下:
void CTestViewportDlg::OnPaint() 
{
	CPaintDC dc(this);

	if (IsIconic())
	{
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CBitmap bitmap;
		CRect rcClient;
		GetClientRect(rcClient);
		bitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
		CDC memDC;
		memDC.CreateCompatibleDC(&dc);
		memDC.SelectObject(&bitmap);

		// Fill bitmap background with write brush.
		CBrush bmpBkBrush(RGB(0, 255, 255));
		memDC.FillRect(rcClient, &bmpBkBrush);

		// Change map mode, positive x right, positive y up.
		int nOldMode = memDC.SaveDC();
		memDC.SetMapMode(MM_ISOTROPIC);
		memDC.SetViewportExt(1, 1);
		memDC.SetWindowExt(1, -1);
		memDC.SetViewportOrg(rcClient.Width() / 2, rcClient.Height());

		// Draw coordinate system.
		CPen pen(PS_SOLID, 2, RGB(0, 0, 0));
		memDC.SelectObject(&pen);
		memDC.MoveTo(-rcClient.Width() / 2, 5);
		memDC.LineTo(rcClient.Width() / 2, 5);
		memDC.MoveTo(0, 5);
		memDC.LineTo(0, rcClient.Height());
		memDC.TextOut(2, 22, CString("0,0"));

		// Draw testing circle.
		CPen shapePen(PS_SOLID, 1, RGB(0 ,0 ,0));
		memDC.SelectObject(&shapePen);
		CBrush shapeBrush(RGB(255, 0, 0));
		memDC.SelectObject(&shapeBrush);
		memDC.Ellipse(5, 102, 25, 82);
		memDC.Ellipse(15, 50, 35, 30);
		memDC.Ellipse(75, 105, 95, 85);


		// We must restore mapping mode before copy bitmap to client context.
		memDC.RestoreDC(nOldMode);

		// Copy double buffer bitmap to client context.
		dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
	}
}
阿源是少年 2015-07-15
  • 打赏
  • 举报
回复

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧