Hi there,

I'm currently developping a project with graphical interface (with RadAsm), and I wanted to use some TabStrip control.
But I just can't understand how exactly it works, I didn't find anything on the web (just a topic but it was for EasyCode, and I don't want to change my IDE at this point of development).

Could someone help me to deal with this TabStrips/Group controls?

I'd be very very grateful..

ps:excuse my english, it's not my language (french)..
Posted on 2006-10-31 08:08:27 by marc_
In RadAsm's Dialog Editor you can drop a "Tab Strip" Control just as easy as you would do an EditControl.

You have to add the Tabs yourself though using the TCM_INSERTITEM message. In Win32.hlp the TabStrip is referred to as " Tab Control ". Maybe that's the confusion.

Usually you create the Tabs, then upon the TCN_SELCHANGE (WM_NOTIFY) message you create or destroy dialogs which you superimpose into the Tab Control.

Tell me if that's enough or if you need more detail :)

Happy Halloween,
Jimmy
Posted on 2006-10-31 08:33:52 by JimmyClif
hello JimmyClif,

firstof all, thank you for replying this quick, I'm really desperate because of these controls  :P

I understood what you wrote, but there's still a thing I don't understand:
when I drop a TabStrip on my Dlg, there's only one tab on it, and I didn't found where I am supposed to add another one.
Maybe it's in a .rc file but couldn't find which one.
You talk about "TCM_INSERTITEM message" which add a tab, you mean when I have to send a TCM_INSERTITEM message just before the Dlg is initialized?

And for the second point, the TCN_SELCHANGE message which change the current dialog, how does it works exactly?
Setting focus on a particular part of the Dlg ? or really destroying the current Dlg for putting a new one?
And where do I have to create the other Dlg?

Sorry for all these newbie question but I really don't find any tuts on this and I'd like to finalize my work ^^

Thanks you

Posted on 2006-10-31 10:28:44 by marc_
I was pondering on what would be faster - me writing a quick example or me trying to explain. I went for the first option. Attached is a working example. It is a little confusing but examine it carefully and it will all make sense.


If there are any further questions don't hesitate asking... I'll do my best explaining what I did.
Attachments:
Posted on 2006-10-31 11:46:26 by JimmyClif
hello JimmyClif,

sorry to not answered earlier (I think ure laughing on my bad english ^^ don't hesitate to tell me what's wrong lol)

Ok, so I tried your .exe, it works perfectly on my computer.

BUT (there's always a "but") I didn't understood everything..

I've read several times your .asm, .inc etc... and for YOUR .exe I understand what's going on: a SendDlgItem on the tabstrip when the DialogBox is initializing, and 3 differents tabs which you can activate by a simple click which send a SendDlgItem.

But I tried to make the same thing for my project, and it don't works. It compiles without error, I made the right includes etc.
But when I run my .exe, I see the same DlgBox than without the strips.. nothing change, but a strange rect around my DlgBox.

I think this is maybe a problem with the ID of the controls (the number like 1001, 2000, etc.), or maybe a problem with my compiler (I use the Masm32.ini and didn't change anything in it.. should I make some change in it?).

Sorry to not understand, I appreciate you made a project for me, but after 2 days studying it I still don't understand everything.)

Could you explain me the order of the things to add to an existing exe (with just one DlgBox) for having 3 tabstrips?

Or anything that can help me lol

Thank u and have a good day
Posted on 2006-11-03 10:25:19 by marc_
How to use TabStrips

First drop a TabStrip in your Dialog using RadAsm's DialogEditor.


Now you need to add Tabs to the control. This is done inside the WM_INITDIALOG handler of your main program. To add Tabs you need to populate the TC_ITEM structure with information about each Tab.


mov tci.imask, TCIF_TEXT
mov tci.pszText, ctxt("First Tab")
mov tci.cchTextMax,256
mov tci.lpReserved1, 0
mov tci.lpReserved2, 0
mov tci.iImage,0
mov tci.lParam,0


Then we add the Tab using the TCM_INSERTITEM message:


invoke SendDlgItemMessage,hWnd,1001,TCM_INSERTITEM,0,addr tci


The second parameter (1001) is the ID of the TabStrip and the second last parameter of the SendDlgItemMessage call is the Tab Number. The First Tab is 0, the second will be 1 and the third will be 2.

Now, I add two more tabs to the control. Our TC_ITEM structure is already filled with most of the information it needs - we only need to change the psztext parameter so that our next Tabs have different names.

mov tci.pszText, ctxt("Second Tab")
invoke SendDlgItemMessage,hWnd,1001,TCM_INSERTITEM,1,addr tci

mov tci.pszText, ctxt("Third Tab")
invoke SendDlgItemMessage,hWnd,1001,TCM_INSERTITEM,2,addr tci


// You could already compile now and have a look, the Tabs are there but when you click on them - nothing happens.

So, let's have a look about how to receive notification if the User clicks on a Tab. This notification is send as a TCN_SELCHANGE message through the WM_NOTIFY handler.

.elseif eax==WM_NOTIFY
mov eax, lParam
.IF .NMHDR.code == TCN_SELCHANGE
; User clicked a Tab. But which one?
.ENDIF

To find out which Tab the User clicked we query the Tab Control itself and ask for the current tab ID.

invoke SendDlgItemMessage,hWnd,1001,TCM_GETCURSEL,0,0

Eax returns the Tab number.

Now, the plan is as follows: When the User clicks on a Tab we have to show him some content. This content will be in a separate dialog which I created and named "a.dlg". Now this dialog has very few features. It's style is Child & Visible. Nothing else. On this dialog I dropped a Static Text saying "Tab Number 0" just for you to have something to see when it's there. As ID for this child dialog I chose 2000. (Important)


As we have three tabs, I created another two dialogs named b.dlg & c.dlg. Having the same features as a.dlg and having as ID 2001 and 2002.

Now, it's about time to tie this whole thing together:


.elseif eax==WM_NOTIFY
mov eax, lParam
.IF .NMHDR.code == TCN_SELCHANGE
.IF hTab != 0
invoke DestroyWindow,hTab
.ENDIF
invoke SendDlgItemMessage,hWnd,1001,TCM_GETCURSEL,0,0
add eax, 2000
invoke CreateDialogParam,hInstance,eax,hTabStrip,offset DialogProc,0
invoke GetClientRect,hTabStrip,addr rect
sub rect.bottom,25
invoke MoveWindow,hTab,0,25,rect.right,rect.bottom,TRUE
.ENDIF


First we see if there is a Dialog active using the:

.IF hTab != 0
invoke DestroyWindow,hTab
.ENDIF

..and if there is - we destroy it.

Then we ask which Tab it is. For the First Tab it will be 0, the second it will be 1 and the third it will be 2. Our Dialogs which we want to display have as ID's 2000, 2001 and 2002. Now after querying the Tab Control it returns either 0, 1 or 2 - then I add 2000 to that result which gives me the ID of the Dialog I want to display, which I immediately create using:

invoke CreateDialogParam,hInstance,eax,hTabStrip,offset DialogProc,0

After creating the Dialog I quickly adjust it's size so that the Dialog doesn't overlap the Tab Buttons. This is done here:

invoke GetClientRect,hTabStrip,addr rect
sub rect.bottom,25
invoke MoveWindow,hTab,0,25,rect.right,rect.bottom,TRUE


All input of the Dialog itself will be sent to the DialogProcedure here:

DialogProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT

mov eax,uMsg
.if eax==WM_INITDIALOG
push hWin
pop hTab
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

DialogProc endp


Only thing left, if you compile and check it out after this point is that upon App start there is no dialog selected. Reason to add this code:

invoke CreateDialogParam,hInstance,2000,hTabStrip,offset DialogProc,0 ; first dialog for first tab
invoke GetClientRect,hTabStrip,addr rect
sub rect.bottom,25
invoke MoveWindow,hTab,0,25,rect.right,rect.bottom,TRUE

in the WM_INITDIALOG handler of the main application.

As one last addition I set thsi code into the WM_SIZE handler to resize the TabStrip to the width and height of the main window. (This code could have been better as the width and height of the main window are passed in either lparam or wparam but I was lazy)

.elseif eax==WM_SIZE
invoke GetClientRect,hWnd,addr rect
invoke GetDlgItem,hWnd,1001 ; 1001 being the TabStrip
invoke MoveWindow,eax,0,0,rect.right,rect.bottom,TRUE





Only confusing thing which is left up to you is how to differentiate between tabs inside your Dialog Handler. You could create a separate DialogProcedure for each Tab using an array of DialogProc offsets like this:

.data
OffsetsHere dd offset Dialogproc, offset Dialogproc1, offset Dialogproc2

; inside WM_NOTIFY
invoke SendDlgItemMessage,hWnd,1001,TCM_GETCURSEL,0,0
mov edx, dword ptr
add eax, 2000
invoke CreateDialogParam,hInstance,eax,hTabStrip,edx,0 ; first dialog for first tab

and have three different Dialogprocedures named Dialogproc, Dialogproc1 and Dialogproc2.

Hope this helps somewhat out.
Posted on 2006-11-03 11:43:11 by JimmyClif
Kudos  8)
Posted on 2006-11-03 23:30:42 by Homer
Hello JimmyCliff,

I'm sorry but... even with your explanations.. IT STILL DOESN'T WORK!!

I really don't understand, I've done all the things you wrote, but when I click on a tab it just happen nothing.

I wonder if it could be a "project type" problem, you know when you create a project, you can choose "DlgApp, DlgAsMain, TabApp".. I've choosen DlgApp and it doesn't work. Maybe I have to chose TabApp ?
Though it should work anyway..

I have another problem too, in my project I created 3 Dlg as you told me, I put some StaticCtrl on it, when I run my .exe it doesn't work but when I close my project and re-open it, my 3 tabs have disappeared !!! They're still in the ProjectFiles but they are very very very little and static controls disappeared! And so for the ID of the 3 dlg, their caption, etc..

I'm sorry to insist once more but I really think that God doesn't wanna me to finish my project..
Posted on 2006-11-06 07:06:00 by marc_
Marc,

I wish I could help you but at this point I can't. I chose as template the "Dialog As Main" which you can easily see in the zipfile's code I attached. I'm afraid you have to try to copy my code 1-1 using the tutorial and the code provided until it works for you.

I also don't know why your dialog is disappearing. Create a new thread describing your problem so that one of us can reproduce it.

Posted on 2006-11-06 07:36:05 by JimmyClif