user1580348
user1580348

Reputation: 6061

FindDragTarget does not detect disabled controls

Create a Delphi VCL Forms Application and put 2 TButton and a TApplicationEvents on the form:

enter image description here

Then insert these event-handlers:

unit Unit2;

interface

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

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ApplicationEvents1: TApplicationEvents;
    procedure ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  Screen.Cursor := crHelp;
end;

procedure TForm2.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
var
  Target: TControl;
  Point: TPoint;
begin
  if Msg.Message = WM_LBUTTONDOWN then
  begin
    if Screen.Cursor = crHelp then
    begin
      Screen.Cursor := crDefault;
      Handled := True;
      GetCursorPos(Point);
      Target := FindDragTarget(Point, True);
      if Assigned(Target) then
        ShowMessage(Target.Name)
      else
        ShowMessage(IntToStr(Point.X) + ', ' + IntToStr(Point.Y));
    end;
  end;
end;

end.

Now click on Button1 to change the mouse pointer to crHelp.

Then click again on Button1 which correctly shows the name "Button1".

Now click again on Button1 to change the mouse pointer again to crHelp.

Then click on the disabled Button2: You can see that now FindDragTarget has not detected the disabled control although the argument AllowDisabled is set to True.

So how can I detect a disabled control with a mouse-click?

Delphi 10.1.2

Upvotes: 2

Views: 394

Answers (1)

kobik
kobik

Reputation: 21252

The "problem" (this is actually by design) is that the FindDragTarget function does not check for disabled child Windowed Controls.

function FindDragTarget(const Pos: TPoint; AllowDisabled: Boolean): TControl;
var
  Window: TWinControl;
  Control: TControl;
begin
  ...
  Control := Window.ControlAtPos(Window.ScreenToClient(Pos), AllowDisabled);
  ...
end;

Note that Window.ControlAtPos only passes AllowDisabled argument but NOT the AllowWinControls (which is False by default).

FindDragTarget will only find child TGraphicControl descendant controls (which use their parent Handle).

You can use this function instead:

function FindDragTargetEx(const Pos: TPoint; AllowDisabled: Boolean; AllowWinControls: Boolean): TControl;
var
  Window: TWinControl;
  Control: TControl;
begin
  Result := nil;
  Window := FindVCLWindow(Pos);
  if Window <> nil then
  begin
    Result := Window;
    Control := Window.ControlAtPos(Window.ScreenToClient(Pos), AllowDisabled, AllowWinControls);
    if Control <> nil then Result := Control;
  end;
end;

Upvotes: 5

Related Questions