孙鑫VC学习笔记(图形的保存和重绘)

MFC中图形的临时保存和重绘 (1)图形的临时保存 为使所绘制的图形始终在窗口中呈现出来,就需要在提前将这些图形临时保存起来。保存图形的方式有多种,对于本程序的图形主要有以下要素:起点、终点、绘制的类型(点、线、矩形、或椭圆)、位图起点坐标、线宽、线型、颜色等。为此我们创建CGraph类,来保存图形要素,这里仅列出重载的构造函数。 //重载构造函数 CGraph::CGraph(UINT m_nDrawType,CPo 阅读详情
孙鑫VC学习笔记 11(1)

第11课  如何让CDC上输出的文字、图形具有保持功能

1.创建4个菜单,为其添加消息响应,用成员变量保存绘画类型。添加LButtonDown和Up消息。
2.当窗口重绘时,如果想再显示原先画的数据,则需要保存数据。为此创建一个新类来记录绘画类型和两个点。
class CGraph 
{
public:
CPoint m_ptOrigin;//起点
CPoint m_ptEnd;//终点
UINT m_nDrawType;//绘画类型
CGraph();
CGraph(UINT m_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd);//此为构造函数。
virtual ~CGraph();

};
   然后在void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)中加入如下代码
//CGraph graph(m_nDrawType,m_ptOrigin,point);//不能用局部变量
//m_ptrArray.Add(&graph);//加入这种指针数组中
/* OnPrepareDC(&dc);//这个函数中可以重新设置窗口原点,对于滚动条中,保存数据前要调用此函数
dc.DPtoLP(&m_ptOrigin);//将设备坐标转换为逻辑坐标
dc.DPtoLP(&point);//
CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point);//在堆中创建新的对象
m_ptrArray.Add(pGraph);*///加入到指针数组中
在GraphicView.h中有如下代码
CPtrArray m_ptrArray;
   在OnDraw中重画时调出数据
for(int i=0;i<m_ptrArray.GetSize();i++)
3.在CView::OnPaint()调用了OnDraw(),但在void CGraphicView::OnPaint()中MFC的Wizard没有调用OnDraw(),要注意这个区别。如果你此时想调用,必须手动添加代码。 OnDraw(&dc);

实际上也是调用了BeginPaint和EndPaint

如果在CGraphicView里面捕获了OnPaint,必须在里面调用OnDraw函数

void CGraphicView::OnPaint()

{

CPaintDC dc(this);

OnPrepareDC(&dc);//坐标转换-->-->-->-->-->

OnDraw(&dc);

}
4.让窗口具有滚动条的功能。
   第1.将CGraphicView的头文件中的CView全部替换成CSrollView
   第2.添加如下的代码
void CGraphicView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();

// TOD Add your specialized code here and/or call the base class
SetScrollSizes(MM_TEXT,CSize(800,600));//设置映射模式,设定窗口大小。OK!
}

5.坐标系的转换,此处不再详细介绍,需要时请查阅相关资料。


6.解决重绘时线跑到上面的问题。为什么会错位?因为逻辑坐标和设备坐标没有对应起来。

在CScrollView::OnInitialUpdate()函数中: ptVpOrg=-GetDeviceScrollPosition();

pDC->SetViewportOrg(ptVpOrg);
解决方法:
  在OnLButtonDown画完图后,保存之前。调用
/* OnPrepareDC(&dc);//重新设置逻辑坐标的原点!!!
dc.DPtoLP(&m_ptOrigin);//设备坐标转化为逻辑坐标
dc.DPtoLP(&point);
CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point);
m_ptrArray.Add(pGraph);*/
7.另外两种方法来保存数据。
  一种是用CMetaFileDC,另一种是利用兼容DC,重绘时利用 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&m_dcCompatible,0,0,SRCCOPY);
将兼容DC的图拷贝到屏幕DC上去。
此处不再详细介绍这两种方法,因为介绍多了容易搞晕。呵呵

孙鑫VC学习笔记:第十一讲 坐标空间与各种转换的概念

介绍一下坐标空间、逻辑空间、映射方式等概念
MicroSoft Windows 下的程序运用坐标空间和转换来对图形输出进行缩放,平移,旋转,斜切和反射。
一个坐标空间是一个二维空间,通过使用连个相互垂直并且长度相等的轴来定义二维对象

坐标空间
API使用四种坐标空间:世界坐标系空间,页面空间,设备空间,和物理设备空间。基于Win32的应用程序运用世界坐标系空间对图形输出进行旋转、斜切或者反射。

