12-27-2012 08:19 AM
Hello,
I'm using a Tab control and can't find out how to handle the following situation.
We know that when operating a Tab control we can jump from Tab to Tab by pressing <Ctrl-Tab>.
When at the last Tab I would like to jump to another conbtrol and not again to the first Tab.
Unfortunately in this situation <Ctrl-Tab> doesn't generate an EVENT_KEYPRESS.
Is there a way to handle this situation?
Solved! Go to Solution.
12-27-2012 04:01 PM
I don't understand why you cannot get the keypress event: I have tried to modify TabExample example installing a callback on the tab control and properly get the keypress event on Ctrl+Tab. Here the code for the tab control callback function:
int CVICALLBACK TabCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int nextCtrl, lastTab, pageIdx, virtualKey, modifierKey; if (event == EVENT_KEYPRESS) { GetActiveTabPage (panel, control, &pageIdx); GetNumTabPages (panel, control, &lastTab); lastTab--; // Zero-based index virtualKey = eventData1 & VAL_VKEY_MASK; modifierKey = eventData1 & VAL_MODIFIER_KEY_MASK; // Properly handle Ctrl+Tab if (modifierKey == VAL_MENUKEY_MODIFIER && virtualKey == VAL_TAB_VKEY && pageIdx == lastTab) { GetCtrlAttribute (panel, PANEL_TAB, ATTR_NEXT_CTRL, &nextCtrl); SetActiveCtrl (panel, nextCtrl); return 1; // Swallow the keypress event so that active page doesn't change } } return 0; }
Alternatively, you can handle the situation inside a panel callback:
int CVICALLBACK PanelCallback (int panel, int event, void *callbackData, int eventData1, int eventData2) { int lastTab, control, pageIdx, virtualKey, modifierKey, nextCtrl; if (event == EVENT_KEYPRESS) { if ((control = GetActiveCtrl (panel)) == PANEL_TAB) { GetActiveTabPage (panel, control, &pageIdx); GetNumTabPages (panel, control, &lastTab); // eventData1: a 4-byte integer consisting of 3 fields: 0x00MMVVAA // MM = the modifier key, VV = the virtual key, AA = the ASCII key // key masks are defined in userint.h virtualKey = eventData1 & VAL_VKEY_MASK; modifierKey = eventData1 & VAL_MODIFIER_KEY_MASK; // Properly handle Ctrl+Tab if (modifierKey == VAL_MENUKEY_MODIFIER && virtualKey == VAL_TAB_VKEY && (pageIdx == lastTab - 1)) { GetCtrlAttribute (panel, PANEL_TAB, ATTR_NEXT_CTRL, &nextCtrl); SetActiveCtrl (panel, nextCtrl); return 1; } } } return 0; }
12-28-2012 07:07 AM
Thank you for your inputs.
But if a control is active on a tab page then <Ctrl-Tab> switches through the tabs without sending an EVENT_KEYPRESS.
Please see below
12-28-2012 10:52 AM
I see. I cannot test it at the moment: I will make some test later this evening.
I can suppose that when the active control is e.g. the numeric the keypress event is sent to the numeric control callback, if any, and not to the tab control.
Nevertheless, keypress events are received from the panel callback as well, and I seem to remember that they are received there before the control callbacks, so you can try handling this particular key combination in the panel callback.
12-28-2012 05:31 PM
After making some tests I can confirm your analysis: when pressing Ctrl+Tab on a control inside the panel, no KEYPRESS event is received from the control, from the tab control or from the panel owning the tab control. I tried also installing the main callback to see if I can detect some condition under which to trap that particular situation but with no success.
It is possible that that event is handled internally by the tab control and its events are not exposed to the system; I don't know how much native tab control inherits from the former EasyTab, but in that instrument code Ctrl+Tab key combination was specifically handled by swallowing its events: maybe the tab control operates in a similar way.
Handling the EVENT_ACTIVE_TAB_CHANGE is not a feasible solution since it is received after the tab page has already changed: even if you return to the previous page the user will notably see the page changes.
01-11-2013 03:55 PM
This issue is recorded under known issue 241929 (it is not currently in the Known Issues List by mistake, but it will be there next time I revise the list). This is a limitation of the way our UI framework is designed. The problem is that <Ctrl>+Tab is a built-in hotkey for the Tab control. For hotkeys, the event goes straight to the control owning the hotkey as you suspected. For now, we do not intend to change this behavior because it is fundamental to our implementation of hotkeys.
We have not been able to find a work around to accomplish what you described. Could you provide some additional information about why this behavior is useful in your UI, and then maybe we can help come up with alternative solutions?
01-13-2013 10:07 AM
Thank you for your answer.
My UI is seperated in different frames. Using the <Tab> key allows to jump from control to control.
But in order to go more quickly to the wanted control I have implemented <Ctrl>+<Tab> to jump from frame to frame.
The issue is that when I'm on the tab control I cannot get out of it with <Ctrl>+<Tab>.
01-18-2013 05:13 PM
I believe I found a workaround. You can use InstallWinMsgCallback to install a callback for the panel and check for the WM_KEYDOWN message. This is a bit more involved because you will not receive eventData1 and eventData2 to tell you what key and modifier is being used, so you will have to check for the control key separately (I use a global flag to specify if CTRL is pressed).
In main, you will have to install the callback like so:
InstallWinMsgCallback (panelHandle, WM_KEYDOWN, MyCallback, VAL_MODE_INTERCEPT, NULL, &postHandle); ... //in clean-up RemoveWinMsgCallback (panelHandle, WM_KEYDOWN);
Then in the callback, use the following code:
int CVICALLBACK MyCallback (int panelHandle, int message, unsigned int *wParam, unsigned int *lParam, void* callbackData) { int lastTab, control, pageIdx, nextCtrl; switch(message) { case WM_KEYDOWN: if(*wParam == VK_CONTROL) { ctrlDown = 1; } else if(*wParam == VK_TAB) { if ((control = GetActiveCtrl(panelHandle)) == PANEL_TAB) { GetActiveTabPage (panelHandle, control, &pageIdx); GetNumTabPages (panelHandle, control, &lastTab); if(pageIdx == lastTab - 1) { GetCtrlAttribute (panelHandle, PANEL_TAB, ATTR_NEXT_CTRL, &nextCtrl); SetCtrlAttribute(panelHandle, PANEL_TAB, ATTR_CTRL_INDEX, pageIdx); SetActivePanel(panelHandle); SetActiveCtrl (panelHandle, nextCtrl); return 1; } } } break; case WM_KEYUP: if(*wParam == VK_CONTROL) ctrlDown = 0; } return 0; }
Note: You must call SetActivePanel before SetActiveCtrl to transfer focus from the tab page to the panel.
01-22-2013 02:22 PM
Thank you very munch
Bertrand