Delphi PaintBox ohne Schlüsselereignisse
Frage
Ich sehe meine Version von Delphi und habe keine Schlüsselereignisse (OnKeyDown, OnKeyUp, OnKeyPress) für TPaintBox.Ich würde so etwas gerne verarbeiten.Hatte jemand einen Paintbox mit diesen Ereignissen?
Lösung
Wie TLama sagte, müssen Sie von TCustomControl erben. Sie benötigen jedoch zusätzlichen Code, um alle Tastaturereignisse zu veröffentlichen. Sie können den einfachen Weg wählen und von TPanel erben, da TPanel bereits einen Canvas und eine Reihe von Tastaturereignissen verfügbar macht.
Hier ist jedoch ein Code, der zeigt, wie ein neues Steuerelement erstellt und registriert wird, das die Eigenschaften von TCustomControl veröffentlicht und ein neues OnPaint-Ereignis einführt:
Wenn Sie ein neues Paket erstellen, dieses Gerät hinzufügen und installieren, verfügen Sie über ein neues TGTPaintBox-Steuerelement, das den Fokus haben kann (obwohl Sie es nicht sehen). Es kann auch Tastatureingaben abrufen.
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.
Ich habe einige Funktionen hinzugefügt, um das Steuerelement transparent zu machen, da dies auch eine PaintBox ist. Ein Nachteil ist, dass Sie das übergeordnete Element neu streichen müssen, um den zuvor gezeichneten Inhalt zu löschen. In der Demo-Anwendung ist dies einfach genug. Ich mache nur das Formular anstelle des Steuerelements ungültig. : p
Wenn Sie es nicht benötigen, können Sie WMEraseBkGnd
, CreateParams
und SetParent
aus dem Steuerelement entfernen.
Kleine Demo: Bringen Sie ein Etikett auf einem Formular an. Legen Sie eine TGTPaintBox darauf und vergrößern Sie sie etwas. Fügen Sie dann einen Timer und möglicherweise einige andere Steuerelemente hinzu.
Stellen Sie sicher, dass Sie die TabStop-Eigenschaft der GTPaintBox auf True
setzen.
Implementieren Sie dann die folgenden Ereignisse:
// 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;
Andere Tipps
Sie können auch einen Rahmen mit dem Farbkasten erstellen (ausgerichtet auf alClient
) und den Rahmen nach Bedarf wiederverwenden.TFrame
ist ein Fenstersteuerelement, das alle Tastaturereignisse enthält.Sie werden nicht veröffentlicht, aber Sie können sie im Code zuweisen.