Win32 API把世界坐标系空间和页面空间称为逻辑空间;最后一种坐标空间(即物理设备空间)通常指应用程序窗口的客户区;但是他也包括整个桌面、完整的窗口(包括框架、标题栏和菜单栏)或打印机的一页或绘图仪的一页纸。物理设备的尺寸随显示器、打印机、绘图仪的所设置的尺寸而改变。

转换
如果要在一个物理设备上绘制输出,Windows把一个矩形区域从一个坐标空间拷贝到(或映射到)另一个坐标空间,直至最终完整的输出呈现在物理设备上(通常是屏幕或打印机)

如果该应用程序调用了SetWorldTransForm函数,那么映射就从应用程序的世界坐标系空间开始;否则,映射在页面空间中进行。在 Windows把矩形区域的每一点从一个空间拷贝到另一个空间时,他采用一种被称作转换的算法,转换是把对象从一个坐标空间拷贝到另一个坐标空间时改变(或转变)这一对象的大小,方位,和形态,尽管转换把对象看成一个整体,但他也作用与对象的每一个点或每一条线。

---------------------------------------------------------------------------------
页面空间到设备空间的转换
页面空见到设备空间的转换是原Windows程序接口的一部分。这种转换确定与一特定设备描述表相关的所有图形输出的映射方式。
所谓映射方式是指确定用于绘图操作的单位大小的一种量度转换,映射方式是一种影响几乎任何客户区绘图的设备环境属性。另外还有四种设备环境属性:窗口原点,视口原点,窗口范围和视口范围,这四种属性与映射关系密切相关。

页面空间到设备空间的转换所用的是两个矩形的宽与高的比率,其中页面空间中的矩形被称为窗口,设备空间中的矩形被称为视口。Windows把窗口原点映射到视口原点,把窗口范围映射到视口范围,就完成了这种转换。

---------------------------------------------------------------------------------
设备空间到物理空间的转换
设备空间到物理空间的转换:只限于平移,并由Windows窗口管理部分控制,这种转换的唯一用途是确保设备空间的原点被映射到物理设备上的适当点上。没有函数能设置这种转换,也没有函数能获取有关数据。
所以通常我们所要考虑的是从页面空间到设备空间的转换。页面空间通常称为逻辑空间。

---------------------------------------------------------------------------------
默认转换
一旦应用程序建立了设备描述表,并立即开始调用GDI绘图或输出函数,则运用默认页面空间到设备空间的转换和设备空间到客户区的转换,(在应用程序调用SetWorldTransform之前不会世界坐标空间到页面空间的转换。

默认页面空间到设备空间的转换是一对一的映射;即页面空间上给出的一点映射到设备空间上的一个点。这种转换没有以矩阵指定,而是通过把视口宽除以窗口宽,把视口高除以窗口高而得出的,在默认情况下,视口尺寸为1*1像素,窗口尺寸为1*1页单位。

设备空间到物理设备(客户区,桌面和打印机),得转换结果总是一对一的;既设备空间上的一个单位总是与客户区,桌面,和打印机上的一个单位对应。这一转换的唯一用途是平移,无论窗口移到桌面的什么位置,它永远取保输出能够正确无误地出现在窗口上。

默认装换的一个独特之处是设备空间与应用程序窗口的y轴方向。
在默认的状态下,y轴正向朝下,-y方向朝上。

---------------------------------------------------------------------------------
逻辑坐标和设备坐标
几乎在所有GDI函数中使用的坐标值都是逻辑单位,Windows必须将逻辑坐标值转换为“设备单位”,
即像素。这种转换是由映射方式,窗口和视口的原点以及窗口和视口的范围决定的。
Windows对所有消息(如WM_SIZE,WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_LBUTTONUP),所有的非GDI函数和一些GDI函数(GetDeviceCaps函数(获取设备的范围)),永远使用设备坐标。

窗口是基于逻辑坐标的,逻辑坐标可以是像素,毫米,英寸等单位,使口是基于设备坐标(像素)的。通常,视口和客户区是相同的。
缺省的映射模式是MM_TEXT,在这种映射模式下,逻辑单位和设备单位相同。

---------------------------------------------------------------------------------
窗口(逻辑)坐标和视口(设备)坐标的转换
xViewPort=(xWindow-xWinOrg)*xViewExt/xWinExt+xViewOrg;
yViewPort=(yWindow-yWinOrg)*yViewExt/yWinExt+yViewOrg;
视口(设备)坐标和窗口(逻辑)坐标的转换与上面相反;
---------------------------------------------------------------------------------
在MM_TEXT映射方式下窗口(逻辑)坐标和视口(设备)坐标的转换:
xViewPort=xWindow-xWinOrg+xViewOrg;
yViewPort=yWindow-yWinOrg+yViewOrg;
视口(设备)坐标和窗口(逻辑)坐标的转换与上面相反;
---------------------------------------------------------------------------------
CDC中提供两个成员函数SetViewpoitOrg和SetWindowOrg,用来改变视口和窗口的原点。
如果将视口原点设为(xViewOrg,yViewOrg),则逻辑点(0,0)就会被映射为设备点(xViewOrg,yViewOrg),如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)就会被映射为设备点(0,0),
即左上角。
不管对窗口和视口原点作什么改变,设备点(0,0)始终是客户区的左上角。

