Bunte Kästchen, wie in den Defrag-Tools
-
Hi!
Ich muss mit VS2019 in MFC einen Dialog bauen, der ein 8x15 Feld mit quadratischen Kästchen darstellen soll. Diese soll man zur Laufzeit in den Farben grün, schwarz und gelb einfärben können. Also quasi so wie diese bunten Blockanzeigen in so gut wie allen Defragmentierungs Tools unter Windows. In der Toolbox von VS habe ich spontan keine Funktion gefunden und ich weiß tatsächlich auch nicht, unter welchen Begriffen ich im Internet nach einer Antwort suchen soll.
Ist so etwas überhaupt mit relativ geringem Aufwand in MFC zu realisieren?
Vielen lieben Dank für eure Hinweise!
-
Vorsicht, zusammengegoogeltes Halbwissen:
Bau dir eine Matrix aus 8x15 quadratischen CStatic Elementen und gib ihnen jeweils eine eigene ID. Anschließend überschreibst du die
OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
Methode deines Fensters. Der ParameternCtlColor
enthält die ID des Steuerelements, das gerade behandelt wird. Wenn es einer deiner CStatic IDs ist kannst du dempDC->SetDbColor()
eine Farbe zuweisen. Du musst dir halt nur irgendwo merken, welche CStatic welche Farbe haben soll.
-
@DocShoe :
Halbwissen trifft es sehr gut! Ich finde MFC ja gruselig...Gibt es irgendwo Material zu "Bau dir eine Matrix aus 8x15 quadratischen CStatic Elementen"?
-
Sag mir jetzt bitte nicht, dass du damit überfordert bist, Elemente aus einer Toolbar auf ein Formular zu ziehen
Komfortabler isses natürlich, im Initialisierungsschritt des Fensters in zwei Schleifen die CStatic Boxen zu erzeugen und die passenden Eigenschaften zu setzen. Aber das ist wirklich trivial, wenn du dabei schon Probleme hast solltest du zuerst in die Doku gucken.
-
Achsoooooo, das meinst du mit "Matrix erstellen". Mit der Maus Dinge aus der Toolbox ziehen bekomme ich hin.
Leider ist alles etwas komplizierter geworden.
Statt bunten Kästchen müssen es jetzt 120 PNG-Grafiken (in fünf Varianten) mit Alphakanal sein, die dann zur Laufzeit ausgetauscht werden.Jetzt darf ich mich auch noch mit CImage, CBitmap usw. beschäftigen.
-
Habe es jetzt so gelöst:
OnInitDialog(){ [...] VERIFY(m_image_black.Load(IDB_PNG_BLACK)); unsigned short offsetX = 10; unsigned short offsetY = 10; unsigned short gapX = 3; unsigned short gapY = 3; unsigned short imageWidth = 23; unsigned short imageHeight = 32; unsigned short topX = 0; unsigned short topY = 0; unsigned short bottomX = 0; unsigned short bottomY = 0; unsigned short count = 0; for (unsigned short y=0; y<15; y++) { for (unsigned short x=0; x<8; x++) { topX = offsetX + x * (imageWidth + gapX); topY = offsetY + y * (imageHeight + gapY); bottomX = topX + imageHeight; bottomY = topY + imageHeight; m_images[count] = new CStatic; m_images[count]->Create(_T("X"), SS_BITMAP | WS_VISIBLE | SS_REALSIZEIMAGE, CRect(topX, topY, bottomX, bottomY), this); m_images[count]->SetBitmap(m_image_black); count++; } } [...] }
Header:
[...] CPngImage m_image_black; CStatic* m_images[120]{}; [...]
Scheint zu funktionieren.
Frage mich nur, ob ich mir hierdurch nicht 120 Memory Leaks generiere und wenn ja, wie kann ich die verhindern? Habe mir einen Destructor mitfor (unsigned short i = 0; i < 120; i++) { if (m_images[i] != nullptr) { delete m_images[i]; } }
gebaut. Aber ich frage mich, ob dies eine "saubere" Lösung ist.
-
@ikarsian
Ja, das kann man so machen und es entsteht kein Speicherleck. Falls dein Compiler C+11 oder später unterstützt solltest du dich mit smart pointern wie std: :unique_ptr oder std: :shared_ptr befassen. Und mit den Containerklassen der STL.
-
Oh, stimmt. Die gibt es ja auch noch - da habe ich tasächlich gar nicht dran gedacht. War erst einmal froh, dass alles funktioniert. Habe sogar C++17 zur Verfügung.
@DocShoe sagte in Bunte Kästchen, wie in den Defrag-Tools:
unique_ptr
-
Ich halte es eigentlich für keine gute Idee, für jedes Kästchen ein eigenes PNG zu generieren.
Nehmen wir mal eine definierte Menge z.B. 3 verschiedene Farben an.Macht es da nicht mehr Sinn, genau diese 3 PNG's bei der Initialisierung zu erzeugen und an entsprechender Stelle anzuzeigen? - Man kann ja gut und gerne eine Grafik mehrfach auf den Bildschirm ausgeben.