从SetScrollSizes谈CScrollView和绘图技巧

    此函数的接口说明参见MSDN官方文档http://msdn.microsoft.com/en-us//library/3ew6s3ez(v=vs.110).aspx

    其中sizeTotal参数设置的是滚动视图的滚动范围大小,采用逻辑单位。

新建一个基于单文档的标准的MFC应用程序,其中视图采用滚动视图,仅仅在绘图操作中添加如下代码(采用GDI+库)

CSize totalDocSize = GetTotalSize();
	CDC memDC;
	CBitmap memBmp;
	CBitmap *pReplacedBmp = NULL;
	memDC.CreateCompatibleDC(pDC);
	memBmp.CreateCompatibleBitmap(pDC,2*totalDocSize.cx,2*totalDocSize.cy);
	pReplacedBmp = memDC.SelectObject(&memBmp);

	Gdiplus::Graphics myGraphics(memDC.m_hDC);
	myGraphics.SetSmoothingMode(SmoothingModeHighQuality);
	Gdiplus::FontFamily myFontFamily(L"Microsoft Sans Serif");
	Gdiplus::Font myFont(&myFontFamily, 24, FontStyleRegular, UnitPixel);
	PointF      pointF(30.0f, 10.0f);
	Gdiplus::SolidBrush  solidBrush(Color(255, 0, 0, 255));
	myGraphics.DrawString(L"Bayesian Network", -1, &myFont, pointF, &solidBrush);
	myGraphics.FillRectangle(&solidBrush,totalDocSize.cx,totalDocSize.cy,totalDocSize.cx,totalDocSize.cy);
	pDC->BitBlt(0,0,totalDocSize.cx*2,totalDocSize.cy*2,&memDC,0,0,SRCCOPY);
该绘制操作展示了在DC映射模式为MM_TEXT像素模式下,内存绘图、滚动范围大小的意义。


编译通过,调试运行,得到下面的结果:

从SetScrollSizes谈CScrollView和绘图技巧_第1张图片

分析:

  1. 窗口没有出现滚动条,是因为默认的滚动尺寸设置为100*100,视窗的范围已经足够显示绘制内容
  2. 窗口视图的滚动范围一般和文档的大小是一致的,这样在滚动的范围内可以展示所有的文档绘制内容,参考代码如下
    void CMyScrollView::OnInitialUpdate()
    {
       CScrollView::OnInitialUpdate();
    
       // The GetMyDocSize() member function is implemented in  
       // your document class. The return type is CSize.
       CMyScrollDoc* pMyDoc = (CMyScrollDoc*)GetDocument();
       SetScrollSizes(MM_TEXT, pMyDoc->GetMyDocSize());
    }
  3. 当视图窗口的尺寸小于滚动范围的时候,会出现滚动条,触发滚动条操作的时候,会调整的设备环境(DC)的窗口原点,以使文档显示达到友好的交互效果.参考图                                                                      从SetScrollSizes谈CScrollView和绘图技巧_第2张图片
  4. 当你用鼠标不停的放大和缩小窗口尺寸的时候,WM_PAINT消息会被频繁的发送到主窗口,进行视图的重绘操作,先是填充窗口背景,然后进行图形的绘制操作,时间反差愈大,闪烁效果愈加明显...参考代码
    BOOL CbayesarchitectView::OnEraseBkgnd(CDC* pDC)
    {
    	// TODO: Add your message handler code here and/or call default
    
    	//return CScrollView::OnEraseBkgnd(pDC);
    	return TRUE;
    }

解决方案:禁止窗口背景的擦除,直接在与视图DC兼容的内存DC中绘制文档的内容,然后一次性的贴在视图DC上进行显示。由于禁止了窗口背景的擦除,设置内存DC的画布要足够大,使得在屏幕窗口显示范围内不出现没有擦除的区域即可.若内存DC的画布BMP过小,禁止窗口擦除后会出现下面的效果

从SetScrollSizes谈CScrollView和绘图技巧_第3张图片

可以通过处理视图的WM_SIZE消息记录窗体的尺寸大小,进行调整。有一点需要注意,如果内存BMP尺寸太大,拷贝会很耗时的,在改变窗口尺寸的时候会明显的感觉到.文档尺寸设置为适用大小即可...


你可能感兴趣的:(从SetScrollSizes谈CScrollView和绘图技巧)