---------------------------------------------------------------------------------

 

图形的保存和重绘
编写画图代码,设定一个标识,在OnLButtonDown中保存鼠标按下去的点,在OnLButtonUp中捕获鼠标弹起的点,利用switch语句分别画图。这是上节课的内容,上节课还讲了窗口重绘的原理,实际上分为两步,
首先擦除以前的背景,然后再进行窗口重绘。
所以当拖动窗口改变窗口大小时,窗口要发生重绘,首先会擦除以前的背景,于是先前所画图像会消失。

解决办法是将画图代码写在OnDraw()函数中,窗口每次重绘都会调用该函数重新绘制图像。
但是怎么保存每次重绘图像需要的代码呢?
事实上,要画的图形由三个因素决定:
1.图形类型(点、直线、矩形、椭圆)
2.图形绘制初始点
3.图形绘制终点
所以我们可以用数组类保存三个变量:m_nDrawType,m_ptOrigin,m_ptEnd。

首先需要新建一个Class type为Generic Class的名为CGraph类,
在CGraph中增加三个成员变量UINT m_nDrawType,CPoint m_pOrigin,CPoint m_pEnd,
并在不带参数构造函数中将三个成员变量初始化。
然后构造一个带参数的构造函数 CGraph(UINT m_nDrawType,CPoint m_pOrigin,CPoint m_pEnd);
用来接收三个变量值,代码如下:

CGraph::CGraph(UINT m_nDrawType,CPoint m_pOrigin,CPoint m_pEnd)
{
  this->m_nDrawType=m_nDrawType;
  this->m_pOrigin=m_pOrigin;
  this->m_pEnd=m_pEnd;
}
至此,我们可以用CGraph类保存绘制一个图形的三要素,根据这三要素可以绘制我们所作的图形。
--------------------------------------------------------------------------------
但是如果我们绘制了多个图形怎么办?
如果用CGraph类对象的一个数组,那么它只能保存有限个对象,
而我们在绘制图形的时候,并不能限定只能绘制多少个图形。
用链表可以实现动态存储,但是操作十分复杂,
于是我们想到了MFC提供一集合类,如前面用到过的CStringArray,可以动态存储CString对象
这里要用到的是另一个集合类,CPtrArray,它用来动态保存CGraph对象。
(它的用法大家可以参见 MSDN或右边。)

于是在OnLButtonUp函数中画完图形之后 ,我们想创建一个CGraph对象,
把画这个图形所必须的三要素保存到这个对象之中。
如果我们直接在尾部增加下面两行代码:
  graph(m_nDrawType,m_ptOrigin,point)
m_ptrArray.Add(&graph);
但是运行程序之后,我们所绘制的图形没能在OnDraw函数中重绘。
这是因为我们在OnLButtonUp函数中创建的CGraph对象在本函数结束时被销毁,内存被回收。
---------------------------------------------------------------------------------
解决办法:
在OnLButtonUp函数中创建的CGraph对象指针,然后用new方法为它在堆中分配内存。
因为new方法分配的内存在堆中,除非显式地调用Delete方法去释放它,
否则其生命周期直到程序结束时才结束 。
CGraph *=new CGraph(m_nDrawType,m_ptOrigin,point);
m_ptrArray.Add(pGraph);
虽然pGraph 指针在函数结束时也会析构,但是没有关系,m_ptrArray已经保存了该指针,
而new所建立的对象是在堆上的,除非显式地调用Delete方法去释放它,
否则其生命周期直到程序结束时才结束 。

窗口重绘会调用OnDraw函数,所以要在此函数中增加画图代码,代码如下:

注:
1. m_ptrArray.GetSize()从得到数组长度,构造for循环
2. ((CGraph*)m_ptrArray.GetAt(i))->得到CGraph类的各变量,
3. 其中m_ptrArray.GetAt(i)返回CObject*,要强制转换成CGraph*。
--------------------------------------------------------------------------------

