Laden...

Compilier-Problem bei eigenem Control

Erstellt von Matscher vor 15 Jahren Letzter Beitrag vor 14 Jahren 1.206 Views
Matscher Themenstarter:in
84 Beiträge seit 2008
vor 15 Jahren
Compilier-Problem bei eigenem Control

Hallo zusammen,

ich habe ein kleines Problem.

Ich hab lange mich drum herum gedrückt eigene Controls zu programmieren. Hab eben die Standrad-Controls maximal etwas abgeändert. Nun wollte ich mich an eine eigene TextBox schmeißen. (Soll eben mehr können als die RichTextBox.)

Als ich mit dem Zeichnen des Controls anfangen wollte ist mir ein Problem aufgefallen was ich einfach nicht verstehe.

Ich fange unter WndProc die WindowMessage WM_PAINT ab. Ich möchte die OnPaint-Methoden also selber abschicken.

Das Abfangen der Message sollte nicht falsch sein (hofft man... ):


switch ( ( MB.API.Constants.WindowMessages )m.Msg )
{
case MB.API.Constants.WindowMessages.WM_PAINT:
    this.WmPaint( ref m );
    break;
default:
    base.WndProc( ref m );
    break;
}

In der Methode WmPaint besorg ich mir mein Graphics-Objekt über folgende Schritte:


private void WmPaint( ref Message m )
{
    IntPtr hWnd = m.HWnd;

    Rectangle rWnd = new Rectangle();

    {
        MB.API.NativeStructs.RECT rect;
        if ( !MB.API.Methods.User32.GetWindowRect( hWnd, out rect ) )
        {
            return;
        }
        rWnd = rect.Rectangle;
    }

    Rectangle rClip = new Rectangle( 0, 0, rWnd.Width, rWnd.Height );
    IntPtr hDC = MB.API.Methods.User32.GetWindowDC( hWnd );

    IntPtr hCDC = MB.API.Methods.Gdi32.CreateCompatibleDC( hDC );
    IntPtr hBitmap = MB.API.Methods.Gdi32.CreateCompatibleBitmap( hDC, rClip.Width, rClip.Height );
    MB.API.Methods.Gdi32.SelectObject( hCDC, hBitmap );
    MB.API.Methods.Gdi32.BitBlt( hCDC, 0, 0, rClip.Width, rClip.Height, hDC, 0, 0, MB.API.Constants.TernaryRasterOperations.SRCCOPY );

    using ( Graphics g = Graphics.FromHdc( hCDC ) )
    {
        this.OnPaintBackground( new PaintEventArgs( g, rClip ) );

        Rectangle textRect = this.TextRectangle;
        g.IntersectClip( textRect );
        this.OnPaint( new PaintEventArgs( g, textRect ) );
    }

    MB.API.Methods.Gdi32.BitBlt( hDC, 0, 0, rClip.Width, rClip.Height, hCDC, 0, 0, MB.API.Constants.TernaryRasterOperations.SRCCOPY );
    MB.API.Methods.Gdi32.DeleteObject( hBitmap );
    MB.API.Methods.Gdi32.DeleteDC( hCDC );
    MB.API.Methods.User32.ReleaseDC( hWnd, hDC );
}

Diesen Code habe ich mir aus einen anderem Thread hier im Forum besorgt ([Offen] Outlook Senden/Empfangen Button nachbilden).

In den OnPaintBackground und OnPaint-Methoden kann man drauf rum zeichnen... kein Problem.

Nur sobald dieser Code wirksam (also nicht auskommentiert) ist und in VS2008 der Designer, für ein Form mit diesem Control offen ist, wird nicht mehr kompiliert. Da kann man warten wie man will. Bis der Designer nicht geschlossen ist, wird nicht kompiliert.

