Recent

Author Topic: Make visual components non-focusable  (Read 1973 times)

pleumann

  • Jr. Member
  • **
  • Posts: 95
Make visual components non-focusable
« on: September 27, 2023, 08:14:30 pm »
Hi,

I have several components on the top level of my form. Some should receive focus and be navigable by tab and cursor keys (namely some TBitBtn instances) and some I would not expect to or want to receive focus (namely a TPanel and a TStaticText). The latter two are focusable, though. Not by tab, but by cursor keys. This can confuse users because the elements don't have any highlight that would indicate their focused state.

How can I prevent this? I don't want set Enabled := False because I don't want the grayed-out appearance that comes with it.

Best regards
Joerg

(FPC 3.0.2 & Lazarus 2.2.6  on Mac, Ubuntu and Raspberry Pi.)
« Last Edit: September 27, 2023, 08:18:57 pm by pleumann »

zeljko

  • Hero Member
  • *****
  • Posts: 1668
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: Make visual components non-focusable
« Reply #1 on: September 27, 2023, 08:42:01 pm »
TabStop := False for tabbing, probably ControlStyle := ControlStyle + [csNoFocus].... works with qt4,5,6.

pleumann

  • Jr. Member
  • **
  • Posts: 95
Re: Make visual components non-focusable
« Reply #2 on: September 27, 2023, 09:08:20 pm »
TabStop := False for tabbing, probably ControlStyle := ControlStyle + [csNoFocus].... works with qt4,5,6.

TabStop is off already. I tried your snippet for everything that should not receive focus. Doesn't work. No Qt, though. MacOS native UI and GTK2 on Linux. Does it work only on Qt?

Is that a bug? I mean, why should a TStaticText ever receive focus?

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Make visual components non-focusable
« Reply #3 on: September 28, 2023, 12:02:46 am »
1. Put in your "uses" this -> "LCLType"
2. Go to object inspector, highlight your form (Form1?)
3. activate KeyPreview = True inside properties
4. Inside "Events" go to "OnKeyDown" and doubleclick the free space to create an empty handler
5. copy and paste this code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  2.   );
  3. var
  4.   NextControl: TWinControl;
  5. begin
  6.   NextControl := nil;
  7.   if (Key = VK_RIGHT) or (Key = VK_DOWN) then
  8.     NextControl := FindNextControl(ActiveControl, True, True, False);
  9.   if (Key = VK_LEFT) or (Key = VK_UP) then
  10.     NextControl := FindNextControl(ActiveControl, False, True, False);
  11.   if (NextControl <> nil) then
  12.     begin
  13.       NextControl.SetFocus;
  14.       Key := 0;
  15.     end;
  16. end;
6. Run your application, now only things that have TabStop and are focusable should be valid as a target by arrow keys
7. Reply in here if this is what you wanted to achieve
« Last Edit: September 28, 2023, 12:11:48 am by KodeZwerg »
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jamie

  • Hero Member
  • *****
  • Posts: 6733
Re: Make visual components non-focusable
« Reply #4 on: September 28, 2023, 02:24:16 am »
it must be a bug, it works fine on Win32/Windows, turn off tabstop and it does not tab there.

Personally, I call this a bug all around that it accepts a tab operation to start with, just like the TGroupBox, tab Bug.
The only true wisdom is knowing you know nothing

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Make visual components non-focusable
« Reply #5 on: September 28, 2023, 10:44:43 am »
it must be a bug, it works fine on Win32/Windows, turn off tabstop and it does not tab there.

Personally, I call this a bug all around that it accepts a tab operation to start with, just like the TGroupBox, tab Bug.
With arrow key, at least on windows, it is a normal behavior that it try to switch to next control, no matter if focusable or not.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

pleumann

  • Jr. Member
  • **
  • Posts: 95
Re: Make visual components non-focusable
« Reply #6 on: September 28, 2023, 05:20:17 pm »
1. Put in your "uses" this -> "LCLType"
2. Go to object inspector, highlight your form (Form1?)
...
6. Run your application, now only things that have TabStop and are focusable should be valid as a target by arrow keys
7. Reply in here if this is what you wanted to achieve

