SetViewportExt mit CMemDC verheiraten geht nicht
-
Ich nutze die Klasse CMemDC (double buffering) als dc Ersatz. Nun möchte ich hineinzeichenen, allerdings mit einem anderen Koordinatensystem. Grund ist das ich Daten aus einem Array plotten möchte das nicht die Größe des Windows hat.
Das sollte mit SetViewportExt zu machen sein. Also habe ich in CMemDC die Zeilen
(CMemDC: http://www.codeproject.com/gdi/flickerfree.asp)SetMapMode(pDC->GetMapMode()); SetWindowExt(pDC->GetWindowExt()); SetViewportExt(pDC->GetViewportExt());zu
SetMapMode(MM_ANISOTROPIC); SetWindowExt(CSize(m_rect_dest.Width(), m_rect_dest.Height())); SetViewportExt(CSize(m_rect_source.Width(), m_rect_source.Height()));m_rect_source gibt die Größe der Datenquelle und m_rect_dest die Größe des Windows an.
Das ganze funktioniert auch, die Daten werden skaliert, ABER
bei Ausgeben der Daten wird nur die Größe von m_rect_source ausgegeben, bzw. konkret:Wenn das Window die Größe 100x100 hat die Daten aber nur 50x50 dann werden diese auf 100x100 hochskaliert, davon aber nur 50x50 ausgegeben. Wenn die Daten eine Größe von 300x300 haben dann werden auch diese auf 100x100 skaliert, aber nur der Bereich 33x33 ausgegeben, also immer nur der Teiler.
Ich bin total ratlos was da falsch läuft und bitte um Hilfe.
Matthias
-
Dann musst Du Dein eigenes Double Buffering machen. Mit einer Klasse wie CMemDC wird es nicht gehen, weill es aleine schon Rundungsprobleme zu den entsprechenden Koordinaten gibt.
http://support.microsoft.com/default.aspx?scid=kb;en-us;89215Zudem, wen Du sowieso schon Auschnittweise zeichnest dürfte es wohl auch möglich sein ohne double buffering auszukommen, oder selber eines zu implementieren.
-
Martin Richter schrieb:
Dann musst Du Dein eigenes Double Buffering machen.
Warum? CMemDC macht das ganze für mich ja. Wenn ich es selber machen würde könnte ich doch auch nur den Code kopieren und ohne die Kapselung in der Klasse verwenden.
Martin Richter schrieb:
Mit einer Klasse wie CMemDC wird es nicht gehen, weill es aleine schon Rundungsprobleme zu den entsprechenden Koordinaten gibt.
Das ist mir klar und im Prinzip auch egal.
Martin Richter schrieb:
Zudem, wen Du sowieso schon Auschnittweise zeichnest dürfte es wohl auch möglich sein ohne double buffering auszukommen, oder selber eines zu implementieren.
Ich benutze es weil ich kein Flackern haben möchte und das funktioniert ja auch sehr gut.
Was ich nicht verstehe ist warum du sagst, dass es prinzipiell nicht gehen könnte (zumindest habe ich dich so verstanden) und desweiteren nicht sehe warum es so wie ich es probiert habe nicht funktioniert.
Matthias
-
CMemDC arbeitet eben nur korrekt auf MM_TEXT!
Ichhabe nicht gesagt, dass es nicht prinzipiell geht. Du musst nur eine andere Klasse schreiben (oder es eben so machen), die die Koordinaten Umrechnung für Dich tätigt.
Das runden kann Dir nicht egal sein, denn es wird zu Brüchen/Stufen in der Ausgabe kommen!
-
Martin Richter schrieb:
CMemDC arbeitet eben nur korrekt auf MM_TEXT!
Ichhabe nicht gesagt, dass es nicht prinzipiell geht. Du musst nur eine andere Klasse schreiben (oder es eben so machen), die die Koordinaten Umrechnung für Dich tätigt.
Ich verändere die Klasse ja auch, schreibe also quasi meine eigene. Ich habe folgendes geändert
//SetMapMode(pDC->GetMapMode()); SetMapMode(MM_ANISOTROPIC);Martin Richter schrieb:
Das runden kann Dir nicht egal sein, denn es wird zu Brüchen/Stufen in der Ausgabe kommen!
Die Ausgabe benötige ich für eine Vorschau und da ist es mir im Moment nur wichtig keine vollkommen unsinnigen Ausgaben zu haben.
Matthias
-
Da umsetzen des Mapping modes langt nicht. Dazu IMHO ist mehr nötig! Die Korrdinaten Bereiche für LP und DP müssen angepasst werden, wie es im originalen DC eben auch ist.
Du musst aufpassen, das die Koordinaten eben nicht zweimal transformiert werden...
-
Martin Richter schrieb:
Da umsetzen des Mapping modes langt nicht. Dazu IMHO ist mehr nötig! Die Korrdinaten Bereiche für LP und DP müssen angepasst werden, wie es im originalen DC eben auch ist.
Du musst aufpassen, das die Koordinaten eben nicht zweimal transformiert werden...
Im originäre DC verändere ich gar nichts, da sollten also keine Transformationen ein Problem darstellen.
Der Code komplette Code von CMemDC ist unten gezeigt.
Hochskalieren funktioniert damit, nur runterskalieren bringt Unsinn.Wenn die Daten die Größe 300x300, das Fenster die Größe 100x100 hat, dann werden auf dem Bildschirm nur 33x33 Pixel angezeigt, also der Teiler Windowgröße/Datengröße - was mir vollkommen unerklärlich ist.
class CMemDC : public CDC { private: CBitmap m_bitmap; // Offscreen bitmap CBitmap* m_oldBitmap; // bitmap originally found in CMemDC CDC* m_pDC; // Saves CDC passed in constructor CRect m_rect_dest; // Rectangle of drawing area. CRect m_rect_source; // Rectangle of source area. BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. public: CMemDC(CDC* pDC, const CRect* pSourceRect = NULL, const CRect* pDestRect = NULL) : CDC() { ASSERT(pDC != NULL); // Some initialization m_pDC = pDC; m_oldBitmap = NULL; m_bMemDC = !pDC->IsPrinting(); // Get the rectangle to draw if (pDestRect == NULL) { pDC->GetClipBox(&m_rect_dest); } else { m_rect_dest = *pDestRect; } // Get the rectangle to draw if (pSourceRect == NULL) { pDC->GetClipBox(&m_rect_source); } else { m_rect_source = *pSourceRect; } if (m_bMemDC) { // Create a Memory DC CreateCompatibleDC(pDC); pDC->LPtoDP(&m_rect_dest); m_bitmap.CreateCompatibleBitmap(pDC, m_rect_dest.Width(), m_rect_dest.Height()); m_oldBitmap = SelectObject(&m_bitmap); //SetMapMode(pDC->GetMapMode()); pDC->SetMapMode(MM_ANISOTROPIC); //SetWindowExt(pDC->GetWindowExt()); pDC->SetWindowExt(m_rect_source.Width(), m_rect_source.Height()); //SetViewportExt(pDC->GetViewportExt()); pDC->SetViewportExt(m_rect_dest.Width(), m_rect_dest.Height()); pDC->DPtoLP(&m_rect_dest); SetWindowOrg(m_rect_dest.left, m_rect_dest.top); } else { // Make a copy of the relevent parts of the current DC for printing m_bPrinting = pDC->m_bPrinting; m_hDC = pDC->m_hDC; m_hAttribDC = pDC->m_hAttribDC; } // Fill background FillSolidRect(m_rect_dest, pDC->GetBkColor()); } ~CMemDC() { if (m_bMemDC) { //m_pDC->StretchBlt( // m_rect_dest.left, // x-coord of destination upper-left corner // m_rect_dest.top, // y-coord of destination upper-left corner // m_rect_dest.Width(), // width of destination rectangle // m_rect_dest.Height(), // height of destination rectangle // this, // handle to source DC // 0, // x-coord of source upper-left corner // 0, // y-coord of source upper-left corner // m_rect_source.Width(), // width of source rectangle // m_rect_source.Height(), // height of source rectangle // SRCCOPY); m_pDC->BitBlt( m_rect_dest.left, // x-coord of destination upper-left corner m_rect_dest.top, // y-coord of destination upper-left corner m_rect_dest.Width(), // width of destination rectangle m_rect_dest.Height(), // height of destination rectangle this, m_rect_dest.left, // x-coord of destination upper-left corner m_rect_dest.top, // y-coord of destination upper-left corner SRCCOPY); //Swap back the original bitmap. SelectObject(m_oldBitmap); } else { // All we need to do is replace the DC with an illegal value, // this keeps us from accidently deleting the handles associated with // the CDC that was passed to the constructor. m_hDC = m_hAttribDC = NULL; } } // Allow usage as a pointer CMemDC* operator->() { return this; } // Allow usage as a pointer operator CMemDC*() { return this; } };Damit habe ich das gleiche Problem wie zuvor mit der Lösung mit StrechBlt.
Matthias