Для рисования на поверхности панели
TPaintBox
, растянуть его на всю область панели и рисовать в его событии OnPaint. Мы здесь используем более сложный способ перехвата сообщения WM_PAINT
только в учебных целях.При перехвате сообщения WM_PAINT
OnCreate
формы (листинг 1.29).Рис. 1.9.
type
TForm1 = class(TForm)
Panel: TPanel;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
// Здесь будет храниться исходный обработчик сообщений
// панели
FOldPanelWndProc: TWndMethod;
// Этот метод будет перехватывать сообщения,
// предназначенные панели
procedure NewPanelWndProc(var Msg: TMessage);
end;
…
procedure TForm1.FontCreate(Sender: TObject);
begin
FOldPanelWndProc:= Panel.WindowProc;
Panel.WindowProc:= NewPanelWndProc;
end;
Сам перехватчик выглядит так, как показано в листинге 1.30.
procedure TForm1.NewPanelWndProc(var Msg: TMessage);
var
NeedDC: Boolean;
PS: TPaintStruct;
PanelCanvas: TCanvas;
begin
if Msg.Msg = WM_RBUTTONDBLCLK then
begin
Label1.Left:= Msg.LParamLo;
Label1.Top:= Msg.LParamHi;
Msg.Result:= 0;
end
else if Msg.Msg = WM_PAINT then
begin
// Проверяем, был ли запрошен контекст устройства
// обработчиком, стоящим раньше по цепочке, и если не
// был, то запрашиваем его.
NeedDC:= Msg.WParam = 0;
if NeedDC then Msg.WParam:= BeginPaint(Panel.Handle, PS);
// Вызываем старый обработчик WM_PAINT. Его нужно
// вызывать обязательно до того, как мы начнем рисовать
// на поверхности что-то свое, т. к. в противном случае
// это что-то будет закрашено стандартным обработчиком.
POldPanelWndProc(Msg);
// При использовании графических функций API самое
// неудобное — это вручную создавать и уничтожать кисти,
// карандаш и т. п. Поэтому здесь создается экземпляр
// класса TCanvas для рисования на контексте устройства
// с дескриптором, полученным при вызове BeginPaint.
PanelCanvas:= TCanvas.Create;
try
PanelCanvas.Handle:= Msg.WParam;
FanelCanvas.Pen.Style:= psClear;
PanelCanvas.Brush.Style:= bsSolid;
PanelCanvas.Brush.Color:= clWhite;
PanelCanvas.Ellipse(10, 10, Panel.Width — 10, Panel.Height — 10);