March 28, 2024, 08:23:19 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Tabbing backwards in Dialog

Started by billhsln, August 02, 2019, 02:20:43 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

billhsln

I have a fairly large program that I control the tabbing going forward.  How would I know that some one tried to do a backward tab.  I can program for it, just don't know how to recognise that the user did a back tab.  For the most part tabbing forward is just adding 1 to a variable that has the current cursor position to get to the next.  I just don't know what to do to figure out what to look for.

Thanks,
Bill
When all else fails, get a bigger hammer.

fasecero

Using @TABSTOP -> default behavior for tabbing backward is SHIFT + tab.

billhsln

August 04, 2019, 10:55:59 AM #2 Last Edit: August 04, 2019, 09:15:23 PM by billhsln Reason: Adding source code for testing.
Ok, I screwed up, it is a Window, not Dialog.  I have the logic built in to go forward, just wondering how I can put in logic to go backwards while tabbing.  Working on sample that I can upload, so you can see exactly what I am doing.  Like I said, it works forward, just need an idea how to tell when some one does a shift tab (guessing read keypress)?

New: Tabbing works forwards and backwards, but I would also like the Enter key to move to the next edit field.  Have tried a couple of things, but they don't work.  Prefer to keep tabbing working both directions.

Thanks,
Bill

Added sample, compile as windows.
When all else fails, get a bigger hammer.

billhsln

Right now all I want is to be able to tell when the user presses the ENTER key.  No matter what I do, it does not show the MESSAGEBOX that I have defined for either the @IDCHAR or the @IDKEYDOWN.  I will end up leaving the tab working as it does, because it now goes back and forth.  Just wanted to allow the user to move forward when pressing the ENTER key, but I can't seem to get it be even be recognized.

Hopefully some one can give me a hint as to what I am doing wrong.

Thanks,
Bill
When all else fails, get a bigger hammer.

fasecero

Is this what you're looking for? Had to remove some code and change some edit styles to get it to work. The focus goes to the next edit when the costumer press ENTER or TAB.

billhsln

I got the program to work that way with the old way I was doing it.  But I need to allow the user to go forwards and backwards via tab and back-tab.  I was hoping for logic that would recognize the enter key and I would handle it in that code to move forward.  Still looking to figure out how to read an ENTER key and know that it was pressed, so I can handle the moving forward.

Also, made 2 changes to your code:

FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21)

You had ce00, but ce00 and ce01 are there for viewing only, not entering.

IF focusedID = lastID THEN nextID = firstID

was

IF focusedID = lastID THEN nextID = lastID

This allows the program to roll back to the top after hitting the bottom.

Also, when I tested the code, I don't know why, but it stopped at the 'Comment Code', but when I clicked into 'Invoice Handling Code', it continued tabbing just fine.  Which is very strange, considering it went thru every edit box, might be since CE19 is not enabled?

Thanks for looking into it.

Bill
When all else fails, get a bigger hammer.

fasecero

OK. I've added your revisions. I've worked for fun a bit more around your code. Now skip any disabled control and will go backwards pressing shift + tab. Good Luck!

SUB subclassProc(hWnd:INT,uMsg:INT,wParam:INT,lParam:INT,uIdSubclass:UINT_PTR,dwRefData:DWORD_PTR),INT
SELECT uMsg
CASE WM_KEYDOWN
SELECT wParam
CASE VK_RETURN
CASE& VK_TAB
IF GetKeyState(VK_SHIFT) THEN
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, -1)
ELSE
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, 1)
ENDIF

RETURN 0
ENDSELECT
ENDSELECT

RETURN DefSubclassProc(hWnd, uMsg, wParam, lParam)
ENDSUB

SUB FocusNextEdit(INT focusedID, INT firstID, INT lastID, INT direction)
INT nextID = focusedID
INT nextHWND = 0

' skip if disabled
DO
nextID = nextID + direction
IF nextID = lastID + 1 THEN nextID = firstID
IF nextID = firstID - 1 THEN nextID = lastID
nextHWND = GetDlgItem(wOpp0100c.hwnd, nextID)
UNTIL IsWindowEnabled(nextHWND)

' set current focus
_SetFocus(nextHWND)
ENDSUB

fasecero

And how about moving to next and previous edit using UP AND DOWN keys, quite intuitive

SUB subclassProc(hWnd:INT,uMsg:INT,wParam:INT,lParam:INT,uIdSubclass:UINT_PTR,dwRefData:DWORD_PTR),INT
SELECT uMsg
CASE WM_KEYDOWN
SELECT wParam
CASE VK_RETURN
CASE& VK_TAB
IF GetKeyState(VK_SHIFT) THEN
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, -1)
ELSE
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, 1)
ENDIF
RETURN 0

CASE VK_UP
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, -1)
RETURN 0
CASE VK_DOWN
FocusNextEdit(GetDlgCtrlID(hWnd), ce02, ce21, 1)
RETURN 0
ENDSELECT
ENDSELECT

RETURN DefSubclassProc(hWnd, uMsg, wParam, lParam)
ENDSUB

billhsln

If I was dealing with PC people, then yes, up and down would be easier, but this is replacing a program that was originally written on an iSeries (AS/400), old green screen.  So, they are used to tabbing to get around.

