2011-01-14 2 views
1

Привет всем Я создал новый компонент, полученный от TWinControl. Я положил его на TPanel, и я попытался вызвать процедуру PaintTo панели. Результатом является панель и ее подпись, а мой компонент вообще не нарисован на холсте. Что я должен делать по этому поводу?PaintTo не работает с моим компонентом

часть источника (как это спросил дорогой Давид):

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

Как ваш контроль рисует сам? –

+0

Если панель, ее подпись, * и * ваш элемент управления не окрашены, почему, по вашему мнению, проблема связана с вашим управлением, а не с панелью? –

+0

Вы используете перегрузку «холста»? Или, если вы используете перегрузку «DC» и передаете ей «Canvas», блокируете ли вы холст? –

ответ

1

В вашем методе обработки сообщения WM_PAINT вы НЕ можете использовать Canvas напрямую, потому что WM_PAINT указывает дескриптор GDI (HDC) в параметре Message.DC.

Посмотрите, например, на этом фрагменте кода из TGraphicControl, что справиться с этим, как и ожидалось:

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; 

Так проверить метод реализации WM_PAINT, и следовать этой схеме кода.

Вместо вышеописанного метода «Краска» поместите свой собственный код чертежа, используя свойство Canvas.

Метод «PaintTo» будет работать должным образом.

Другая возможность заключается в использовании прямых чертежей Windows API с использованием дескриптора Message.DC ... но я думаю, что вышеописанный метод, позволяющий использовать обычный холст, проще для большинства из нас! ;)

Во всех случаях WM_PAINT не должно быть местом, где компоненты Delphi реализуют рисунок, а только переопределенный метод Paint. Поэтому пусть ваш компонент наследует TGraphicControl и поместит весь код чертежа в переопределенный метод Paint.

2

Вы действительно не должны когда-нибудь понадобится, чтобы позвонить или переопределить PaintTo.

Вместо этого вы должны сделать 100% своей картины в переопределенном методе Paint. Живопись может произойти в любое время, и компонент должен иметь возможность рисовать по требованию. Как это происходит, Windows отправляет сообщение WM_PAINT, которое VCL переводит в вызов метода Paint вашего компонента.

Поэтому убедитесь, что ваш компонент может нарисовать то, что ему нужно в любое время, и выполните всю вашу картину в переопределенном методе краски.

+1

У меня не было чувства, что Джавид реализует свою краску в PaintTo. Я больше чувствовал, что он называет PaintTo, потому что он хотел, чтобы его контроль рисовал на холсте (вот почему PaintTo существует). Но я могу ошибаться! –

+0

Дэвид прав. Мой контроль работает отлично. Только PaintTo нельзя использовать для этого. – Javid

+0

PaintTo иногда очень полезен, когда вы работаете над созданием отчетов и вставляете некоторые компоненты в содержимое метафайла. Но вы правы в том, что WM_PAINT не должно быть местом, где компоненты Delphi реализуют эту картину, но только метод Overriden Paint. –

1

Ваш базовый класс должен быть TCustomControl, а не TWinControl. Первый устанавливает холст элемента управления, чтобы вы могли правильно рисовать его, переопределяя Paint.

Если вы настаиваете на обращении wm_Paint, убедитесь, что вы используете параметр WParam в качестве контекста отображения, если он предусмотрен. Формально этот параметр не используется, но VCL (и некоторые общие элементы управления) используют это для DC, что упрощает реализацию сообщения wm_PrintClient.

Смежные вопросы