Question

Je vois ma version de delphi, ne dispose pas d'événements clés (OnKeyDown, OnKeyUp, OnKeyPress) pour TPaintBox. Je voudrais traiter quelque chose comme ça. Avait quelqu'un un paintbox avec ces événements?

Était-ce utile?

La solution

Comme TLama dit, vous aurez besoin d'hériter de TCustomControl. Mais vous aurez besoin d'un code supplémentaire pour publier tous les événements de clavier. Vous pouvez choisir la voie facile et hérite de TPanel depuis TPanel expose déjà une toile et un certain nombre d'événements de clavier.

Mais voici un code pour montrer comment créer et enregistrer un nouveau contrôle qui a publié les propriétés de TCustomControl et introduit un nouvel événement OnPaint:

Si vous créez un nouveau package, ajoutez cette unité, et l'installer, vous aurez un nouveau contrôle TGTPaintBox qui peut avoir la mise au point (même si vous ne le voyez pas). Il peut récupérer trop saisie au clavier.

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.

J'ai ajouté quelques fonctionnalités pour tenter de rendre le contrôle transparent, parce qu'un PaintBox est trop. Un inconvénient est que vous devez repeindre le parent pour effacer le contenu dessiné précédemment. Dans l'application de démonstration est ce assez facile. J'invalident juste la forme au lieu du contrôle. : P
Si vous ne avez pas besoin, vous pouvez supprimer WMEraseBkGnd, CreateParams et SetParent du contrôle.

Petite démo: Mettez une étiquette sur un formulaire. Mettez un TGTPaintBox sur le dessus de celui-ci et en faire un peu plus grand. Ensuite, ajoutez une minuterie, et peut-être quelques autres commandes.

Assurez-vous que vous définissez la propriété TabStop du GTPaintBox à True.

Ensuite, mettre en œuvre les événements suivants:

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

Autres conseils

Vous pouvez aussi créer un cadre avec la paintbox sur elle (aligné sur alClient) et réutiliser le cadre au besoin. TFrame est un contrôle fenêtré il a tous les événements de clavier. Ils ne sont pas publiées mais vous pouvez les assigner dans le code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top