Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Freigabe von Screenshot?

6 views
Skip to first unread message

Kevin

unread,
Oct 8, 2009, 5:43:41 PM10/8/09
to
Hey,

Ich habe ein kleines Problem mit meinem Programm.
Dieses "scannt" auf dem Bildschirm nach gewissen Pixeln und reagiert darauf.
Da ich ziemlich viele Pixel auslese, hab ich mir gedacht, direkt ein
Snapshot in ein Array einzulesen und dann damit zu arbeiten.
Dies geht auch viel schneller als immer mit GetPixel, jedoch hab ich das
Problem, dass mein Programm sehr viel Speicher benᅵtigt.
Ich schaffe es jedoch nicht, diesen Speicher wieder Freizugeben und ich
weiᅵ nicht, wieso.

Erstmal der Code:
#include <windows.h>
...
int dx = GetSystemMetrics(SM_CXSCREEN);
int dy = GetSystemMetrics(SM_CYSCREEN);
RGBQUAD* mem = new RGBQUAD[dx * dy*sizeof(RGBQUAD)];
...
RGBQUAD* getScreen(){
printf("getScreen 0x%X\n",mem);
BITMAPINFO info = {0};
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = dx;
info.bmiHeader.biHeight = dy;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32; // 32:RGBQUAD; 24:RGBTRIPLE
HBITMAP bitmap;
// delete [] mem; <- mit delete [] versucht, ging nicht.
RGBQUAD* memory = mem;
hdcDesktop = GetDC(0);
bitmap = CreateDIBSection(hdcDesktop, &info, DIB_RGB_COLORS,
(void**)&memory, 0, 0);
if(!bitmap || !memory) return 0;
//free(mem); <- mit free versucht, ging nicht.
HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
HGDIOBJ oldbitmap = SelectObject(hdcMemory, bitmap);
BitBlt(hdcMemory, 0, 0, dx, dy, hdcDesktop, 0, 0, SRCCOPY);
SelectObject(hdcMemory, oldbitmap);
DeleteDC(hdcMemory);
DeleteObject(oldbitmap);
DeleteObject(bitmap);
ReleaseDC(0,hdcDesktop);
return memory;
}
...

Nun die Frage, wie schaffe ich es, dass ich in main() auf mem Zugreifen
kann, ohne, dass ich den ganzen Speicher zumᅵlle?

MfG

Kevin

Thomas J. Gritzan

unread,
Oct 8, 2009, 6:49:01 PM10/8/09
to
Kevin schrieb:

> Ich habe ein kleines Problem mit meinem Programm.
> Dieses "scannt" auf dem Bildschirm nach gewissen Pixeln und reagiert darauf.
> Da ich ziemlich viele Pixel auslese, hab ich mir gedacht, direkt ein
> Snapshot in ein Array einzulesen und dann damit zu arbeiten.

Gute Idee.

> Dies geht auch viel schneller als immer mit GetPixel, jedoch hab ich das
> Problem, dass mein Programm sehr viel Speicher benᅵtigt.
> Ich schaffe es jedoch nicht, diesen Speicher wieder Freizugeben und ich
> weiᅵ nicht, wieso.

Weil du die Dokumentation der Funktionen nicht liest.

> Erstmal der Code:
> #include <windows.h>

> ....


> int dx = GetSystemMetrics(SM_CXSCREEN);
> int dy = GetSystemMetrics(SM_CYSCREEN);
> RGBQUAD* mem = new RGBQUAD[dx * dy*sizeof(RGBQUAD)];

Hier reservierst du mit new[] Speicher, der eigentlich mit delete[]
wieder freigegeben wird, aber...

> ....


> RGBQUAD* getScreen(){
> printf("getScreen 0x%X\n",mem);
> BITMAPINFO info = {0};
> info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
> info.bmiHeader.biWidth = dx;
> info.bmiHeader.biHeight = dy;
> info.bmiHeader.biPlanes = 1;
> info.bmiHeader.biBitCount = 32; // 32:RGBQUAD; 24:RGBTRIPLE
> HBITMAP bitmap;
> // delete [] mem; <- mit delete [] versucht, ging nicht.
> RGBQUAD* memory = mem;
> hdcDesktop = GetDC(0);
> bitmap = CreateDIBSection(hdcDesktop, &info, DIB_RGB_COLORS,
> (void**)&memory, 0, 0);

...hier benutzt du eine Funktion, die eigenen Speicher reserviert. Du
ᅵbergibst einen Zeiger auf die Variable memory, damit die Funktion diese
Variable ᅵndern kann. D.h. memory zeigt nicht mehr auf Speicher, den du
mit delete[] freigeben kannst. Der Speicher wird automatisch
freigegeben, sobald du das Handle bitmap mit DeleteObject lᅵschst. Das
steht in der Beschreibung der Funktion CreateDIBSection in der MSDN
(Google nach dem Funktionsnamen).

Das hat allerdings nicht direkt etwas mit C++ zu tun, sondern mit der
API, die du benutzt, also die Windows API. Fragen dazu wᅵren z.B. in
comp.os.ms-windows.programmer.win32 besser aufgehoben.

> if(!bitmap || !memory) return 0;
> //free(mem); <- mit free versucht, ging nicht.
> HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
> HGDIOBJ oldbitmap = SelectObject(hdcMemory, bitmap);
> BitBlt(hdcMemory, 0, 0, dx, dy, hdcDesktop, 0, 0, SRCCOPY);
> SelectObject(hdcMemory, oldbitmap);
> DeleteDC(hdcMemory);
> DeleteObject(oldbitmap);
> DeleteObject(bitmap);
> ReleaseDC(0,hdcDesktop);
> return memory;
> }

