how to release HDC object

HDC object hwindowDC increase memory,but it must be flushed with destructor
tried below
DeleteObject(hwindowDC);
DeleteDC(hwindowDC);
CancelDC(hwindowDC);


Function hwindowDC = GetDC(hwnd) can not be flushed with destructor functions I use

I need to flush all memory related to functions below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class hwnd2Mat
{
public:
    hwnd2Mat(HWND hwindow, float scale = 1);
    virtual ~hwnd2Mat();
    virtual void read();
    Mat image;

private:
    HWND hwnd;
    HDC hwindowDC, hwindowCompatibleDC;
    int height, width, srcheight, srcwidth;
    HBITMAP hbwindow;
    BITMAPINFOHEADER  bi;
};

hwnd2Mat::hwnd2Mat(HWND hwindow, float scale)
{
    hwnd = hwindow;
    hwindowDC = GetDC(hwnd);  
    hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
   SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);
    RECT windowsize;
    GetClientRect(hwnd, &windowsize);
   srcheight = windowsize.bottom;
    srcwidth = windowsize.right;
    height = (int)(windowsize.bottom * scale);
    width = (int)(windowsize.right * scale);
    image.create(height, width, CV_8UC4);
    hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = width;
    bi.biHeight = -height;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
    SelectObject(hwindowCompatibleDC, hbwindow);
    read();

};

void hwnd2Mat::read()
{
    StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
    GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, image.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);  //copy from hwindowCompatibleDC to hbwindow
};

hwnd2Mat::~hwnd2Mat()
{
    DeleteObject(hbwindow);
    DeleteDC(hwindowCompatibleDC);
    ReleaseDC(hwnd, hwindowDC);
    DeleteObject(hwindowDC);
    DeleteDC(hwindowDC);
    CancelDC(hwindowDC);


    //hwindowDC = GetDC(hwnd);
    image.release(); 

}



void screenCapture ()
{

    hwnd2Mat capDesktop(GetDesktopWindow());
    VideoWriter writer;  
    int codec = VideoWriter::fourcc('X', 'V', 'I', 'D');
    double fps = 10.0;
    string filename = "./caP3.mkv";
    writer.open(filename, codec, fps, capDesktop.image.size(), true);
    capDesktop.read();
    cvtColor(capDesktop.image, image1, COLOR_BGRA2BGR);  
}

can not add code tag
Last edited on
The reverse of GetDC() is ReleaseDC()
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-releasedc

The reverse of CreateCompatibleDC() is DeleteDC()
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deletedc

The reverse of CreateCompatibleBitmap() is DeleteObject()
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deleteobject

As are already used.
Last edited on
The ReleaseDC function releases a device context (DC), freeing it for use by other applications. The effect of the ReleaseDC function depends on the type of DC. It frees only common and window DCs. It has no effect on class or private DCs.
is there any other way to solve this?
I already tried these, but It have no effect

ReleaseDC(hwnd, hwindowDC);
DeleteObject(hwindowDC);
DeleteDC(hwindowDC);
CancelDC(hwindowDC);

need to flush all related to hwindowDC
Re GetDC()

From MSDN
After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC. The number of DCs is limited only by available memory.


https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc

still does not flush memory
How do you know?
I check with application

int processNumber = _getpid();


int PrintMemoryInfo( DWORD processID ){
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
if (processID == processNumber)
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID );
//if (NULL == hProcess)
//return 1;
else
return 0;
if (processID == processNumber)
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)))
temp = pmc.WorkingSetSize;
hProcess = NULL;
//CloseHandle( hProcess );
return temp;
}

wait I will share you code
[shared a code]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#define WINVER 0x0500
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <QFile>
#include <cstdlib>
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::cin;
using std::ios;
using std::setiosflags;
using std::hex;
using std::oct;
using std::dec;
using std::cout;
using std::endl;
using std::cin;
using std::ios;
using std::setiosflags;
using std::hex;
using std::oct;
using std::dec;
using namespace std;

void screenCapture ();
int PrintMemoryInfo( DWORD processID );

class hwnd2Mat
{
public:
    hwnd2Mat(HWND hwindow, float scale = 1);
    virtual ~hwnd2Mat();
    virtual void read();
    cv::Mat image;

private:
    HWND hwnd;
    HDC hwindowDC, hwindowCompatibleDC;
    int height, width, srcheight, srcwidth;
    HBITMAP hbwindow;
    BITMAPINFOHEADER  bi;
};

hwnd2Mat::hwnd2Mat(HWND hwindow, float scale)
{

    hwnd = hwindow;
    hwindowDC = GetDC(hwnd);
    hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
    SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);
    RECT windowsize;
    GetClientRect(hwnd, &windowsize);
    srcheight = windowsize.bottom;
    srcwidth = windowsize.right;
    height = (int)(windowsize.bottom * scale);
    width = (int)(windowsize.right * scale);
    image.create(height, width, CV_8UC4);
    ReleaseDC(hwnd, hwindowDC);
    hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = width;
    bi.biHeight = -height;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
    SelectObject(hwindowCompatibleDC, hbwindow);
    read();



}

void hwnd2Mat::read(){
    StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
    GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, image.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);  //copy from hwindowCompatibleDC to hbwindow
    }

hwnd2Mat::~hwnd2Mat(){
    DeleteObject(hbwindow);
    DeleteDC(hwindowCompatibleDC);
    ReleaseDC(hwnd, hwindowDC);
    image.release();
    cout << "destructor called" << endl;
    }

int main()
{
    int processNumber = _getpid();
    int i = 0;
    int memoryLoad = 0;
    int first = 0;
    while (true)
    {
    cout << i << endl;
    screenCapture();
    memoryLoad = PrintMemoryInfo( processNumber );
    cout << " Load " << memoryLoad << " MB " <<  memoryLoad/1000000  <<  endl;
    if (i == 0 )
    first = memoryLoad;

    cout << "first " << first << endl;
    cout << "load "  << memoryLoad << endl;
    i++;
    }

}


int PrintMemoryInfo( DWORD processID ){
    int memory_value;
    int processNumber = _getpid();
    HANDLE hProcess;
    PROCESS_MEMORY_COUNTERS pmc;
    if (processID == processNumber)
    hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID );
    else
    return 0;
    if (processID == processNumber)
    if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)))
    memory_value = pmc.WorkingSetSize;
    hProcess = NULL;
    return memory_value;
               }




    void screenCapture (){
    cv::Mat capturedImage;
    hwnd2Mat capDesktop(GetDesktopWindow());
    cv::VideoWriter writer;
    int codec = cv::VideoWriter::fourcc('X', 'V', 'I', 'D');
    double fps = 10.0;
    string filename = "./caP3.mkv";
    writer.open(filename, codec, fps, capDesktop.image.size(), true);
    capDesktop.read();
    cv::cvtColor(capDesktop.image, capturedImage, cv::COLOR_BGRA2BGR);
    }

Last edited on
still does not flush memory

It's Windows, using the Window API. Windows manages memory and constructs by its own schemes.

Get used to it.

still does not flush memory
On line 72 the window dc is released. I.e. you don't have access to the hwindowDC anymore. I suggest to move line 72 after line 86. Or due to line 100 remove line 72 entirely
Registered users can post here. Sign in or register to post.