2011-01-14 3 views
1

Hallo alle Ich habe eine neue Komponente von TWinControl abgeleitet. Ich legte es auf eine TPanel und ich versuchte, die PaintTo Prozedur des Panels aufzurufen. Das Ergebnis ist das Panel und seine Beschriftung und meine Komponente ist überhaupt nicht auf der Leinwand gemalt. Was soll ich dagegen tun?PaintTo funktioniert nicht mit meiner Komponente

ein Teil der Quelle (wie lieber David fragte):

Procedure TApListBox.Paint; 
var 
    C: TCanvas; 
    B: TBitmap; 
    ItemClient: TPoint; 
Begin 
    Try 
    If (FUpdating > 0) Then 
     Exit; 
    Try 
     BeginUpdate; 
     B := TBitmap.Create; 
     B.Width := Width; 
     B.Height := Height; 
     With B.Canvas Do Begin 
     Lock; 
     // Begin : 
     ItemClient := Point(IVisPanel + 3, 2); 

     // Draw Items 
     PaintItems(B.Canvas, ItemClient); 
     Unlock; 
     End; 

     C := TCanvas.Create; 
     C.Handle := GetWindowDC(Self.Handle); 
     C.Lock; 
     inherited; 
     C.Draw(1, 1, B); 
     If (RenameEdit.Visible) Then 
     RenameEdit.Repaint; 
    Finally 
     C.Unlock; 
     ReleaseDC(0, C.Handle); 
     C.Free; 
     B.Free; 
     Dec(FUpdating); 
    End; 
    Except 
    End; 
End; 
+0

Wie malt sich Ihre Kontrolle? –

+0

Wenn das Panel, seine Beschriftung, * und * Ihr Steuerelement nicht lackiert sind, warum denken Sie, das Problem ist mit Ihrer Kontrolle und nicht das Panel? –

+0

Verwenden Sie die Überladung "Canvas"? Oder wenn Sie die DC-Überladung verwenden und ein Canvas-Handle an sie übergeben, sperren Sie die Zeichenfläche? –

Antwort

1

In Ihrer Methode, die die WM_PAINT-Nachricht verarbeitet, können Sie Canvas nicht direkt verwenden, da WM_PAINT ein GDI-Handle (HDC) im Parameter Message.DC angeben.

Schauen Sie zum Beispiel an diesem Code-Schnipsel aus TGraphicControl, die es handhaben wie erwartet:

procedure TGraphicControl.WMPaint(var Message: TWMPaint); 
begin 
    if Message.DC <> 0 then 
    begin 
    Canvas.Lock; 
    try 
     Canvas.Handle := Message.DC; 
     try 
     Paint; // this is where the painting is done, using a "locked" Canvas 
     finally 
     Canvas.Handle := 0; 
     end; 
    finally 
     Canvas.Unlock; 
    end; 
    end; 
end; 

So Ihre WM_PAINT Implementierungsmethode überprüfen und diesen Code-Schema folgen.

Anstelle der obigen "Paint" -Methode können Sie Ihren eigenen Zeichnungscode mithilfe der Canvas-Eigenschaft festlegen.

Die "PaintTo" -Methode wird wie erwartet funktionieren.

Eine andere Möglichkeit ist die direkte Verwendung von Windows-API-Zeichnungen mit dem Message.DC-Handle ... aber ich denke, die obige Methode, die die Verwendung eines normalen Canvas ermöglicht, ist für die meisten von uns einfacher! ;)

In allen Fällen sollte WM_PAINT nicht der Ort sein, an dem Delphi-Komponenten das Bild implementieren, sondern nur eine überschriebene Paint-Methode. Lassen Sie also Ihre Komponente von TGraphicControl erben und fügen Sie den gesamten Zeichnungscode in eine überschriebene Paint-Methode ein.

2

Sie wirklich nicht immer PaintTo anrufen müssen sollen oder außer Kraft setzen.

Stattdessen sollten Sie 100% Ihres Gemäldes in einer überschriebenen Paint-Methode ausführen. Malen kann jederzeit passieren und eine Komponente muss in der Lage sein, sich bei Bedarf selbst zu malen. Auf diese Weise sendet Windows eine WM_PAINT-Nachricht, die die VCL in einen Aufruf der Paint-Methode Ihrer Komponente übersetzt.

So stellen Sie sicher, dass Ihre Komponente malen kann, was es zu jeder Zeit benötigt, und machen Sie alle Ihre Malerei in der überschriebenen Farbmethode.

+1

Ich hatte nicht das Gefühl, dass Javid seine Farbe in PaintTo implementierte. Ich hatte mehr das Gefühl, dass er PaintTo anrief, weil er seine Kontrolle auf eine Leinwand ziehen wollte (weshalb PaintTo da ist). Aber ich könnte falsch liegen! –

+0

David hat Recht. Meine Kontrolle funktioniert perfekt. Nur PaintTo kann nicht dafür verwendet werden. – Javid

+0

PaintTo ist manchmal sehr nützlich, wenn Sie an Berichten arbeiten und einige Komponenten in einen Metadatei-Inhalt einbetten. Aber Sie haben Recht damit, dass WM_PAINT nicht der Ort sein sollte, an dem Delphi-Komponenten das Bild implementieren, sondern nur eine überschriebene Paint-Methode. –

1

Ihre Basisklasse sollte TCustomControl sein, nicht TWinControl. Mit der ersten Option wird die Leinwand des Steuerelements so eingerichtet, dass Sie sie ordnungsgemäß malen können, indem Sie Paint überschreiben.

Wenn Sie darauf bestehen, wm_Paint selbst zu bearbeiten, stellen Sie sicher, dass Sie den Parameter WParam als Anzeigekontext verwenden, sofern dieser bereitgestellt wird. Formal ist dieser Parameter nicht verwendet, aber die VCL (und einige allgemeine Steuerelemente) verwenden das für den DC, was die Implementierung der wm_PrintClient Nachricht erleichtert.

Verwandte Themen