Problem mit Regions und BitBlt
-
??
dein code macht das:CPaintDC dc(this); CRect copyRect; CBitmap bmp, *pOldBmp; GetClientRect(©Rect); HDC memDC = CreateCompatibleDC(dc); // memDC ist jetzt ein DC mit den gleichen attributen wie dc bmp.CreateCompatibleBitmap(&dc,copyRect.Width(),copyRect.Height()); // bmp ist ne leere bitmap mit dem selben attributen wie selektierte in dc pOldBmp = memDC.SelectObject(&bmp); // du hast die leere bitmap (schwarz) in den memDC selektiert // du kopierst jetzt die den memDC (schwarz) in den paint-dc dc.BitBlt(0,0,copyRect.Width(),copyRect.Height(),&memDC,0,0,SRCCOPY);
klar dass da was schwarzes raus kommt
-
Kannst du mir denn nen Hinweis geben, wie ich das beheben könnte?
Ich dachte zuerst an SetBkColor aber das geht nicht.
Übersehe ich da irgendwas?
Bin echt verzweifelt und deprimiert, dass ich das nicht hinbekomme.Danke übrigens für deine Hilfe.
-
Wie ich das verstehe ist die Bitmap schuld, oder?
Dann schaue ich da nochmal.
-
Kannst du mir denn nen Hinweis geben, wie ich das beheben könnte?
dazu müsste ich erst mal kapieren was genau du vor hast...
zeig mal bitte deinen ganzen code. wo, wie zeichnest du die diagramme?
-
Ok, im Grunde übernehme ich Daten über die RS-232-Schnittstelle, welche ich dann grafisch darstellen möchte.
Da es dann aber ziemlich flackert, will ich das Doublebuffering nutzen, was ich ja mit CreateCompatibleDC & Co realisiere.Mein Code (zeichne hier nur in die erste Region, Diagram im eigentlichen Sinn noch nicht fertig [Achsen, Beschriftung <- ist aber auch unwichtig]):
CPaintDC dc(this); CRect copyRect; GetClientRect(©Rect); HDC memDC = CreateCompatibleDC(dc); HBITMAP bmp = CreateCompatibleBitmap(dc,copyRect.Width(),copyRect.Height()); SelectObject(memDC,bmp); //Erstelle mit Gdiplus regions Gdiplus::Graphics gdi(memDC); static Gdiplus::Point coords1[500]; static Gdiplus::Point coords2[500]; Gdiplus::Rect speedRect(200,75,400,300); Gdiplus::Rect currentRect(605,75,400,300); Gdiplus::Region gdiSpeed(speedRect); Gdiplus::Region gdiCurrent(currentRect); Gdiplus::Pen plotPen(Gdiplus::Color(255,0,170,0)); Gdiplus::SolidBrush regionBrush(Gdiplus::Color(255,255,255,255)); Gdiplus::Status status; // nur zum Überprüfen status = gdi.FillRegion(®ionBrush, &gdiSpeed); status = gdi.FillRegion(®ionBrush, &gdiCurrent); gdi.SetClip(&gdiSpeed, Gdiplus::CombineModeReplace); // zeichne erst in die erste region if (timercounter == 0) // wird im timer inkrementiert { coords1[timercounter].X = 0; coords1[timercounter].Y = 220; coords2[timercounter].X = 0; coords2[timercounter].Y = 220; } else { coords1[timercounter].X = timercounter; coords1[timercounter].Y = Data*2; //Data enthält die empfangenen Daten coords2[timercounter].X = coords1[timercounter-1].X; coords2[timercounter].Y = coords1[timercounter-1].Y; } for (int i = 0; i <= timercounter;i++) { gdi.DrawLine(&plotPen,coords2[i].X+205,coords2[i].Y+80,coords1[i].X +205,coords1[i].Y+80); } BitBlt(dc,0,0,copyRect.Width(),copyRect.Height(),memDC,0,0,SRCCOPY); CDialog::OnPaint();
Danke, für die Mühe.
-
hmmm.. funktioniert bestens bei mir (bis auf das problem das nach ~500 durchläufen gar nix mehr passiert weil ein DeleteObject(bmp) und DeleteDC (memDC) fehlt => resource fertig
)
-
Und es ist bei dir nicht schwarz???
Die DeleteDC und DeleteObject - Methoden habe ich mittlerweile hinzugefügt.
Vielleicht sollte ich mal versuchen, alles zu rebuilden.
-
Also, ich habe nun alles rebuilded, habe auch die Dateien aus dem Debug-Ordner gelöscht, dann noch mal aufbauen lasse, aber es hilft nichts.
Kann das vielleicht damit zusammenhängen, dass ich diesen Dialog aus einem anderen Dialog öffne? Wüsste zwar nicht warum, aber villeicht wäre das ein Unterschied zu dir.
-
Falls du es mit meinem code testen willst (sorry ist WinAPI keine MFC, aber um schnell was zu testen baue ich immer nur ne WinMain..
):
#include <windows.h> #include <gdiplus.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; memset(&wcex,0,sizeof(WNDCLASSEX)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)COLOR_BACKGROUND; wcex.lpszMenuName = NULL; wcex.lpszClassName = "test"; RegisterClassEx(&wcex); Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, 0); HWND hWnd = CreateWindow("test", "test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); SetTimer(hWnd,0,100,0); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } static int timercounter = 0; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_TIMER: timercounter++; if(timercounter>=500) timercounter = 0; InvalidateRect(hWnd,NULL,FALSE); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); { // dein code (auf WinAPI umgebaut) RECT copyRect; GetClientRect(hWnd,©Rect); long width = copyRect.right - copyRect.left; long height = copyRect.bottom - copyRect.top; HDC memDC = CreateCompatibleDC(hdc); HBITMAP bmp = CreateCompatibleBitmap(hdc,width,height); HBITMAP oldBmp = (HBITMAP)SelectObject(memDC,bmp); Gdiplus::Graphics gdi(memDC); static Gdiplus::Point coords1[500]; static Gdiplus::Point coords2[500]; Gdiplus::Rect speedRect(200,75,400,300); Gdiplus::Rect currentRect(605,75,400,300); Gdiplus::Region gdiSpeed(speedRect); Gdiplus::Region gdiCurrent(currentRect); Gdiplus::Pen plotPen(Gdiplus::Color(255,0,170,0)); Gdiplus::SolidBrush regionBrush(Gdiplus::Color(255,255,255,255)); Gdiplus::Status status; status = gdi.FillRegion(®ionBrush, &gdiSpeed); status = gdi.FillRegion(®ionBrush, &gdiCurrent); gdi.SetClip(&gdiSpeed, Gdiplus::CombineModeReplace); if (timercounter == 0) { coords1[timercounter].X = 0; coords1[timercounter].Y = 220; coords2[timercounter].X = 0; coords2[timercounter].Y = 220; } else { coords1[timercounter].X = timercounter; coords1[timercounter].Y = 100*2; //Data enthält die empfangenen Daten coords2[timercounter].X = coords1[timercounter-1].X; coords2[timercounter].Y = coords1[timercounter-1].Y; } for (int i = 0; i <= timercounter;i++) { gdi.DrawLine(&plotPen,coords2[i].X+205,coords2[i].Y+80,coords1[i].X +205,coords1[i].Y+80); } BitBlt(hdc,0,0,width,height,memDC,0,0,SRCCOPY); SelectObject(memDC,oldBmp); DeleteObject(bmp); DeleteDC(memDC); } EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
zeichnet ne schöne linie
-
Guten Morgen,
danke für den Quellcode. Ich habe den sofort mal ausprobiert. Er zeichnet auch eine schöne Linie in einem weissen Rechteck, jedoch ist der Hintergrund bei mir immer noch schwarz!?!Also, so sieht es aus (kann leider keine Screenshots hochladen):
* = schwarz
| = weiss (ausser an den Rändern)-----------------------------------------------------------------------------------
||
|diese Fläche ist schwarz|
|***** -----------------------******** -------------------------------|
|| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
||||diese ist weiss|||||diese ist auch weiss||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||hier wird|||||||||||||||||||||||||||||||||||||||||||
||||||gezeichnet!||||||||||||||||||||||||||||||||||||
|***** ---------------------- ******** ------------------------------- |
|**********************************************|
-----------------------------------------------------------------------------------.....
Für nen Augenblick dachte ich, es liegt an COLOR_BACKGROUND, denn in der MSDN stehtCOLOR_BACKGROUND
DesktopUND dann habe ich einfach mal bei mir unter Anzeigeneinstellung geschaut und da ist eingestellt, dass der Desktop die Farbe Schwarz zugewiesen hat. (Ich weiss, ist eigentlich eine saublöde Idee, aber wenn man verzweifelt ist...
) Eine Änderung brachte auch nichts.
Aber es scheint an irgendeiner Einstellung zu liegen, denn sonst würden wir ja auf jeden Fall das Gleiche sehen müssen.
-
Ist dosch klar das der hintergrund schwarz ist, wie gesagt die bitmap ist leer und du zeichnerst da ja nur dein diagramm rein.
Wenn du den hintergrund vom orgrinal fenster haben willst mache ein
BitBlt(memDC,0,0,width,height,hdc,0,0,SRCCOPY);
nach dem
HBITMAP oldBmp = (HBITMAP)SelectObject(memDC,bmp);
-
So langsam sehe ich meinen Fehler.
Also,
1.zuerst erstelle ich ein BITMAP, das ist aber leer
2.dann sollte ich das originale Fenster (DC) dort hinein kopieren, damit es auch dieselbe Hintergrundfarbe besitzt
3.dann zeichne ich da hinein, um
4.letztendlich alles wieder in das original Fenster hinein zu kopieren. ;
Bei deiner Anwendung klappt es auch. Bei meiner kriege ich das richtige DC nicht?!?
CPaintDC dc(this); CRect copyRect; GetClientRect(©Rect); HDC memDC = CreateCompatibleDC(dc); HBITMAP bmp = CreateCompatibleBitmap(dc,copyRect.Width(),copyRect.Height()); HBITMAP oldBmp = (HBITMAP)SelectObject(memDC,bmp); BitBlt(memDC,0,0,copyRect.Width(),copyRect.Height(),dc,0,0,SRCCOPY);
Wenn ich nur dc da übergebe ist immer noch alles schwarz?
Vielleicht noch ein kleiner Hinweis?
Danke.EDIT: Sehe gerade, dass ich was Falsches geschrieben habe: Wenn ich dc übergebe bleibt es nicht schwarz, sondern übernimmt die Farben,Fläche des darunterliegenden Fenster.
-
Ok, kann den Fehler vielleicht eingrenzen:
Und zwar gebe ich in der Behandlung der Nachricht WM_ERASEBKGND normalerweise einfach einTRUE
zurück.
Ändere ich das wieder aufreturn CDialog::OnEraseBkgnd(pDC);
um, dann ist auch der Hintergrund wieder grau!
Leider geht die Performance ziemlich in den Keller!