下面研究一下,OnDraw函数为什么能在窗口重绘过程中被调用
OnDraw函数不是WM_PAINT的相应函数,为什么能在窗口重绘过程中被调用?
下面是一段MFC资源文件中的代码:(是WM_PAINT消息响应函数OnPaint())
void CView::OnPaint()
{
// standard paint routine
  CPaintDC dc(this);
  OnPrepareDC(&dc);
  OnDraw(&dc);
}
从上面的代码我们知道,原来在基类View类中调用了OnDraw函数,所以我们认为OnDraw专门用来重绘的
其实我们也可以增加WM_PAINT消息响应,自己在其响应函数写重绘窗口的代码。
前面讲过,在响应WM_PAINT时候,只能利用BeginPaint()获得dc的句柄,用EndPaint()释放dc句柄。
而上面代码并没有发现BeginPaint()与EndPaint(),查看一下CPaintDC 就知道,
CPaintDC 类的构造函数中调用了BeginPaint(),析构函数中调用了EndPaint()。

注意:CPaintDC只能在OnPaint中使用,因为在MSDN中这样说了:
CClientDC objects encapsulate working with a device context that represents only the client area of a window. The CClientDC constructor calls the GetDC function, and the destructor calls the ReleaseDC function. CWindowDC objects encapsulate a device context that represents the whole window, including its frame.
如果要在OnPaint以外地方获得dc句柄的话,调用GetDC ,释放用ReleaseDC。

CPtrArray----->MSDN!!

 

如何把元文件保存到文件当中


1.为“打开”,“保存”添加命令相应函数。
2.用 CopyMetaFile 拷贝元文件到指定文件中
CopyMetaFile
将windows格式的元文件拷贝到指定的文件当中。
首先我们在“保存”命令响应函数OnFileSave()中完成保存元文件到文件的功能,

执行之后在项目工程文件夹中增加了一个meta.wmf的文件,用ACDsee可以打开。
--------------------------------------------------------------------------------
然后在“打开”命令响应函数OnFileOpen()中完成保存元文件到文件的功能,打开文件时用GetMetaFile或GetEnhMetaFile,接着将将文件的图形拷贝到m_dcMetaFile元文件中,最后调用Invalidate()引起窗口重画,使图形在OnDraw()重绘,代码如下:

注:CopyMetaFile,GetMetaFile函数已经被废弃现在使用增强的函数CopyEnhMetaFile,GetEnhMetaFile。用法相同,为了与16-bit Windows API兼容,老函数仍能使用。
-----------------------------------------------------------------------------

介绍利用兼容DC保存图形与重绘图形的方式


1.构造兼容DC对象:CDC  m_dcCompatible
2.在CGraphicView::OnLButtonUp写下面代码

void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    CClientDC dc(this);
    CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
    //dc.SelectObject(pBrush);
    m_dcMetaFile.SelectObject(pBrush);

    if(!m_dcCompatible.m_hDC)
    {
        m_dcCompatible.CreateCompatibleDC(&dc);
        CRect rect;
        GetClientRect(&rect);
        CBitmap bitmap;
        bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
        m_dcCompatible.SelectObject(&bitmap);
   

    m_dcCompatible.BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);


        m_dcCompatible.SelectObject(pBrush);
    }


3.在CGraphicView::OnDraw中写入下面代码:

CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&m_dcCompatible,0,0,SRCCOPY);

//出现问题,见下面粗斜体,解决代码见上面粗斜体;
CBitmap::CreateCompatibleBitmap
通过指定的宽高创建一个兼容位图。初始化一个与指定设置相兼容的位图
BOOL CreateCompatibleBitmap(CDC* pDC,int nWidth,int nHeight );
--------------------------------------------------------------------------------
CreateCompatibleBitmap 返回的位图对象只包含相应设备描述表中的位图信息头,不包含颜色表和像素数据块。因此,选入该位图对象的设备描述表不能像选入普通对象的设备描述表一样使用,必须在SelectObject函数之后,调用BitBlt将原始设备描述表的颜色表以及像素数据块拷贝到兼容设备描述表。

 

如果我们想在保存图象的同时显示图像,可以在调用
m_dcCompatible.MoveTo(m_ptOrigin);
m_dcCompatible.LineTo(point);
的同时调用
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

如何使窗口具有滚动条?


本程序的CGraphicView 类是从View类继承的
class CGraphicView : public Cview
首先将基类改成CScrollView
class CGraphicView : public CScrollView
然后将源文件cpp文件中的CView全部替换成CScrollView
在文件中替换字或词的步骤,
从菜单中选择 Edit->Replace,
在弹出的对话框中再选择 Match whole word only(仅全词匹配)
--------------------------------------------------------------------------------
要使窗口可以滚动,还需要设置一些滚动的参数:
用SetScrollSizes方法来设置映射模式、滚动视图总的尺寸等等
而这个函数最好在虚函数的重载函数OnInitiaUpdate里面调用。
这个虚函数在一个视图与一个文档关联之后调用,也就是在窗口完全创建之后第一个调用的函数。
不过它的调用是在OnDraw函数调用之前。所以这个函数可以做一些窗口创建之后的初始化工作。

