GDI+

双缓冲技术(基于GDI+实现)
http://blog.csdn.net/woaisia/article/details/46788965

设置对话框背景色
SetBackgroundColor(RGB(0,0,255));

一、GDI+初始化


(1)、引用stdafx.h


#include <GdiPlus.h>
using namespace Gdiplus;
#pragma comment( lib, "Gdiplus.lib")

(2)、public CWinApp头文件定义两个全局变量


GdiplusStartupinput m_Gdiplus
ULONG_PTR m_pGdiToken

(3)、在应用程序或对话框初始化时加载GDI+(InitInstance)


GdiplusStartup(&m_pGdiToken,&m_Gdiplus,NULL)


(4)、在应用程序结束时卸载GDI+(ExitInstance)


GdiplusShutdown(m_pGdiToken)


二、简单的GDI+双缓冲的分析与实现


1.在内存中建立一块“虚拟画布”:

 //获取窗口客区宽高 
 RECT r; 
 GetClientRect(m_hWnd,&r); 
 m_bufW=r.right; m_bufH=r.bottom; 
 //在内存中建立一个Image的派生类Bitma对象做为"画布" 
 Bitmap memBitmap(m_bufW,m_bufH);


2.获取这块内存画布的Graphics引用:

 Graphics memGr(&memBitmap); 


3.在这块内存画布上绘图:

 //这里可以通过memGr在memBitmap上绘制多个图元
 //我只举例绘制了一张图片
 Image* pimage=NULL;
 pimage=new Image(L"res//图片1.png");
 int w=pimage->GetWidth();
 int h=pimage->GetHeight();
 memGr.DrawImage(pimage,0,0,0,0,w,h,UnitPixel);
 delete pimage;
 pimage=NULL;


4、将内存画布画到窗口中
 m_hDC = GetDC(m_hWnd);
 Graphics gr(m_hDC);
 gr.DrawImage(&memBitmap,0,0);
  ReleaseDC(m_hWnd,m_hDC);



三、背景透明


//1///

CMyListCtrl::OnEraseBkgnd(CDC* pDC) 
{
    CMyListCtrl *pParent = (CMyListCtrl*)GetParent();
    CWnd *pParent = GetParent();   
    CRect rc;
    GetWindowRect(rc);
    pParent->ScreenToClient(rc);
    pParent->InvalidateRect(rc,false);
    pParent->UpdateWindow();
    CDC *dcParent = pParent->GetDC();   
    pDC->BitBlt(0,0,rc.Width(),rc.Height(),dcParent,rc.left,rc.top,SRCCOPY);
    pParent->ReleaseDC(dcParent);
 return true;
}



/2

::OnEraseBkgnd(CDC* pDC)
{
   if (m_Bmp.GetSafeHandle() == NULL)
   {
      CRect Rect;
      GetWindowRect(&Rect);
      CWnd *pParent = GetParent();
      ASSERT(pParent);
      pParent->ScreenToClient(&Rect);  //convert our corrdinates to our parents
      
      //copy what's on the parents at this point
      CDC *pDC = pParent->GetDC();
      CDC MemDC;
      MemDC.CreateCompatibleDC(pDC);
      m_Bmp.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height());
      CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
      MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY);
      MemDC.SelectObject(pOldBmp);
      pParent->ReleaseDC(pDC);
   }
   else //copy what we copied off the parent the first time back onto the parent
   {
      CRect Rect;
      GetClientRect(Rect);
      CDC MemDC;
      MemDC.CreateCompatibleDC(pDC);
      CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
      pDC->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);
      MemDC.SelectObject(pOldBmp);
   }
   return TRUE;
}



3//

HBRUSH CMFCDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
 //这种情况除非背景是纯色才行
/* if(nCtlColor == CTLCOLOR_BTN)
 {
  pDC->SetBkMode(TRANSPARENT);
  hbr = (HBRUSH) ::GetStockObject(NULL_BRUSH);
 } */
 //没办法,搞一个万能的。很奇怪,在背景是图片的情况下,nCtlColor都不等于CTLCOLOR_BTN了,但经过断点可以肯定,
 //每个控件都会进入这个消息
 UINT id = pWnd->GetDlgCtrlID();
 if(id == IDC_RADIO1 || id == IDC_CHECK1|| id== IDC_LIST1)
 {
  
   pDC->SetBkMode(TRANSPARENT);
  CRect rc;
  pWnd->GetWindowRect(&rc);
  ScreenToClient(&rc);
  CDC* dc = GetDC();
  pDC->BitBlt(0,0,rc.Width(),rc.Height(),dc,rc.left,rc.top,SRCCOPY); //把父窗口背景图片先画到按钮上
  ReleaseDC(dc);
  hbr = (HBRUSH) ::GetStockObject(NULL_BRUSH);
 } 
  return hbr;
}


四、GDI+双缓冲

方案1

CDC dcMemory;
dcMemory.CreateCompatibleDC(&dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc,1024,768);
dcMemory.SelectObject(&bmp);
 
