Das Ereignis OnMouseDown im TDBGrid wird bei einem Klick in eine Zelle des Datengitters nicht ausgelöst. Dieses Verhalten zeigt Delphi schon vermutlich seit der ersten Version, und daran wird sich wahrscheinlich auch in den nächsten Versionen nichts ändern. Es gibt aber eine einfache Lösung, wie man bei einem Mausklick trotzdem reagieren kann.

Jede Komponente, die von TControl abstammt, besitzt eine Property WindowProc. Damit bekommt man eine elegante Möglichkeit, für die jeweilige Komponente bestimmte Windows-Botschaften abzufangen, die von den Entwicklern nicht als Ereignis vorgesehen sind oder aus irgendeinem Grund nicht durchgereicht werden.

Zur Verdeutlichung habe ich ein Formular mit einem DBGrid. Zur Anzeige von Daten fehlt natürlich noch mindestens eine Table oder Query und eine DataSource, aber hier geht es nur ums Prinzip.


Im OnCreate-Ereignis des Formulars wird die originale WindowProc von DBGrid1 in einer Variablen gespeichert, anschließend bekommt DBGrid die neue WindowProc'NewDBGridWindowProc 'untergeschoben'. In dieser kommen von nun an alle Botschaften an, die für DBGrid1 bestimmt sind. Mit WM_LBUTTONDOWN filtert man die Botschaft heraus, die Windows bei einem Klick mit der linken Maustaste verschickt. Nun kann man geeignet darauf reagieren, sollte dabei aber nicht vergessen, die alte WindowProc FOldDBGridWindowProc aufzurufen, da sonst das Verhalten von DBGrid1 sehr merkwürdig ausfallen dürfte. Möglich ist es natürlich auch, zuerst die alte WindowProc aufzurufen und erst anschließend auf WM_LBUTTONDOWN zu reagieren.

 

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.DBGrids;

type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    procedure DBGrid1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FOldDBGridWindowProc: TWndMethod;
    procedure NewDBGridWindowProc(var Message: TMessage);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DBGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  // event is not triggered by clicking a cell
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // save the original method pointer
  FOldDBGridWindowProc := DBGrid1.WindowProc;
  // assign the new windowproc
  DBGrid1.WindowProc := NewDBGridWindowProc;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // not really necessary
  // assign the original method pointer
  DBGrid1.WindowProc := FOldDBGridWindowProc;
end;

procedure TForm1.NewDBGridWindowProc(var Message: TMessage);
begin
  // when the left mouse button is clicked
  if Message.Msg = WM_LBUTTONDOWN then
  begin
    // do something
  end;
  // don't forget to call the original method
  FOldDBGridWindowProc(Message);
end;

end.