--
Thomas

Kevin

unread,
Oct 9, 2009, 10:11:39 AM10/9/09
to
Hey,

Danke jetzt funktioniert es =)
In der Tat, ich habe die MSDN nicht gelesen, sondern mir etwas code
"zusammenkopiert".

Ich werds mir fᅵr nᅵchstes mal merken.


Danke nochmal.


Kevin

Björn Hendriks

unread,
Oct 12, 2009, 9:39:13 AM10/12/09
to

Hi,

die Antwort von Thomas Gritzan ist wohl die richtige Lösung für dein
Problem. Trotzdem noch eine Anmerkung zu deinem Programm.

Kevin wrote:
> Ich schaffe es jedoch nicht, diesen Speicher wieder Freizugeben und ich

> weiß nicht, wieso.


>
> Erstmal der Code:
> #include <windows.h>
> ...
> int dx = GetSystemMetrics(SM_CXSCREEN);
> int dy = GetSystemMetrics(SM_CYSCREEN);
> RGBQUAD* mem = new RGBQUAD[dx * dy*sizeof(RGBQUAD)];

Hier reservierst du einmalig beim Initialisieren des Programms Speicher auf
dem Heap.

> ...
> RGBQUAD* getScreen(){
> printf("getScreen 0x%X\n",mem);
> BITMAPINFO info = {0};
> info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
> info.bmiHeader.biWidth = dx;
> info.bmiHeader.biHeight = dy;
> info.bmiHeader.biPlanes = 1;
> info.bmiHeader.biBitCount = 32; // 32:RGBQUAD; 24:RGBTRIPLE
> HBITMAP bitmap;
> // delete [] mem; <- mit delete [] versucht, ging nicht.

Angenommen, die Zeile wäre nicht auskommentiert. Dann würdest du hier bei
jedem Aufruf der Funktion den oben reservierten Speicher zurückgeben. Das
darfst du nur einmal tun, also müsstest du sicherstellen, dass deine
Funktion nur ein einziges Mal aufgerufen wird während eines Programmlaufs.

Selbst wenn das der Fall wäre, würde ich so eine Konstruktion für schlechten
Stil halten, denn sie sieht sehr nach einem Fehler aus.

> RGBQUAD* memory = mem;

Immer noch angenommen, obiges delete wäre nicht auskommentiert. Dann zeigt
memory jetzt genauso wie mem auf Speicher, der dir nicht mehr gehört. Jeder
Zugriff (auch lesender) auf diesen Speicher ist damit definitiv ein Fehler.

> hdcDesktop = GetDC(0);
> bitmap = CreateDIBSection(hdcDesktop, &info, DIB_RGB_COLORS,
> (void**)&memory, 0, 0);
> if(!bitmap || !memory) return 0;
> //free(mem); <- mit free versucht, ging nicht.

free ist das Gegenstück zu malloc(), so wie delete ([]) das Gegenstück zu
new ([]) ist. Mischen darf man nicht.

> HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
> HGDIOBJ oldbitmap = SelectObject(hdcMemory, bitmap);
> BitBlt(hdcMemory, 0, 0, dx, dy, hdcDesktop, 0, 0, SRCCOPY);
> SelectObject(hdcMemory, oldbitmap);
> DeleteDC(hdcMemory);
> DeleteObject(oldbitmap);
> DeleteObject(bitmap);
> ReleaseDC(0,hdcDesktop);
> return memory;
> }
> ...


Gruß
Björn

Kevin

unread,
Oct 12, 2009, 6:53:49 PM10/12/09
to
Hey,

ich meinen Speichermurks jetzt auch bemerkt gehabt^^
Falls wer die Funktion will, hier ist sie:
RGBQUAD* mem = 0;

RGBQUAD* getScreen(){


BITMAPINFO info = {0};
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = dx;
info.bmiHeader.biHeight = dy;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32; // 32:RGBQUAD; 24:RGBTRIPLE
HBITMAP bitmap;

RGBQUAD* memory = 0;


hdcDesktop = GetDC(0);
bitmap = CreateDIBSection(hdcDesktop, &info, DIB_RGB_COLORS,
(void**)&memory, 0, 0);

HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
HGDIOBJ oldbitmap = SelectObject(hdcMemory, bitmap);
BitBlt(hdcMemory, 0, 0, dx, dy, hdcDesktop, 0, 0, SRCCOPY);

if(mem != 0) delete[] mem;


mem = new RGBQUAD[dx * dy*sizeof(RGBQUAD)];

memcpy(mem, memory, dx*dy*sizeof(RGBQUAD));


SelectObject(hdcMemory, oldbitmap);
DeleteDC(hdcMemory);
DeleteObject(oldbitmap);
DeleteObject(bitmap);
ReleaseDC(0,hdcDesktop);

return mem;
}

0 new messages