void CGraphyicView::OnInitialUpdate()
{
  CScrollView::OnInitialUpdate();
  SetScrollSizes(MM_TEXT,CSize(800,600));
}

--------------------------------------------------------------------------------

程序运行之后,将窗口的大小调到小到800*600时,就可以看到滚动条了。
但是我们发现一个问题,先将垂直滚动条下拉一些,然后在窗口右下角画一条直线,将其最小化,还原之后直线的位置上移了,这是什么原因呢?

调试之后,可以断定OnLButtonDown与重绘函数OnDraw中所画图形的三个要素相同,所以不是它们的问题。

在前面研究窗口重绘为什么调用OnDraw函数的时候,
void CView::OnPaint()
{
// standard paint routine
  CPaintDC dc(this);
  OnPrepareDC(&dc);
  OnDraw(&dc);
}
发现在调用OnDraw之前调用了OnPrepareDC ,问题就出在这里。 
在MFC资源文件中去查看OnPrepareDC 发现这样一条代码:pDC->SetViewportOrg(ptVpOrg);
调试一下,发现ptVpOrg=(x=0, y= -150);  可见OnPrepareDC调整了显示上下文的属性将视口的原点设置为(0,-150),根据公式yViewPort=yWindow- yWinOrg+yViewOrg;得到设备点y坐标出现在原先显示地方的上方。
--------------------------------------------------------------------------------
关于解决办法的说明:
首先,绘制图形之后保存坐标点之前调用OnPrepareDC调整显示上下文的属性,将视口原点设置为(0,-150)然后调用设备坐标转换逻辑坐标函数DPtoLP将设备坐标(680,390)转换为逻辑坐标,
根据公式  yWindow=yViewport-yViewOrg+yWinOrg;得到y坐标为540。
窗口重绘时会先调用OnPrepareDC,调整显示上下文的属性,将视口的原点设置为(0,-150)
然后GDI函数用逻辑坐标点(680,540)绘制图形,被转换为(680,390)

所以解决的办法就是在OnLButtonDown函数中,绘制完图形之后,保存图形元素之前 加入下面代码:
OnPrepareDC(&dc);
dc.DPtoLP(&m_ptOrigin); //视口(设备)坐标和窗口(逻辑)坐标
dc.DPtoLP(&point);

当滚动条在最上端,窗口发生重绘时OnPrepareDC调整显示上下文,
会将视口的原点设置为(0,0),而不是(0,-150)
OnPrepareDC会随时根据滚动窗口的位置来调整视口的原点 

介绍两种保存图形与重绘图形的方式


第一种,要利用要一个类 CMetaFileDC
第一步创建一个CMetaFileDC 对象。 (private)
接着调用CMetaFileDC 构造器,然后再调用Create 函数 创建一个设备上下文与CMetaFileDC 对象关联起来。

下一步给CMetaFileDC 对象发送一系列的CDC命令

在为元文件发送完命令之后,调用Close成员函数关闭元文件的设备上下文,
并返回一个元文件 的句柄。接着就可以处理CMetaFileDC 对象。

CDC::PlayMetaFile 方法可以用来使用元文件句柄播放元文件,我们可以多次调用本函数

介绍一些与本操作相关的成员函数
--------------------------------------------------------------------------------
CMetaFileDC::Create
BOOL Create(LPCTSTR lpszFilename = NULL );
如果指定一个字符串,那么就指定了元文件的文件名,用来保存元文件
如果变量pszFilename 为空,那么就会在内存中创建一个元文件
--------------------------------------------------------------------------------
CMetaFileDC::Close
关闭一个设备上下文,返回一个DC句柄。

--------------------------------------------------------------------------------
用元文件来重绘图形的具体步骤:
1.先在CGraphicView类中,增加一个CMetaFileDC变量m_dcMetaFille (private)
2.在CGraphicView类的构造函数中调用m_dcMetaFille的Create()方法,
  Create方法的参数的NULL时创建一个内存的元文件
3.在CGraphicView类的OnLButtonUp()方法中,写入绘图命令,
   OnLButtonUp()方法代码如下:

m_dcMetaFile.SelectObject(pBrush);

 

HMETAFILE hmetaFile=m_dcMetaFile.Close();

pDC->PlayMetaFile(hmtaFile);

m_dcMetaFile.Create();//前面已经关闭了,可能再绘制图形,故重新创建一个

m_dcMetaFile.PlayMetaFile(hmtaFile);

