惭愧,我这外行人错用了N年的CreateDIBSection

外行人自学编程的最大坏处是知其然,不知其所以然,所以自己错了也不知道,不理解也没关系,只要代码跑得起来就不问对错了。CV键不停的用,成果都是自己的。还好本人不从事码农工作,不然就坑大发了。

我最早自学编程,是为了给游戏做辅助,自己做了个登陆接奖励的程序,800个小号上一上午登陆自动取名,领奖,截图,还挺有成就感的。后来只要有必要,经常自己动手做点小小程序,代码基本全靠背,毕竟这玩意用几回就记住了,函数后面的原理啥的完全不懂,也不可能懂,毕竟我是外行人。

做游戏辅助程序最重要就是跟图片打交道。我认为最方便的就是用CreateDIBSection。

前些天又做了一个小程序,需要打开很多图片,结果我照以往的代码,直接敲了上去,最后发现一个问题,每打开一个图片,内存开销就会涨10M,我一直搞不懂为什么,一直尝试释放内存,不成功。后来在网上经高人指点才知道自己的代码错了。

这是我用了十年的代码

 R = ReadFile(hFile, &fif, sizeof(BITMAPINFOHEADER), &num, NULL);
 GetClientRect(hWnd, &rect);
 dataSize = bfh.bfSize - bfh.bfOffBits;
 data = (BYTE*)malloc(dataSize);
 pbmi.bmiHeader = fif;
 width = fif.biWidth;
 height = fif.biHeight;
winDC = GetDC(hWnd);
 memDC = CreateCompatibleDC(winDC);
 hBit = CreateDIBSection(memDC, &pbmi, DIB_RGB_COLORS, (void**)&data, NULL, 0);
R = ReadFile(hFile, data, dataSize, &num, NULL);
SelectObject(memDC, hBit); 

我也忘了最早是在哪抄的了,反正我一直认为,放像素数据的内存块是需要预先申请的,申请之后再给CreateDIBSection用,只要内存DC,内存位图对象形成后,再把数据写入内存就可以了,最后删除掉对象就可以了。当年甚至都没有想过要释放内存,那会对内存开销也没啥概念,也正因为如此,我这个错误的程序一用就是十年。

昨天我一直尝试释放内存free(data),只要代码运行到这就异常。我一直猜这个位图对象是系统管理的,所以才不能手动释放,于是不停的尝试删除对象,释放DC,然后再释放内存,但最后都以失败告终。没办法,我还问了一下chargpt,他回答得相当全面,说了各种DC的释放方法,内存DC需要先载入另一个对象,再释放。他教的方法是这样

hOldBit = (HBITMAP) SelectObject(memDC, hBit);

我也照着做了,最后还是失败。(其实他教的是对的,只不过我错的不在这里)

后来我去某论坛问了一下,有大神就教了我,他把代码整体改了一下,瞬间就不那么业余了。

GetClientRect(hWnd, &rect);
  winDC = GetDC(hWnd);
  memDC = CreateCompatibleDC(winDC);

  pbmi.bmiHeader = fif;
  width = fif.biWidth;
  height = fif.biHeight;

  hBit = CreateDIBSection(memDC, &pbmi, DIB_RGB_COLORS, (void**)&data, NULL, 0);
  if (!hBit) {
    data = NULL;
    DeleteDC(memDC); memDC = NULL;
    ReleaseDC(hWnd, winDC); winDC = NULL;
    CloseHandle(hFile);
    return NULL;
  }

  dataSize = bfh.bfSize - bfh.bfOffBits;

  R = (ReadFile(hFile, data, dataSize, &num, NULL) && (num == dataSize));

  hOldBit = (HBITMAP) SelectObject(memDC, hBit);

原来根本就不需要申请内存,createdibsedction直 接分配了内存,所以只要删除掉位图对象,释放DC就可以了。需要注意的是,释放内存DC需要用DeleteDC,而不是ReleaseDC。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值