我用SDK写的一个树控件,自己响应WM_PAINT消息,为树控件添加了一个背景图片。自认为什么GDI资源都正确释放了。另外树控件还支持拖放操作,拖放操作时创建的imagelist也正确释放了。在XP下,程序比较稳定,可是到了98/me下,经过大量操作后,就会出错,弄得拖放的位图创建不起来,背景图片也会没有掉。实在是查不出什么原因了,附代码如下: case WM_PAINT:
{
if(g_pBackPicture == NULL)
{
break;
}
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
HDC hMemDc = CreateCompatibleDC(ps.hdc);
RECT rcWnd;
GetWindowRect(hwnd, &rcWnd);
int width = rcWnd.right - rcWnd.left;
int height = rcWnd.bottom - rcWnd.top;
HBITMAP hbmp = (HBITMAP)CreateCompatibleBitmap(ps.hdc, width, height);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDc, hbmp);

OldProc = (WNDPROC)GetProp(hwnd, "prevproc");
CallWindowProc(OldProc, hwnd, WM_PAINT, (WPARAM)hMemDc , lParam);
HDC hmaskdc = CreateCompatibleDC(ps.hdc);//this dc may be null, so the background may be unavailabe.I puzzled about this!
HBITMAP hmaskbmp= NULL;
HBITMAP hmaskOldBmp = NULL;
if(hmaskdc != NULL)//I don't want this statement to be true in fact!
{
hmaskbmp = CreateCompatibleBitmap(ps.hdc, width, height);
hmaskOldBmp = (HBITMAP)SelectObject(hmaskdc, hmaskbmp);
RECT rcDraw = {0, 0, width, height};
if(g_pBackPicture)
PutPicture(g_pBackPicture, hmaskdc, rcDraw);//hmaskdc
BitBlt(hMemDc , 0, 0, width, height,hmaskdc,0,0,SRCAND);
}
BitBlt(ps.hdc, 0, 0, width, height, hMemDc,0,0,SRCCOPY);
SelectObject(hMemDc, hOldBmp);
DeleteObject(hbmp);
DeleteDC(hMemDc); if(hmaskdc)
{
SelectObject(hmaskdc, hmaskOldBmp);
DeleteObject(hmaskbmp);
DeleteDC(hmaskdc);
}

EndPaint(hwnd, &ps);
}
return TRUE;

解决方案 »

  1.   

    Error lookup 查出来是这样,但为什么呢?我说了,经过大量操作后,才会出现这种情况,为什么首先一直是正确的呢?肯定是有某些资源没有正确释放吧。。也可能是某些api调用以后,有副作用,但我实在是查不出来了!
      

  2.   

    我建议你有些HDC 和 HBITMAP 可以一直保留,不用建建删删的,至少我这样干以后,2000 下编译的程序跑98 还是没问题的
      

  3.   

    Good idear, I'll try it tomorrow
      

  4.   

    不应该是创建和删除 GDI 对象的问题。我认为关键在于你又对 WM_PAINT 消息调用了原来的回调函数,BeginPaint/EndPaint 这两个函数有点古怪,要做许多其它的工作,和 GetDC/ReleaseDC 等函数不太一样,如果你要获得原始输出,推荐你使用 WM_PRINTCLIENT 消息对原来的回调函数进行调用。
      

  5.   

    其实我认为问题就是在于你调用原来的回调函数时,BeginPaint/EndPaint 函数对进行了嵌套调用。
      

  6.   

    robothn(雷鸟) :由于树控件支的大小会改变,DC和bitmap保留的话,就要处理大小的问题,要调用StretchBlt,这好像是个很耗资源的api,所以效果会不好。dandycheung:谢谢,你的方法我试过了,不过还是老样子。
      

  7.   

    程序到98上跑跑才知道XP超强, 我这几天也为98的GDI资源问题烦死了, 跑跑就把GDI资源耗光了
      

  8.   

    GDI又是怎么被耗光了呢?我觉得每次申请过的资源都释放过的啊
      

  9.   

    这个问题也捆扰了我很久,一直没有很好的解决办法
    使用boundschecker也找不到问题根源
    期待高手
      

  10.   

    主要是资源删除有先后, 打个比方:
    HDC hMemDC = CreateCompatibleDC(hDC);
    Graphics gc(hMemDC);
    ...
    //绘图
    ...
    DeleteDC(hMemDC);
    虽然hMemDC你删除了, 实际上是没有被删除, 因为gc还在引用它;
    相关的问题还有很多, 但在XP一点问题都没有, 但在98下GDI资源马上就耗光了;而且伴随着很多GDI32访问违规(GDI32 ACCESS VIOLATION)提示, 实际你根本找不到哪一句访问违规;
      

  11.   

    我一般把一个 HDC 和 HBITMAP 绑定到一起(做成一个类),析构时自动把两个都干掉