Will add code from first revision to see what it does.

Funny, when I add your code to my original, it complains about not finding VK_RETURN, but when using yours it does not.  Where is VK_RETURN defined?

Thanks,
Bill
When all else fails, get a bigger hammer.

billhsln

Added the new code and it works exactly as what I am looking for.  Only one more (hopefully minor) addition.

I added:  CONTROLCMD wOpp0100c,nextHWND,@EDSETSELECTION,0,-1 to the end.  However, it does not seem to select the entire field when there is a value in it.

Thanks,
Bill

When all else fails, get a bigger hammer.

billhsln

Never mind, I figured it out.  That code needs to be in the Handler.

Thanks for all the help.  Wish I could understand what you did, but will definitely try to understand the logic you used.  Very interesting, but it does exactly what I have been trying to do.  I have been fooling with this for over a week.

So, thank you again,
Bill
When all else fails, get a bigger hammer.

fasecero

No problem. Thanks. One final sugestion, you could changle the background color of the focused edit to give the costumer a visual "clue" about where the focus resides, taking into account the number of input controls.

SUB FocusInit(INT firstID, INT lastID)
INT j

' subclass all edits
FOR j = firstID TO lastID
SetWindowSubclass(GetDlgItem(wOpp0100c.hwnd, j), &subclassProc, subclassID, 0)
NEXT j

' get the focused edit and change its background color
INT handle = GetFocus()

IF handle THEN
INT id = GetDlgCtrlID(handle)
IF id THEN SETCONTROLCOLOR(wOpp0100c, id, RGB(0,0,0), RGB(80,220,100))
ENDIF
ENDSUB

SUB FocusNextEdit(INT focusedID, INT firstID, INT lastID, INT direction)
INT nextID = focusedID
INT nextHWND = 0

' skip if disabled
DO
nextID = nextID + direction
IF nextID = lastID + 1 THEN nextID = firstID
IF nextID = firstID - 1 THEN nextID = lastID
nextHWND = GetDlgItem(wOpp0100c.hwnd, nextID)
UNTIL IsWindowEnabled(nextHWND)

' change backcolors
SETCONTROLCOLOR(wOpp0100c, nextID, RGB(0,0,0), RGB(80,220,100))
SETCONTROLCOLOR(wOpp0100c, focusedID, RGB(0,0,0), RGB(255,255,255))

' set current focus
_SetFocus(nextHWND)
ENDSUB

billhsln

Fantastic idea!!!  I love it, never even thought about it, but yes.  Will definitely make it easier on the user.  Will add code as soon as possible.

Thank you,
Bill
When all else fails, get a bigger hammer.

fasecero

Sorry, I've only just realized that the coloring have to be moved from FocusNextEdit(...) to WM_SETFOCUS / WM_KILLFOCUS to work properly after a button press, or after a random focus change with the mouse. Have fun!

CASE WM_SETFOCUS
id = GetDlgCtrlID(hWnd)
SETCONTROLCOLOR(wOpp0100c, id, RGB(0,0,0), RGB(80,220,100))

CASE WM_KILLFOCUS
id = GetDlgCtrlID(hWnd)
SETCONTROLCOLOR(wOpp0100c, id, RGB(0,0,0), RGB(255,255,255))

billhsln

Figured that out too.  Moved the code and works fine.

Funny thing, there has to be some thing different from having a single program and having a project.  I have run into this before.  The single program (used to create and modify the screen quickly), looks one way, but when I move the code over into the project, the screen looks just a little different.  Well it seems to be this way here too.  Your code works 100% as expected, but when I put it into the project, the back tab does not work on some fields and the enter does not work at all.  I don't understand why it happens, but it does.

Right now, what I have works, it does the forward and backward tabbing, but I can't seem to get the ENTER key to work.

Thanks for your help,
Bill
When all else fails, get a bigger hammer.

fasecero

August 05, 2019, 09:52:47 PM #15 Last Edit: August 05, 2019, 09:56:00 PM by fasecero
Yup that's strange.

Quote from: undefinedthe back tab does not work on some fields

did you change the edit layout IDS?

ENUM_global
...
...
'Edits
ce00
ce01
...
ce21
...
...
ENDENUM

for my code to work it needs all of them being consecutive integers. The jumping is suggesting they are not consecutive...

Quote from: undefinedand the enter does not work at all.

Are you copy / pasting the code? For my code to work it needs every edit with @TABSTOP|@CTEDITMULTI. If you remove @CTEDITMULTI, the enter key will not work.

---

Are you using AUTODEFINE? Maybe some variable is not getting the correct value for not being global... if i have to guess some variable you are using becomes NULL in project mode. I would put message boxes here and there and compare the values between single / project mode.

billhsln

I think you have found it.  I am not using the @CTEDITMULTI, will add that to all the fields and see what happens.  I do have the fields in sequence, but the ENUM looks out of sequence.  Ended up adding a few more fields after I had started, so there are 4 that are out of sequence.  I prefer AUTODEFINE "OFF".

Thanks again,
Bill
When all else fails, get a bigger hammer.

Brian

Been messing with the example in the Help File, and came up with this. I may have gone a bit overboard with the SETCONTROLCOLOR calls - maybe it could be tightened up

Brian