Hintergrundfarbe für Controls ermitteln OHNE GetPixel

  • Ich würde gerne eine Lösung teilen, mit der man die Hintergrundfarbe von Controls ermitteln kann, ohne GetPixel zu verwenden. Dabei sollen ganz unterschiedliche Controls berücksichtig werden, wie z.B. Label, Edit, Input, Button, ComboBox, usw.


    Besteht Interesse, oder gibt es schon eine Lösung?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Ich würde gerne eine Lösung teilen, mit der man die Hintergrundfarbe von Controls ermitteln kann, ohne GetPixel zu verwenden. Dabei sollen ganz unterschiedliche Controls berücksichtig werden, wie z.B. Label, Edit, Input, Button, ComboBox, usw.


    Besteht Interesse, oder gibt es schon eine Lösung?

    Irgendwie verstehe ich nicht, was Du eigentlich willst.

    Du möchtest Deine Lösung mit uns teilen? Warum machst Du es nicht?

    In der ShoutBox liest sich das allerdings wieder anders.

    Du suchst eine Lösung?

    Was gefällt Dir an "PixelGetColor" oder "_WinAPI_GetPixel" nicht?

  • Irgendwie verstehe ich nicht, was Du eigentlich willst.

    Ganz einfach: Ich habe lange recherchiert und eine Lösung gefunden, die die Hintergrundfarbe eines Controls zuverlässig ausliest. Aber dass ich so lange dran gesessen habe, heißt ja nicht, dass nicht jemand anderes schon eine Lösung hat, eventuell sogar die gleiche. Dann wäre es witzlos, das nochmal zu posten.


    Was gefällt Dir an "PixelGetColor" oder "_WinAPI_GetPixel" nicht?

    Nichts! Damit ist alles in Ordnung. Aber in diesem Thread geht es um eine Lösung OHNE GetPixel. Das ist alles.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Aber in diesem Thread geht es um eine Lösung OHNE GetPixel. Das ist alles.

    Hmm...dann bitte, poste doch Deine Lösung.

    Ich wüsste jetzt spontan keine Lösung, außer vielleicht Screenshot und dann in den Bilddaten suchen.

    Aber eigentlich fallen mir dafür auch nicht so viele Einsatzmöglichkeiten ein, weshalb ich mich damit nicht so wirklich beschäftigt habe.

  • Nun gut, es geht zwar nicht um GetPixel, aber zum Verständnis: GetPixel hat einige Schwächen, jenachdem welches Pixel man bei welchem Control ausliest. Wenn man das Pixel "0, 0" ausliest, kann das bei einem Label ohne Rahmen funktionieren. Bei einem Button schon wieder nicht. Macht man für den Button ein Offset z.B. Pixel bei "3, 3" (siehe EN Forum) funktioniert es evtl. bei einem Edit nicht, wenn der gelesene Pixel genau das Caret erwischt, usw.


    Hmm...dann bitte, poste doch Deine Lösung.

    Ok, werde es ein wenig aufbereiten. :)

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Ok, das ist für mich insofern interessant, weil ich jetzt weiß, dass "_WinAPI_GetBkColor" nur nach dem "_SendMessage" korrekt funktioniert.

    Ich weiß zwar noch nicht, ob ich das jemals brauchen werde (und wenn ja, ob ich mich dann daran erinnere :)), aber schonmal danke für's teilen! :thumbup:

    Gibt es für Dich denn eine direkte Notwendigkeit dafür?

    Ich meine, eigentlich kennt man doch die Hintergrundfarbe der Control-Elemente (man hat sie ja selbst gesetzt).

  • Gibt es für Dich denn eine direkte Notwendigkeit dafür?

    Offen gesagt, sehe ich das ähnlich wie du, normalerweise weiß man welche Hintergrundfarbe man für seine Controls verwendet. Bei mir ergab sich die Idee, als ich mit dem Hover-Effekt arbeitete. Da hätte man nur die Hover-Color übergeben brauchen, die Normal-Color hätte man auslesen können.


    Weitere Szenarien wären vielleicht, wenn man ein Addon mit GUI für ein fremdes Programm entwickelt und man die Farben an die des Hauptprogramms angleichen will, oder wenn man Skins entwickelt und eine Möglichkeit benötigt, die alten Farben wiederherzustellen. Denkbar wäre auch, dass man die Schriftarbe ändern will und vorher prüft, welche Farbe ein Edit bei User hat, der ein dunkles Window-Theme eingestellt hat - wäre ja blöd, wenn man dort das Edit dunkelgrau ist und man eine dunkelblaue Schrift zeigt.


    Summa summarum denke ich, das ist eine Funktion, die man eher selten benötigt. Aber besser man hat sie und braucht sie nicht, als man braucht sie und hat sie nicht. 8o

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • _SendMessage(_WinAPI_GetParent($hWnd), $WM_CTLCOLORSTATIC, $hDC, $hWnd)

    Hm, diese Zeile macht meinem Verständnis nach keinen Sinn:

    • weil die Message (vom Parent-Window) nicht ausgewertet wird
    • weil die Zeile keinen Einfluss auf den Rückgabewert der Funktion GUICtrlGetBkColor_WinAPI_2 hat

    Zudem funktioniert $WM_CTLCOLORSTATIC nur bei selbst erstellten statischen Controls.


    Damit bekomme ich als Ergebnis 0xFFFFFF... ist bei mir aber 0xADC2DE.

    ConsoleWrite('! $iColor = 0x' & Hex(GUICtrlGetBkColor_WinAPI_2(ControlGetHandle('', '', '[CLASS:Scintilla; INSTANCE:1]')), 6) & @CRLF)


    #include <WindowsConstants.au3>

    $WM_CTLCOLOR = 0x0019

    $WM_CTLCOLORMSGBOX = 0x0132

    $WM_CTLCOLOREDIT = 0x0133

    $WM_CTLCOLORLISTBOX = 0x0134

    $WM_CTLCOLORBTN = 0x0135

    $WM_CTLCOLORDLG = 0x0136

    $WM_CTLCOLORSCROLLBAR = 0x0137

    $WM_CTLCOLORSTATIC = 0x0138

  • Zudem funktioniert $WM_CTLCOLORSTATIC nur bei selbst erstellten statischen Controls.

    Das kann gut sein. - Gerade vor kurzem habe ich es gelesen, leider weiß ich nicht mehr wo. Der Sinn war ungefähr, dass es Namenskonventionen gibt, wobei Befehle die mit "Control" beginnen (-GetPos, -GetHandle, -GetFocus, ...) auch auf fremde Controls anwendbar sind, während Befehle mit "GUICtrl" im Namen (auch mit Unterstrich davor) nur auf eingene Controls anwendbar sind. Aber nagel mich bitte nicht fest, kann mich auch irren.


    Bei der Namensgebung "GUICtrlGetBkColor...()" habe ich versucht, mich an diese Vorgaben zu halten. Eine Verwendung bei fremden Controls hatte ich nicht auf dem Schirm. ;)


    Damit bekomme ich als Ergebnis 0xFFFFFF... ist bei mir aber 0xADC2DE.

    ConsoleWrite('! $iColor = 0x' & Hex(GUICtrlGetBkColor_WinAPI_2(ControlGetHandle('', '', '[CLASS:Scintilla; INSTANCE:1]')), 6) & @CRLF)

    Leider kann ich dir da nicht helfen, aber vielleicht hast du eine Chance mit der Funktion "GUICtrlGetBkColor_Bilgus()".


    Hm, diese Zeile macht meinem Verständnis nach keinen Sinn:

    • weil die Message (vom Parent-Window) nicht ausgewertet wird

    Hat auch niemand behauptet. 8o Was der SendMessage-Befehl genau macht, konnte ich mir bis vor ein paar Minuten auch nicht erklären, und gerade da hat Bilgus im EN Forum eine Antwort gepostet.

    • weil die Zeile keinen Einfluss auf den Rückgabewert der Funktion GUICtrlGetBkColor_WinAPI_2 hat

    Also bei mir schon. Wenn ich die Zeile auskommentiere, wird beim Reset der Farben auf weiß (0xFFFFFF) gesetzt.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Bitnugger


    Ich habe versucht das nachzuvollziehen, was du wegen dem nicht-eigenen Control gepostet hast. Ich habe sowohl die GUICtrlGetBkColor_WinAPI_2() probiert, als auch die GUICtrlGetBkColor_Bilgus(). Das Ergebnis ist das gleiche wie bei dir, es wird immer 0xFFFFFF ermittelt. Das ist jedoch nicht verwunderlich, denn es scheint schon daran zu scheitern, dass kein Handle für das Scintilla Control ermittelt werden kann. Leider bin ich da nicht weiter gekommen.

    AutoIt
    Local $hCtrl = ControlGetHandle('', '', '[CLASS:Scintilla; INSTANCE:1]')
    Local $iColr = GUICtrlGetBkColor_WinAPI_2($hCtrl)
    ConsoleWrite('! $iColor = 0x' & Hex($iColr) & " $iColr: " & $iColr & " $hCtrl: " & $hCtrl & @CRLF)
    
    ; Ausgabe in der Console: ! $iColor = 0xFFFFFFFF, $iColr = -1, $hCtrl = 0x00000000

    Auch mit anderen AutoIt Fenstern habe ich es probiert, ging leider auch nicht.


    Oscar


    Wie oben zu lesen, scheint sich GUICtrlGetBkColor() nur im eigenen Script verwenden zu lassen. Das wiederum bedeutet, dass so wie du vermutet hast, die Anwendungsmöglichkeiten recht gering sind. Die von mir angeführten Anwendungs-Beispiele mit externen Programmen sind wohl hinfällig. Nun ja, wie dem auch sei,

    ich werde den Code trotzdem aufbereiten und im Forum Bereich "Skripte" posten. Die Fragen zu SendMessage und dem Freigeben des Brush-Objekts sind geklärt und vielleicht kann es doch mal jemand gebrauchen. ;)

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • ich werde den Code trotzdem aufbereiten und im Forum Bereich "Skripte" posten. Die Fragen zu SendMessage und dem Freigeben des Brush-Objekts sind geklärt und vielleicht kann es doch mal jemand gebrauchen. ;)

    Solche Informationen (auch die anderen Beiträge in diesem Thread) kann man immer gebrauchen :thumbup:.

    Zu wissen, dass etwas nicht, oder nur unter bestimmten Rahmenbedingungen, funktioniert, erspart einem frustierende Selbstversuche ;).

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Ich verweise da gerne auf den Thread: Sammelthread "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    Nicht speziell um die Thematik da hinzuzufügen, aber generell damits mal jeder gesehen hat.

    Ich denke schon, dass das ein Punkt wäre, den man dort eintragen könnte :).

    Professor Bernd :

    Vielleicht hast Du ja Zeit und Lust einen zusammenfassenden Beitrag im o.g. Thread zu erstellen. Ich übernehme ihn dann in die Gesamtübersicht.

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Musashi


    Einen Beitrag zu erstellen ist kein Problem, aber bist du sicher, dass es dort hin passt? Wie weiter oben geschrieben, bin ich eigentlich davon ausgegangen, dass der Code nur im eigenen Script funktioniert. Deshalb habe ich den Zusatz "GUICtrl" im Namen verwendet, der das laut Namenskonventionen ausdrückt (ohne Gewähr).


    Gerade fällt mir auf, dass meine Funktion ironischerweise vor WinAPI-Funktionen nur so strotzt. :/

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Das ist jedoch nicht verwunderlich, denn es scheint schon daran zu scheitern, dass kein Handle für das Scintilla Control ermittelt werden kann.

    Local $hCtrl = ControlGetHandle('', '', '[CLASS:Scintilla; INSTANCE:1]')

    Seltsamerweise funktioniert es so anscheinend nicht zuverlässig... und ich denke, ich habe den Grund dafür gefunden:

    Wird ein leerer String für den ersten Parameter (title) übergeben, wird das Handle des aktiven Fensters verwendet!


    So ist es besser:

    AutoIt
    Local $hCtrl = ControlGetHandle(WinGetHandle('[CLASS:SciTEWindow]'), '', '[CLASS:Scintilla; INSTANCE:1]')


    Die Fragen zu SendMessage und dem Freigeben des Brush-Objekts sind geklärt

    Ja... und soweit ich das jetzt verstehe, wird die Message von der Default-WinProc verarbeitet.

    • Offizieller Beitrag

    Ja... und soweit ich das jetzt verstehe, wird die Message von der Default-WinProc verarbeitet.

    Stimmt! Und eigentlich sollte das SendMessage gar nicht nötig sein (für mein Verständnis), aber "_WinAPI_GetBkColor" liefert ohne das SendMessage nur 0x00FFFFFF.

    In der Funktion "GUICtrlGetBkColor_WinAPI_1" hat Professor Bernd das ja aufgeführt.

    Entweder ist das ein Bug in Windows oder ein Feature. ^^


    Edit: Ok, wohl eher ein "Bug" in AutoIt, weil das mit Nim ohne SendMessage funktioniert:

    Ergebnis = GetBkColor: 0x00FFAA88

  • Musashi Ok. :)


    Bitnugger  Oscar Interessante Informationen!


    wohl eher ein "Bug" in AutoIt, weil das mit Nim ohne SendMessage funktioniert:

    Wie sieht denn "GetBkColor(hDC)" innendrin aus, wird da vielleicht ein SendMessage verwendet?


    Frage: "Wozu braucht man SendMessage an dieser Stelle?"

    Ich interpretiere die Antwort so: Windows verfährt nach einem Mantra/Prinzip, nichts zu speichern/berechnen, bevor es wirklich gebraucht wird. Deshalb enthält das DC erstmal ein leeres (oder kein?) Brush-Objekt. Durch das SendMessage wird Windows gesagt, dass ein Brush benötigt wird und ein Brush wird erzeugt mit den Eigenschaften, die in SendMessage angegeben werden (in diesem Fall $WM_CTLCOLORSTATIC).


    Local $hBrushOLD = _SendMessage(_WinAPI_GetParent($hWnd), $WM_CTLCOLORSTATIC, $hDC, $hWnd)


    Von SendMessage wird das Handle auf das leere Brush zurückgegeben (= $hBrushOLD), das DC enthält nun einen neuen Brush mit ColorStatic ($hBrushNEW). Nachdem die Aufgabe erfüllt ist, sollte man den Ausgangszustand wieder herstellen. Vielleicht könnte man das ebenfalls mit SendMessage erledigen, aber SelectObject macht den Job:


    Local $hBrushNEW = _WinAPI_SelectObject($hDC, $hBrushOLD) ; put the original object back, return the current object


    Das ist es, wie ich mir das erkläre. Falls ich falsch liege, oder jemand das besser erklären kann: Feedback willkommen. :)

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.