Delphi PaintBox sin eventos clave
Pregunta
Veo mi versión de delphi, no tiene eventos de eventos clave (OnKeyDown, OnKeyUp, OnKeyPress) para TPaintBox.Me gustaría procesar algo así.¿Alguien tenía una caja de pinturas con estos eventos?
Solución
Como dijo TLama, deberá heredar de TCustomControl. Pero necesitará un código adicional para publicar todos los eventos de teclado. Puede elegir la forma más fácil y heredar de TPanel, ya que TPanel ya expone un Canvas y una serie de eventos de teclado.
Pero aquí hay un código para mostrar cómo crear y registrar un nuevo control que publicó las propiedades de TCustomControl e introduce un nuevo evento OnPaint:
Si crea un nuevo paquete, agrega esta unidad y la instala, tendrá un nuevo control TGTPaintBox que puede tener el foco (aunque no lo vea). También puede recuperar la entrada del teclado.
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.
He agregado algunas funciones en un intento de hacer que el control sea transparente, porque un PaintBox también lo es. Una desventaja es que debe volver a pintar el elemento principal para borrar el contenido dibujado anteriormente. En la aplicación de demostración, esto es bastante fácil. Solo invalido el formulario en lugar del control. : p
Si no lo necesita, puede eliminar WMEraseBkGnd
, CreateParams
y SetParent
del control.
Pequeña demostración: Ponga una etiqueta en un formulario. Pon un TGTPaintBox encima y hazlo un poco más grande. Luego agregue un temporizador y tal vez algunos otros controles.
Asegúrese de establecer la propiedad TabStop de GTPaintBox en True
.
Luego, implemente los siguientes eventos;
// 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;
Otros consejos
También puede crear un marco con la caja de pinturas (alineado con alClient
) y reutilizar el marco según sea necesario.TFrame
es un control en ventana por lo que tiene todos los eventos de teclado.No están publicados pero puede asignarlos en código.