Quantcast
Channel: Форум программистов и сисадминов Киберфорум
Viewing all articles
Browse latest Browse all 517576

Утечка памяти из-за переполнения GDI-объектами - C++ и WinAPI

$
0
0
Господа! помогите пожалуйста разобраться с непонятным недокументированным багом в моей маленькой программе в следствии которого в программе появляются лишние GDI-объекты а конкретно DC (контексты устройства) и программа начинает "кушать" память. Это регистрируется диспетчером задач виндовс(столбцы память, объекты GDI). Контексты устройства создаются при вызове функции BeginPaint() и удаляются при вызове EndPaint() НО!!! так происходит только тогда когда в блоке рисования не используется функция DrawText() (или она закомментирована или не вызывается в соответствии с кодом программы) Соответственно когда она хотя бы единожды была вызвана функция EndPaint() уже не удаляет созданный ранее объект GDI и они начинают накапливаться.. И вообще странно что функции BeginPaint() создаёт какие-то объекты. Ведь как известно она лишь получается хендл контекста устройства у системы, а он ОБЩИЙ..

Код:

#include <windows.h>
#include <tchar.h>
#include "судоку.h"
 
LRESULT APIENTRY WndProc(HWND, UINT, WPARAM, LPARAM);

struct rter
{
        RECT rt;
        RECT ref;
        bool er;
};


rter area[9][9];

cell tab;
info str;
TCHAR out[150];

#define x0 5 //отступ слева
#define y0 5 //отступ сверху

const TCHAR mb[][19]={"Судоку","Цифра недопустима","Решение не найдено"};


int CALLBACK _tWinMain(HINSTANCE This, // Дескриптор текущего приложения
HINSTANCE Prev, // В современных системах всегда 0
LPTSTR cmd, // Командная строка
int mode) // Режим отображения окна
{
HWND hWnd; // Дескриптор главного окна программы
MSG msg; // Структура для хранения сообщения
WNDCLASS wc; // Класс окна
// Определение класса окна
wc.hInstance = This;
wc.lpszClassName = "WINDOW"; // Имя класса окна
wc.lpfnWndProc = WndProc; // Функция окна
wc.style; // Стиль окна
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Стандартная иконка
wc.hCursor = LoadCursor(NULL,IDC_ARROW); // Стандартный курсор
wc.lpszMenuName = NULL; // Нет меню
wc.cbClsExtra = 0; // Нет дополнительных данных класса
wc.cbWndExtra = 0; // Нет дополнительных данных окна
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH );// Заполнение окна светло-серым цветом
RegisterClass(&wc); // Регистрация класса окна
// Создание окна
hWnd = CreateWindow("WINDOW", // Имя класса окна
mb[0], // Заголовок окна
WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, // Стиль окна
CW_USEDEFAULT, // x
CW_USEDEFAULT, // y Размеры окна
331, // Width
400, // Height
NULL, // Дескриптор родительского окна
NULL, // Нет меню
This, // Дескриптор приложения
NULL); // Дополнительной информации нет
CreateWindow("BUTTON","Очистить всё",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 80, 330, 110, 35, hWnd,(HMENU)0, This ,NULL) ;
CreateWindow("BUTTON","Решить",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 210, 330, 110, 35, hWnd,(HMENU)101, This ,NULL) ;
ShowWindow(hWnd, mode); //Показать окно

while(GetMessage(&msg, NULL, 0, 0))// Цикл обработки сообщений
{
TranslateMessage(&msg);// Функция трансляции кодов нажатой клавиши
DispatchMessage(&msg); // Посылает сообщение функции WndProc()
}
return msg.wParam;

}

