Nächster Schritt - Ein eigener Button



  • Hier kurz was ich meine. Hoffe man kann es einigermaßen erkennen.

    http://s14.directupload.net/images/140917/7d75k4d2.jpg

    Das Bild unten ist nach mehrmaligem klicken.
    An den Rändern links-rechts kann man erkennen, das es überlappt.



  • @Martin
    Habe gerade ne Antwort von dir in nem anderen Post gelesen.
    --->>> http://www.c-plusplus.net/forum/328006

    Martin Richter schrieb:

    Diese Methode hat einen klaren Nachteil, dass Artefakte bleiben, wenn man das Label ändert. Wenn es statisch bleibt ist das OK...

    Ich glaube, das genau das bei meinem Problem der Fall ist.

    Martin Richter schrieb:

    Der "nomale" Weg ist eigentlich, dass dennoch eben der Hintergrund des Parents gezeichnet wird.

    Meinst du damit, das vor dem erneuten Zeichnen der Bitmap(in meinem Fall) erst
    noch der Hintergrund erneut gezeichnet werden muss, um quasi wieder transparent zu sein?

    Hoffe du verstehst was ich meine und kannst mir helfen.


  • Mod

    Naja.
    Weg 1: Durch WM_CTLCOLOR... gibt das Parent den korrekten Brush zurück der gezeichnet werden soll im Aufruf von WM_ERASEBKGNBD.
    Das ist der korrekte Weg, wenn der Hintergrund mehr oder weniger statisch ist.
    Funktioniert auch nicht, wenn das Parent, den Bereich unter dem Control verändert.

    Weg 2: Das Client fordert das Parent durch WM_EARSEBKGND auf den Hintergrundbereich neu zu zeichnen, dazu setzt man evtl. noch eine Clipping Region....

    Grundsätzlich hat man hier das Problem, dass natürlich auch static neu gezeichnet werdenmuss, wenn der Inhalt des Parent darunter sich ändert...

    PS: Die Artfakte entstehen, weil durch das Zeichnen des Textes alleine eben der alte Text "transparent übermalt wird" wenn der neu gesetzt wird. Er bleibt eben faktisch auch stehen.


  • Mod

    Ich sehe gerade Dein Bild: Du willst keine Transparenz! Du willst einen Button, der nicht rechteckig ist....

    Such mal nach "non rectangular windows"

    Nachtrag: http://www.codeproject.com/Articles/11683/CRoundButton2-A-fancy-graphical-button



  • Danke fürs Antworten.

    Zu Weg1
    Bei der MSDN steht bei WM_ERASEBKGNBD unter Bemerkung ja folgendes

    The DefWindowProc function erases the background by using the class background brush specified by the hbrBackground member of the WNDCLASS structure.
    If hbrBackground is NULL, the application should process the WM_ERASEBKGND message and erase the background.
    ...

    Jetzt frage ich mich, wann die Funktion den Hintergrund löscht?
    Also z.b. bei Veränderung der Größe oder so...?

    Martin Richter schrieb:

    Naja.
    Funktioniert auch nicht, wenn das Parent, den Bereich unter dem Control verändert.

    Das ist in meinem Fall nicht der Fall 🙂

    Martin Richter schrieb:

    PS: Die Artfakte entstehen, weil durch das Zeichnen des Textes alleine eben der alte Text "transparent übermalt wird" wenn der neu gesetzt wird. Er bleibt eben faktisch auch stehen.

    Also muss sozusagen der Text erst mit dem Hintergrund "übermalt"(gelöscht) und dann erneut gezeichnet werden, falls ich es richtig verstanden habe.
    Oder in meinem Fall halt nicht Text sondern die Bitmap.

    Martin Richter schrieb:

    Ich sehe gerade Dein Bild: Du willst keine Transparenz! Du willst einen Button, der nicht rechteckig ist....

    Genau. Im Grunde habe ich es "vom Optischen her" mit AlphaBlend geschafft. Das einzige, was noch zu tun ist, ich muss es irgendwie hinkriegen, das es nicht mehr
    als Button gezählt wird, wenn ich in den transparenten Bereich der Bitmap klicke. In dem Fall ja, ich will einen Button, der nicht Rechteckig ist.
    Beim Suchen nach "non rectangular windows" fallen einem sofort Regions und der gleichen ins Auge.

    Jedoch weiss ich nicht genau, wie ich es mit Regions lösen könnte.
    Wäre echt super, wenn du mir da noch ein bischen weiter helfen könntest.


  • Mod

    Siehe mein Link... wenn es nicht um ein nicht rechteckiges Fenster geht...
    Dann kannst Du alles andere mit WM_ERASEBKGND vergessen.

    Ansonsten WM_NCHITTEST HTTRANSPARENT um eine Mauseingabe an das Parent weiterzugeben.



  • Martin Richter schrieb:

    Siehe mein Link... wenn es nicht um ein nicht rechteckiges Fenster geht...
    Dann kannst Du alles andere mit WM_ERASEBKGND vergessen.

    Ansonsten WM_NCHITTEST HTTRANSPARENT um eine Mauseingabe an das Parent weiterzugeben.

    Ehrlich gesagt habe ich diesen Post von dir nicht verstanden.

    Zum Link: Ich würde gerne bei "reinem" WinAPI bleiben. Außerdem habe ich ja nur noch das Problem,
    das Klicken auf den transparenten Bereich meiner Bitmap nicht als Button zu zählen.

    Ich habe zudem auch keine richtige Lösung dieses Problems in deinem Link gefunden um ehrlich zu sein.
    Vielleicht habe ich dich auch falsch verstanden.


  • Mod

    Auch die MFC nutzt nur die reine Windows API...
    Man kann das Beispiel direct übertragen. Das ist absolut simple. Es geht um die Windows Regions hier!

    Wenn Du Mausnachrichten an das Parent weitergeben willst (Transparenz) must Du WM_NCHITTEST behandeln.



  • Ok, danke fürs Antworten. Ich werde es mit WM_NCHITTEST noch versuchen.

    Aber jetzt noch kurz eine Verständnissfrage zu folgendem

    HTTRANSPARENT
    -1	
    
    In a window currently covered by another window in the same thread (the message
    will be sent to underlying windows in the same thread until one of them 
    returns a code that is not HTTRANSPARENT).
    

    So wie ich das verstanden habe, würde er im transparenten Bereich meines Buttons diese Message an meinen Button
    und meinen eigentlichen Fenster senden, bis einer von denen(in diesem Fall mein Fenster, vermute ich) einen anderen Code als HTTRANSPARENT liefert, oder?

    Oder geht diese Message nur an die darunter liegenden Fenster? Wird in dem Fall automatisch
    erkannt, das dieser Bereich meines Buttons transparent ist und somit nicht zum Button gehören soll?

    Wäre super, wenn du mich korrigieren köntest, falls ich es falsch verstanden habe.
    Ich werde es nachher noch ausprobieren.


  • Mod

    Du sollst WM_NCHITTEST behandeln und HTTRANSPARENT für die Transparenten Teile Deines Fensters liefern. Also die die nicht auf einen Klick reagieren sollen.



  • Sorry Martin, aber ich blicke da immer noch nicht ganz durch.
    Ich habe jetzt schon eine ganze weile gegoogelt über WM_NCHITTEST. Ich habe verstanden, wofür ich das benutzen kann,
    jedoch komme ich nicht darauf wie.

    Habe folgende Fragen dazu:
    1. Wie muss ich der Message klar machen, das es um das Button-Fenster geht, da die Message ja in der Prozedur des Hauptfensters behandelt wird.
    2. Du hast folgendes geschrieben:

    Du sollst WM_NCHITTEST behandeln und HTTRANSPARENT für die Transparenten Teile Deines Fensters liefern

    Ich habe verstanden, was du meinst, jedoch weiss ich nicht, wie ich den transparenten Bereich "markieren" soll, um dann HTTRANSPARENT zu setzen.
    Wie soll ich der WM_NCHITTEST mitteilen, welche Teile transparent sind?

    Ich hoffe, du hast meine Fragen verstanden, und kannst mir helfen.
    Im Netz find ich kaum was, was in meinem Fall hilfreich wäre.


  • Mod

    WM_NCHITTEST wird NICHT vom Hauptfenster behandelt.

    Ein Fenster bekommt bei einer Mausbewegung zuerst WM_NCHITTEST. Nun schaust Du in Deinem Messagehandler für Dein Fenster wohin die Maus zeigt. Ist der Cursor in einer Deiner abgerundeten Ecken, dann gibst Du HTTRANSPARENT zurück.
    Windows leitet dann die Nachricht an das darunter liegende Fenster weiter. Bis kein Fenster mehr da ist oder ein Fenster was anderes als HTTRANSPARENT zurückgibt. Die Mausaktion wird dann behandelt.

    Steht doch in der MSDN... 😉



  • Ah ok, das kam mir schon in den Sinn, jedoch war ich nicht sicher. Vielen Dank.

    Martin Richter schrieb:

    Steht doch in der MSDN... 😉

    Ja, du hast recht. Ich habe das wohl etwas falsch verstanden.

    Ok, sagen wir mal, die Maus ist in einer transparenten Ecke des Buttons.
    Jetzt muss ich HTTRANSPARENT setzen, soweit sogut. Nur wie prüfe ich, ob der Cursor im transparenten Bereich ist?

    Ich kann ja nicht die Koordinaten jedes transparenten Pixels des Buttons ermitteln und sie dann mit den Koordinaten der aktuellen Cursorposition vergleichen.
    Es muss doch eine einfache Lösung dafür geben. Und genau diese Lösung finde ich gerade nicht.
    Vielleicht ist es etwas ganz einfaches, jedoch komme ich gerade nicht drauf.


  • Mod

    Ok, sagen wir mal, die Maus ist in einer transparenten Ecke des Buttons.
    Jetzt muss ich HTTRANSPARENT setzen, soweit sogut. Nur wie prüfe ich, ob der Cursor im transparenten Bereich ist?

    Sorry: Du zeichnest doch Deinen Button. Du gibst ihm Dimensionen und Aussehen. Also kannst Du es auch prüfen. Wie auch immer...



  • Ja, aber es muss doch einen anderen Weg geben, als auf "Pixelebene".
    Naja, wenn ich keine Lösung finde, werde ich es mit CreateRoundRectRgn machen.



  • Ich habe noch ein kleines Problem, meinen Button erneut zu zeichnen.
    Wenn geklickt wird, rufe ich InvalidateRect auf und zeichne den Button dann mit der Klick-Grafik.
    Nur irgendwie wird diese einfach auf die vorherige Bitmap drauf gezeichnet, sodass
    Artefakte entstehen.

    Wie muss ich den Hintergrund meines Buttons löschen, um nei zeichnen zu können?



  • Ich weiss, es nervt, jemandem wie mir zu helfen, jedoch würde ich mich freuen, wenn es doch jemand tut 🙂




  • Mod

    friendly schrieb:

    Ich weiss, es nervt, jemandem wie mir zu helfen, jedoch würde ich mich freuen, wenn es doch jemand tut 🙂

    Stell Fragen, die nicht schon beantwortet wurden.

    Wenn Du einen Button zeichnest, seine Aussehen bestimms, dann machst Du das mit bestimmten Werten. das ist nicht auf "Pixelbasis" Du beschreibst den Button z.B., mit eine Region, wie ich es Dir bereits mit einem Link nahe gelegt habe. Dann musst Du nichts machen mit WM_NCHITTEST.

    Du hast Links. Selbst wenn es MFC ist, lässt sich das mit den vollkommen namensgleichen WinApi Funktionen umsetzen.
    Benutz Google. Lies was man Dir gibt!


Anmelden zum Antworten