DeleteMetaFile(hmtaFile);


  有了元文件的句柄,就可以利用CDC::PlayMetaFile来播放它。
   注意:关闭元文件并不意味着删除元文件。

View::OnFileSave()

HMETAFILE hmetaFile=m_dcMetaFile.Close();

CopyMetaFile(hmetaFile,"meta.wmf");

m_dcMetaFile.Create();//前面已经关闭了,可能再绘制图形,故重新创建一个

DeleteMetaFile(hmtaFile);

View::OnFileOpen

GetEnhMetaFile();

void CGraphicView::OnFileOpen()
{
    // TODO: Add your command handler code here
    HMETAFILE hmetaFile;
    hmetaFile=GetMetaFile("meta.wmf");
    m_dcMetaFile.PlayMetaFile(hmetaFile);
    DeleteMetaFile(hmetaFile);
    Invalidate();
}

4.窗口重绘时,即在OnDraw()函数中,去关闭元文件,从而获得元文件句柄。
MFC解决窗口保存及重绘闪烁问题的一种比较好的方案 框架 /****************************************************** SolveFlashingAndRedraw框架说明 ******************************************************/ /** 项目名称: SolveFlashingAndRedraw框架 包含文件: 1. ReadMe.txt 2. SolveFlashingAndRedraw MFC工程 版本号: v1.0.1 第一作者: Jef 地址: 中国/江苏 日期: 20091126 电子邮箱: dungeonsnd@126.com QQ: 420554565 (加好友时注明下载的文件名) 版权: 1.您可以修改及免费使用本程序。 2.修改之后附上您的个人信息发送到上面的作者邮箱,作者负责在全面测试后发布您修改后的新版本。 3.您使用本程序而导致任何伤害以及经济损失,由过错方依法承担所有责任,一概与第一作者及合作单位无关。 4.如果您使用本程序则表示您已经同意此版本协议!否则请勿使用! 项目功能: SolveFlashingAndRedraw 样例工程是MFC解决窗口保存及重绘闪烁问题的一种比较好的方案(Win32解决方法类似)。 运行步骤: 直接运行里面的程序,在窗口上任意拖拉鼠标画线,然后点击菜单栏的几个示范菜单项,然后移动窗口、 改变窗口大小、最大最小化窗口、用其它窗口覆盖此窗口、鼠标放到任务栏。。。 以上种种操作观察窗口内的图像变化。可以发现窗口内图像几乎看不到闪烁,而且窗口的元素已经保存下来重绘时任然可以看到图像。 如何使用: 进行项目开发时,可以先建立项目,然后把本解决方案框架拷贝到新建项目中即可。 也可以自己根据需要修改。 其它: 友情提示,小心 View类头文件及View类的实现文件中有说明,使用时别把它弄到你实际项目里哦! 进行大量复杂的图形的输出,而且对效率要求特别高时要考虑适当修改此框架(如增加裁剪区)后再使用哦。 如何有任何问题欢迎与作者分享!!! 立即下载

相关推荐

数字图像处理 MFC bmp格式图片打开与保存,VC6.0

VC++ MFC 数字图像处理,BMP图片的打开与保存源代码,非常适合初学者,VC6.0的编译环境。

VC 点滴 之 重绘

一基本知识: 1.OnPaint和OnDraw函数View的父类的OnPaint函数调用了OnDraw函数,若在子类为WM_PAINT消息添加响应函数OnPaint,OnDraw函数将不会被调用。2.CpaintDC和CclietnDCCpaintDC的构造函数中调用了BeginPaint(),析构函数中调用了EndPaint();CclietnDC的构造函数中调用了GetDC

awnucel的专栏 4015

VC6.0 MFC下截取窗口特定部分并保存为bmp图片的类

/*类名称:bmpScreen.h。 ; 类功能:提供了一个MFC下截取窗口特定部分并保存为bmp图片的类。 ; 类成员函数:void screenShot(CRect rect,int left,int top,char *name) ; 函数参数:Crect rect, int left, int top, int top, char* name。 ; 类参数说明: ; (1)Crect rect 定义截图框的大小。 ; (2)int left 定义截图框距截图窗口左边的距离。 ; (3)int top 定义截图框距截图窗口上边的距离。 ; (4)char *name 定义所截图的bmp图像的名称,该图像默认保存在所建项目的目录下。 */

MFC三种不同方式实现图形的保存和重绘---方法二: 运用CMetaFileDC

在OnButtonUp()函数中的代码 //选中透明画刷 CBrush* brush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); m_mfDc.SelectObject(brush); //m_mfDc为CMetaFileDC对象,全局的 //通过m_mfDc绘图 switch(m_gType) { ...

weixin_33946020的博客 629

Windows服务器渗透必备:5款杀软在线识别平台实测对比(附避坑指南)

