Ich versuche, ein Steuerelement für die Suche in MFC zu erstellen, das ständig ein Symbol im Steuerungsfenster anzeigt (unabhängig vom Status und dem Text des Steuerelements). Ich habe so etwas vor vielen Jahren geschrieben und funktionierte sehr gut, aber der Code funktioniert nicht mehr auf Windows 7 und neuer (vielleicht sogar Vista, aber habe das nicht versucht). Was passiert ist, ist, dass das Bild im Steuerelement mit dem Eingabebereich überlappt (siehe Bild unten).
Die Idee hinter dem Code:
CEdit
abgeleitet ist (die das Malen in OnPaint übernimmt) PreSubclassWindow()
, OnSize()
und OnSetFont()
angewendet.
So wird die Eingabegröße für die Bearbeitung angewendet:
%Vor% Das folgende Bild zeigt das Problem mit den Einzelzeilen-Bearbeitungen (die Bilder wurden für eine bessere Ansicht herangezoomt). Der gelbe Hintergrund dient nur zur Hervorhebung, in echtem Code verwende ich die Systemfarbe COLOR_WINDOW
. Sie können sehen, dass, wenn die Einzelzeilenbearbeitung Text hat und die Eingabe hat, das linke Bild übermalt wird. Dies passiert nicht bei der mehrzeiligen Bearbeitung, bei der SetRect
das Formatierungsrechteck korrekt festlegt.
Ich habe versucht, ExcludeClipRect zu verwenden, um den Bereich des Bearbeitungsbereichs zu entfernen Das Bild wird angezeigt.
%Vor%Dies scheint keine Auswirkung auf das Ergebnis zu haben.
Als Referenz ist dies die Malmethode, die vor Jahren geschrieben wurde und früher unter Windows XP gut funktionierte, aber nicht mehr korrigiert wurde.
%Vor%Ich habe mir andere Implementierungen ähnlicher Edit-Steuerelemente angeschaut und sie haben jetzt alle den gleichen Fehler.
Offensichtlich ist die Frage, wie kann ich den Bildbereich aus dem Eingabebereich des Steuerelements ausschließen?
Ich denke was passiert, ist das CPaintDC
ruft BeginPaint()
auf, was ein WM_ERASEBKGND
an das Bearbeitungsfeld sendet. Ich konnte es nicht ignorieren, also schätze ich, dass es an ein internes STATIC
Fenster gesendet wird? Nicht sicher.
Der Aufruf von ExcludeClipRect()
in Ihrem OnPaint()
-Handler führt nichts aus, weil EDIT
den Clipping-Bereich entweder in BeginPaint()
oder in seinem eigenen WM_PAINT
-Handler auf den gesamten Client-Bereich zurücksetzt.
Allerdings sendet EDIT
einen WM_CTRCOLOREDIT
direkt vor dem eigentlichen Bemalung an seinen Eltern, aber scheinbar nach dem Festlegen der Ausschneide-Region. So können Sie ExcludeClipRect()
dort aufrufen. Klingt wie ein Implementierungsdetail, das sich mit zukünftigen Versionen der allgemeinen Steuerelemente ändern kann. In der Tat scheint es so zu sein.
Ich habe einen schnellen Test ohne MFC unter Windows 7 gemacht, hier ist meine Fensterprozedur:
%Vor% Ich habe dann das EDIT
Fenster subclassiert, um mein eigenes Icon in WM_PAINT
zu zeichnen, und dann die Nachricht weitergeleitet, so dass ich nicht alles selbst zeichnen musste.
Beachten Sie, dass ich BeginPaint()
und EndPaint()
(das Äquivalent zum Erstellen eines CPaintDC
) in WM_PAINT
nicht aufrufen konnte, da der Rahmen nicht gezeichnet wurde. Ich vermute, es hat etwas damit zu tun, BeginPaint()
zweimal aufzurufen (einmal manuell, einmal per EDIT
) und die Behandlung von WM_ERASEBKGND
. YMMV, insbesondere mit MFC.
Schließlich setze ich die Ränder direkt nach dem Erstellen der EDIT
:
Sie müssen die Ränder möglicherweise erneut aktualisieren, wenn sich die Systemschriftart ändert.
Tags und Links c++ visual-c++ mfc paint editcontrol