Eigener Button - Frage zum Style/zur Funktion
-
Hi Leute,
ich habe mich hier im WinAPI-Forum mal ein bischen umgesehen und auch ein paar hilfreiche Beiträge zu Owner Draw Buttons gefunden.
Ich weiss jetzt nicht mehr, wo geneu er war, doch ich habe von einem Beitrag einen Lösungsvorschlag von jemandem übrnommen und etwas geändert.Kurze Info vorab. Es soll ein eigener Button erstellt werden, mit folgenden Zuständen:
Normaler Zustand: http://s14.directupload.net/images/131204/5g8vfcaq.jpg
Bei Mous-Over: http://s14.directupload.net/images/131204/x4vlbize.jpg
Beim Klick: http://s1.directupload.net/images/131204/voauclft.jpgDie Bilder sind ScreenShots beim Ausführen des Programms.
Hier der Code://Button-Status bool defstatus = (s_draw->itemState & ODS_DEFAULT); bool selstatus = (s_draw->itemState & ODS_SELECTED); bool focstatus = (s_draw->itemState & ODS_FOCUS); bool disabled = (s_draw->itemState & ODS_DISABLED); //Koordinaten RECT rect = s_draw->rcItem; HDC hDC = s_draw->hDC; Graphics grafik(hDC); //Bilder Image bild1(L"\\Code1.png"); Image bild2(L"\\Code2.png"); Image bild3(L"\\Code3.png"); PAINTSTRUCT ps; ps.fErase = false; ps.rcPaint = rect; ps.hdc = hDC; BeginPaint(hButton, &ps); { grafik.DrawImage(&bild1, 0, 0, 200, 100); if(defstatus == true) grafik.DrawImage(&bild1, 0, 0, 200, 100); else if(selstatus == true) grafik.DrawImage(&bild2, 0, 0, 200, 100); else if(focstatus == true) grafik.DrawImage(&bild3, 0, 0, 200, 100); } EndPaint(hButton, &ps); //Aufräumen ReleaseDC(s_draw->hwndItem, hDC); return true;
Meine Fragen:
1. Ich möchte, das Bild1 im normalen Zustand angezeigt wird. Bild2 soll nur dann angezeigt werden,
wenn die Maus drüber ist. Und Bild3 nur dann, wenn geklickt wurde.Jetzt ist es bei mir aber so, das er erst zu Bild2(Grün) wechselt, wenn ich das erste mal geklickt habe und nicht bei mous-over.
Dann bleibt er auch bei Bild2(Grün). Wenn ich klicke, wechselt er zu Bild3(Blau), bis ich die Maustaste loslasse.
Dann wechselt er wieder zu Grün. Was muss ich machen?2. Ihr seht ja auf den Bildern das weiße Rechteck, welches den Button darstellt. Wie kann ich das weg machen?
Ich dachte, das bei Owner Draw Buttons garnichts vom Button gezeichnet wird.Hoffe ich habe mich ausreichend verständlich ausgedrückt & ihr könnt mir helfen.
PS: Ich sagte bereits, das ich den Code zum Teil von einem anderen Beitrag hier habe. Wenn jemand mir einen anderen Lösungsweg empfehlt, wäre ich auch darüber dankbar.
-
1. Suche "non rectangular button", sollte Dichnicht überfordern.
2. Scheiß bitte den ReleaseDC raus. Was soll der Dort? Du hast doch BeginPaint und EndPaint...
3. Macht es wenig Sinn (im Sinne der Performance) bei jedem Paint alle Bilder zu laden, selbst wenn Du diese nicht brauchst. Bzw. solltest Du die Grafik bur einmal laden...
-
ja genau ... sch* ihn einfach raus
... oh mann ... wie unqualifiziert ... aber der musste einfach sein :p
-
OK. Ein echt guter Typo.
schMeiß...
-
Ne Leute, ich werd ihn nicht raussch***en
So jetzt zurück zum Thema.
@Martin Richter
Meinst du mit non rectangular button Regions, oder was?3. Macht es wenig Sinn (im Sinne der Performance) bei jedem Paint alle Bilder zu laden, selbst wenn Du diese nicht brauchst. Bzw. solltest Du die Grafik bur einmal laden...
Der Code steht in der DrawItem-Funktion, die bei WM_DRAWITEM aufgerufen wird.
-
need help schrieb:
Der Code steht in der DrawItem-Funktion, die bei WM_DRAWITEM aufgerufen wird.
Und auch da macht es keinen Sinn. Und dann macht dort weder BeginPaint,EndPaintnoch ReleaseDC Sinn!
-
Und auch da macht es keinen Sinn. Und dann macht dort weder BeginPaint,EndPaint noch ReleaseDC Sinn!
Geb ich dir völlig recht. Ich benutze diese Projektmappe lediglich für Versuche. Da ich den Code zum Teil von nem anderen Beitrag kopiert hab,
habe ich auch nicht so darauf geachtet, wie "unschön" der Code ist. Mir war nur wichtig, das es funktioniert.
Ich weiss, das ist echt blöd von mir, werde es auch noch umschreiben.Jedoch bleiben meine Fragen immer noch offen(siehe ersten Post).
Wie kann ich die 3 Zustände korrekt anzeigen(Fehler siehe ersten Post).
Und kann man den weissen Rechteck vom Button entfernen?
-
Du hast doch schon eine Antwort.
Der weiße Bereich entsteht doch dadurch, dass Dien Bild nicht den Bereich des Buttons füllt.Also entweder einen "non rectangular control" bauen. (Habe ich schon gechrieben GidF). Oder den Hintergrund korrekt vorbereiten und nur den "eigentlichen Button" transparent in den Hintergrund zeichnen.
-
Du hast doch schon eine Antwort.
Der weiße Bereich entsteht doch dadurch, dass Dien Bild nicht den Bereich des Buttons füllt.Ach so, ich hatte gehofft, das man den Button irgendwie ganz "ausblenden" könnte. Naja, danke.
Also entweder einen "non rectangular control" bauen. (Habe ich schon gechrieben GidF). Oder den Hintergrund korrekt vorbereiten und nur den "eigentlichen Button" transparent in den Hintergrund zeichnen.
Ok, werd ich dann so machen.
Kleine Frage noch. Es gibt ja diese Item-States wie ODS_DEFAULT oder ODS_SELECTED.
Wie genau kann ich es machen, dass auch ein eigenes Bild für den fall, das sich die Maus darüber befindet, angezeigt wird?
-
need help schrieb:
Kleine Frage noch. Es gibt ja diese Item-States wie ODS_DEFAULT oder ODS_SELECTED.
Wie genau kann ich es machen, dass auch ein eigenes Bild für den fall, das sich die Maus darüber befindet, angezeigt wird?ODS_HOTLIGHT gibt es IMHO nutr für Comboboxen.
Aber wo hast Du den hier ein Problem?
1. Kannst Du beim Zeichnen prüfen ob der Cursor im/auf dem Button steht.
2. Kannst Du DeinenButton subclassen und so auch mitbekommen wenn die Maus über den Button fährt.
3. Gibt es TrackMouseEvent mit dem man sogar mit bekommt, dass das Fenster verlassen wird. Da gibt es auch WM_MOUSEHOVER etc...
-
Soweit ich das jetzt verstanden habe(MSDN), sendet TrackMouseEvent unter anderem die Messages WM_MOUSEHOVER & WM_MOUSELEAVE,
die ich dann bequem abfangen und dem entsprechend darauf reagieren kann.Ich bin mir jetzt aber nicht ganz sicher, wo ich die Funktion TrackMouseEvent aufrufen soll. Etwa bei WM_PAINT? Wäre
toll, wenn du mir da weiterhelfen würdest.
-
in WM_MOUSEMOVE
-
Stimmt, hatte ich total vergessen.
-
Leute, ich komme echt nicht klar. Ich versuche schon die ganze Zeit mit Regions und GDI+(Graphics::Image) meinen Button zu zeichnen. Doch ich weiss nicht,
wie genau ich das machen muss.case WM_DRAWITEM: { pdis = (LPDRAWITEMSTRUCT)lParam; }
Ich weiss einfach nicht, wie ich weiter vorgehen muss. Habe mit HRGN und SetWindowRgn() herumprobiert. Wenn ich zum Beispiel eine Ellipse setze,
dann wird es auch angezeigt, jedoch auch das weisse Rechteck des Buttons.Ich weiss, für euch ist es lästig, aber kann mir jemand bitte sagen, wie ich mein Vorhaben umsetzen kann?
Habe mir auch schon manches im Netzt angeschaut, z.b. das http://www.rohitab.com/discuss/topic/26786-irregular-shaped-buttonswin32/.
-
Hast Du den Button-Style BS_OWNERDRAW gesetzt, sonst erhälst Du nie WM_DRAWITEM?
-
Achte darauf, dass Du das HRGN-Handle nach erfolgreichem SetWindowRgn nicht löschst. Das System übernimmt das Handle und legt keine Kopie an.
-
Hast Du den Button-Style BS_OWNERDRAW gesetzt, sonst erhälst Du nie WM_DRAWITEM?
Klar hab ich.
Achte darauf, dass Du das HRGN-Handle nach erfolgreichem SetWindowRgn nicht löschst. Das System übernimmt das Handle und legt keine Kopie an.
Ja, darauf achte ich auch.
Wie schon oben geschrieben, wird das Region auch angezeigt, wenn ich z.b. eine Ellipse mit SetWindowRgn() setzte. Nur das Problem ist,
das diese Ellipse im weissen Rechteck des Buttons ist, dieser also nicht verschwindet. Weiss jemand da weiter?Außerdem, kann mir jemand sagen, wie ich ein Bild(Graphics::Image) mit Alpha(PNG)
durch Regions oder so als meinen Button definieren kann?
Bei mir klappt es wie schon gesagt nicht.
-
Hast Du WS_CLIPCHILDREN definiert? Dann zeichnet das Parent nicht den Untergrund.
Ansonsten wenn die Region wirklich korrekt gesetzt ist zeichnet das Parent auch den Untergrund.Ansonsten habe Ich Dir Transparent BLT schon genannt...
-
Hast Du WS_CLIPCHILDREN definiert?
Ja, habe ich. Ich habe jetzt mal zum Testen folgenden Code Kopiert:
case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdiControl = (LPDRAWITEMSTRUCT)lParam; if(lpdiControl->CtlType == ODT_BUTTON) { HRGN hrgnButton1 = CreateRectRgn(0, 0, 0, 0); GetWindowRgn(lpdiControl->hwndItem, hrgnButton1); RECT rcClient; GetClientRect(lpdiControl->hwndItem, &rcClient); FillRect(lpdiControl->hDC, &lpdiControl->rcItem, (HBRUSH)GetStockObject(DKGRAY_BRUSH)); if(lpdiControl->itemState & ODS_SELECTED) { rcClient.top += 1, rcClient.left += 1; HRGN hrgnButton2 = CreateEllipticRgnIndirect(&rcClient); FillRgn(lpdiControl->hDC, hrgnButton1, (HBRUSH)GetStockObject(BLACK_BRUSH)); FillRgn(lpdiControl->hDC, hrgnButton2, (HBRUSH)GetStockObject(BLACK_BRUSH)); DeleteObject(hrgnButton2); } else { rcClient.bottom -= 1, rcClient.right -= 1; HRGN hrgnButton2 = CreateEllipticRgnIndirect(&rcClient); FillRgn(lpdiControl->hDC, hrgnButton1, (HBRUSH)GetStockObject(DKGRAY_BRUSH)); FillRgn(lpdiControl->hDC, hrgnButton2, (HBRUSH)GetStockObject(DKGRAY_BRUSH)); DeleteObject(hrgnButton2); } } }
Den Code habe ich von http://www.rohitab.com/discuss/topic/26786-irregular-shaped-buttonswin32/ vom Beispiel von Napalm.
Bei mir sieht das so aus:
Normal -> http://s7.directupload.net/images/131206/ha2h3inv.jpg
Geklickt -> http://s14.directupload.net/images/131206/blg3rsgv.jpgWie man sieht, wird das ganze Rechteck mit der Farbe gefüllt, die ich bei der Ellipse als Normal-Zustand habe.
Vielleicht mach ich auch nur einen dummen Fehler. Wäre also über Antworten glücklich!
-
Wie Du unschwer sehen kannst Hast Du nicht das Fenster selbst auf eine abweichende Region gesetzt. Sondern Du zeicnest nur in diese Region.