Editor Gadget, use the tab key

Just starting out? Need help? Post your questions and find answers here.
RJP Computing
Enthusiast
Enthusiast
Posts: 202
Joined: Sun Apr 27, 2003 4:44 am
Location: Michigan, USA
Contact:

Post by RJP Computing »

RJP Computing wrote:I have tried all that I can think of and still can't get the 'TAB' key to work.
I used GPI's code but still no go. All I have on my window is a menu,
toolbar, Editor gadget, and status bar. I have tried to use NoTabJump on
all of them. Still know luck. Please help.


Here is an example to work off of

.... Code removed

Thanks
Is this a Bug? Does anybody know? Should I start a thread in the bug section? I really think that the 'TAB' Key should work in the Editor Gadget.
-Ryan
RJP Computing

Ubuntu 8.10/WinXP, AMD Athlon 64 3000+, 1000MB RAM, AC 97 Audio, nVidia GeForce 7600GT 512MB
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Editor Gadget, use the tab key

Post by Keya »

The Tab key still doesn't work by default ... for example, create New Form, simply add two Editor controls, and F5 to Run ... ensure Editor1 has focus, and press Tab. It inserts an actual Tab character.

Does anybody know how to change this behavior so a tab character isn't inserted, but instead the focus moves to the next control? (is this a #WS_TABSTOP thing perhaps?)

[edit] I just came across this:
In the past, a lot of people were asking for the EditorGadget to actually act
this way, instead of TAB switching to the next gadget.

So then Fred happily changed it in v3.93 according to all the wishes:

Fixed: TAB in an EditorGadget() doesn't give the focus to others gadgets anymore but insert a Tab

And now people want it to work the old way again? :roll: Give Fred a break.[

So it seems that the Editor control USED to behave normally (ie. Tab key sends focus to next control), but is now "broken" (or "fixed" depending on POV!) to insert Tab instead of switch Focus :(
It seems pretty clear that coders need this as a choice, instead of forced one way or the other. In it's current "fixed" state of inserting a Tab character it's actually just "broken" it for my needs.

Inserting a Tab character seems only useful for large text processing (ive never had a single use for it), whereas the vast majority of editor controls are small texts that never need Tab characters. So, this "fix" is a hindrance the vast majority of the time. Or all the time in my case. Anyone know how to unbreak it? :)
jwrjrjwrjr
User
User
Posts: 14
Joined: Sat May 23, 2015 3:12 am
Location: The other Georgia

Re: Editor Gadget, use the tab key

Post by jwrjrjwrjr »

The Tab key is working 'correctly' for me. Pressing the Tab key moves from editor gadget to editor gadget as desired. A/The trick is to be sure the gadgets are created, enumerated or numbered in the order you want the tab to proceed (Tab order, I think it is.) I'm using v5.31 on Win7 x 32 and x64. Now if the Team would allow the 'correct' use of the Return key in v5.4 I would be on the Moon!
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Editor Gadget, use the tab key

Post by Keya »

hrm, well I don't know if that's a good thing that it works as a Focus switch for you, and a Tab character for me! Ive only tested using XP-32
User avatar
Vera
Addict
Addict
Posts: 858
Joined: Tue Aug 11, 2009 1:56 pm
Location: Essen (Germany)

Re: Editor Gadget, use the tab key

Post by Vera »

Hi,
in the WinApi-Lib one can find two codes dealing with the tab functionality for the EditorGadget() allowing to use it one way or the other.

Focusing Gadgets with tab key

Code: Select all

EnableExplicit

Global lpPrevFunc

Procedure RichEditProc(hWnd,uMsg,wParam,lParam)
  Select uMsg
    Case #WM_CHAR
      If wParam = #VK_TAB
        SetFocus_(GetWindow_(hWnd,#GW_HWNDNEXT))
        ProcedureReturn 1
      EndIf
  EndSelect
  ProcedureReturn CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
EndProcedure

If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  EditorGadget(1,10,10,100,100,0)
  EditorGadget(2,120,10,100,100,0)
  
  lpPrevFunc = SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@RichEditProc())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Off tab [Tab key turned off]

Code: Select all

Global lpPrevFunc

Procedure RichEditProc(hWnd,uMsg,wParam,lParam)
  If wParam = #VK_TAB
    ProcedureReturn 0
  EndIf
  ProcedureReturn CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)  
EndProcedure

If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  EditorGadget(1,10,10,480,230)
  
  lpPrevFunc = SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@RichEditProc())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
jwrjrjwrjr
User
User
Posts: 14
Joined: Sat May 23, 2015 3:12 am
Location: The other Georgia