Desweiteren werden im Designer, sobald das Control sich auf einem Form befindet, keine Eigenschaften mehr angezeigt. Bzw. die Eigenschaften des zu letzt markierten Controls werden nicht mehr gewechselt. (Was direkt nach dem öffnen des Designer's eben nichts ist.)

Ein Fehlerhinweis ist eventuell folgendes:
Der Verschieb- und Vergrößerungsrahmen, den man im Designer angezeigt bekommt, scheint ein wenig zu flackern. Also zumindest der Teil der Anfassmarken, der über das Control gelegt ist. Als ob es die ganze Zeit neugezeichnet wird.

Ich weiß dass ich das Problem letztens schon einmal hatte, aber kein Internet parad hatte --> Unter den Teppich gefallen...
Außerdem liegt das Problem meines erachtens nach nicht wirklich an dem hier installiertem VS2008, da es sich bei mir daheim nicht ander's verhält.

Vielleicht kann mir einer von euch einen Hinweis geben was ich in der Methode falsch mache. Danke!

Einen freundlichen Gruß,
Matscher

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Matscher ,

warum mischt du dich überhaupt in das Message-Processing ein? Du kannst doch auch einfach so OnPaint und OnPaintBackground überschreiben.

Da es in deiner eigentlichen Frage um die Wirkung des Controls auf VS geht, nach "Entwicklungs- und Laufzeitumgebung (Infrastruktur)" verschoben.

herbivore

Matscher Themenstarter:in
84 Beiträge seit 2008
vor 14 Jahren

Klar kann ich einfach OnPaint und OnPaintBackground überschreiben. Doch sollten noch andere Paint-Methoden hinzugefügt werden. Zum Beispiel für Zeilennummern usw.

Ich wollte an der Stelle eben nicht alles über die OnPaint verwalten. Aber wie es aussieht wird's wohl darauf hinaus laufen, da ich diesen Fehler nicht beseitigt bekomme.

R
234 Beiträge seit 2007
vor 14 Jahren

Ich bin mir jetzt nicht so sicher ob du von TextBox ableitest, oder selbst ein Control entworfen hast. Falls ersteres zutrifft:

Das OnPaint einer TextBox zu überschreiben ist nicht so trivial. Das zeichnen der TextBox passiert wohl gaaanz tief im Kern von Windows und OnPaint wird leider nicht aufgerufen.

Mittels

SetStyle(ControlStyles.UserPaint, true);

kann der Aufruf von OnPaint erzwungen werden, jedoch muss man dann alles selbst zeichnen.

Dein Ansatz, Matscher, mit dem Überschreiben von WndProc, ist schon der richtige.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Matscher,

Klar kann ich einfach OnPaint und OnPaintBackground überschreiben. Doch sollten noch andere Paint-Methoden hinzugefügt werden. Zum Beispiel für Zeilennummern usw.

es hindert dich ja keiner daran, die Arbeit nicht im OnPaint selbst zu erledigen, sondern dort nur zu entscheiden, welche anderen Paint-Methoden aufgerufen werden müssen.

herbivore

Matscher Themenstarter:in
84 Beiträge seit 2008
vor 14 Jahren

Hallo zusammen!

Ich bin mir jetzt nicht so sicher ob du von TextBox ableitest, oder selbst ein Control entworfen hast.

Also abgeleitet wird das ganze von einem Control, also keine TextBox. Ist vielleicht übertrieben das alles komplett selber zu machen, aber das will ich jetzt einfach so machen. 😉

es hindert dich ja keiner daran, die Arbeit nicht im OnPaint selbst zu erledigen, sondern dort nur zu entscheiden, welche anderen Paint-Methoden aufgerufen werden müssen.

Ich weiß schon, ich kann in der OnPaint auch eine OnPaintNumber oder sowas in der Art aufrufen. Kein Ding. Nur will ich zum Beispiel ebenfalls die OnPaintBackground aufrufen, dabei eventuell den zu zeichnenden Bereich eingrenzen usw.
Aber die Abfolge ist nunmal erst OnPaintBackground und dann OnPaint.

Also ich weiß auch dass das ganze ziemlich "überflüssig" ist alles über die WindowsMessages zu machen. Aber ich dachte dass es eventuell etwas "schicker" ist.

Achso:
Bei meiner ersten Variante hab ich im Konstruktor noch SetStyle( ControlStyles.AllPaintingInWmPaint, true ); übergeben. Aber ob mit oder ohne, immer der gleiche Fehler. Hat also nichts geändert.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Matscher,

zu SetStyle siehe Form Resize -> OwnerDraw-Controls flackern.

herbivore