OnPaint mit vielen Daten
-
Hallo Leute,
ich bin gerade dabei mir ein Diagramm zu Kritzeln.
Dazu verwende ich eine eigene Class in der Ich in OnPaint ein eine Rahmen zeichne und die dazugehörigen Linien usw.Jetz wollte ich mir einen Vector füllen der Werte für meine Kurve hat.
Den Vector wollte ich dann in OnPaint über eine Schleiffe Zeichenen lassen.
Wird der Vector groß, > 100 dann wird der Aufbau ziemlich zäh.Wie kann ich da vorgehen ?
Ich brauche eigentlich nur einen einmaligen Aufruf zum Zeichenen der Grundlineien. Wie macht man das ??Gruß und Danke
andy_mann
-
Zeichen deinen krahm am anfang in nen DC. Diese DC speicherst du in deiner klasse und beim OnPaint machst du dann nur mehr ein BitBlt vom einen DC in den anderen.
-
Hallo CMatt,
mmmhh... Du hast nicht ein kleines Beispiel wie Du das meinst ??
Danke
andy_mann
-
Hallo Leute,
kann mir keiner Helfen..
Ich blick das einfach nicht, wie ich ein Grundraster Zeichne, dass nicht dauern aktualisiert werden soll.Hat keiner ein kleines einfaches Beispiel ??
Gruß und Danke
andy_mann
-
Ich glaube, es ist ein MemoryDC gemeint - ich bin aber selber nicht so fit und weiß blos das, was so durch Mitlesen hängen bleibt.
-
http://www.codeproject.com/gdi/flickerfree.asp
Vorteile:
(a) Memory DC ist gern mal schneller
(b) Flicker-Frei
(c) Diagramm muß nur bei Änderungen neu erstellt werden
-
danke Dir...
aber wenn es eben dazu ein kleines beispiel geben tät wehre ich echt dankbar...
Gruß
andy_mann
-
mmmhhh ich danke Dir für das Beispiel....
aber irgendwie ist mir dieser Code etwas zu Kompliziert...Was ich vorhabe...
In einem Dialog möhte ich ein kleinen Bereich erstellen, was ein 2 Diminsionales Raster hat... einmal Anzahl, einmal Zeit.Darin möchte ich eine Kurve reinbringen was vorerst mittels Button aktualisiert wird.
Jetzt will ich aber das Raster Zeichnen seperat Zeichnen, wenn ich meine Kurve aktualisiere nicht jedes mal der Hintergrund miaktualisiert wird....
Gibts für so etwas ein Beispiel ??
Gruß
andy_mann
-
Hi, ich bin grad an nem ähnlichen Projekt, wo ich ne Messkurve von nem Oszilloskop zeichnen lass. Hab dort auch nen SpeicherDC verwendet, also hier dein Beispiel:
Pointer auf SpeicherDC als member der View-Klasse:
[cpp]... private: CDC* m_pSpeicherDC; ...[/cpp]
Der SpeicherDC wird in OnInitialUpdate() initialisiert:
[cpp]void COszi2View::OnInitialUpdate() { CView::OnInitialUpdate(); // Speicher-DC erstellen CDC *pViewDC = GetDC(); delete m_pSpeicherDC; m_pSpeicherDC = new CDC; m_pSpeicherDC->CreateCompatibleDC(NULL); // Farbaufloesung auslesen int nBitsPerPixel = pViewDC->GetDeviceCaps(BITSPIXEL); int nPlanes = pViewDC->GetDeviceCaps(PLANES); // DC des Views wird nun nicht mehr benoetigt ReleaseDC(pViewDC); CRect ClientRect; GetClientRect(&ClientRect); CBitmap ClientBmp; ClientBmp.CreateBitmap(ClientRect.right, ClientRect.bottom, nPlanes, nBitsPerPixel, NULL); m_pSpeicherDC->SelectObject(&ClientBmp); }[/cpp]
Bei einer Größenänderung des Views muss auch die Größe der Bitmap geändert werden, deswegen in die OnSize():
[cpp]void COszi2View::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // Falls noch kein Speicher-DC vorhanden, fertig // (OnInitialUpdate(...) wurde noch nicht ausgefuehrt) if(m_pSpeicherDC == NULL) return; // Farbaufloesung auslesen CDC* pViewDC = GetDC(); int nBitsPerPixel = pViewDC->GetDeviceCaps(BITSPIXEL); int nPlanes = pViewDC->GetDeviceCaps(PLANES); ReleaseDC(pViewDC); // und entsprechende Bitmap erstellen CBitmap ClientBmp; ClientBmp.CreateBitmap(cx, cy, nPlanes, nBitsPerPixel, NULL); // Bitmap dem Speicher-DC zuweisen CBitmap *pOldBitmap = m_pSpeicherDC->SelectObject(&ClientBmp); // alte Bitmap loeschen pOldBitmap->DeleteObject(); }[/cpp]
Der reservierte Speicher des SpeicherDCs sollte am besten in der OnDestroy() wieder freigegeben werden:
[cpp]void COszi2View::OnDestroy() { CView::OnDestroy(); delete m_pSpeicherDC; }[/cpp]
Um das "flackern" zu beiseitigen, muss noch die OnEraseBkgnd überschrieben werden, der Hintergrund soll nämlich nicht gelöscht werden, das soll auch im SpeicherDC geschehen:
[cpp]BOOL COszi2View::OnEraseBkgnd(CDC* pDC) { //Nichts machen!!! return TRUE; }[/cpp]
Damit hast du alle Voraussetzungen für den SpeicherDC geschaffen, und kannst jetzt in der OnDraw() einfach in den Speicher zeichnen, und am Ende auf den normalen DC blitten. Zuerst muss der SpeicherDC auf jeden Fall mit einem weißen Rechteck gefüllt werden, da ja das vorherige Bild nicht gelöscht wird! Z.B.:
[cpp]void COszi2View::OnDraw(CDC* pDC) { COszi2Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //Speicher-DC zuweisen und weißes Rechteck reinschreiben: CRect ClientRect; GetClientRect(&ClientRect); m_pSpeicherDC->FillSolidRect(&ClientRect,RGB(255,255,255)); //Und dann halt drauf los zeichnen. Z.B.: pOriginalPen = m_pSpeicherDC->SelectObject(&AchsenPen); m_pSpeicherDC->MoveTo(ZeitToW(0),Data1ToW(0)); m_pSpeicherDC->LineTo(ZeitToW(0),Data1ToW(pDaten->Data1max)); //... usw... //Am Ende noch das Blitten: m_pSpeicherDC->SelectObject(pOriginalPen); pDC->BitBlt(0,0,ClientRect.right,ClientRect.bottom,m_pSpeicherDC,0,0,SRCCOPY); }[/cpp]
Das ist natürlich nicht ganz das was du willst, da ich der Bitmap ja auch bei jedem Aufruf der OnDraw neu gezeichnet wird. (Ich hab den SpeicherDC nur der Schönheit wegen verwendet
Das kannst du ja aber leicht ändern, indem du den Code zum zeichnen nicht in die OnDraw schreibst, sondern an die Stellen, wo du die Kurve aktualisieren willst (z.B. in die OnSize und natürlich in die Funktion deinens Buttons der die Kurve aktualisiert.) In die OnDraw muss dann halt nur noch das Blitten.
Gruß Brainiac
-
Generelles zum Verfahren mit dem MemoryDC (Verfahren wird auch DoubleBuffer oder BackBuffer genannt) kannst du dir auch unter diesem LINK unter Beitrag 8 anschauen. Englisch wäre vorteilhaft, ist aber nicht unbedingt nötig.