Benutzer mit den meisten Antworten
Screenshot Probleme

Frage
-
Folgende Funktion läuft ohne Fehler durch, erstellt ein Bild, aber dieses ist IMMER schwarz, kann mir jemand sagen wo der Fehler liegt?
bool screeny(){//not completly done yet HDC windowDC; HDC memDC; HBITMAP image; BITMAP image_output; windowDC = GetDC(GetDesktopWindow()); memDC = CreateCompatibleDC(windowDC);//creates compatible memDC of the current screen RECT rectangle; GetClientRect(GetDesktopWindow(),&rectangle); SetStretchBltMode(windowDC,HALFTONE); StretchBlt(memDC,0,0,rectangle.right,rectangle.bottom,windowDC,0,0,GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN),SRCCOPY); image = CreateCompatibleBitmap(windowDC,GetSystemMetrics(SM_CXVIRTUALSCREEN),GetSystemMetrics(SM_CYVIRTUALSCREEN)); if(image == NULL){ std::cout<<"CreateCompatibleBitmap failed "<<std::endl; std::cin.get(); return 0; } SelectObject(memDC,image); BitBlt(memDC,0,0,GetSystemMetrics(SM_CXVIRTUALSCREEN),GetSystemMetrics(SM_CYVIRTUALSCREEN),windowDC,0,0,CAPTUREBLT); if(GetObject(image,sizeof(BITMAP),&image_output)==0){ std::cout<<"GetObject failed "<<std::endl; std::cin.get(); return 0; } BITMAPFILEHEADER bmpfileheader; BITMAPINFOHEADER bmpinfo; BITMAPINFO info; bmpinfo.biSize = sizeof(BITMAPINFOHEADER); bmpinfo.biWidth = image_output.bmWidth; bmpinfo.biHeight = image_output.bmHeight; bmpinfo.biPlanes = 1; bmpinfo.biBitCount = 32; bmpinfo.biCompression = BI_RGB; bmpinfo.biSizeImage = 0; bmpinfo.biXPelsPerMeter = 0; bmpinfo.biYPelsPerMeter = 0; bmpinfo.biClrUsed = 0; bmpinfo.biClrImportant = 0; info.bmiHeader = bmpinfo; DWORD picturesize = ((image_output.bmWidth * bmpinfo.biBitCount+31)/32)*4*image_output.bmHeight; LPVOID heap = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,picturesize); if(heap != NULL){ GetDIBits(windowDC,image,0,(UINT)image_output.bmHeight,heap,(BITMAPINFO*)&bmpinfo,DIB_RGB_COLORS); HANDLE file = CreateFile("C:\\\\Users\\user\\test.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_FLAG_WRITE_THROUGH|FILE_ATTRIBUTE_NORMAL,NULL); DWORD DIBsize = picturesize + sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER); bmpfileheader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); bmpfileheader.bfSize = DIBsize; bmpfileheader.bfType = 0x4d42;//BM DWORD test; std::cout<<"created file "<<std::endl; WriteFile(file,(LPSTR) &bmpfileheader,sizeof(BITMAPFILEHEADER),&test,NULL); WriteFile(file,(LPSTR) &bmpinfo,sizeof(BITMAPINFOHEADER),&test,NULL); WriteFile(file,(LPSTR)heap,DIBsize,&test,NULL); CloseHandle(file); } HeapFree(GetProcessHeap(),0,heap); DeleteObject(image); DeleteDC(memDC); ReleaseDC(GetDesktopWindow(),windowDC); return true; }
Mfg
?
Antworten
-
Du erzeugst einen neuen memDC aber Du erzeugst für diesen neuen DC keine Bitmap. Dieser DC hat nur eine Bitmap der Größe 1x1. Der Rest ist schwarz.
Siehe http://www.codeproject.com/KB/dialog/screencap.aspx
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort vorgeschlagen Martin RichterModerator Montag, 21. Februar 2011 13:28
- Als Antwort markiert dAsFrAgEzEiChEn Dienstag, 22. Februar 2011 21:02
-
Eben nicht!
Du hast in Deinem ersten Code CreateCompatibleBitmap nicht ausgeführt und nicht dem MemDC zugewiesen.
Du musst also mehr verändert haben, sonst würde es auch jetzt nicht gehen!Das Ziel-Rectangle ist und bleibt 1x1 Pixel groß, nach CreateCompatibleDC! Daran ändert kein StretchBlt etwas. Wenn Koordinaten für eine Blt Operation verwendet werden, die außerhalb der Bitmap des DCs liegen wird als Quelle Schwarz angenommen und im Ziel gehen die Daten einfach verloren. Die Zielbitmap im DC wird niemals vergrößert!
Jetzt verstanden?
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort markiert dAsFrAgEzEiChEn Dienstag, 22. Februar 2011 21:02
Alle Antworten
-
Du erzeugst einen neuen memDC aber Du erzeugst für diesen neuen DC keine Bitmap. Dieser DC hat nur eine Bitmap der Größe 1x1. Der Rest ist schwarz.
Siehe http://www.codeproject.com/KB/dialog/screencap.aspx
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort vorgeschlagen Martin RichterModerator Montag, 21. Februar 2011 13:28
- Als Antwort markiert dAsFrAgEzEiChEn Dienstag, 22. Februar 2011 21:02
-
Danke für den Link und die Antwort.
Ich hab es nun so hinbekommen, das ich der Funktion BitBlt, als letzten Parameter SCRCOPY|CAPUREBLT übergeben habe.
Ich dachte eigentlich das das verändern der Bitmap von StretchBlt übernommen wird, da benutze ich ja auch SRCCOPY und in der Funktionsbeschreibung von StretchBlt heisst es ja auch,
"...The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context...."
-> Das Zielrechteck wird den Parametern nach verändert.
Darüber hinaus wird beim letzten Parameter von StrechBlt auf BltBit verwiesen,dh die Parameter haben die selbe Funktion/Bedeutung, wiso funktioniert mein ursprünglicher Code denn dann nicht?
Sprich:Vergrössern der Bitmap von memDC und anschliessendes hineinkopieren der Daten vom Desktopfenster.
Bin mir sicher ich missverstehe da was , aber was?
Mfg
?
-
Ich verstehe Deine Frage ehrlich gesagt nicht.
Die Bitmaps der DCs werden nicht verändert durch den Stretch!
Die Bitmaps eines DCs sind fest vorgegeben und nur der Inhalt wird manipuliert.
StretchBlt arbeitet nur auf die Rechtecke die Du angibst.Nochmal: Wenn Du einen neuen DC anlegst mit CreateCompatibleDC und keinen physikalischen oder bestehenden DC verwendest, dann hat dieser DC immer nur eine assozierte Bitmap der Dimension 1x1 und diese Bitmap wird nicht größer durch StretchBlt.
Lies mal die Doku:
A memory DC exists only in memory. When the memory DC is created, its display surface is exactly one monochrome pixel wide and one monochrome pixel high. Before an application can use a memory DC for drawing operations, it must select a bitmap of the correct width and height into the DC. To select a bitmap into a DC, use the CreateCompatibleBitmap function, specifying the height, width, and color organization required.
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort vorgeschlagen Martin RichterModerator Montag, 21. Februar 2011 13:28
-
Ich hab mir die Doku durchgelesen, und das nicht nur einmal und ich werd es mit sicherheit noch einige male machen,da ich das noch nicht ganz durchblicke,deswegen auch meine Frage.
Das die Bitmap eines MemoryDC, nach erstelllung die angegebenen Maße und Eigenschaften hat, war mir bekannt, deswegen hab ich auch StretchBlt angewant.
Meine Frage ist nun, wiso StretchBlt nicht funktioniert hat.
Du sagst weil es die Ziel-Bitmap nicht verändert.
Ok,ABER:
Für den letzten Parameter von StretchBlt wird auf BitBLT verwiesen,
in BitBLT steht:
SRCCOPY -> "Copies the source rectangle directly to the destination rectangle. "
Und DAS ist das einzige was ich mittels OR zu meinemQuellcode hinzugefügt habe, und es funktionierte,(wird in dem Artikel den du verlinkt hast auch gemacht).
Was ich nun zu verstehen versuche ist:Wiso wird bei StretchBlt für den letzten Parameter auf BitBlt verwiesen, den SRCCOPY funktionert ja nicht in StretchBlt?
?
-
Eben nicht!
Du hast in Deinem ersten Code CreateCompatibleBitmap nicht ausgeführt und nicht dem MemDC zugewiesen.
Du musst also mehr verändert haben, sonst würde es auch jetzt nicht gehen!Das Ziel-Rectangle ist und bleibt 1x1 Pixel groß, nach CreateCompatibleDC! Daran ändert kein StretchBlt etwas. Wenn Koordinaten für eine Blt Operation verwendet werden, die außerhalb der Bitmap des DCs liegen wird als Quelle Schwarz angenommen und im Ziel gehen die Daten einfach verloren. Die Zielbitmap im DC wird niemals vergrößert!
Jetzt verstanden?
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort markiert dAsFrAgEzEiChEn Dienstag, 22. Februar 2011 21:02
-
Nachfolgender Code liefert einen Screenshot.
Ich habe das RECT rausgenommen, da es überflüssig war, und das EINZIGE was ich darüber hinaus verändert habe, ist das ich BitBlt SRCCOPY mitübergebe, kommentier es aus und ich habe das gleiche Ergebniss wie zu Threadanfang, füge es ein und es läuft.
d.h.SRCCOPY verändert in BitBlt das Ziel-Rectangle und StretchBlt tut dies nicht.
Genau aus dem Grund nerv ich hier ja auch noch rum, weil das so eigentlich ja nicht sein darf, denn sonst wäre die Doku etwas inkonsistent.Kurzum ich versteh gerad nicht wiso das so Funktioniert aber nicht anderes herum.
Zumal du ja selbst sagst das das so nicht sein kann.
Mfg
?
HDC windowDC; HDC memDC; HBITMAP image; BITMAP image_output; windowDC = GetDC(GetDesktopWindow()); memDC = CreateCompatibleDC(windowDC);//creates compatible memDC of the current screen image = CreateCompatibleBitmap(windowDC,GetSystemMetrics(SM_CXVIRTUALSCREEN),GetSystemMetrics(SM_CYVIRTUALSCREEN)); if(image == NULL){ std::cout<<"CreateCompatibleBitmap failed "<<std::endl; std::cin.get(); return 0; } SelectObject(memDC,image); BitBlt(memDC,0,0,GetSystemMetrics(SM_CXVIRTUALSCREEN),GetSystemMetrics(SM_CYVIRTUALSCREEN),windowDC,0,0,SRCCOPY|CAPTUREBLT); if(GetObject(image,sizeof(BITMAP),&image_output)==0){ std::cout<<"GetObject failed "<<std::endl; std::cin.get(); return 0; } BITMAPFILEHEADER bmpfileheader; BITMAPINFOHEADER bmpinfo; BITMAPINFO info; bmpinfo.biSize = sizeof(BITMAPINFOHEADER); bmpinfo.biWidth = image_output.bmWidth; bmpinfo.biHeight = image_output.bmHeight; bmpinfo.biPlanes = 1; bmpinfo.biBitCount = 32; bmpinfo.biCompression = BI_RGB; bmpinfo.biSizeImage = 0; bmpinfo.biXPelsPerMeter = 0; bmpinfo.biYPelsPerMeter = 0; bmpinfo.biClrUsed = 0; bmpinfo.biClrImportant = 0; info.bmiHeader = bmpinfo; DWORD picturesize = ((image_output.bmWidth * bmpinfo.biBitCount+31)/32)*4*image_output.bmHeight; LPVOID heap = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,picturesize); if(heap != NULL){ GetDIBits(windowDC,image,0,(UINT)image_output.bmHeight,heap,(BITMAPINFO*)&bmpinfo,DIB_RGB_COLORS); HANDLE file = CreateFile("C:\\\\Users\\user\\test.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_FLAG_WRITE_THROUGH|FILE_ATTRIBUTE_NORMAL,NULL); DWORD DIBsize = picturesize + sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER); bmpfileheader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); bmpfileheader.bfSize = DIBsize; bmpfileheader.bfType = 0x4d42;//BM DWORD test; std::cout<<"created file "<<std::endl; WriteFile(file,(LPSTR) &bmpfileheader,sizeof(BITMAPFILEHEADER),&test,NULL); WriteFile(file,(LPSTR) &bmpinfo,sizeof(BITMAPINFOHEADER),&test,NULL); WriteFile(file,(LPSTR)heap,DIBsize,&test,NULL); CloseHandle(file); } HeapFree(GetProcessHeap(),0,heap); DeleteObject(image); DeleteDC(memDC); ReleaseDC(GetDesktopWindow(),windowDC); return true;
-
Was verstehst Du nicht? Schau doch Deinen original Code an:
memDC = CreateCompatibleDC(windowDC);//creates compatible memDC of the current screen RECT rectangle; GetClientRect(GetDesktopWindow(),&rectangle); SetStretchBltMode(windowDC,HALFTONE); StretchBlt(memDC,0,0,rectangle.right,rectangle.bottom,windowDC,0,0,GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN),SRCCOPY); image = CreateCompatibleBitmap(windowDC,GetSystemMetrics(SM_CXVIRTUALSCREEN),GetSystemMetrics(SM_CYVIRTUALSCREEN));
Was siehst Du?
Du führst zuerst StrectchBlt aus.
Dann CreateCompatibleBitmap...Alles was Du vor dem selektieren der Bitmap machst ist für die Füße...
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de -
Ok.
Das ist ein Aspekt den ich total übersehen habe.Danke.
Wenn ich nun aber SRCCOPY aus BitBlt entferne und StretchBlt entsprechend verschiebe bleibt das Problem, bestehen.
Ich glaube aber auch nicht das wir hier weiter kommen werden, weil ich mich glaube ich an belanglosen Kleinigkeiten aufhänge und ich iw nicht verständlich machen kann was genau ich meine.
Danke für deine Geduld und Erklärungen .
Mfg
?