Recent

Author Topic: TTabControl no keyboard support?  (Read 9207 times)

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
TTabControl no keyboard support?
« on: June 02, 2017, 08:02:08 pm »
Am I missing something, why I cannot switch to other tabs using keyboard? I want users to be able to use both mouse and keyboard to navigate on TTabControl.

I tried TPageControl, it worked correctly. It has [nboKeyboardTabSwitch] in TPageControl.Options.

To reproduce my issue:
Drop a TTabControl (under Common Controls) to a form. Right click and add some tabs. Run it.

So the question is:
Is it a bug, or unimplemented feature, or I did something wrong?

edit: It may have been implemented, but it's didn't work on my Linux Gtk2 tests.

Note:
Ubuntu Mate 16.10 64-bit Lazarus 1.6.4 Gtk2
« Last Edit: June 03, 2017, 05:08:02 pm by Handoko »

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 220
Re: TTabControl no keyboard support?
« Reply #1 on: June 02, 2017, 09:14:37 pm »
Just an information: TTabControl is a TPageControl descendant in Lazarus. (Well it shouldn't be so :/)

=> It offers just the same functionality as TPageControl with some options/properties set to different ones. IMO your TTabControl doesn't have focus and so it doesn't change the tabs.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #2 on: June 03, 2017, 11:01:22 am »
IMO your TTabControl doesn't have focus and so it doesn't change the tabs.

TTabControl should have focus. Because on the Object Inspector, I can see TabOrder and TabStop properties. See my attached screenshot. Also we know, a GUI application is not a good program if it can't be navigated using keyboard (except on mobile phones).

Luckily I found that TTabControl's ancestor has OnKeyDown event, so using workaround suggested by SkyKhan (on previous thread), I can write my own keyboard navigation code.
http://forum.lazarus.freepascal.org/index.php/topic,37022.msg247542.html#msg247542

So far, this issue is solved for my case. But the bugs are still present.

- Issue #1
TTabControl cannot use keyboard to switch tab.

- Issue #2
To make TTabControl more customizable, please publish OnKeyDown, OnKeyPress and OnKeyUp events.

- Issue #3
To make TPageControl more customizable, please publish OnKeyDown, OnKeyPress and OnKeyUp events.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #3 on: June 03, 2017, 01:06:12 pm »
Finally, I have finished writing the code to make the TTabControl to be able to navigate using keyboard. Everything seems to work correctly, but I found an issue. To reproduce the issue:

01. Run the program
02. Click the tab "one"
03. The keyboard keys to switch tab now works weird

I tested it on Linux 64-bit Lazarus 1.6.4 Gtk2. Any volunteer please help me test the code and solve the problem. You can downloaded the zip file on the attachments.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Graphics, Dialogs, ComCtrls, LCLType, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     btnInfo: TButton;
  16.     btnQuit: TButton;
  17.     Label1: TLabel;
  18.     TabControl1: TTabControl;
  19.     procedure btnInfoClick(Sender: TObject);
  20.     procedure btnQuitClick(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure TabControl1Change(Sender: TObject);
  23.     procedure TabControl1Enter(Sender: TObject);
  24.     procedure TabControl1Exit(Sender: TObject);
  25.   private
  26.     procedure TabKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  27.   end;
  28.  
  29. var
  30.   Form1: TForm1;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. type
  39.   TEnableTabControlKeyDown = class(TTabControl);
  40.  
  41. procedure TForm1.FormCreate(Sender: TObject);
  42. begin
  43.   TEnableTabControlKeyDown(TabControl1).OnKeyDown := @TabKeyDown;
  44. end;
  45.  
  46. procedure TForm1.btnInfoClick(Sender: TObject);
  47. begin
  48.   ShowMessage('To navigate on the TabControl, use: ' + #13 +
  49.     '[tab], [shift+tab], [left], [ right], [up], [down]');
  50. end;
  51.  
  52. procedure TForm1.btnQuitClick(Sender: TObject);
  53. begin
  54.   Close;
  55. end;
  56.  
  57. procedure TForm1.TabControl1Change(Sender: TObject);
  58. begin
  59.   Label1.Caption := 'You are on tab #' + IntToStr(TabControl1.TabIndex+1);
  60. end;
  61.  
  62. procedure TForm1.TabControl1Enter(Sender: TObject);
  63. begin
  64.   TabControl1.Color := clHighlight;
  65. end;
  66.  
  67. procedure TForm1.TabControl1Exit(Sender: TObject);
  68. begin
  69.   TabControl1.Color := clBackground;
  70. end;
  71.  
  72. procedure TForm1.TabKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  73. var
  74.   CurrentTabIndex: Integer;
  75. begin
  76.   if not(Sender is TTabControl) then Exit;
  77.   CurrentTabIndex := TEnableTabControlKeyDown(TabControl1).TabIndex;
  78.   case Key of
  79.     VK_TAB:   if (ssShift in Shift) then
  80.                  Dec(CurrentTabIndex)
  81.               else
  82.                 Inc(CurrentTabIndex);
  83.     VK_LEFT:  Dec(CurrentTabIndex);
  84.     VK_RIGHT: Inc(CurrentTabIndex);
  85.     VK_UP:    Form1.SelectNext(TabControl1, False, True);
  86.     VK_DOWN:  Form1.SelectNext(TabControl1, True, True);
  87.   end;
  88.   if (CurrentTabIndex < 0) then CurrentTabIndex := TabControl1.Tabs.Count-1;
  89.   if (CurrentTabIndex > TabControl1.Tabs.Count-1) then CurrentTabIndex := 0;
  90.   TEnableTabControlKeyDown(TabControl1).TabIndex := CurrentTabIndex;
  91.   Key := 0;
  92. end;
  93.  
  94. end.
« Last Edit: June 03, 2017, 01:08:38 pm by Handoko »

sky_khan

  • Guest
Re: TTabControl no keyboard support?
« Reply #4 on: June 03, 2017, 01:11:37 pm »
Define weird ? It seems to work on windows.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #5 on: June 03, 2017, 01:15:12 pm »
After started the program, the tab switching works correctly using [tab], [shift+tab],
, [ right], [up], [down].

But if after started the program, I click the tab "one" immediately then I must press the navigation keys repeatedly about 10 times or more the to be able to navigate using keyboard normally. It's definitely a bug perhaps on Gtk only, or maybe something wrong on my system.

Edit:
The html autoformating feature causes the text in the first paragraph looks weird. Not my fault.
« Last Edit: June 03, 2017, 01:20:22 pm by Handoko »

sky_khan

  • Guest
Re: TTabControl no keyboard support?
« Reply #6 on: June 03, 2017, 01:20:28 pm »
Nope. It works here with any key or mouse combination.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #7 on: June 03, 2017, 01:22:38 pm »
Did you tested using Linux Gtk2?

sky_khan

  • Guest
Re: TTabControl no keyboard support?
« Reply #8 on: June 03, 2017, 01:32:40 pm »
After you asked, I tested it on Linux-gtk2 in Virtualbox too. It works. I think you have a serious configuration problem with your os.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #9 on: June 03, 2017, 02:00:36 pm »
I used CompizConfig to add effects on my desktop appearance. But I have just tried to disable CompizConfig and switched my Window Manager back to Marco (No compositor), and restarted my computer. The problem is still present on my Ubuntu Mate 16.10 64-bit.

The issue is 100% reproducible if I click the first tab immediately after program started. And sometimes happens if you press the left-right keys followed with tab clicking using mouse repeatedly quickly.

Now, I do not know what should I do.

Anyways, thanks for testing.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #10 on: June 03, 2017, 02:45:40 pm »
 :D Something has sent the focus a black hole so it can't be detected.

I added a status bar and a timer to detect the current active control. Here is the code:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. begin
  3.   StatusBar1.SimpleText := Form1.ActiveControl.Name;
  4. end;

After the program started, the active control (current focus) is TabControl1. But if I click the tab "one" then the active control is nowhere to be found.  :o

Please download the test.zip to see if it also happens on your test.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: TTabControl no keyboard support?
« Reply #11 on: June 03, 2017, 03:11:20 pm »
You've fallen from the deep end if you don't mind me say so. The thinks are way, way, waaaaay easier than what you are doing. Here is a small demo application build with lazarus 1.4.4 just to prove a point.
run, press ctrl+tab to go forward ctrl+shift+tab to go backwards.

EDIT:
  By clicking on the tab the tabit self becomes focused and a focus rect is drawn around the text in windows. Pressing tab then uses the default behavior that is to rotate through all the visible control in the form but you can still navigate the tab (when a tab is focused) using the arrow keys (the default behavior). The bug is that when the tabcontrol get focus it does not pass it along to the active tab instead it keeps it for it self. try setting the tabstops to false and see if you both rotate the visible controls with tab and when the tab sheet is focused the tabs with arrows.
« Last Edit: June 03, 2017, 03:22:44 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

sky_khan

  • Guest
Re: TTabControl no keyboard support?
« Reply #12 on: June 03, 2017, 03:11:38 pm »
try this
Code: Pascal  [Select][+][-]
  1.   StatusBar1.SimpleText := Format('%s [%s]',[ActiveControl.Name,ActiveControl.ClassName]);
  2.  

apparently there is some kind of internal control for tab headers and it is get focused but I dont know about Lazarus internals about this subject.
Btw, it still works! :)

sky_khan

  • Guest
Re: TTabControl no keyboard support?
« Reply #13 on: June 03, 2017, 03:30:43 pm »
Btw, I think I would just use a page control. Why do you need a tab control anyway ? It's tabs are not a container. It just makes things harder.

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: TTabControl no keyboard support?
« Reply #14 on: June 03, 2017, 03:45:01 pm »
Code: Pascal  [Select][+][-]
  1.   StatusBar1.SimpleText := Format('%s [%s]',[ActiveControl.Name,ActiveControl.ClassName]);
  2.  

I saw it now, it was [TNoteBookStringTabControl]. But my TabControl's focus is still trapped, the only ways to release it, are using mouse click or arrow keypressing repeatedly.

No, for my case PageControl is not suitable, I don't need containers. I am writing a program that the object is same/shared on all the tabs, the tabs are not predefined on design time but can added/removed by user on runtime. Not to mentiond, i found a bug on TPageControl yesterday, on my test it needs pressing tab twice to switch tab.

THeaderControl could be used but because the appearance is too simple and the tab width is not auto resized on the tab's caption change, so not suitable for my case.

@taazz

Thank you for the solution. It worked. I know TActionList, I just rarely use it. It solves my case now.

Anyways, wouldn't it nice if TTabControl has internal keyboard navigation feature?
« Last Edit: June 03, 2017, 03:52:59 pm by Handoko »

 

TinyPortal © 2005-2018