Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Removing Tabs from tab control
#1
Hi Gintaras,
I am using the following code to have a tab control that displays different text in a single textbox (this is not a multi-page dialog) depending on which tab is selected. The number of tabs and their names change depending on the number of elements in an array (for _i 0 to ContainerArray.len(2) (this is based on the tab control dialogs in the Forum Resources archive)


Code:
Copy      Help
,case WM_INITDIALOG
,,TCITEM ti.mask=WINAPI.TCIF_TEXT
,,int TabCounter
,,for TabCounter 0 ContainerArray.len(2);;I don't know ahead of time how many tabs I will need per instance
,,,,if empty(ContainerArray[0 TabCounter]); break
,,,,ti.pszText=ContainerArray[3 TabCounter];;TabName is the 4th element in the first dimension of the array
,,,,SendMessage htb WINAPI.TCM_INSERTITEMA TabCounter &ti
,,,_s = ContainerArray[4 TabCounter];  _s.setwintext(id(5 hDlg));;Tab-Selected Text is the 5th element in the first dimension of the array    
,,goto g11

When the user selects a tab in the dialog, it gets updated like this:

Code:
Copy      Help
;messages3
NMHDR* nh=+lParam
sel nh.code
,case WINAPI.TCN_SELCHANGE
,_i=SendMessage(nh.hwndFrom WINAPI.TCM_GETCURSEL 0 0)
,_s = ContainerArray[4 _i];  _s.setwintext(id(5 hDlg))
,,goto g11
,;g11
,DT_Page hDlg _i

The next time this is run (differerent case so different number of elements in the array, different tab names, different text in the array), I have been just closing the dialog and then starting over. I think it would be better use of resources to just use same dialog and "refresh" it with new information. I can code this except for the tabs. I don't know how to "erase" the current tabs and refill the space in the dialog with a new
Code:
Copy      Help
;3 SysTabControl32 0x54000300 0x0 0 36 172 342 ""
or keep the SysTabCOntrol32 and just replace the tabs with new ones. I can't simply rename the tabs because I don't know the number of tabs I will need ahead of time.

I hope this is clear. Let me know if I need to explain more. Thanks so much for any help.

Stuart
Living the 'QM' life!
#2
Look in MSDN library.

SendMessage hwndTab TCM_DELETEALLITEMS 0 0
#3
Thank you so much for pointing me back (again!) to the MSDN library.
I now see all the info about TCM I could want!!!

Tab Control Messages:
http://msdn.microsoft.com/en-us/library/...S.85).aspx

Quote:TCM_ADJUSTRECT
TCM_DELETEALLITEMS
TCM_DELETEITEM
TCM_DESELECTALL
TCM_GETCURFOCUS
TCM_GETCURSEL
TCM_GETEXTENDEDSTYLE
TCM_GETIMAGELIST
TCM_GETITEM
TCM_GETITEMCOUNT
TCM_GETITEMRECT
TCM_GETROWCOUNT
TCM_GETTOOLTIPS
TCM_GETUNICODEFORMAT
TCM_HIGHLIGHTITEM
TCM_HITTEST
TCM_INSERTITEM
TCM_REMOVEIMAGE
TCM_SETCURFOCUS
TCM_SETCURSEL
TCM_SETEXTENDEDSTYLE
TCM_SETIMAGELIST
TCM_SETITEM
TCM_SETITEMEXTRA
TCM_SETITEMSIZE
TCM_SETMINTABWIDTH
TCM_SETPADDING
TCM_SETTOOLTIPS
TCM_SETUNICODEFORMAT

and also Tab Control Styles
http://msdn.microsoft.com/en-us/library/...S.85).aspx

Quote:TCS_BOTTOM
Version 4.70. Tabs appear at the bottom of the control. This value equals TCS_RIGHT. This style is not supported if you use ComCtl32.dll version 6.

TCS_BUTTONS
Tabs appear as buttons, and no border is drawn around the display area.

TCS_FIXEDWIDTH
All tabs are the same width. This style cannot be combined with the TCS_RIGHTJUSTIFY style.

TCS_FLATBUTTONS
Version 4.71. Selected tabs appear as being indented into the background while other tabs appear as being on the same plane as the background. This style only affects tab controls with the TCS_BUTTONS style.

TCS_FOCUSNEVER
The tab control does not receive the input focus when clicked.

TCS_FOCUSONBUTTONDOWN
The tab control receives the input focus when clicked.

TCS_FORCEICONLEFT
Icons are aligned with the left edge of each fixed-width tab. This style can only be used with the TCS_FIXEDWIDTH style.

TCS_FORCELABELLEFT
Labels are aligned with the left edge of each fixed-width tab; that is, the label is displayed immediately to the right of the icon instead of being centered. This style can only be used with the TCS_FIXEDWIDTH style, and it implies the TCS_FORCEICONLEFT style.

TCS_HOTTRACK
Version 4.70. Items under the pointer are automatically highlighted. You can check whether or not hot tracking is enabled by calling SystemParametersInfo.

TCS_MULTILINE
Multiple rows of tabs are displayed, if necessary, so all tabs are visible at once.

TCS_MULTISELECT
Version 4.70. Multiple tabs can be selected by holding down the CTRL key when clicking. This style must be used with the TCS_BUTTONS style.

TCS_OWNERDRAWFIXED
The parent window is responsible for drawing tabs.

TCS_RAGGEDRIGHT
Rows of tabs will not be stretched to fill the entire width of the control. This style is the default.

TCS_RIGHT
Version 4.70. Tabs appear vertically on the right side of controls that use the TCS_VERTICAL style. This value equals TCS_BOTTOM. This style is not supported if you use visual styles.

TCS_RIGHTJUSTIFY
The width of each tab is increased, if necessary, so that each row of tabs fills the entire width of the tab control. This window style is ignored unless the TCS_MULTILINE style is also specified.

TCS_SCROLLOPPOSITE
Version 4.70. Unneeded tabs scroll to the opposite side of the control when a tab is selected.

TCS_SINGLELINE
Only one row of tabs is displayed. The user can scroll to see more tabs, if necessary. This style is the default.

TCS_TABS
Tabs appear as tabs, and a border is drawn around the display area. This style is the default.

TCS_TOOLTIPS
The tab control has a tooltip control associated with it.

TCS_VERTICAL
Version 4.70. Tabs appear at the left side of the control, with tab text displayed vertically. This style is valid only when used with the TCS_MULTILINE style. To make tabs appear on the right side of the control, also use the TCS_RIGHT style. This style is not supported if you use ComCtl32.dll version 6.

Can you believe I discovered all these TCS just by changing the numbers sequentially in the flag number!!!!!!
This is MUCH MUCH better!!
Thanks again Gintaras...your help is incalculable!!!!

Stuart
#4
Could you give a crazy example using all of these to show what can be done?

I'm really curious now!!

Thanks for all the leg work,
Jimmy Vig
#5
give me a day or two....
Stuart
#6
Hi All,

I created a dialog that:
  • adds a new tab (1 higher than highest tab number's name. I made the name a number to make this easy ...see code.)
  • Deletes the Selected Tab
  • Deletes All Tabs



Function TabControlVariations
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

out
if(!ShowDialog("TabControlVariations" &TabControlVariations)) ret

;BEGIN DIALOG
;0 "" 0x10C80A44 0x100 0 0 571 63 "Form"
;1 Button 0x54030001 0x4 272 46 48 14 "OK"
;2 Button 0x54030000 0x4 330 46 48 14 "Cancel"
;4 Button 0x54032000 0x4 386 46 18 14 "?"
;3 SysTabControl32 0x54000040 0x0 0 2 266 25 ""
;16 Button 0x54032000 0x0 270 4 50 22 "Add Tab"
;17 Button 0x54032000 0x0 322 4 50 22 "Delete Selected Tab"
;18 Button 0x54032300 0x0 376 4 48 22 "Delete All Tabs"
;END DIALOG
;DIALOG EDITOR: "" 0x2030109 "" "" ""

ret
;messages
sel message
,case WM_INITDIALOG    
,int+ htb3=id(3 hDlg)

,TCITEM ti.mask=WINAPI.TCIF_TEXT    
,ti.pszText="1"
,SendMessage htb3 WINAPI.TCM_INSERTITEMA 0 &ti    
,ti.pszText="2"    
,SendMessage htb3 WINAPI.TCM_INSERTITEMA 1 &ti
,ti.pszText="3"    
,SendMessage htb3 WINAPI.TCM_INSERTITEMA 2 &ti    
,
,goto g11
,case WM_DESTROY
,case WM_COMMAND goto messages2
,case WM_NOTIFY goto messages3
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
,case 16;;add tab htb3
,,int TabCount = SendMessage(htb3 WINAPI.TCM_GETITEMCOUNT 0 0);; wParam and lParam must both be zero (see MSDN link http://msdn.microsoft.com/en-us/library/bb760592(v=VS.85).aspx)    
,,str TabText
,,TC_GetTabText htb3 TabCount-1 TabText;;TabCount -1 because zero order tab index but total number of tabs is 1-order
,,int TabTextToVal = val(TabText)
,,str NextHighterTab = TabTextToVal+1
,,TCITEM TabName.mask=WINAPI.TCIF_TEXT
,,TabName.pszText = NextHighterTab
,,SendMessage htb3 WINAPI.TCM_INSERTITEMA TabCount+1 &TabName;; so that it adds it as the nexth (zero-order) tab        

,case 17;;Delete Selected Tab
,,int SelectedTab = SendMessage(htb3 WINAPI.TCM_GETCURSEL 0 0);;Determines the currently selected tab in a tab control, wParam and lParam must be zero, returns selected tab index or -1 if no tab selected
,,SendMessage htb3 WINAPI.TCM_DELETEITEM SelectedTab 0  ;; Removes an item from a tab control, wParam = index of item to delete, lParam must be zero)
,case 18;; Delete All Tabs
,,SendMessage htb3 WINAPI.TCM_DELETEALLITEMS 0 0;;


ret 1
;messages3
NMHDR* nh=+lParam
sel nh.code
,case WINAPI.TCN_SELCHANGE
,_i=SendMessage(nh.hwndFrom WINAPI.TCM_GETCURSEL 0 0)
,;g11
,DT_Page hDlg _i

Function TC_GetTabText
Code:
Copy      Help
;/
function! htb item str&s

;Gets tab control item text.
;Returns 1 if not empty, 0 if empty.

;htb - SysTabControl32  handle
;item - 0-based tab index
;s - receives text.



TCITEM TabText.mask=WINAPI.TCIF_TEXT
BSTR b.alloc(260)
TabText.pszText=b
TabText.cchTextMax=260
SendMessage(htb TCM_GETITEM item &TabText)
s = TabText.pszText
ret s.len!=0

Note: to get the name of the tab text, I had to create a custom in order to use TCM_GETITEM. From reading MSDN, I learned that if getting an item you have to allocate its string buffer and its max character length (ugh!!). So I reverse-engineered LvGetItemText from the QM grid functions which also defines similar values. It worked!!!!!!! (my first new "user-defined" function based on a MSDN SendMessage

However, I couldn't figure out how to apply all the STYLES or specifically change a tabs size because it required a value DWORD which I didn't know how to define
e.g.
http://msdn.microsoft.com/en-us/library/...S.85).aspx
also this is extended style and I don't know how to apply regular style...

I hope this is a good start and would be interested to see what Gintaras makes of all this.

Stuart
#7
DWORD is type unsigned int. In QM use int.

In MSDN, syntax and examples are in C++ language.
There are many types that are the same or very similar as QM intrinsic types: DWORD, HWND, char, short, LPSTR, LPWSTR...
But how to know it? QM status bar does not show any info for these types.
Here is how to show type info in QM status bar:
1. Download and declare reference file WINAPI2: More Windows API declarations for QM
2. Now QM status bar will show typeinfo for these types. In most cases it will be type character (# int, $ lpstr, @ word...).
These type names cannot be used in QM. They are added to WINAPI2 just to show what QM type to use instead.

Examples
Macro Macro1449
Code:
Copy      Help
WINAPI2.DWORD
WINAPI2.HWND
WINAPI2.HANDLE
WINAPI2.char
WINAPI2.CHAR
WINAPI2.short
WINAPI2.WCHAR
WINAPI2.LPCSTR
WINAPI2.LPTSTR
WINAPI2.LPWSTR

Now click DWORD, HWND, etc, and look in status bar. It will show type DWORD = #. Here # is type character for int. Now you know that it is int.
#8
that's a great explanation...I will have to play with this some more now that I am getting a little taste of raiding the MSDN to enhance QM!!!!

Thanks!!
Stuart
#9
Your TC_GetTabText is almost correct but does not support Unicode.

This version supports Unicode.
Function TC_GetTabText
Code:
Copy      Help
;/
function! htb item str&s

;Gets tab control item text.
;Returns 1 if not empty, 0 if empty.

;htb - SysTabControl32 handle
;item - 0-based tab index
;s - receives text.



TCITEMW TabText.mask=WINAPI.TCIF_TEXT
BSTR b.alloc(260)
TabText.pszText=b
TabText.cchTextMax=260
SendMessageW(htb TCM_GETITEMW item &TabText)
s.ansi(b)
ret s.len!=0
#10
To set extended style:

SendMessage hwnd TCM_SETEXTENDEDSTYLE exstyle exstyle

---------------------

To set style (not extended), look what is the value of the constant and add the value in dialog definition.

For example, to add TCS_FIXEDWIDTH style:
Paste TCS_FIXEDWIDTH in QM editor and look in status bar. It shows def TCS_FIXEDWIDTH 0x0400. Undo.
Now add 0x400 in dialog definition.
If was
;3 SysTabControl32 0x54000040 0x0 0 2 266 25 ""
, make it
;3 SysTabControl32 0x54000440 0x0 0 2 266 25 ""

Easier way - use SetWinStyle. But it does not work with some styles, because these styles must be set when creating the control, and cannot be changed.
#11
Hi Gintaras,
I am using a tabcontrol with button styles but want to make it so that each button becomes "undepressed" immediately after each push so that the action from depressing the tab/button can be repeated. Ideally, that button will still stay highlighted, which I know is a distinct state from whether it is actually depressed (I think focus vs selected, but I am note sure).
Thanks!
Stuart

Function TabControlVariations
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages


if(!ShowDialog("TabControlVariations" &TabControlVariations)) ret

;BEGIN DIALOG
;0 "" 0x10C80A44 0x100 0 0 571 63 "Form"
;1 Button 0x54030001 0x4 272 46 48 14 "OK"
;2 Button 0x54030000 0x4 330 46 48 14 "Cancel"
;4 Button 0x54032040 0x4 386 46 18 14 "?"
;3 SysTabControl32 0x54000340 0x0 0 2 266 60 ""
;16 Button 0x54032000 0x0 270 4 50 22 "Add Tab"
;17 Button 0x54032000 0x0 322 4 50 22 "Delete Selected Tab"
;18 Button 0x54032300 0x0 376 4 48 22 "Delete All Tabs"
;END DIALOG
;DIALOG EDITOR: "" 0x2030208 "" "" ""

def TCS_HOTTRACK 0x0040
def TCS_MULTILINE 0x0200
def TCS_BUTTONS 0x0100

ret
;messages
sel message
,case WM_INITDIALOG    
,int+ htb3=id(3 hDlg)
,for _i 0 10
,,_s=_i
,,TCITEM ti.mask=WINAPI.TCIF_TEXT    
,,ti.pszText= _s
,,SendMessage htb3 WINAPI.TCM_INSERTITEMA _i &ti    

,
,goto g11
,case WM_DESTROY
,case WM_COMMAND goto messages2
,case WM_NOTIFY goto messages3
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
,case 16;;add tab htb3
,,int TabCount = SendMessage(htb3 WINAPI.TCM_GETITEMCOUNT 0 0);; wParam and lParam must both be zero (see MSDN link http://msdn.microsoft.com/en-us/library/bb760592(v=VS.85).aspx)    
,,str TabText
,,TC_GetTabText htb3 TabCount-1 TabText;;TabCount -1 because zero order tab index but total number of tabs is 1-order
,,int TabTextToVal = val(TabText)
,,str NextHighterTab = TabTextToVal+1
,,TCITEM TabName.mask=WINAPI.TCIF_TEXT
,,TabName.pszText = NextHighterTab
,,SendMessage htb3 WINAPI.TCM_INSERTITEMA TabCount+1 &TabName;; so that it adds it as the nexth (zero-order) tab        

,case 17;;Delete Selected Tab
,,int SelectedTab = SendMessage(htb3 WINAPI.TCM_GETCURSEL 0 0);;Determines the currently selected tab in a tab control, wParam and lParam must be zero, returns selected tab index or -1 if no tab selected
,,SendMessage htb3 WINAPI.TCM_DELETEITEM SelectedTab 0  ;; Removes an item from a tab control, wParam = index of item to delete, lParam must be zero)
,case 18;; Delete All Tabs
,,SendMessage htb3 WINAPI.TCM_DELETEALLITEMS 0 0;;


ret 1
;messages3
NMHDR* nh=+lParam
sel nh.code
,case WINAPI.TCN_SELCHANGE
,_i=SendMessage(nh.hwndFrom WINAPI.TCM_GETCURSEL 0 0)
,;g11
,DT_Page hDlg _i
#12
Under case WINAPI.TCN_SELCHANGE:

Deselect all with TCM_DESELECTALL.
Dehighlight all with TCM_HIGHLIGHTITEM.
Highlight button with TCM_HIGHLIGHTITEM.

Or instead of TCM_HIGHLIGHTITEM use TCM_SETCURFOCUS, or change icon.

Or use toolbar control instead.
#13
Thanks!!!!!
S


Forum Jump:


Users browsing this thread: 1 Guest(s)