// Оконная функция вызывается операционной системой
// и получает сообщения из очереди для данного приложения
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static int Y=0,X=0;
static HFONT hF;
static HPEN hP2,hP3;
static LOGBRUSH lb;
static HBRUSH hB;
static HCURSOR hC;
int c;
TCHAR F;
int yd,xd;
bool res;


        switch(message)
{
        case WM_CREATE:
                hF=CreateFont(36,    // высота шрифта
                0,    // ширина символов
                0,    // угол наклона букв
                0,    // угол наклона строки
                FW_NORMAL,    // толщина букв («жирность»)
                0,  // курсив
                0,  // подчеркивание
                0,  // перечеркивание
                DEFAULT_CHARSET,  // набор символов
                OUT_DEFAULT_PRECIS,  // точность вывода
                CLIP_DEFAULT_PRECIS,  // точность отсечения
                DEFAULT_QUALITY,  // качество вывода
                DEFAULT_PITCH,  // шаг между буквами
                "Calibri" // имя шрифта
                );
                lb.lbColor=RGB(0,0,255);
                hP2=CreatePen(PS_SOLID,2,RGB(0,0,0));  //толстые линии
                hP3=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_SQUARE,4,&lb,0,NULL);  //линии курсора
                hB= CreateSolidBrush(RGB(255,119,119));
                hC=LoadCursor(NULL,IDC_WAIT);
                for(int yc=0,yd=0;yc<9;yc++,yd+=35)
                        for(int xc=0,xd=0;xc<9;xc++,xd+=35)
                        {
                                tab.fig[yc][xc]=0;
                                area[yc][xc].rt.left=xd;
                                area[yc][xc].rt.right=xd+35;
                                area[yc][xc].rt.top=yd;
                                area[yc][xc].rt.bottom=yd+35;

                                area[yc][xc].ref.left=xd+x0-2;
                                area[yc][xc].ref.right=xd+x0+37;
                                area[yc][xc].ref.top=yd+y0-2;
                                area[yc][xc].ref.bottom=yd+y0+37;

                                area[yc][xc].er=true;
                        }

                        break;

        case WM_LBUTTONDOWN:
               
                if((LOWORD(lParam)-x0)/35U<9 &&(HIWORD(lParam)-y0)/35U<9)
                        if(area[Y][X].er)
                        {
                InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                X = (LOWORD(lParam)-x0)/35;
                Y = (HIWORD(lParam)-y0)/35;
                InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                        }
                else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                break;
       
        case WM_COMMAND:
                switch(wParam)
                {
                case 0:

                                        for(int y=0;y<9;y++)
                        for(int x=0;x<9;x++)
                        {
                                tab.fig[y][x]=0;
                                area[y][x].er=true;
                        }
                        break;
               
                case 101:
                        if(area[Y][X].er)
                        {

                                hC=SetCursor(hC);
                                res=process(&tab,&str);
                                hC=SetCursor(hC);
                                if(!res)
                                        MessageBox(hWnd,mb[2],mb[0],MB_OK| MB_ICONASTERISK );
                        }
                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                        break;
                }
                InvalidateRect(hWnd,NULL,TRUE);
                SetFocus(hWnd);
                break;
        case WM_SETFOCUS:
                break;



        case WM_KEYDOWN:
                switch(wParam)
                {
                        case VK_UP:
                                if(Y>0)
                                        if(area[Y][X].er)
                                        {
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        Y--;
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        }
                                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                                break;
                        case VK_DOWN:
                                if(Y<8)
                                        if(area[Y][X].er)
                                        {
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        Y++;
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        }
                                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                                break;
                        case VK_LEFT:
                                if(X>0)
                                        if(area[Y][X].er)
                                        {
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        X--;
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        }
                                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                                break;
                        case VK_RIGHT:
                                if(X<8)
                                        if(area[Y][X].er)
                                        {
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        X++;
                                        InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                                        }
                                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                                break;
                        case VK_DELETE:
                for(int y=0;y<9;y++)
                        for(int x=0;x<9;x++)
                        {
                                tab.fig[y][x]=0;
                                area[y][x].er=true;
                        }
                        InvalidateRect(hWnd,NULL,TRUE);
                break;
                        case VK_RETURN:
                        if(area[Y][X].er)
                        {
                                hC=SetCursor(hC);
                                res=process(&tab,&str);
                                hC=SetCursor(hC);
                                if(res)

                                        InvalidateRect(hWnd,NULL,TRUE);
                                else
                                                MessageBox(hWnd,mb[2],mb[0],MB_OK| MB_ICONASTERISK );
                        }
                        else
                        MessageBox(hWnd,mb[1],mb[0],MB_OK|MB_ICONWARNING);
                                break;

                        case VK_F1:

                                wsprintf(out,"Всего итераций:\t\t%d\nЗаходов в case1:\t\t%d\nЗаходов в case2:\t\t%d\nЗаходов в case0:\t\t%d\nМакс длина очереди:\t%d",str.iter,str.c1,str.c2,str.c0,str.maxq);
                                        MessageBox(hWnd,out,"Техническая информация",MB_OK| MB_ICONASTERISK );
       
                }
                break;


        case WM_CHAR:
                if(wParam-48<10 && wParam-48!=tab.fig[Y][X])
                {
                tab.fig[Y][X]=c=wParam-48;
                area[Y][X].er=true;
                InvalidateRect(hWnd,&area[Y][X].ref,TRUE);
                if(c==0) c=-1;
                                        for(yd=Y;yd>2;yd-=3);
                                        for(xd=X;xd>2;xd-=3);

                                                for(int xu=0;xu<9;xu++)
                                                        if(xu!=X)
                                                        if(tab.fig[Y][xu]==c)
                                        {
                                                area[Y][xu].er=false;
                                                area[Y][X].er=false;
                                                InvalidateRect(hWnd,&area[Y][xu].ref,TRUE);

                                        }
                                                        else
                                                        {
                                                                if(area[Y][xu].er==false)
                                                InvalidateRect(hWnd,&area[Y][xu].ref,TRUE);
                                                                area[Y][xu].er=true;
                                                        }

                                                for(int yu=0;yu<9;yu++)
                                                        if(yu!=Y)
                                                                if(tab.fig[yu][X]==c)
                                        {
                                                area[yu][X].er=false;
                                                area[Y][X].er=false;
                                                InvalidateRect(hWnd,&area[yu][X].ref,TRUE);
                                        }
                                                                else
                                                                {
                                                                        if(area[yu][X].er==false)
                                                                        InvalidateRect(hWnd,&area[yu][X].ref,TRUE);
                                                                        area[yu][X].er=true;
                                                                }
                                        for(int yu=Y-yd;yu<Y-yd+3;yu++)
                                                for(int xu=X-xd;xu<X-xd+3;xu++)
                                                if(yu!=Y && xu!=X)
                                                        if(tab.fig[yu][xu]==c)
                                                {
                                                area[yu][xu].er=false;
                                                area[Y][X].er=false;
                                                InvalidateRect(hWnd,&area[yu][xu].ref,TRUE);
                                                }
                                                        else
                                                        {
                                                                if(area[yu][xu].er==false)
                                                                InvalidateRect(hWnd,&area[yu][xu].ref,TRUE);
                                                                area[yu][xu].er=true;
                                                        }

                }

                break;

        case WM_PAINT:
                hDC=BeginPaint(hWnd,&ps);
                SetViewportOrgEx(hDC, x0,y0 , NULL);
                                SelectObject(hDC,hF);
                SetBkMode(hDC,TRANSPARENT);
                for(int y=0;y<9;y++)
                        for(int x=0;x<9;x++)
                                if(tab.fig[y][x]!=0  )
                                {
                                        if(area[y][x].er==false)
                                                FillRect(hDC,&area[y][x].rt,hB);
                        wsprintf(&F,"%d",tab.fig[y][x]);
                        DrawText(hDC,&F, 1, &area[y][x].rt,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
                                }


       
                for(int a=35;a<281;a+=35)
                {
                        MoveToEx(hDC,a,0,NULL);
                        LineTo(hDC,a,315);
                        MoveToEx(hDC,0,a,NULL);
                        LineTo(hDC,315,a);
                }

                SelectObject(hDC,hP2);
                for(int a=0;a<316;a+=105)
                {
                        MoveToEx(hDC,a,-1,NULL);
                        LineTo(hDC,a,315);
                        MoveToEx(hDC,0,a,NULL);
                        LineTo(hDC,315,a);

                }

                SetViewportOrgEx(hDC, area[Y][X].rt.left+x0,area[Y][X].rt.top+y0 , NULL);
                SelectObject(hDC,hP3);
                MoveToEx(hDC,0,9,NULL);
                LineTo(hDC,0,0);
                LineTo(hDC,9,0);
                MoveToEx(hDC,26,0,NULL);
                LineTo(hDC,35,0);
                LineTo(hDC,35,9);
                MoveToEx(hDC,35,26,NULL);
                LineTo(hDC,35,35);
                LineTo(hDC,26,35);
                MoveToEx(hDC,9,35,NULL);
                LineTo(hDC,0,35);
                LineTo(hDC,0,26);               
       
                EndPaint(hWnd,&ps);

                break;


case WM_CLOSE :
        DeleteObject(hP2);
        DeleteObject(hP3);
        DeleteObject(hF);
        DeleteObject(hB);
        PostQuitMessage(0);

break; // Завершение программы
// Обработка сообщения по умолчанию
default : return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}


Viewing all articles
Browse latest Browse all 517576

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>