01-12-2018 05:23 AM
Hello all,
sometimes a panel is better in it own window, sometimes it's better as part of a tab... and sometimes the user can't make up his mind and it would be nice to have the possibility to switch between one and the other at will. I know there are a few differences between using a tabbed panel and a separate one, so before I spend some time on this, are there any examples of .UIR where the user can separate at will ?
For instance I don't think you can drop a panel onto a tab and hope to catch a DROP even. So some kind of button would be required. Any other issues to consider ?
Thanks.
Solved! Go to Solution.
01-12-2018 06:09 AM - edited 01-12-2018 06:12 AM
I don't expect the drop command to work either!
What you can think of is to let the user select the desired aspect and then use InsertPanelAsTabPage to transform from independent panels to a tab control, and DuplicatePanel to move the opposite direction. Provided you save the panel handle (whichever it is) to a variable that you use in every UI call, you should notice no major difference in program behaviour. When changing the way the application is run you will need to update the variable with the new handle and discard the old panel afterwards.
(It's more or less what View >> Workspace View Selection option in CVI IDE environment does)
01-15-2018 08:17 AM
Yup, I got it to work. Here's the heart of the code. I've tested it starting from a bunch of filled tabs and top-level panels.
/* The following 2 functions switch between SDI and MDI SDI: Single Document Interface - The panel is top-level MDI: Multiple Document Interface - The panel is in a Tab Have a panel with a tab ready Place a picture ring (without inc/dec arrows) in the panel you wish to (un)tab and use the following callback function on it: int CVICALLBACK cb_TabToPanel(int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { BOOL ToTab; switch (event) { case EVENT_LEFT_CLICK: GetCtrlVal(panel, control, &ToTab); SetCtrlVal(panel, control, ToTab=!ToTab); if (ToTab) MovePanelToTab(pTab, PTAB_TAB, &PnlHandle); // And not 'panel' as the value will change else PnlHandle=MovePanelFromTab(pTab, PTAB_TAB, PnlHandle==0 ? -1 : GetTabIndexFromPanel(pTab, PTAB_TAB, PnlHandle)); break; } return 0; } */ /////////////////////////////////////////////////////////////////////////////// /// HIFN Take an existing top-level panel and pushes it inside a tab (at the last position) /// OUT Panel /// HIPAR Panel/Panel to put inside a tab. /// HIPAR Panel/THE HANDLE WILL CHANGE, so use a variable, not a callback function parameter /// HIPAR pTab/Panel containing the tab /// HIPAR TabCtrl/Handle of the tab control /// HIRET Index of the newly created tab /////////////////////////////////////////////////////////////////////////////// int MovePanelToTab(int pTab, int TabCtrl, int *Panel) { if (*Panel<0) return -1; int NewTabIndex = InsertPanelAsTabPage (pTab, TabCtrl, -1, *Panel); DiscardPanel(*Panel); GetPanelHandleFromTabPage (pTab, TabCtrl, NewTabIndex, Panel); SetCtrlAttribute (pTab, TabCtrl, ATTR_CTRL_INDEX, NewTabIndex); return NewTabIndex; } /////////////////////////////////////////////////////////////////////////////// /// HIFN Takes a tab and turn it into an independant panel /// HIFN Note that it removes it from the tab, so the index of the next tabs will change /// HIPAR pTab/Panel containing the tab /// HIPAR TabCtrl/Handle of the tab control /// HIPAR index/index of the tab to turn into a panel (will be deleted) or -1 to use active one /// HIRET Panel handle of newly independant tab /// HIRET - note that it is different from the handle obtained from the tab /////////////////////////////////////////////////////////////////////////////// int MovePanelFromTab(int pTab, int TabCtrl, int index) { int Pnl, Len; if (index<0) GetActiveTabPage (pTab, TabCtrl, &index); GetPanelHandleFromTabPage (pTab, TabCtrl, index, &Pnl); int NewPnl = DuplicatePanel (0, Pnl, 0, VAL_KEEP_SAME_POSITION, VAL_KEEP_SAME_POSITION); SetPanelAttribute(NewPnl, ATTR_TITLEBAR_VISIBLE, 1); // Optional GetPanelAttribute (NewPnl, ATTR_TITLE_LENGTH, &Len); if (Len==0) { char Str[256]; GetTabPageAttribute (pTab, TabCtrl, index, ATTR_LABEL_TEXT, Str); SetPanelAttribute (NewPnl, ATTR_TITLE, Str); } DeleteTabPage (pTab, TabCtrl, index, 1); DisplayPanel (NewPnl); SetActivePanel (NewPnl); return NewPnl; } /////////////////////////////////////////////////////////////////////////////// /// HIFN Get the index of a panel that's inside a tab /// HIPAR pTab/Panel containing the tab /// HIPAR TabCtrl/Handle of the tab control /// HIPAR Panel/Handle of the panel to look for within that tab /// HIRET The tab index of the panel, or -1 if not found /////////////////////////////////////////////////////////////////////////////// int GetTabIndexFromPanel(int pTab, int TabCtrl, int Panel) { int Count, i, Pnl; GetNumTabPages (pTab, TabCtrl, &Count); for (i=0; i<Count; i++) { GetPanelHandleFromTabPage (pTab, TabCtrl, i, &Pnl); if (Pnl==Panel) return i; } return -1; }