画图时 内存不停 增长 的解决 CreateCompatibleDC(NULL) 创建失败

来源:互联网 发布:机关网络舆情工作总结 编辑:程序博客网 时间:2024/06/09 23:39

今天做贪食蛇的时候,当吃了几个食物的时候,系统报错,我是在group上画图,蛇头,蛇尾,蛇身,三张位图。

CreateCompatibleDC(NULL) 创建失败,网上查了原因,应该是内存不足引起的,查看任务管理器,果然发现内存一直增长。

经过排查原因发现是dc没有释放。

 

 

 HDC memDc=CreateCompatibleDC(NULL);//这种的必须要释放 DeleteDC(memDc);//必须释放,要不占内存

 

但是 CDC sourceDC, destDC;

sourceDC.CreateCompatibleDC(NULL);

destDC.CreateCompatibleDC(NULL);

这种的就不用释放,内存不会增加,个人推测这种是包装过的类,应该是退出函数时,调用析构函数进行释放了。不需要显式释放。

 

类似的

CWnd *cw=GetDlgItem(IDC_GROUP_MAIN);
   HDC hdc=cw->GetDC()->GetSafeHdc();
 

这种通过 HDC来接受的就需要 显式的调用释放函数 DeleteDC(hdc);      cdc应该就不用

 

其中误解了很多地方占用内存没释放,事后发现其实没有,误解的地方:

cbitmap不用释放内存 和LoadBitmap 没有关系 和bitmap也没关系,不用手动释放

和还原原始设备也没关系 SelectObject(memDc,bitold);

和CArray<CPoint,CPoint&> arr_points; 没关系,他会自动释放,也不用removeall

 

另外。

个人觉得,这个是立刻释放内存的做法,这个应该不算内存泄露,因为debug的时候没有内存泄露的提示,而且,最小化后,再最大化,内存减了很多。

 

总结就是:指针和原始类需要手动释放内存,其他的不需要。

 

相关源代码如下:

