请选择 进入手机版 | 继续访问电脑版

C++编程

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2425|回复: 1

浅谈GDI编程正确方法

[复制链接]

8

主题

31

帖子

323

积分

版主

Rank: 7Rank: 7Rank: 7

积分
323
QQ
发表于 2015-11-18 21:22:16 | 显示全部楼层 |阅读模式
本帖最后由 嬴政 于 2015-11-18 21:39 编辑

本文不打算告诉大家什么叫GDI,各种GDI函数的作用是什么,有关详细的GDI知识可以去以下网站查看。http://www.panshy.com/articles/dev-66_3.html在这里只是让大家知道如何正确使用GDI,并且查找GDI资源占用问题,也就是类似C++中new完后不delete一样,会把系统资源消耗光,GDI资源也是有限的,消耗太多窗体会卡,还会伴有黑色的现象或者是别的窗体贴在本窗体上等效果。

首先让大家来看看一般GDI都有哪些函数,这里只列出贴图和双缓冲用得到的函数:

GetWindowDC 获取整个窗体的DC,包含标题栏这种非客区
GetDC获取窗体的客户区的DC,就是窗体能放控件的地方
CreateCompatibleDC 创建兼容DC
SelectObject选入某一GDI对象到DC中,返回DC中原有的对象
DeleteObject删除对象
ReleaseDC释放DC
DeleteDC删除DC
。。。。
以上函数CreateCompatibleDC与DeleteDC 一对、GetWindowDC - GetDC与ReleaseDC一对、SelectObject与DeleteObject一对
现在介绍以上函数正确使用方法,实例是将内存中的图片贴到窗体上,这里只列出伪代码
  1. LONG lTemp;   
  2. PAINTSTRUCT pai = {};   
  3. BITMAPINFOHEADER BmihSuccess;   
  4. BLENDFUNCTION Blend;   
  5. LONG x = 0;   
  6. RECT r;   
  7.   
  8. Blend.BlendOp = 0;   
  9. Blend.BlendFlags = 0;   
  10. Blend.AlphaFormat = AC_SRC_ALPHA;   
  11. Blend.SourceConstantAlpha = 255;   
  12.   
  13. ::BeginPaint(m_hWnd, &pai);   
  14.   
  15. DWORD dwExStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);   
  16. if ((dwExStyle & 0x80000) != 0x80000)   
  17. {   
  18.     ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwExStyle ^ 0x80000);   
  19. }   
  20.   
  21. CRect rcWindow;   
  22. ::GetWindowRect(m_hWnd, &rcWindow);   
  23.   //以上代表不用管,看不懂不要紧

  24. HDC hdcTemp = ::GetWindowDC(m_hWnd);   //创建窗体DC,包含标题栏,菜单栏
  25. HDC hdcMemory = ::CreateCompatibleDC(hdcTemp);   //内存DC,兼容窗体的DC
  26.   
  27. ZeroMemory(&BmihSuccess, sizeof(BITMAPINFO));   
  28.   
  29. BmihSuccess.biSize = sizeof (BITMAPINFOHEADER) ;   
  30. BmihSuccess.biWidth = rcWindow.Width() ;   
  31. BmihSuccess.biHeight = rcWindow.Height();   
  32. BmihSuccess.biPlanes = 1 ;   
  33. BmihSuccess.biBitCount = 32;   
  34. BmihSuccess.biCompression = BI_RGB ;   
  35. BmihSuccess.biSizeImage = 0 ;   
  36. BmihSuccess.biXPelsPerMeter = 0 ;   
  37. BmihSuccess.biYPelsPerMeter = 0 ;   
  38. BmihSuccess.biClrUsed = 0 ;   
  39. BmihSuccess.biClrImportant = 0 ;   
  40.   
  41. HBITMAP hBitMap = ::CreateDIBSection(hdcTemp,   
  42.         (BITMAPINFO *)&BmihSuccess, 0, NULL, NULL, 0) ;  //创建一个GDI对象
  43. HGDIOBJ oldObj = ::SelectObject(hdcMemory, hBitMap);   //将GDI对象选入DC
  44.   ////////////////////////////////////////////////////////////////////////////////////
  45. Gdiplus::Graphics gph(hdcMemory);   
  46.   
  47.     Gdiplus::Bitmap *m_pImgLeft;   
  48. _pImgLeft = new Bitmap(_T("c:\\Login_msg_left1.png"));   
  49. if(m_pImgLeft != NULL)   
  50.     {   
  51.         gph.DrawImage(m_pImgLeft, 0, 0,   
  52.             m_pImgLeft->GetWidth(), m_pImgLeft->GetHeight());   
  53.     }   
  54.   
  55. :UpdateLayeredWindow(m_hWnd, hdcTemp,   
  56.     &CPoint(rcWindow.left, rcWindow.top),   
  57.     &CSize(rcWindow.Width(), rcWindow.Height()),   
  58.     hdcMemory, &CPoint(0, 0), 0, &Blend, ULW_ALPHA);   
  59.   /////////以上圈起来的代码不用管//////////////////////////////////////////
  60. 以下是重点,是释放GDI资源的重点,顺序是选回旧的GDI对象,删除创建的GDI对象,删除DC
  61. ::SelectObject(hdcMemory, oldObj);   
  62. ::DeleteObject(hBitMap);   
  63. ::ReleaseDC(m_hWnd, hdcTemp);   
  64. ::DeleteDC(hdcMemory);   
  65. ::EndPaint(m_hWnd, &pai);

复制代码
好了上面说了如何正确使用GDI的方法了,其实就是释放GDI资源顺序,那么如何查看GDI占用情况呢,现在和大家说一下
打开任务栏管理器,选中进程那一个选项卡,点菜单中的查看-》选择列 子菜单,找到GDI对象

确定后在进程列表就能看到

如果是窗体使用GDI,只要把窗体不断放大缩小,就能查看到GDI的使用情况,如果没有正确释放会,你会发现GDI对象数值一直在涨。
好了,今天就说到这呢,有不懂的,可以回复问我。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
VC纵横、磐实编程网
回复

使用道具 举报

4

主题

9

帖子

65

积分

码农

Rank: 2

积分
65
发表于 2015-11-18 22:08:05 | 显示全部楼层
原来还有这个说法。。。难怪非要成对使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|C++编程  

GMT+8, 2019-8-19 07:28 , Processed in 0.093750 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表