画图时 内存不停 增长 的解决 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;}}
- 画图时 内存不停 增长 的解决 CreateCompatibleDC(NULL) 创建失败
- 解决界面使用轮播图,不停创建界面,导致adapter和adapter里的默认图创建不停的生成,导致内存溢出
- MFC双缓冲解决闪烁问题 CreateCompatibleDC 创建内存兼容DC 转载自百度经验
- 日志文件不停增长的原因以及解决的相关方法
- 解决使用fusioncharts时浏览器内存占用不停增大的问题
- 关于sqlite4java内存不断增长的解决
- SQL SERVER 事务日志文件不停增长解决
- SQL SERVER 事务日志文件不停增长解决
- SQL SERVER 事务日志文件不停增长解决
- CreateCompatibleDC创建兼容DC
- delphi 缓冲画图(内存画图)解决画图闪烁问题
- delphi 缓冲画图(内存画图)解决画图闪烁问题
- delphi 缓冲画图(内存画图)解决画图闪烁问题
- 解决NSArray和NSDictionary中含有null时 writeToFile 失败的问题
- AVAudioplayer时error解决 创建失败
- AVAudioplayer时error解决 创建失败
- 对CreateCompatibleDC的认识
- CreateCompatibleDC函数的使用
- hashCode方法与HashSet类
- 三元组的数量(from pongo)
- init
- 五种经典js返回上页代码
- wikioi-天梯-提高一等-最短路-1041:Car的旅行路线
- 画图时 内存不停 增长 的解决 CreateCompatibleDC(NULL) 创建失败
- path: root/examples/inittab
- Sublime Text 2支持GB2312和GBK
- 如何使用win7自带的备份还原以及创建系统镜像------傻瓜式教程
- 【Node】node编译(windows)
- 柱状图内最大的矩形面积 Largest Rectangle in Histogram @LeetCode
- 如何在网站底部显示第几位访客代码
- 神经网络综述
- 阶乘因式分解&&蛇形填数