Getting the control under the cursor

I am implementing the Shift-F10 behaviour of bringing up the context menu for a control. I have written the code below to implement it:

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  Pos : TPoint;
  Control : TControl;

begin
  if (ssShift in Shift) and (Key = vk_F10) then // pop up the context menu
    try
      GetCursorPos(Pos);
      Control := FindVCLWindow(Pos);
      if Assigned(Control) then
        with Control do
          if Assigned(PopupMenu) then
            PopupMenu.Popup(Pos.X, Pos.Y);
    except
      // Don't worry about it
    end;
end;

However, FindVCLWindow always appears to return Nil. I can't see why this doesn't work, I think it should.

Anyone have any clues? I'm sure its something very obvious :-)

Cheers,

Raymond.
LVL 12
rwilson032697Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

fulg0reCommented:
welp, i am not sure about the way to find contorl, yet it is for sure, not the one u use... FindVCL works on Twincontrol... so it WILL find, let's say TPanel... hmmm... maybe a loop on all children of the form, and check of coordinates will help?
0
rwilson032697Author Commented:
I initially started using ControlAtPos, but it only looks at the direct children, so a treeview embedded in a panel on a form wouldn't be picked up (at least thats what appeared to be happening, so I switched to FindVCLWindow...)

Cheers,

Raymond.
0
aldynCommented:
Nice puzzle :-)

1) If you set breakpoint before or exactly on FindVCLWindow then Control will be nil because window is switched to the source code window.
2) The code
        with Control do
          if Assigned(PopupMenu) then
checks the PopupMenu of the form, not of the control itself, because this property is declared as PROTECTED in TControl. Change it to
if Assigned(Tzzz(Control).PopupMenu) then
Tzzz(Control).PopupMenu.Popup(Pos.X, Pos.Y);
where Tzzz is any descendant of TControl wich publishes property PopupMenu
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rwilson032697Author Commented:
aldyn:

1) Yes - you are right! I'll try it without the breaks!

Yup - FindVCLWindow works..

Here's the code that now works:

type
  THackedControl = class(TControl)
  end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);

var
  Pos : TPoint;
  TheControl : TControl;
  HackedControl : THackedControl;

begin
  if (ssShift in Shift) and (Key = vk_F10) then // pop up the context menu
    try
      GetCursorPos(Pos);
      TheControl := FindVCLWindow(Pos) as TControl;
      if Assigned(TheControl) then
        if Assigned(THackyControl(TheControl).PopupMenu) then
          begin
            THackyControl(TheControl).PopupMenu.Popup(Pos.X, Pos.Y);
            key := 0; // swallow the key
          end;
    except
      // Don't worry about it
    end;
end;

Thanks for the help out. Its getting too late for coding :-)

Cheers,

Raymond.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.