Как сказал TLama, вам нужно наследовать от TCustomControl. Но вам понадобится дополнительный код для публикации всех событий клавиатуры. Вы можете выбрать простой способ и наследовать от TPanel, поскольку TPanel уже предоставляет Canvas и ряд событий клавиатуры.
Но вот некоторый код, показывающий, как создать и зарегистрировать новый элемент управления, который опубликовал свойства TCustomControl и представил новое событие OnPaint:
Если вы создадите новый пакет, добавите этот модуль и установите его, у вас будет новый элемент управления TGTPaintBox, который может иметь фокус (хотя вы его не видите). Он также может получить ввод с клавиатуры.
unit uBigPaintbox;
interface
uses Windows, Classes, Messages, Controls;
type
TGTPaintBox = class(TCustomControl)
private
FOnPaint: TNotifyEvent;
protected
// Three methods below are for transparent background. This may not work that great,
// and if you don't care about it, you can remove them.
procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
procedure CreateParams(var Params: TCreateParams); override;
procedure SetParent(AParent: TWinControl); override;
protected
procedure Paint; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
public
property Canvas;
published
// Introduce OnPaint event
property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
// Publish keyboard and mouse events.
property OnKeyPress;
property OnKeyDown;
property OnKeyUp;
property OnClick;
property OnDblClick;
property OnMouseUp;
property OnMouseDown;
property OnMouseMove;
// And some other behavioral property that relate to keyboard input.
property TabOrder;
property TabStop;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('GolezTrol', [TGTPaintBox]);
end;
{ TGTPaintBox }
procedure TGTPaintBox.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;
procedure TGTPaintBox.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
inherited;
// Focus the control when it is clicked.
if not (csDesigning in ComponentState) and CanFocus then
SetFocus;
end;
procedure TGTPaintBox.Paint;
begin
inherited;
// Call paint even if it is assigned.
if Assigned(FOnPaint) then
FOnPaint(Self);
end;
procedure TGTPaintBox.SetParent(AParent: TWinControl);
var
NewStyle: Integer;
begin
inherited;
if AParent = nil then
Exit;
// Make sure the parent is updated too behind the control.
NewStyle := GetWindowLong(AParent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN;
SetWindowLong(AParent.Handle, GWL_STYLE, NewStyle);
end;
procedure TGTPaintBox.WMEraseBkGnd(var Msg: TWMEraseBkGnd);
begin
SetBkMode(Msg.DC, TRANSPARENT);
Msg.Result := 1;
end;
end.
Я добавил некоторые функции в попытке сделать элемент управления прозрачным, потому что PaintBox тоже. Одним из недостатков является то, что вам нужно перекрасить родительский элемент, чтобы очистить ранее нарисованный контент. В демонстрационном приложении это достаточно просто. Я просто аннулирую форму вместо элемента управления. : p
Если вам это не нужно, вы можете удалить WMEraseBkGnd
, CreateParams
и SetParent
из элемента управления.
Небольшая демонстрация:
Поместите ярлык на форму. Поместите TGTPaintBox поверх него и сделайте его немного больше. Затем добавьте таймер и, возможно, некоторые другие элементы управления.
Убедитесь, что вы установили свойство TabStop GTPaintBox на True
.
Затем реализовать следующие события;
// To repaint the lot.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Invalidate;
end;
// Capture key input and save the last entered letter in the tag.
procedure TForm1.GTPaintBox1KeyPress(Sender: TObject; var Key: Char);
begin
if Key in ['a'..'z'] then
TGTPaintBox(Sender).Tag := Integer(Key);
end;
// Paint the control (this is called every second, when the timer invalidates the form
procedure TForm1.GTPaintBox1Paint(Sender: TObject);
var
PaintBox: TGTPaintBox;
begin
PaintBox := TGTPaintBox(Sender);
// Draw a focus rect too. If you want the control to do this, you would normally
// implement it in the control itself, and make sure it invalides as soon as it
// receives or loses focus.
if PaintBox.Focused then
PaintBox.Canvas.DrawFocusRect(PaintBox.Canvas.ClipRect);
// It just draws the character that we forced into the Tag in the KeyPress event.
PaintBox.Canvas.TextOut(Random(200), Random(200), Char(PaintBox.Tag));
end;