Pergunta

Vejo minha versão do delphi, não tem eventos Key Events (OnKeyDown, OnKeyUp, OnKeyPress) para TPaintBox.Eu gostaria de processar algo assim.Alguém tinha uma caixa de pintura com esses eventos?

Foi útil?

Solução

Como o TLama disse, você precisará herdar de TCustomControl. Mas você precisará de algum código adicional para publicar todos os eventos do teclado. Você pode escolher a maneira mais fácil e herdar do TPanel, pois o TPanel já expõe um Canvas e uma série de eventos de teclado.

Mas aqui está um código para mostrar como criar e registrar um novo controle que publicou as propriedades de TCustomControl e introduz um novo evento OnPaint:

Se você criar um novo pacote, adicionar esta unidade e instalá-lo, você terá um novo controle TGTPaintBox que pode ter o foco (embora você não o veja). Ele também pode recuperar a entrada do 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.

Eu adicionei algumas funcionalidades na tentativa de tornar o controle transparente, porque um PaintBox também é. Uma desvantagem é que você precisa redesenhar o pai para limpar o conteúdo desenhado anteriormente. No aplicativo de demonstração, isso é bastante fácil. Eu apenas invalido o formulário em vez do controle. : p
Se não precisar dele, você pode remover WMEraseBkGnd, CreateParams e SetParent do controle.

Pequena demonstração: Coloque uma etiqueta em um formulário. Coloque um TGTPaintBox em cima dele e aumente um pouco mais. Em seguida, adicione um cronômetro e talvez alguns outros controles.

Certifique-se de definir a propriedade TabStop de GTPaintBox como True.

Em seguida, implemente os seguintes 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;

Outras dicas

Você também pode criar um quadro com a caixa de pintura (alinhado a alClient) e reutilizar o quadro conforme necessário.TFrame é um controle em janela que contém todos os eventos de teclado.Eles não são publicados, mas você pode atribuí-los no código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top