alogrep 0 Posted yesterday at 01:42 AM Hi I got this neat piece of code froma OpenAI GPT searc type TMyHintWindow = class(THintWindow) protected procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; end; procedure TMyHintWindow.WMLButtonDown(var Message: TWMLButtonDown); begin // Close the hint window when clicked ReleaseHandle; end; I put the first part in the interface section, the second in the implementation. But the the WMLButtonDown (clic left button, right?) never gets triggered. What is missing to make it work? Also, in case I make it work, I lso have set the timerr to hide it after 2 seconds. In the timere I use wh (The TMyHintWindow control) if wh <> Nil then begin wh.releasehandle. wh.free; wh:=Nil; end. How can I make the same inside the WMLButtonDown event? Thanks very much. wh Share this post Link to post
Lars Fosdal 1864 Posted 21 hours ago Did you override the HintWindowClass before Application.Run is executed? https://docwiki.embarcadero.com/Libraries/Athens/en/Vcl.Controls.THintWindowClass Share this post Link to post
Remy Lebeau 1611 Posted 12 hours ago (edited) The correct link is https://docwiki.embarcadero.com/Libraries/en/Vcl.Forms.HintWindowClass Also, you don't need to assign the HintWindowClass before Application.Run() is called (though you certainly can). Just be sure to assign it before any hints are displayed at runtime. For instance, in the MainForm's OnCreate event would suffice. Also, if you don't want to override the hint behavior globally, you can customize the hint on a per-invocation basis by using the TApplication[Events].OnShowHint event. It gives you access to a THintInfo describing the hint that is about to be displayed, which has a HintWindowClass field (amongst many others). Edited 12 hours ago by Remy Lebeau Share this post Link to post
alogrep 0 Posted 9 hours ago Thanks both. But it still does not work. This is the code. I crated a unit unit myhint; interface uses classes, messages,graphics,controls, comctrls; type TMyHintWindow = class(THintWindow) protected procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; public constructor Create(AOwner: TComponent); override; end; implementation constructor TMyHintWindow.Create(AOwner: TComponent); begin inherited Create(AOwner); Color := clinfobk; end; procedure TMyHintWindow.WMLButtonDown(var Message: TWMLButtonDown); begin // Close the hint window when clicked ReleaseHandle; end; end. unit myhint; interface uses classes, messages,graphics,controls, comctrls; type TMyHintWindow = class(THintWindow) protected procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; public constructor Create(AOwner: TComponent); override; end; implementation constructor TMyHintWindow.Create(AOwner: TComponent); begin inherited Create(AOwner); Color := clinfobk; end; procedure TMyHintWindow.WMLButtonDown(var Message: TWMLButtonDown); begin // Close the hint window when clicked ReleaseHandle; end; end. in the dr: Application.Initialize; HintWindowClass:=TMyHintWindow; Then in the form i include myhint.pas. In the FormCreate I crete the control wh:=TMyhintWindow.crete(nil) The wh constructor is executed (the beakpoint is triggered). But when I clkic on the hintt, the procedure TMyHintWindow.WMLButtonDown(var Message: TWMLButtonDown); begin // Close the hint window when clicked ReleaseHandle; end; is not triggered. Share this post Link to post
Anders Melander 2019 Posted 8 hours ago A window will only receive mouse messages if the mouse cursor is within its client area or it has captured the mouse. I don't think a hint window will satisfy either of those criteria. See also: https://learn.microsoft.com/en-us/windows/win32/inputdev/about-mouse-input 1 Share this post Link to post
Remy Lebeau 1611 Posted 6 hours ago (edited) You don't need to create an instance of your hint class. By setting the HintWindowClass variable, the VCL will instantiate your class when needed. In any case, the reason your code doesn't work is because by default THintWindow responds to WM_NCHITTEST to return HTTRANSPARENT, thus all mouse activity gets directed to the window that is underneath the hint. You can intercept WM_NCHITTEST yourself to return HTCLIENT instead, so thus your WM_LBUTTONDOWN handler will be triggered when clicking on the hint window. However, then you run into a new problem, because as soon as the mouse enters the hint window, it effectively leaves the control underneath the hint, and thus the control hides the hint immediately before you can click on it. You can work around that by having TMyHintWindow override the virtual ShouldHideHint() method to return False. Then, you will have opportunity to click on the hint window. However, then you run into a new problem, because as soon as your click closes the hint, the mouse will effectively re-enter the control that was underneath the hint, and the control will reshow the hint again. Isn't this fun? What exactly are you trying to accomplish by messing with the hint window's default behavior? Edited 6 hours ago by Remy Lebeau Share this post Link to post