Domanda

Vedo la mia versione di delphi, non ha eventi chiave (OnKeyDown, OnKeyUp, OnKeyPress) per TPaintBox.Vorrei elaborare qualcosa del genere.Qualcuno aveva una scatola di colori con questi eventi?

È stato utile?

Soluzione

Come ha detto TLama, dovrai ereditare da TCustomControl. Ma avrai bisogno di codice aggiuntivo per pubblicare tutti gli eventi della tastiera. Puoi scegliere il modo più semplice ed ereditare da TPanel poiché TPanel espone già una tela e una serie di eventi della tastiera.

Ma ecco del codice per mostrare come creare e registrare un nuovo controllo che ha pubblicato le proprietà di TCustomControl e introduce un nuovo evento OnPaint:

Se crei un nuovo pacchetto, aggiungi questa unità e la installi, avrai un nuovo controllo TGTPaintBox che può avere il focus (anche se non lo vedi). Può anche recuperare l'input da tastiera.

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.

Ho aggiunto alcune funzionalità nel tentativo di rendere il controllo trasparente, perché anche un PaintBox lo è. Uno svantaggio è che è necessario ridipingere il genitore per cancellare il contenuto disegnato in precedenza. Nell'applicazione demo questo è abbastanza facile. Ho appena invalidato il modulo invece del controllo. : p
Se non ne hai bisogno, puoi rimuovere WMEraseBkGnd, CreateParams e SetParent dal controllo.

Piccola demo: Metti un'etichetta su un modulo. Mettici sopra un TGTPaintBox e ingrandiscilo leggermente. Quindi aggiungi un timer e forse altri controlli.

Assicurati di impostare la proprietà TabStop di GTPaintBox su True.

Quindi, implementa i seguenti eventi;

// 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;

Altri suggerimenti

Puoi anche creare una cornice con la scatola dei colori (allineata a alClient) e riutilizzare la cornice secondo necessità.TFrame è un controllo a finestra quindi ha tutti gli eventi della tastiera.Non sono pubblicati ma puoi assegnarli in codice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top