[try Beta version]
Not logged in

 
how to release HDC object

Jan 8, 2023 at 9:10am
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 Jan 8, 2023 at 9:11am
Jan 8, 2023 at 10:58am
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 Jan 8, 2023 at 12:06pm
Jan 8, 2023 at 11:07am
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?
Jan 8, 2023 at 11:09am
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
Jan 8, 2023 at 11:34am
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

Jan 8, 2023 at 12:05pm
still does not flush memory
Jan 8, 2023 at 12:37pm
How do you know?
Jan 8, 2023 at 12:42pm
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 Jan 8, 2023 at 1:31pm
Jan 10, 2023 at 4:25pm
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.

Jan 11, 2023 at 8:12am
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
Topic archived. No new replies allowed.