最近做的項目中需要顯示視頻監控窗口,從采集卡中讀到圖像的數據,需要實時顯示出來,而且速度比較快。
由於比較簡單,就直接使用了GDI畫圖,以前復雜的都用openGL啥的工具了,這次這個簡單,就直接用GDI了。
先獲取DC,然后畫圖
pDC = this ->GetDC(); // 獲得顯示控件的 DC this->GetClientRect(rect); MemDC.CreateCompatibleDC(NULL); //這時還不能繪圖,因為沒有地方畫 ^_^ //下面建立一個與屏幕顯示兼容的位圖,至於位圖的大小嘛,可以用窗口的大小 MemBitmap.CreateCompatibleBitmap(pDC,640,480); pentemplate.CreatePen(PS_SOLID,1,RGB(0,255,255)); penkuang.CreatePen(PS_SOLID,1,RGB(255,0,255)); MemDC.SelectObject(&MemBitmap); //printf("\n 拷貝圖片"); StretchDIBits(MemDC.m_hDC, // 設備環境句柄 0, //目標X坐標 0, // 目標Y坐標 640, // 目標寬度 480, // 目標高度 0, // 源X坐標 0, // 源Y坐標 640, // 源寬度 480, // 源高度 ImageBuff, //圖像數據指針BYTE* &bmpInfo, // 指向位圖信息結構的指針 DIB_RGB_COLORS, // 使用的顏色數目 SRCCOPY);
結束后進行釋放內存DC和創建的畫筆對象
pDC->BitBlt(0,0,640,480,&MemDC,0,0,SRCCOPY); //printf("畫圖結束\n"); MemBitmap.DeleteObject(); penkuang.DeleteObject(); pentemplate.DeleteObject(); MemDC.DeleteDC();
注意,此時只對創建的內存DC和畫筆對象進行了釋放,對獲取的pDC沒有釋放,這樣短時間沒什么問題,但是程序跑了幾分鍾以后,界面就沒有反映了,整個界面卡死了,完全動不了。
這個問題困擾了我好幾天,試了各種方法無果。
后來請教了一個朋友,朋友看到代碼后,說pDC沒有釋放,我說GetDC需要釋放嗎,又不是new的。他說需要釋放。
於是添加了
ReleaseDC(pDC);
重新跑下程序,跑了一天一也沒有死。
但是問什么不釋放會使程序界面卡死呢?於是對釋放和不釋放兩個版本的程序進行觀察。
啟動任務管理器,把GDI對象添加到進程列中,觀察兩個版本的程序運行情況。程序名為OnlineFast

使用釋放的版本,可以看到GDI對象保持157不變。
如果沒有釋放的話,GDI對象會一直增加


當然,此時程序還沒有死,但運行一段時間后,當GDI對象增加到10000的時候,程序就死了,這就是GDI對象的極限了。
所以,GetDC 和ReleaseDC一定要配對使用,獲取了,沒有去釋放,windows不會自動去釋放,一直占用這,直到到達極限,資源耗盡,程序就崩潰了。
照例貼上倆兒子的照片,又離家一個月了,一個月沒見到倆兒子了。

