我在一个timer中为了根据数据变换pen的颜色,需要在timer中createpen,结果程序跑一
阵子createpen返回值开始为NULL,继续往下debug时程序会在selectobject处会跳到win
core.cpp中的某个位置(不知道是不是什么抛出异常之类的)。程序都是一开始正常,然后运行100s左右才会出现这个情况,任务管理器中从头到尾GDI
资源并没有一直增长,内存和处理器占用也没有增长。CreatePen()返回0,之后GetLastE
rror返回0;无法运行到SelectObject下一步,F10会直接执行到下次进入该Timer在Sele
ctObject之前的断点,无断点的话就进入wincore.cpp了。代码大致如下:
TimerProc
{
...
pDC=pThis->picturecontrl.GetDC();
CPen pen;//甚至试过每次*pen=new CPen然后再delete pen;--!
pen.CreatePen(...)//CreatePenIndirect也试过了
old_pen=pDC->SelectObject(&pen);
...
pDC->SelectObject(old_pen);
pen.DeleteObject();
pThis->ReleaseDC();
...
}真心求教T_T,帮帮忙吧~

解决方案 »

  1.   

    应该是GDI资源没有释放,造成资源不足,无法分配了。
      

  2.   

    F10会直接执行到下次进入该Timer在Sele
    ctObject之前的断点,无断点的话就进入wincore.cpp了。代码大致如下有错误。F11看看
      

  3.   

    To 2#:
    资源管理器里显示GDI资源没有增加,而且我的流程中有什么可能造成GDI资源没有有效释放的操作么?
      

  4.   

    你为什么非要在定时器里用CreatePen呢?在外面先创建好不行吗?
      

  5.   

    看这两行
    pDC=pThis->picturecontrl.GetDC();
    ......
    pThis->ReleaseDC();
      

  6.   

    To 4#:
    发现在pDC=picturecontrol.GetDC()
    那一步返回值也是0了,所以说getDC和createpen都失败了....这是什么情况?
      

  7.   

    最好不要再OnTimer中创建任何东西
      

  8.   

    Oh, My God,我其实不大清楚releaseDC到底是在干什么,releaseDC是用于销毁自己创建的dc的么?我以为是解除pDC与picturectrl的关系用的....
      

  9.   

    那请问这里应该怎么处理呢,不release的话也是过一会就死了
    要写一个画图这部分功能的函数把上面的代码放进去么?
      

  10.   

    当然要Release,不过应该这样写:
    pDC->ReleaseDC();
      

  11.   

    当然要Release,不过应该这样写:
    pDC->ReleaseDC();
    ==========
    错了,应该这样写:
    pThis->picturecontrl.ReleaseDC();
      

  12.   

    啊 我看了一下,不好意思,是我之前粘代码时偷懒了
    我写的是
    pThis->ReleaseDC(pDC);有问题么?
    现在即使换成pThis->picturecontrl.ReleaseDC();
    问题依旧....
      

  13.   

    不好意思,是我偷懒了,我看了一下我原来写的是pThis->ReleaseDC(pDC)
      

  14.   

    啊 我看了一下,不好意思,是我之前粘代码时偷懒了
    我写的是
    pThis->ReleaseDC(pDC);有问题么?
    ========
    你前面的DC是picturecontrl的DC,现在释放当然也是释放这个DC了.
    另外,pDC这个指针是什么变量呢?它的定义部分你放到什么地方了?
      

  15.   

    CDC* pDC也在这个timerproc中定义的,就是用来表示picturecontrol的dc的
    所以只用在pDC=picturecontrol.getDC()
    然后pDC->各种画
    然后pThis->ReleaseDC(pDC);这个效果是不是和picturecontrol.releasedc()一样啊?
      

  16.   

    然后pThis->ReleaseDC(pDC);这个效果是不是和picturecontrol.releasedc()一样啊?
    =============
    当然不一样了,你的pThis和picturecontrol难道是同一个CWnd对象啊?CDC* pDC也在这个timerproc中定义的,就是用来表示picturecontrol的dc的
    ================
    如果你是new出来的话,最后不用时你必须要delete
      

  17.   

    谁的DC谁释放。
    pThis->picturecontrl.ReleaseDC(pDC);
      

  18.   

    to 20楼:
    他都pDC=pThis->picturecontrl.GetDC()了,你还让他delete什么啊?
      

  19.   

    我发现可能的一个原因了,实际上我是有timerproc1和timerproc2的,是不是因为这个两个线程里都有GetDC会引发冲突啊....
      

  20.   

    嗯,现在改成这样写了,问题依旧....55555,是不是两个线程不能都有picturectrl.getDC(),应该统一放到一个函数下面画
      

  21.   

    你用的是两个线程还是只不过两个SetTimer里的回调函数?如果真的是两个线程,那么这两个必须做同步处理。
      

  22.   

    只是两个settimer里的回调函数...SetTimer里的回调函数如果有两个,接受WM_Timer是怎么个过程,两个回调函数接受WM_TIMER的频率还是一样的
      

  23.   

    pThis->ReleaseDC();
    把这个删除应该就没问题了
    这个是在程序结束的时候调用的,你每次都释放,在ONPAINT里面调用不到DC就会出问题的。
    DC不是你在timer里创建的,你只是在timer里调用,所以不需要释放
      

  24.   

    两个回调函数是没问题的。Windows会自动按照你的两个TimeID来调用不同的回调函数。你在pDC=pThis->picturecontrl.GetDC()后面加上:
    if(pDC == NULL) {
       DWORD dw = ::GetLastError();  // 在这里设断点,看看错误号是多少。
    }
      

  25.   

    这个是我发帖的时候疏忽了,实际上我写的是pThis->ReleaseDC(pDC);如果去掉这一句我也试过,还是不行
    程序运行一段时间以后,pDC=pictrl.GetDC()和pen.CreatePen()都会返回0 
      

  26.   

    和createpen一样,GetLastError()都返回0....
      

  27.   

    我的意思是两个timeproc的执行顺序,因为每次这两个timerproc都是相同的触发间隔,
    SetTimer(1,30,timerproc1)
    SetTimer(2,30,timerproc2)
    它们俩如果同时执行的话会不会有同时GetDC的问题,他们俩如果依次执行的话先执行哪一个?
      

  28.   

    把你的这段代码全部改成API方式的,不要用MFC里的任何东西,例如:
    HWND hWnd;
    HDC hDC;
    HPEN hPen, hOldPen;hWnd = pThis->picturecontrl.GetSafeHwnd();
    hDC = ::GetDC(hWnd);
    if(hDC == NULL) {
      DWORD dw = ::GetLastError(); // 在这里设断点,看看错误号是多少。
    }hPen = ::CreatePen(...);
    if(hPen == NULL) {
      DWORD dw = ::GetLastError(); // 在这里设断点,看看错误号是多少。
    }
    hOldPen=(HPEN)::SelectObject(hDC, hPen);
    ......
    ::SelectObject(hDC, hOldPen);
    ::DeleteObject(hPen);
    ::ReleaseDC(hWnd, hDC);
      

  29.   

    我的意思是两个timeproc的执行顺序,因为每次这两个timerproc都是相同的触发间隔,
    SetTimer(1,30,timerproc1)
    SetTimer(2,30,timerproc2)
    它们俩如果同时执行的话会不会有同时GetDC的问题,他们俩如果依次执行的话先执行哪一个?
    ==========
    不会同时执行的,你这个还是单线程的。
      

  30.   

    这样改了以后,dw仍然返回的是0
    不过发现是CreatePen先返回0,这个时候hDC是正常的,但这之后再次进入这里,hDC也变成0了
      

  31.   

    啊 好像不对 是hDC先返回0的
    GetLastError一直是0....
      

  32.   

    你的两个timerproc都是一样的吗?如果不是的话,那个又是怎么写的?有没有出问题?
      

  33.   

    我现在把timerproc1中所有画图过程都去掉了,没有getdc也没有画图也没有createpen,但是还是会运行到一定地方死,死的时候加断点只能进入timerproc1不能进入timerproc2....这是什么问题啊?
      

  34.   

    “运行到一定地方死”是什么意思?“死”的表现是什么?既然加断点还能进入timerproc1,那不是说明还没死吗?
      

  35.   

    没错,其实是没死,但是从界面上看画图已经停止了,也就是说timerproc1还在不断运行,但是画不出来图,也就是无法GetDC或者是createpen了;更奇特的是,我现在把timerproc2中的取DC画图的部分全部注释了,在timerproc1中修改表示图像的那个二维数组中的值,然后调用一个timerproc1外定义的一个函数,在这个函数中getDC,不createpen了。但是运行一段时间后,这个函数中的getDC开始返回0,而且从此以后debug无法进入timerproc2中
      

  36.   

    我大概明白是什么问题了,是我还有一个地方的dc资源没有释放;但是修改了以后gdi还是会涨,因为有一个timerproc中有
    CPen pen;
    pen.createpen()
    oldpen=selectobject(&pen)
    ...
    selectobject(old_pen)
    ...
    oldpen=selectobject(&pen)
    ...
    selectobject(old_pen)
    pen.deleteObject();
    如果把这个关于这个pen使用的代码去掉就好了。pen也属于gdi资源是吧?声明和释放的时候应该注意什么?
      

  37.   

    额....我又在pen.DeleteObject前ReleaseDC了,是在对不起大家,耽误了大家很多时间,问题都已解决,完全是我疏忽了....不过跟大家学到很多东西,谢谢!!!