本文针对Windows服务器渗透测试中的关键环节,实测对比了五款主流的在线杀软识别平台。文章从实战场景出发,深入分析了各平台在识别准确率、响应速度、隐匿性及使用风险上的差异,并提供了详尽的避坑指南与高级隐匿技巧,旨在帮助安全人员快速、精准地识别目标环境安全防护,为后续行动奠定情报基础。

weixin_29322553的博客 433

手把手教你调试eDP接口:Main Link信号异常、AUXCH通信失败怎么办?

本文提供了一份详尽的eDP接口调试实战指南,重点解决Main Link信号异常与AUXCH通信失败两大核心难题。文章系统介绍了从工具准备、信号完整性分析(眼图、抖动测量)到AUXCH协议解码、HPD信号检查的完整排查流程,并分享了链路训练诊断与常见避坑技巧,帮助硬件工程师高效定位并解决显示问题。

Jerry的专栏 832

MFC学习笔记之图形保存与重绘

先增加一个新的菜单项 绘图 ,然后在里面增加4个子菜单项 点 线 矩形 椭圆 ,在View类中响应各个子菜单项,为View类增加一个私有数据成员 int m_nDrawType 用来保存用户所做的选择 这个和上一篇日志的一样 所以代码不贴了,然后就是响应 OnLButtonDown 和 ONLButtonUp 消息 进行相应的绘图。我们知道当窗口大小改变或是窗口被切换的时候,程序就会发送一个WM_...

lovecontry 721

qcc304x笔记之手机端显示电量(九)

默认的sdk有些安卓手机不支持电量显示,所以需要加电量显示的补丁 流程分析 1. 首先新建一个task,并将task注册给电池模块 appBatteryRegister(batteryRegistrationForm) 实现handler处理函数,当battery模块电池电量更新后,会将电池百分比值发送到本模块,然后我们就可以在handler中将实时电量同步到手机端了。 hfpAtCmdInit atCmdTask.task.handler = appAtCmdHandleM...

在云巅的博客 2201

孙鑫VC学习笔记 (图形的保存和重绘)