// SnakeView.cpp : implementation of the CSnakeView class//#include "stdafx.h"#include "Snake.h"#include "SnakeDoc.h"#include "SnakeView.h"#include "GAMESET.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define  TimerMain 1int GetRand(double MAX,double MIN);HBITMAP GetRotatedBitmapNT( HBITMAP hBitmap, float radians, COLORREF clrBack);/////////////////////////////////////////////////////////////////////////////// CSnakeViewIMPLEMENT_DYNCREATE(CSnakeView, CFormView)BEGIN_MESSAGE_MAP(CSnakeView, CFormView)//{{AFX_MSG_MAP(CSnakeView)ON_WM_KEYDOWN()ON_WM_TIMER()ON_BN_CLICKED(IDC_BTN_START, OnBtnStart)ON_WM_SHOWWINDOW()ON_COMMAND(IDM_GAME_SET, OnGameSet)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CSnakeView construction/destructionCSnakeView::CSnakeView():CFormView(CSnakeView::IDD),m_iDircFlag(3),m_changeTail(FALSE),m_iTailDegree(0),m_pFood(CPoint(0,0)),iRandomSeed(0),i_Speed(0)//默认是向右{// TODO: add construction code here}CSnakeView::~CSnakeView(){}BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying//  the CREATESTRUCT csreturn CFormView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CSnakeView drawingvoid CSnakeView::OnDraw(CDC* pDC){CSnakeDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereint size=m_snake.m_points.GetSize(); for (int i=0;i<size;i++) { CBitmap bit; //HBITMAP bitold; HBITMAP hbitmap; if (i==0||i==size-1)//表示是头或者尾巴 { if (i==0) { bit.LoadBitmap(IDB_SHead);//头  int degree;  switch (m_iDircFlag)  {  case 0:  degree=90;  break;  case 1:  degree=-90;  break;  case 2:  degree=180;  break;  case 3:  degree=0;  break;  }  hbitmap=(HBITMAP)GetRotatedBitmapNT(bit,degree*3.14159265359/180,pDC->GetBkColor());//旋转图片  bit.Detach();  bit.Attach(hbitmap); } else { bit.LoadBitmap(IDB_STail);//尾巴  if (m_changeTail)  {  switch (m_iDircFlag)  {  case 0:  m_iTailDegree=90;  break;  case 1:  m_iTailDegree=-90;  break;  case 2:  m_iTailDegree=180;  break;  case 3:  m_iTailDegree=0;  break;  }  m_changeTail=FALSE;  }    hbitmap=(HBITMAP)GetRotatedBitmapNT(bit,m_iTailDegree*3.14159265359/180,pDC->GetBkColor());//旋转图片  bit.Detach();  bit.Attach(hbitmap);  } } else { bit.LoadBitmap(IDB_SBody); } CWnd *cw=GetDlgItem(IDC_GROUP_MAIN); HDC hdc=cw->GetDC()->GetSafeHdc();  HDC memDc=CreateCompatibleDC(NULL); (HBITMAP)SelectObject(memDc,bit);  BITMAP bm; bit.GetBitmap(&bm); CPoint cp=m_snake.m_points[i];    BitBlt(hdc,cp.x,cp.y+8,bm.bmWidth,bm.bmHeight,memDc,0,0,SRCCOPY);  DeleteDC(memDc);//必须释放,要不占内存DeleteDC(hdc);//必须释放,要不占内存}DrawFoodPoint();//画食物点}/////////////////////////////////////////////////////////////////////////////// CSnakeView printingBOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CSnakeView diagnostics#ifdef _DEBUGvoid CSnakeView::AssertValid() const{CFormView::AssertValid();}void CSnakeView::Dump(CDumpContext& dc) const{CFormView::Dump(dc);}CSnakeDoc* CSnakeView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));return (CSnakeDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CSnakeView message handlersvoid CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {// TODO: Add your message handler code here and/or call defaultCFormView::OnKeyDown(nChar, nRepCnt, nFlags);}//蛇移动事件void CSnakeView::Move(){int size=m_snake.m_points.GetSize();CArray<CPoint,CPoint&> arr_points;//复制一个临时的数组arr_points.Copy(m_snake.m_points);//思路:移动时,除了第一个坐标根据上下左右的不同,重新赋值外,其他的坐标复制他们前面一个坐标的值。 CPoint origTail=m_snake.m_points[size-2];for (int i=1;i<size;i++){m_snake.m_points[i]=arr_points[i-1];}//获取group范围 判断蛇的位置是否超出范围,如果是的话,则提示失败,重新开始CWnd *cGroupWnd=GetDlgItem(IDC_GROUP_MAIN);RECT groupRect;cGroupWnd->GetClientRect(&groupRect);BOOL blIsOut=FALSE;switch (m_iDircFlag){case 0://上m_snake.m_points[0].y-=16;if (m_snake.m_points[0].y<groupRect.top)//超出范围{blIsOut=TRUE;break;}if (origTail.y!=m_snake.m_points[size-2].y)//判断倒数第二个的x,y是否变化,来决定尾巴图片是否旋转{m_changeTail=TRUE;}break;case 1://下m_snake.m_points[0].y+=16;if (m_snake.m_points[0].y+16>groupRect.bottom)//超出范围{blIsOut=TRUE;break;}if (origTail.y!=m_snake.m_points[size-2].y){m_changeTail=TRUE;}break;case 2://左m_snake.m_points[0].x-=16;if (m_snake.m_points[0].x<groupRect.left)//超出范围{blIsOut=TRUE;break;}if (origTail.x!=m_snake.m_points[size-2].x){m_changeTail=TRUE;}break;case 3://右m_snake.m_points[0].x+=16;if (m_snake.m_points[0].x+16>groupRect.right)//超出范围{blIsOut=TRUE;break;}if (origTail.x!=m_snake.m_points[size-2].x){m_changeTail=TRUE;}break;}if (blIsOut){m_snake.Initialize();//重新初始化m_iDircFlag=3;//方向初始化m_changeTail=FALSE;//尾巴是否改变初始化m_iTailDegree=0;//尾巴角度初始化KillTimer(TimerMain);MessageBox("失败!");}//吃东西,如果头坐标和食物坐标相等,追加一个坐标if (m_snake.m_points[0].x==m_pFood.x&&m_snake.m_points[0].y+8==m_pFood.y){m_snake.m_points.Add(arr_points[size-1]);CString cs;cs.Format("%d",m_snake.m_points.GetSize());SetDlgItemText(IDC_SNAKELEN,cs);GenerateFoodPoint();//生成食物点}//重绘客户区RECT temprect(groupRect);temprect.right+=32;temprect.bottom+=32;InvalidateRect(&temprect);}// GetRotatedBitmapNT - Create a new bitmap with rotated image// Returns - Returns new bitmap with rotated image// hBitmap - Bitmap to rotate// radians - Angle of rotation in radians// clrBack - Color of pixels in the resulting bitmap that do// not get covered by source pixelsHBITMAP GetRotatedBitmapNT( HBITMAP hBitmap, float radians, COLORREF clrBack ){// Create a memory DC compatible with the displayCDC sourceDC, destDC;sourceDC.CreateCompatibleDC(NULL);destDC.CreateCompatibleDC(NULL);// Get logical coordinatesBITMAP bm;GetObject( hBitmap, sizeof( bm ), &bm );float cosine = (float)cos(radians);float sine = (float)sin(radians);// Compute dimensions of the resulting bitmap// First get the coordinates of the 3 corners other than originint x1 = (int)(bm.bmHeight * sine);int y1 = (int)(bm.bmHeight * cosine);int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);int x3 = (int)(bm.bmWidth * cosine);int y3 = (int)(-bm.bmWidth * sine);int minx = min(0,min(x1, min(x2,x3)));int miny = min(0,min(y1, min(y2,y3)));int maxx = max(0,max(x1, max(x2,x3)));int maxy = max(0,max(y1, max(y2,y3)));int w = maxx - minx;int h = maxy - miny;// Create a bitmap to hold the resultHBITMAP hbmResult=::CreateCompatibleBitmap(CClientDC(NULL), w, h);HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );// Draw the background color before we change mapping modeHBRUSH hbrBack = CreateSolidBrush( clrBack );HBRUSH hbrOld = (HBRUSH)::SelectObject(destDC.m_hDC, hbrBack );destDC.PatBlt( 0, 0, w, h, PATCOPY );::DeleteObject(::SelectObject(destDC.m_hDC, hbrOld));// We will use world transform to rotate the bitmapSetGraphicsMode(destDC.m_hDC, GM_ADVANCED);XFORM xform;xform.eM11 = cosine;xform.eM12 = -sine;xform.eM21 = sine;xform.eM22 = cosine;xform.eDx = (float)-minx;xform.eDy = (float)-miny;SetWorldTransform( destDC.m_hDC, &xform );// Now do the actual rotating - a pixel at a timedestDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY );// Restore DCsSelectObject(sourceDC.m_hDC, hbmOldSource );SelectObject(destDC.m_hDC, hbmOldDest );return hbmResult;}void CSnakeView::OnTimer(UINT nIDEvent) {// TODO: Add your message handler code here and/or call defaultMove();//贪食蛇移动事件CFormView::OnTimer(nIDEvent);}BOOL CSnakeView::PreTranslateMessage(MSG* pMsg) {// TODO: Add your specialized code here and/or call the base classif (pMsg->message==WM_KEYDOWN){switch (pMsg->wParam){case VK_UP:m_iDircFlag=0;break;case VK_DOWN:m_iDircFlag=1;break;case VK_LEFT:m_iDircFlag=2;break;case VK_RIGHT:m_iDircFlag=3;break;}Move();}return CFormView::PreTranslateMessage(pMsg);}void CSnakeView::OnBtnStart() {// TODO: Add your control notification handler code hereif (i_Speed==0){SetTimer(TimerMain,500,NULL);}else if (i_Speed==1){SetTimer(TimerMain,300,NULL);}else{SetTimer(TimerMain,100,NULL);}}//画食物的点void CSnakeView::DrawFoodPoint(){CWnd *cwnd=GetDlgItem(IDC_GROUP_MAIN);CBitmap bit;bit.LoadBitmap(IDB_SBody);BITMAP bm;bit.GetBitmap(&bm);HDC hdc=CreateCompatibleDC(NULL);(HBITMAP)SelectObject(hdc,bit);HDC grouphdc=cwnd->GetDC()->GetSafeHdc();BitBlt(grouphdc,m_pFood.x,m_pFood.y,bm.bmWidth,bm.bmHeight,hdc,0,0,SRCCOPY);DeleteDC(grouphdc);DeleteDC(hdc);}//重新生成食物点void CSnakeView::GenerateFoodPoint(){if (iRandomSeed==0){srand((unsigned)time(0));//用当前时间}else{srand(iRandomSeed);}iRandomSeed++;CWnd *cGroupWnd=GetDlgItem(IDC_GROUP_MAIN);RECT groupRect;cGroupWnd->GetClientRect(&groupRect);CBitmap bit;bit.LoadBitmap(IDB_SBody);BITMAP bm;bit.GetBitmap(&bm);while (TRUE){BOOL blflag=FALSE;//是否需要重新生成food的点m_pFood.x=(int)(rand()%(groupRect.right/16))*bm.bmWidth;m_pFood.y=(int)(rand()%(groupRect.bottom/16))*bm.bmHeight+8;for (int i=0;i<m_snake.m_points.GetSize(); ++i){if ((m_snake.m_points[i].x==m_pFood.x)&&(m_snake.m_points[i].y==m_pFood.y)){blflag=TRUE;break;}}if (!blflag){break;}}}void CSnakeView::OnShowWindow(BOOL bShow, UINT nStatus) {CFormView::OnShowWindow(bShow, nStatus);GenerateFoodPoint();//生成点// TODO: Add your message handler code here}void CSnakeView::OnGameSet() {// TODO: Add your command handler code hereGAMESET gms;if (IDOK==gms.DoModal()){i_Speed=gms.m_iSpeed;}}


 

0 0
原创粉丝点击