I want to run a piece of code when a specific tab gets selected - I tried to use CHOICE
inside the TabChanging
event, sadly that only gives me the current tab before changing - but how can I check if the tab being changed to, is the tab I want to run the code for?
Try the NewSelection event on the SHEET (not a tab). Then you can check for PROP:ChoiceFEQ.
YourTabFEQ = ?Sheet{PROP:ChoiceFEQ}
With CHOICE(), you just get the position of the tab within the SHEET, which can change as your code gets modified over the years. So ChoiceFEQ is safer.
And I guess I can compare it against the tabs PROP:FEQ
?
The field equate itself, such as ?MyTab.
Against the Tabâs USE(?x_PickMe_PickMe_x)
E.g. if Tab 1 is active then ?Sheet1{PROP:ChoiceFEQ} = ?Tab1
which is probably the value 2 (FEQs are assigned a sequence integer by the compiler).
For Tab 1 the CHOICE(?Sheet1) = 1
⌠currently but CHOICE() could change if the Tabs are reordered, or a new first tab is inserted, and it breaks your code. Using PROP:ChoiceFEQ is more solid code.
SHEET,AT(7,7,101,67),USE(?Sheet1)
TAB('Tab1'),USE(?TAB1)
END
TAB('Tab2'),USE(?TAB2)
END
END
Greetings -
For those who want to see a debug line showing the name of the TAB that is being accessed, the WHICH TAB= line will show you the tab name.
ReturnValue = PARENT.TakeNewSelection()
CASE FIELD()
OF ?SHEET_Lists
UD.Debug('%ControlEvenHandling/?SHEET_Lists/NewSelection/5000')
UD.Debug('WHICH TAB="' & CLIP((?SHEET_Lists{PROP:ChoiceFEQ}){PROP:Value}) & '"')
CASE (?SHEET_Lists{PROP:ChoiceFEQ})
OF (?TAB_PartPrice)
OF (?TAB_Documents)
END
END
Note: Prop:Value leaves out the â&â Ampersand that prefixes the Accelerator Key, while PROP:Text includes it e.g. TAB('By &Vendor')
IIRC youâre right, you canât determine the new tab when you receive EVENT:TabChanging
But you can tell after another trip through the accept loop.
CASE EVENT()
OF EVENT:TabChanging ; POST(EVENT:User:TabChanged)
OF EVENT:TabChanged ; NewTabFEQ = ?Sheet{PROP:ChoiceFEQ}
END
FWIW, I use
Event:APP EQUATE(08000h)
Event ITEMIZE(EVENT:APP),PRE(Event)
!...
User:TabChanged EQUATE(EVENT:App + 100)
!...
END
After Event:TabChanging the Sheet is going to get an Event:NewSelection so Iâm not sure I see the need for a POST(EVENT:User:TabChanged)
. Think that event would come after the NewSelection unless there was a (,,1)
to make it first.
I have done the below where in Tab Changing I save what Tab I came from so in NewSelection I can know e.g. to go back to it in some cases.
CASE FIELD()
OF ?Sheet1
CASE EVENT()
OF EVENT:TabChanging ; TabChangedFrom_FEQ = ?Sheet{PROP:ChoiceFEQ}
OF EVENT:NewSelection
TabSelectedTo_FEQ = ?Sheet{PROP:ChoiceFEQ}
!Code to decide things based on From and To Tab ...
...
TabChangedFrom_FEQ = 0 !Maybe clear so cannot do it since NewSelection could get posted
END
A typical use for EVENT:TabChanging is to validate the tab and prevent changing. Seems like a CYCLE would prevent the change, but I do not see it in the help. I would think a SELECT(?ControlWithProblem) would.
I donât know of a way in Clarion. Maybe look at MSDN the Windows API on Tab Controls.
I see the TCN_SELCHANGING notification code that looks like EVENT:TabChanging. If you search for TCN_SELCHANGING youâll often find the question âHow to know the New Tabâ.
Excerpt from one answer that says what Iâm saying ⌠Save the Previous Tab in Tab Changing.
But⌠why donât you use OnSelChanging to save the previous Tab selected (in a member variable) and OnSelChanged to retrieve the New tab selected, and donât you do in OnSelChanged what you do in OnSelChanging?
Isnât it easier?
My ancient notes on the subject indicate that it matters if the tab change was user initiated or programattically initiated.
And you wonât always get an event:newselection after you get the event:TabChanging
Correct a SELECT(?Tab)
or SELECT(?Sheet, Number)
does not generate either events. That makes sense to me that if you Change Tabs in Code ⌠then in Code you handle what else you want to happen.
I sometimes have a âNext Tabâ button that will use SELECT(?Tab). I have a function for that which has code to Post New Selection:
SelectNextTab PROCEDURE (LONG SheetFEQ,BOOL NoWrapToFirst=False, BOOL NoEventNewSelect=False)
SheetChoice LONG,AUTO
SheetTabs LONG,AUTO
TabFEQ LONG,AUTO
CODE
SheetChoice = CHOICE(SheetFEQ)
SheetTabs = SheetFEQ{PROP:NumTabs}
IF SheetTabs < 2 THEN RETURN. !If just 1 tab, or would be zero if not a sheet then why bother
LOOP SheetTabs + 1 TIMES !Sanity check to prevent infinite loop
SheetChoice += 1
IF SheetChoice > SheetTabs THEN !Are we beyond the last tab
IF NoWrapToFirst THEN BREAK. !The current tab must be the last visible tab so no change.
SheetChoice = 1
END
TabFEQ = SheetFEQ{PROP:Child, SheetChoice}
IF ~TabFEQ OR TabFEQ{PROP:Hide} THEN CYCLE. !Tab Not Exist (=0) or Tab Hidden then move to Next
SELECT(TabFEQ)
IF ~NoEventNewSelect THEN
POST(EVENT:NewSelection,SheetFEQ) !SELECT(Tab) does NOT cause this event and many windows expect it
!Don't get event POST(EVENT:TabChanging, SheetFEQ) and CANNOT Post it because SELECT() above has already changed tab
END
BREAK
END
RETURN
After messing with this for a couple of wizard procedures, I derived a wizard window class adding TakeNext, TakeBack, TakeTabChanging, TakeTabSelection methods. This worked well and didnât confuse an old brain that struggles to keep a charge.
After I found myself wanting those TakeTab methods in non-wizard procedures, I simply moved them to a derived general windows class and dropped the wizard window class. I am sure it is marginally less efficient, but it gets around the EVENT stuff that is impossible for me to always keep in mind.
I had some success by declaring a string variable - e.g.: SHEETVariable
then⌠For the SHEET declaration: USE(SHEETVariable)
In CODE:
If SHEETVariable = 'MyTAB' (Text in TAB properties)
Do Something
End
Yes a SHEET(v) + TAB('&Blarg')
can work
like an OPTION(v) + RADIO,VALUE('Blarg')
and set the a Variable to the selected thingâs value.
Note the Sheet variable gets the Tab PROP:Value without the (&) Ampersand Hotkey Prefix.
I would not code it that way because if someone decided to change the Tab âTextâ it will silently break the code without any compiler error. Same if deleting the Tab. If you spell âthe valueâ wrong it fails silently.
If coded with PROP:ChoiceFEQ it handles most changes, others will cause errors like changing the Tab ?FEQ or spelling it wrong. There is no silent failure.