Re: Editor Gadget, use the tab key

Post by jwrjrjwrjr »

Keya

The description in the Help files for AddKeyboardShortcut has the following Note:

" By default, a window already has the #PB_Shortcut_Tab and #PB_Shortcut_Tab|#PB_Shortcut_Shift shortcuts to handle tab and shift-tab correctly trough the gadgets. "

I wonder if you have somehow created your window without these default?

Best,
John
User avatar
Michael Vogel
Addict
Addict
Posts: 2835
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Editor Gadget, use the tab key

Post by Michael Vogel »

Vera's code works fine for one gadget, but is there a simple way to allow changing the active gadget within a dialog using multiple EditorGadgets?

Using SetWindowCallback does not work fine for me...

Code: Select all

Global lpPrevFunc

Procedure Tab(hWnd,uMsg,wParam,lParam)

	If umsg=#WM_CHAR And wParam=#VK_TAB
		Debug GetActiveGadget()
		SetActiveGadget(GetActiveGadget()+1)
	EndIf

	ProcedureReturn CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
	;ProcedureReturn #PB_ProcessPureBasicEvents

EndProcedure

If OpenWindow(0,0,0,500,300,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

	EditorGadget(1,10,10,480,130)
	EditorGadget(2,10,140,480,130)
	ButtonGadget(3,10,280,480,20,"ok")
	SetActiveGadget(1)

	AddKeyboardShortcut(0,#PB_Shortcut_Tab,999)

	;lpPrevFunc=SetWindowLongPtr_(GadgetID(0),#GWL_WNDPROC,@Tab()); works for one Gadget
	lpPrevFunc=SetWindowLongPtr_(WindowID(0),#GWL_WNDPROC,@Tab()); nope
	;SetWindowCallback(@Tab(),0); :(

	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

...and BindEvent() can detect the tabs but the editor text will be modified - so the following code is a workaround by removing the tab manually...

Code: Select all

Procedure Tabs()

	Protected gadget

	gadget=GetActiveGadget()

	If GadgetType(gadget)=#PB_GadgetType_Editor
		If EventType()=#WM_CUT
			If EventwParam()=#TAB
				SetGadgetText(gadget,ReplaceString(GetGadgetText(gadget),#TAB$,""))
				SetActiveGadget(GetActiveGadget()+1)
			EndIf
		EndIf
	EndIf

EndProcedure

If OpenWindow(0,0,0,500,300,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

	EditorGadget(1,10,10,480,130)
	EditorGadget(2,10,140,480,130)
	ButtonGadget(3,10,280,480,20,"ok")
	SetActiveGadget(1)

	BindEvent(#PB_Event_Gadget,@Tabs())

	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5024
Joined: Sun Apr 12, 2009 6:27 am

Re: Editor Gadget, use the tab key

Post by RASHAD »

Hi MV
For windows

Code: Select all

Global lpPrevFunc

Procedure EditProc(hWnd, uMsg, wParam, lParam) 
  Select uMsg     
    Case #WM_CHAR
      If wParam = #VK_TAB
        SetFocus_(GetWindow_(hWnd,#GW_HWNDNEXT))
        ProcedureReturn 0
      EndIf     
  EndSelect 
  ProcedureReturn CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
EndProcedure

If OpenWindow(0,0,0,500,300,"Window",#PB_Window_SystemMenu| #PB_Window_ScreenCentered)

  EditorGadget(1,10,10,480,100)
  ButtonGadget(2,10,120,40,20,"Test")
  EditorGadget(3,10,150,480,110)
  ButtonGadget(4,10,270,40,20,"ok")
  SetActiveGadget(1)

  lpPrevFunc = SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@EditProc())
  lpPrevFunc = SetWindowLongPtr_(GadgetID(3),#GWL_WNDPROC,@EditProc())
  SendMessage_(WindowID(0), #WM_CHANGEUISTATE, 2 | (1 << 16), 0)
Repeat
  Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
       
  EndSelect
ForEver       
EndIf
Egypt my love
BarryG
Addict
Addict
Posts: 4305
Joined: Thu Apr 18, 2019 8:17 am

Re: Editor Gadget, use the tab key

Post by BarryG »

Rashad, how do I stop/end the following when I no longer need it? Setting lpPrevFunc=0 doesn't work. Do I need to destroy EditProc() somehow? Or does it automatically die when I use CloseWindow() for the window that the gadget is on?

Code: Select all

lpPrevFunc=SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@EditProc())
Also, do the parameters after #WM_CHANGEUISTATE (below) need to be specific to my window?

Code: Select all

SendMessage_(WindowID(0), #WM_CHANGEUISTATE, 2 | (1 << 16), 0)
User avatar
TI-994A
Addict
Addict
Posts: 2790
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Editor Gadget, use the tab key

Post by TI-994A »

BarryG wrote:...how do I stop/end the following when I no longer need it? Setting lpPrevFunc=0 doesn't work...

Code: Select all

lpPrevFunc=SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@EditProc())
Like this:

Code: Select all

SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, lpPrevFunc)
The original process should be restored only if the callback is no longer required. Otherwise, all relevant cleanup is performed upon program termination.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
BarryG
Addict
Addict
Posts: 4305
Joined: Thu Apr 18, 2019 8:17 am

Re: Editor Gadget, use the tab key

Post by BarryG »

TI-994A wrote:Like this:

Code: Select all

SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, lpPrevFunc)
Hi TI-994A! Thanks! So I'll just do that before CloseWindow() for my code? Because the window is opened at various times in my app, and I want to cleanly end EditProc() between each window-opening occurrence.
User avatar
TI-994A
Addict
Addict
Posts: 2790
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Editor Gadget, use the tab key

Post by TI-994A »

BarryG wrote:...I'll just do that before CloseWindow() for my code? Because the window is opened at various times in my app, and I want to cleanly end EditProc() between each window-opening occurrence.
Absolutely. As long as the program has not ended, we'd have to manage and maintain all subclassing manually.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5024
Joined: Sun Apr 12, 2009 6:27 am

Re: Editor Gadget, use the tab key

Post by RASHAD »

Hi BarryG
Switch between subclassed Gadget and normal one

Code: Select all

Procedure EditProc(hWnd, uMsg, wParam, lParam)
  Protected oldproc = GetProp_(hWnd, "oldproc")
  Select uMsg
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "oldproc")
           
    Case #WM_CHAR
      If wParam = #VK_TAB
        SetFocus_(GetWindow_(hWnd,#GW_HWNDNEXT))
        ProcedureReturn 0
      EndIf     
  EndSelect
  ProcedureReturn CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)
EndProcedure

If OpenWindow(0,0,0,500,300,"Window",#PB_Window_SystemMenu| #PB_Window_ScreenCentered)

  EditorGadget(1,10,10,480,100)
  ButtonGadget(2,10,120,40,20,"Set")
  ButtonGadget(3,60,120,40,20,"Remove")
  EditorGadget(4,10,150,480,110)
  ButtonGadget(5,10,270,40,20,"Set")
  ButtonGadget(6,60,270,40,20,"Remove")
  SetActiveGadget(1)

  oldproc = SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, @EditProc())
  SetProp_(GadgetID(1), "oldproc", oldproc)
  oldproc = SetWindowLongPtr_(GadgetID(4), #GWL_WNDPROC, @EditProc())
  SetProp_(GadgetID(4), "oldproc", oldproc)
  SendMessage_(WindowID(0), #WM_CHANGEUISTATE, 2 | (1 << 16), 0)
  
Repeat
  Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 2
            oldproc = SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, @EditProc())
            SetProp_(GadgetID(1), "oldproc", oldproc)
          Case 3
            RemoveProp_(GadgetID(1), "oldproc")
            SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, oldproc)            
          Case 5
            oldproc = SetWindowLongPtr_(GadgetID(4), #GWL_WNDPROC, @EditProc())
            SetProp_(GadgetID(4), "oldproc", oldproc)            
          Case 6
            RemoveProp_(GadgetID(4), "oldproc")
            SetWindowLongPtr_(GadgetID(4), #GWL_WNDPROC, oldproc)
          
        EndSelect
       
  EndSelect
ForEver       
EndIf
Egypt my love
BarryG
Addict
Addict
Posts: 4305
Joined: Thu Apr 18, 2019 8:17 am

Re: Editor Gadget, use the tab key

Post by BarryG »

Rashad, I actually got a "Stack overflow" error (for line 13) while testing your latest code. But don't worry about it: TI-994A answered my questions and your previous code is working great for me.
User avatar
TI-994A
Addict
Addict
Posts: 2790
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Editor Gadget, use the tab key

Post by TI-994A »

RASHAD wrote:

Code: Select all

          Case 3
            RemoveProp_(GadgetID(1), "oldproc")
            SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, oldproc)
Hi Rashad. Just wondering if the return value of the RemoveProp() function should be captured before restoring the process, like so:

Code: Select all

          Case 3
            oldproc = RemoveProp_(GadgetID(1), "oldproc")
            SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, oldproc)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Post Reply