假如窗口的绘图函数
void DrawObject(HDC hdc)
{
   rectangle(hdc, 100, 100, 200, 200);
}
void ondraw(HDC hdc)
{
   DrawObject(hdc);
}
以上的代码在窗口的 100 100的位置绘制一个矩形。我现在是这样的,我要首先创建一个内存DC,尺寸是100 ,100 然后再绘制这个矩形在窗口的100,100 位置。
可是我不希望修改 DrawObject 函数。void ondraw(HDC hdc)
{
   HDC hmemdc = CreateCompatibleDC(hdc);
   HBitmap bmp = CreateCompatibleBitmap(hDC, 100, 100);
   SelectObject(hmemdc, bmp);
   DrawObject(hmemdc);  //注意这里,新建的内存DC,默认左上角是0, 0, 和原始的hdc坐标是不一样的
   BitBlt( 100, 100, 100, 100, 0, 0, SRCCOPY);
}** 我不希望修改 drawobject. 也许需要调用 SetViewportOrgEx 之类的函数修改 内存dc的左上角坐标吧。总之就是第一个方法和第2个方法绘制的位置是一样的。 我试了很多不太会弄。谢谢各位了!

解决方案 »

  1.   

    内存DC和窗口DC是一样的。
    在函数外部建好内存DC并初始化,传hDC进去就行了。  HDC hmemdc = CreateCompatibleDC(hdc);
      HBitmap bmp = CreateCompatibleBitmap(hDC, 100, 100);
      SelectObject(hmemdc, bmp);
      ondraw(hmemdc);
      

  2.   

    就是用SetViewportOrgEx 来修改坐标系啊
      

  3.   

    SetViewportOrgEx 
    第一个参数输入是DC句柄,你想修改哪个内存就用DC的HDC
    第二个参数输入是X,不解释
    第三个参数输入是Y,不解释
    第四个参数是输出的POINT点
      

  4.   

    void ondraw(HDC hdc)
    {
      HDC hmemdc = CreateCompatibleDC(hdc);
      HBitmap bmp = CreateCompatibleBitmap(hDC, 100, 100);
      SelectObject(hmemdc, bmp);
      POINT mypoint;
      SetViewportOrgEx(hmemdc,x,y,&mypoint);
      DrawObject(hmemdc); //注意这里,新建的内存DC,默认左上角是0, 0, 和原始的hdc坐标是不一样的
      BitBlt(hdc, 100, 100, 100,100,hmemdc 0, 0, SRCCOPY); //这句有问题吧??要从hdc画,从hmemdc 读出
    }
      

  5.   

    itBlt(hdc, 100, 100, 100,100,hmemdc 0, 0, SRCCOPY); //这句有问题吧??要从hdc画,从hmemdc 读出什么意思呢?  
      

  6.   

    itBlt(hdc, 100, 100, 100,100,hmemdc 0, 0, SRCCOPY); //这句有问题吧??要从hdc画,从hmemdc 读出什么意思呢?  
      

  7.   

    可以参考楼上的,BitBlt(hdc, 100, 100, 100,100,hmemdc 0, 0, SRCCOPY); 调整一下你自己想要的坐标就可以了。
      

  8.   

    认真看没有,这个内存DC和窗口的dc大小是不一样的。因为不想浪费内存。拜托大家认真点看
      

  9.   

    上述的例子中的矩形rect选用的是整个窗口客户区的矩形,所以下面的那些坐标都用的是这个矩形的坐标,这样就掩盖了坐标映射的问题。但是在我的工 程中并不是对整个窗口客户区进行双缓冲绘图,而是对窗口中的一个小矩形,于是我改变了rect的位置和大小,但其它的代码都没动,因此就显示不出东西了。 事实上,所有的绘图工作都顺利地进行了,只是都画在了我们看不到的地方。
      

  10.   

    在没有MSDN恶劣环境下,经过不断地摸索,我终于搞清楚了内存DC双缓冲显示不出来的问题!其实无论画图代码放在哪里,只要代码正确,肯定是能成功显示出来的,内存DC双缓冲并不要求画图代码非得放在一个什么特定的位置。之前我的工程之所以显示不出东西,简单说来其原因在于DC内部坐标映射的问题,网上内存DC双缓冲并没有说明白这一点。一下是一个典型的内存DC双缓冲例子,转自:http://hi.baidu.com/f234f234/blog/item/a17f4f0863710c950a7b8291.htmlCRect rect; 
    this->GetClientRect(rect); 
    CBitmap bmpFace; 
    bmpFace.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());(1)注意把握rect的尺寸为客户区域大小; 
    之后将这幅画选入内存DC中, 
    CBitmap* pOldBmp = NULL; 
    pOldBmp = MemDC.SelectObject(&bmpFace);; (2)
    之后可以开始在内存DC中进行任何绘制动作; 
    CBrush brush(RGB(255,255,255)); 
    MemDC.FillRect(rect,&brush); 
    for(int i=0;i<500;i++) 

    MemDC.MoveTo(22+i,22); 
    MemDC.LineTo(22+i,277); 

    绘制完后将内存DC中的这幅图绘制到屏幕DC中来, 
    pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,rect.left,rect.top,SRCCOPY); (3)
    最后进行相关的资源回收动作, 
    MemDC.SelectObject(pOldBmp); 
    bmpFace.DeleteObject();。上述代码至少有三处需要注意的地方,我已经标上了序号。其中(1)创建了一个与显示DC相兼容的位图,参数2,3指明了位图的大小,(2)处将这个 位图选入了内存DC中,默认位图的左上角与内存DC的(0,0)处相对应,这一步的作用是让内存DC “有地方用来作画”。经过接下来的一番涂抹之后,在第(3)步把内存DC中的内容复制到显示DC中,前4个参数指明了目的DC(也就是显示DC)的区域坐 标和大小,即我们想把内存DC中的内容复制到显示DC的什么位置,第5个参数指明了源DC(也就是内存DC),第6,7个参数指明了源DC的起始坐标,即 我们想对内存DC中从什么地方开始的内容进行复制。上述的例子中的矩形rect选用的是整个窗口客户区的矩形,所以下面的那些坐标都用的是这个矩形的坐标,这样就掩盖了坐标映射的问题。但是在我的工 程中并不是对整个窗口客户区进行双缓冲绘图,而是对窗口中的一个小矩形,于是我改变了rect的位置和大小,但其它的代码都没动,因此就显示不出东西了。 事实上,所有的绘图工作都顺利地进行了,只是都画在了我们看不到的地方。如果双缓冲的区域不是整个客户区的话,我建议这样做:在内存DC的(0,0)起始点作图,画完之后把内存DC中的内容复制到显示DC的所需的位置; 而不是在内存DC中的相应位置作图,然后在复制到显示DC所需位置,因为这样做的话需要在绘图时在内存DC中做太多的坐标变换,太麻烦。这个描述的就是我前面提到的我的问题。我从baidu找到的。 我现在要做的就是
    “而不是在内存DC中的相应位置作图,然后在复制到显示DC所需位置,因为这样做的话需要在绘图时在内存DC中做太多的坐标变换”。因为我原先的那个绘图DrawObject 函数有特别多的代码。我不可能修改这个东西。所以就求坐标变换
      

  11.   

    void ondraw(HDC hdc)
    {  
       HDC hmemdc = CreateCompatibleDC(hdc);
       HBITMAP bmp = CreateCompatibleBitmap(hdc, 100, 100);
       SelectObject(hmemdc, bmp);
       RECT rect;
       rect.bottom=100;
       rect.right=100;
       rect.top=rect.left=0;
       HBRUSH brush=CreateSolidBrush(RGB(255,255,255));
       ::FillRect(hmemdc,&rect,brush);
       POINT oldpoint,newpoint;
       oldpoint.x=oldpoint.y=0;
       newpoint.x=newpoint.y=-100;
       SetViewportOrgEx(hmemdc,newpoint.x,newpoint.y,&oldpoint);
       DrawObject(hmemdc); 
       SetViewportOrgEx(hmemdc,oldpoint.x,oldpoint.y,&newpoint);
       BitBlt(hdc,100, 100, 100, 100,hmemdc,0, 0, SRCCOPY);
       DeleteObject(bmp);
       DeleteObject(hmemdc);
    }
      

  12.   

    在没有MSDN恶劣环境下,经过不断地摸索,我终于搞清楚了内存DC双缓冲显示不出来的问题!其实无论画图代码放在哪里,只要代码正确,肯定是能成功显示出来的,内存DC双缓冲并不要求画图代码非得放在一个什么特定的位置。之前我的工程之所以显示不出东西,简单说来其原因在于DC内部坐标映射的问题,网上内存DC双缓冲并没有说明白这一点。一下是一个典型的内存DC双缓冲例子,转自:http://hi.baidu.com/f234f234/blog/item/a17f4f0863710c950a7b8291.htmlCRect rect; 
    this->GetClientRect(rect); 
    CBitmap bmpFace; 
    bmpFace.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());(1)注意把握rect的尺寸为客户区域大小; 
    之后将这幅画选入内存DC中, 
    CBitmap* pOldBmp = NULL; 
    pOldBmp = MemDC.SelectObject(&bmpFace);; (2)
    之后可以开始在内存DC中进行任何绘制动作; 
    CBrush brush(RGB(255,255,255)); 
    MemDC.FillRect(rect,&brush); 
    for(int i=0;i<500;i++) 

    MemDC.MoveTo(22+i,22); 
    MemDC.LineTo(22+i,277); 

    绘制完后将内存DC中的这幅图绘制到屏幕DC中来, 
    pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,rect.left,rect.top,SRCCOPY); (3)
    最后进行相关的资源回收动作, 
    MemDC.SelectObject(pOldBmp); 
    bmpFace.DeleteObject();。上述代码至少有三处需要注意的地方,我已经标上了序号。其中(1)创建了一个与显示DC相兼容的位图,参数2,3指明了位图的大小,(2)处将这个 位图选入了内存DC中,默认位图的左上角与内存DC的(0,0)处相对应,这一步的作用是让内存DC “有地方用来作画”。经过接下来的一番涂抹之后,在第(3)步把内存DC中的内容复制到显示DC中,前4个参数指明了目的DC(也就是显示DC)的区域坐 标和大小,即我们想把内存DC中的内容复制到显示DC的什么位置,第5个参数指明了源DC(也就是内存DC),第6,7个参数指明了源DC的起始坐标,即 我们想对内存DC中从什么地方开始的内容进行复制。上述的例子中的矩形rect选用的是整个窗口客户区的矩形,所以下面的那些坐标都用的是这个矩形的坐标,这样就掩盖了坐标映射的问题。但是在我的工 程中并不是对整个窗口客户区进行双缓冲绘图,而是对窗口中的一个小矩形,于是我改变了rect的位置和大小,但其它的代码都没动,因此就显示不出东西了。 事实上,所有的绘图工作都顺利地进行了,只是都画在了我们看不到的地方。如果双缓冲的区域不是整个客户区的话,我建议这样做:在内存DC的(0,0)起始点作图,画完之后把内存DC中的内容复制到显示DC的所需的位置; 而不是在内存DC中的相应位置作图,然后在复制到显示DC所需位置,因为这样做的话需要在绘图时在内存DC中做太多的坐标变换,太麻烦。这个描述的就是我前面提到的我的问题。我从baidu找到的。 我现在要做的就是
    “而不是在内存DC中的相应位置作图,然后在复制到显示DC所需位置,因为这样做的话需要在绘图时在内存DC中做太多的坐标变换”。因为我原先的那个绘图DrawObject 函数有特别多的代码。我不可能修改这个东西。所以就求坐标变换