第11课  如何让CDC上输出的文字、图形具有保持功能 1.创建4个菜单,为其添加消息响应,用成员变量保存绘画类型。添加LButtonDown和Up消息。 2.当窗口重绘时,如果想再显示原先画的数据,则需要保存数据。为此创建一个新类来记录绘画类型和两个点。 class CGraph { public: CPoint m_ptOrigin;//起点 CPoint m_ptEnd;/

Crazy_Frog的专栏 8197

华为s110、s220、s310、s530、s620 配置ssh,配置web登录

在服务器端创建SSH用户。

送个祝福给小豪的博客 318

Python 爬虫教程:企业官网基本信息抓取

本文介绍了使用Python爬虫技术抓取企业官网信息的方法,包括公司名称、简介、联系方式、地址、产品及新闻等数据。通过Requests和BeautifulSoup库实现网页请求与解析,并利用Pandas存储数据为CSV文件。同时提供了应对反爬虫机制(如设置User-Agent、代理IP池、延迟请求等)的解决方案,帮助高效获取企业公开数据。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1861

孙鑫VC学习笔记:第十一讲 图形的保存与重绘方法一

 图形的保存和重绘编写画图代码,设定一个标识,在OnLButtonDown中保存鼠标按下去的点,在OnLButtonUp中捕获鼠标弹起的点,利用switch语句分别画图。这是上节课的内容,上节课还讲了窗口重绘的原理,实际上分为两步,首先擦除以前的背景,然后再进行窗口重绘。所以当拖动窗口改变窗口大小时,窗口要发生重绘,首先会擦除以前的背景,于是先前所画图像会消失。解决办法是将画图代码写在OnDr

遐迩思的专栏 2859

DB文件在编程中的作用及示例代码

通过使用DB文件,我们可以实现数据的持久化存储,并能够高效地进行数据的增删改查操作。在本文中,我们以SQLite数据库为例,演示了如何使用Python语言创建和操作DB文件的示例代码。在实际的编程中,我们可以根据具体的需求和使用的数据库系统来进行更复杂的操作和优化。通过使用DB文件,我们可以实现数据的持久化存储,确保数据在程序关闭后也能被保留,并且能够高效地进行数据检索和更新。在本文中,我们将探讨DB文件的作用,并提供一些示例代码展示如何在编程中使用DB文件。上述代码中,我们使用SQLite提供的。

CodeSpark的博客 1822

孙鑫VC学习笔记:第十一讲 (二) 图形的保存与重绘方法

 图形的保存和重绘编写画图代码,设定一个标识,在OnLButtonDown中保存鼠标按下去的点,在OnLButtonUp中捕获鼠标弹起的点,利用switch语句分别画图。这是上节课的内容,上节课还讲了窗口重绘的原理,实际上分为两步,首先擦除以前的背景,然后再进行窗口重绘。所以当拖动窗口改变窗口大小时,窗口要发生重绘,首先会擦除以前的背景,于是先前所画图像会消失。 解决办法是将画图代码写在OnD

zhangning2095的专栏 570

YOLO11涨点优化:Loss魔改 | WIoU (Wise-IoU) v3版本全面替换,基于动态非单调聚焦机制,让模型更聪明地学习

YOLOv11目标检测中的WIoU v3损失函数改进 本文探讨了YOLOv11目标检测模型中CIoU损失函数的局限性,并提出了WIoU v3改进方案。关键发现包括: CIoU的缺陷:在低质量样本(小目标/遮挡目标)上过度惩罚,导致模型优化方向偏离,小目标AP往往比大目标低30%左右。 WIoU v3的创新: 动态非单调聚焦机制:根据样本"离群度"智能分配梯度 让模型重点优化中等质量样本,减少对低质量样本的无效关注 采用指数移动平均来自适应调整质量评判标准 实际效果:WIoU v3在保持大

2601_95807009的博客 422

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

孙鑫VC学习笔记:第十一讲 (二) 图形的保存与重绘方法一

图形的保存和重绘 编写画图代码,设定一个标识,在OnLButtonDown中保存鼠标按下去的点,在OnLButtonUp中捕获鼠标弹起的点,利用switch语句分别画图。这是上节课的内容,上节课还讲了窗口重绘的原理,实际上分为两步, 首先擦除以前的背景,然后再进行窗口重绘。 所以当拖动窗口改变窗口大小时,窗口要发生重绘,首先会擦除以前的背景,于是先前所画图像会消失。 解决办法是将画

514

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

孙鑫VC学习笔记:第十一讲 图形重绘方法二 利用元文件

介绍两种保存图形与重绘图形的方式第一种,要利用要一个类 CMetaFileDC第一步创建一个CMetaFileDC 对象。接着调用CMetaFileDC 构造器,然后再调用Create 函数 创建一个设备上下文与CMetaFileDC 对象关联起来。下一步给CMetaFileDC 对象发送一系列的CDC命令在为元文件发送完命令之后,调用Close成员函数关闭元文件的设备上下文,并返回一个元

遐迩思的专栏 2188

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

孙鑫VC学习笔记:第十一讲 图形重绘方法三 利用兼容DC

介绍利用兼容DC保存图形与重绘图形的方式1.构造兼容DC对象:CDC  m_dcCompatible2.在CGraphicView::OnLButtonUp写下面代码3.在CGraphicView::OnDraw中写入下面代码:CBitmap::CreateCompatibleBitmap 通过指定的宽高创建一个兼容位图。初始化一个与指定设置相兼容的位图 BOOL CreateCompatible

遐迩思的专栏 2023

孙鑫VC学习系列教程

教程简介 1、循序渐进  从Win32SDK编程开始讲解,帮助大家理解掌握Windows编程的核心 —— 消息循环机制。 2、通俗易懂  编程语言枯燥难懂,然而通过孙鑫老师形象化的讲解,Windows和MFC编程中的难点、重点,让你轻松掌握。 3、实战性强  编程中要注意什么?如何阅读出错提示?如何调试运行程序?如何排查错误,解决问题?通过孙鑫老师的一步步操作讲解,带你迅速掌握程序

学如逆水行舟,不进则退 1821

孙鑫VC第五课学习笔记

孙鑫VC第五课学习笔记文本编程知识点一使用CreateSolidCaret( int nWidth, int nHeight )在文本编辑器中可以创建插入符,这边提到了如果函数的两个参数都设置为0,系统将默认采用窗口边框的高和宽。那么如果知道窗口边框的高和宽,在MSDN中有这样的说明:The system’s window-border width or height can be r

张戟的专栏-H.264学习乐园 6425

孙鑫VC学习笔记:第十一讲 (四) 图形重绘方法三 利用兼容DC

介绍利用兼容DC保存图形与重绘图形的方式 1.构造兼容DC对象:CDC  m_dcCompatible 2.在CGraphicView::OnLButtonUp写下面代码 3.在CGraphicView::OnDraw中写入下面代码: CBitmap::CreateCompatibleBitmap  通过指定的宽高创建一个兼容位图。初始化一个与指定设置相兼容的位图  BOOL

503
上一篇: 使用VC6.0实现窗口的任意分割
下一篇: Windows编程中的映射模式和坐标转换
fairy_study
博客等级 码龄18年 29粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值