Graphics _Graphics(dcMemory.m_hDC);
Gdiplus::Image image(_T("res//asus.png")); 
_Graphics.DrawImage(&image,0,0,1024,768);
//这是在GDI+中的写法。
 
dc.BitBlt(0,0,1024,768,&dcMemory,0,0,SRCCOPY);
_Graphics.ReleaseHDC(dcMemory.m_hDC);
dcMemory.DeleteDC();
bmp.DeleteObject();



方案2(不可取)


(1)在内存中新建画布

Bitmap bmp=new Bitmap(600,600);

(2)获取这块内存画布的Graphics引用

Graphics g=Graphics.FromImage(bmp);

(3)在这块内存画布上绘图

g.FillEllipse(brush,10,10,10,10);

(4)将内存画布画到窗口

Graphics graphice(dc.m_hDC);
graphics.DrawImage(&bmp,rect.left,rect.top,rect.right,rect.bottom);


五、 资源加载方法


 CGdiPlusBitmapResource* pBitmap = new CGdiPlusBitmapResource;
 if (pBitmap->Load(IDB_LOGO, _T("PNG")))
 {
  CClientDC dc(this);
  Gdiplus::Graphics graphics(dc);
  graphics.DrawImage(*pBitmap, 0, 0);
 }
 else
 {
  //AfxMessageBox("Failure loading image");
 }
 delete pBitmap;

 */
/
//picture控件 type=Owner Draw
 /* 
 //第一种,显示实际png图片,与控件大小无关
 //CPaintDC *pDC = new CPaintDC(GetDlgItem(IDC_STATIC_PIC));也可以
 CClientDC *pDC = new CClientDC(GetDlgItem(IDC_STATIC_PIC));
 CRect rect;
 GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect);
 Graphics graphics(pDC->m_hDC); // Create a GDI+ graphics object
 Image image(_T("1.png")); // Construct an image
 graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
 delete pDC;
  */
//
/* 
 //第二种,铺满控件 
 Image image(_T("1.png")); //载入指定路径的图像文件 
 CWnd* pwnd = GetDlgItem(IDC_STATIC_PIC);//IDC_PIC 为图像控件的 ID 
 CDC* dc = pwnd->GetDC(); //获取图像控件的设备上下文 
 CRect rect;
 pwnd->GetClientRect(&rect); //获取客户区域的信息 
 Graphics graph(dc->GetSafeHdc());
 graph.DrawImage(&image, 0, 0, rect.Width(), rect.Height()); //在指定图像控件的区域中绘制图像 
 ReleaseDC(dc); //释放资源 
  */
///
 /*方法二
  CBrush m_brBk;
  CPaintDC dc(this);
  CBitmap bitmap;
  bitmap.LoadBitmap(IDB_BITMAP1);//这个IDB_BITMAP1要自己添加;
  m_brBk.CreatePatternBrush(&bitmap);
  CBrush* pOldBrush= dc.SelectObject(&m_brBk);
  dc.Rectangle(0, 0, 200, 200);// 这些参数可以调整图片添加位置和大小 dc.SelectObject(pOldBrush); 
  
  */
 /*方法三
  CPaintDC dc(this);  
    CBitmap m_bmpBK;  
    m_bmpBK.LoadBitmap(IDB_BITMAP1);  
    CRect rect;  
    GetClientRect(&rect);//获得目标尺寸即窗口客户区的坐标   
    BITMAP bitMap;//位图结构体   
    m_bmpBK.GetBitmap(&bitMap);//获得原图片尺寸    
    CDC dcMem; //目标DC   
    dcMem.CreateCompatibleDC(&dc); //创建与dc兼容的内存DC   
    dcMem.SelectObject(&m_bmpBK);//将位图对象m_bmpBK选入内存DC   
    dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &dcMem, 0, 0, bitMap.bmWidth, bitMap.bmHeight, SRCCOPY);  
 */
 /*方法四
   HANDLE m_hBmp;  
    CPaintDC dc(this); // 用于绘制的设备上下文  
    m_hBmp = LoadImage(NULL, _T("Demo.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);  
    CBitmap bmp;//定义位图对象  
    bmp.Attach(m_hBmp);//将位图关联到位图句柄  
    CDC memDC;//定义一个设备上下文  
    memDC.CreateCompatibleDC(&dc);//创建兼容性的设备上下文  
    memDC.SelectObject(&bmp);//选中位图对象  
    BITMAP BitInfo;          //定义位图结构  
    bmp.GetBitmap(&BitInfo);//获取位图信息                                //获取位图信息  
    int x = BitInfo.bmWidth;                                //获取位图宽度  
    int y = BitInfo.bmHeight;                               //获取位图高度  
    dc.BitBlt(0, 0, x, y, &memDC, 0, 0, SRCCOPY);//绘制位图  
    bmp.Detach();//分离位图句柄  
    memDC.DeleteDC();//释放设备上下文  
    bmp.DeleteObject();//释放位图对象  
  */


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值