I simplified your idea a bit since I have a line of buttons that are all in TabOrder, so I know which is first and which is last:

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
  2.   Shift: TShiftState);
  3. begin
  4.   if ((Key = VK_Up) or (Key = VK_Left)) and (ActiveControl = LanguageBtn) then
  5.     Key := 0
  6.   else if ((Key = VK_Down) or (Key = VK_Right)) and (ActiveControl = AboutBtn) then
  7.     Key := 0;
  8. end;
  9.  

Interestingly, all other attempts to detect an invalid element (such as my Panel) getting selected and using ActiveControl := ... or SetFocus to jump back to the previous one failed, even if using PostMessage. The only other thing that would work was a timer checking the ActiveControl on a regular basis, but that I found somewhat ugly.

Thanks!
Joerg
« Last Edit: September 28, 2023, 05:21:55 pm by pleumann »

pleumann

  • Jr. Member
  • **
  • Posts: 95
Re: Make visual components non-focusable
« Reply #7 on: September 28, 2023, 05:21:30 pm »
it must be a bug, it works fine on Win32/Windows, turn off tabstop and it does not tab there.

Personally, I call this a bug all around that it accepts a tab operation to start with, just like the TGroupBox, tab Bug.
With arrow key, at least on windows, it is a normal behavior that it try to switch to next control, no matter if focusable or not.

So it's probably behavior inherited from Windows or Delphi. Anyway, workaround does the job. I'm happy. :)

zeljko

  • Hero Member
  • *****
  • Posts: 1668
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: Make visual components non-focusable
« Reply #8 on: September 28, 2023, 07:35:39 pm »
TabStop := False for tabbing, probably ControlStyle := ControlStyle + [csNoFocus].... works with qt4,5,6.

TabStop is off already. I tried your snippet for everything that should not receive focus. Doesn't work. No Qt, though. MacOS native UI and GTK2 on Linux. Does it work only on Qt?

Is that a bug? I mean, why should a TStaticText ever receive focus?

csNoFocus should work on all Qt(4,5,6) controls, just tested TEdit and it works. It is bug if csNoFocus is not respected by widgetset.

pleumann

  • Jr. Member
  • **
  • Posts: 95
Re: Make visual components non-focusable
« Reply #9 on: September 28, 2023, 08:20:01 pm »
csNoFocus should work on all Qt(4,5,6) controls, just tested TEdit and it works. It is bug if csNoFocus is not respected by widgetset.

If I find the time I will check in an isolated example on Mac and Linux/GTK2. If it persists I will file a bug.

pleumann

  • Jr. Member
  • **
  • Posts: 95
Re: Make visual components non-focusable
« Reply #10 on: September 30, 2023, 09:41:08 am »
Can confirm the behavior exists also in a trivial new project (attached). A quick grep though the LCL source shows that only Qt and the old Carbon interface make use of csNoFocus at all.

Code: Bash  [Select][+][-]
  1. bash-3.2$ pwd
  2. /Users/joerg/Temp/lazarus/lcl/interfaces
  3. bash-3.2$ egrep -r csNoFocus *
  4. carbon/carbonproc.pp:  if not (csNoFocus in ControlStyle) then
  5. carbon/carbonprivate.pp:    AStyle := AStyle + [csNoFocus];
  6. qt/qtwidgets.pas:       (csNoFocus in LCLObject.ControlStyle)
  7. qt/qtwidgets.pas:      if (csNoFocus in LCLObject.ControlStyle) then
  8. qt/qtwsforms.pp:    if (csNoFocus in TCustomForm(AWidget.LCLObject).ControlStyle) then
  9. qt5/qtwidgets.pas:       (csNoFocus in LCLObject.ControlStyle)
  10. qt5/qtwidgets.pas:      if (csNoFocus in LCLObject.ControlStyle) then
  11. qt5/qtwsforms.pp:    if (csNoFocus in TCustomForm(AWidget.LCLObject).ControlStyle) then
  12.  

Is it worth filing a bug?

sstvmaster

  • Sr. Member
  • ****
  • Posts: 300
greetings Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

 

TinyPortal © 2005-2018