Archived

This topic is now archived and is closed to further replies.

Using tabs (win32)

This topic is 5245 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im trying to create a window that will have tabs so I can group my output data. I have figured out how to create tabs as a child window, but I cant figure out how to add content each particular tab. Does the content for each tab have to be created in a child window of its respective tab? How do you tell your program to switch content when you select another tab? If you can help, please drop me some code to help me understand. Thanks!

Share this post


Link to post
Share on other sites
Ok, now I finished the program and hopefully you are still around to enjoy it!!!

Download Code Here: Tab Control

Hope this helps alot, and if you have more questions about the Tab Conrol, feel free to ask.

- BlueDev

Share this post


Link to post
Share on other sites
THank you so much!!! I have been trying to figure this out for a week!!! Im gonna go read through this now, Ill let you know if I find any more problems

By the way, where did you learn how to do this?

Share this post


Link to post
Share on other sites
Hey, im glad that you''re so excited I was to when I learned, and I have also learned about the Tree Control if you want to learn that someday in the future.

Now to answer your question how I learned all this was the MSDN Library and a lot of R&D (Research and Development) It looks easy but it took me two weeks to learn that and a whole month for the Tree Control so after lots and lots of time stuff just starts forming together and yay it works, hehe. Well, ill do my best to answer any more questions you might have. I know alot about the Tab Control, but not everything

Keep in touch.

- BlueDev

Share this post


Link to post
Share on other sites
I have my first question

I havent been able to compile the code yet, from reading over it, it seems that the code generates a dialog box with tabs, and changes the window name when each tab is selected?

My real question is, I see where the notify message tells the program where to change the name, but how would I:

1) Display items (buttons, fields etc) in a certain tab?
2) Alternate between the actual tab contents when the user changes tabs?

Thanks again for the help!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Noods
I have my first question

I havent been able to compile the code yet, from reading over it, it seems that the code generates a dialog box with tabs, and changes the window name when each tab is selected?

My real question is, I see where the notify message tells the program where to change the name, but how would I:

1) Display items (buttons, fields etc) in a certain tab?
2) Alternate between the actual tab contents when the user changes tabs?

Thanks again for the help!


I think I can answer your questions. First and foremost understand that the TAB''s interface along with some of the newer interfaces such as the slider control, and spinner controls are literally hacked in. They were extended functionality which appeared in Visual C++ 5.0 and the dialog editor hasn''t gone through a decent re-write since. And believe you me it''s in dire need of one.

Onto your questions. Because of the above rather than being able to select a tab and draw your interface on the tab it self like you can in builder, C# or visual basic you are required to create a seperate dialog for each tab. You create your dialog fill it in with all the appropriate things such as buttons and box''s and the like. Because of this the each tab operates like it''s own dialog box, and requires a dialogproc to recieve any messages from the buttons and other items. Now when you switch tabs you use the createdialogindirect() function and display the correct dialog inside of the tab based on which tab was selected.

Share this post


Link to post
Share on other sites
Here is another sample if you want to compare and contrast.

Main

#include <windows.h>
#include <commctrl.h>

#include "resource.h"


#pragma comment(linker, "/opt:nowin98")


///////////////////////////////////////////////////////////////////////////////


BOOL CALLBACK general_DialogProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}


///////////////////////////////////////////////////////////////////////////////



void main_SetPage(HWND hwnd,int page)
{
// 0. get the hwnd''s of the two pages!


HWND hGen = GetDlgItem(hwnd,IDD_PAGE_GENERAL);
HWND hOpt = GetDlgItem(hwnd,IDD_PAGE_OPTIONS);

// deal with hGet


if(page == 0)
{
if(!hGen)
{
hGen = CreateDialog((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(IDD_PAGE_GENERAL),hwnd,general_DialogProc);
SetWindowLong(hGen,GWL_ID,IDD_PAGE_GENERAL);
}

SetWindowPos(hGen,0,0,0,0,0,SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
SetFocus(GetWindow(hGen,GW_CHILD));

}
else if(hGen)
{
SetWindowPos(hGen,0,0,0,0,0,SWP_HIDEWINDOW|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
}

if(page == 1)
{
if(!hOpt)
{
hOpt = CreateDialog((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(IDD_PAGE_OPTIONS),hwnd,general_DialogProc);
SetWindowLong(hOpt,GWL_ID,IDD_PAGE_OPTIONS);
}

SetWindowPos(hOpt,0,0,0,0,0,SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
SetFocus(GetWindow(hOpt,GW_CHILD));
}
else if(hOpt)
{
SetWindowPos(hOpt,0,0,0,0,0,SWP_HIDEWINDOW|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
}
}




void main_SetupTabControl(HWND hwnd)
{
HWND hctl = GetDlgItem(hwnd,IDC_TAB);

TCITEM item;

item.mask = TCIF_TEXT;
item.pszText = "General";

TabCtrl_InsertItem(hctl,0,&item);

item.pszText = "Options";

TabCtrl_InsertItem(hctl,1,&item);
}



void main_HandleTabNotify(HWND hwnd,LPNMHDR pnmhdr)
{
HWND hctl = GetDlgItem(hwnd,IDC_TAB);

if(pnmhdr->code == TCN_SELCHANGE)
{
int p = TabCtrl_GetCurSel(hctl);

main_SetPage(hwnd,p);
}
}


BOOL CALLBACK main_DialogProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
main_SetupTabControl(hwnd);
main_SetPage(hwnd,0);
// main_Create

return TRUE;

case WM_NOTIFY:

if(wParam == IDC_TAB)
main_HandleTabNotify(hwnd,(LPNMHDR)lParam);
else
return FALSE;

return TRUE;

case WM_CLOSE:
EndDialog(hwnd,0);
return TRUE;
}
return FALSE;
}



int WINAPI WinMain(
HINSTANCE hInst,
HINSTANCE,
LPSTR pszCmdLine,
int nCmdShow)
{
INITCOMMONCONTROLSEX ice;
ice.dwSize = sizeof(ice);
ice.dwICC = ICC_TAB_CLASSES|ICC_UPDOWN_CLASS;
InitCommonControlsEx(&ice);
return DialogBoxParam(hInst,MAKEINTRESOURCE(IDD_MAIN),NULL,main_DialogProc,0);
}


EXTERN_C int WINAPI WinMainCRTStartup()
{
return WinMain(GetModuleHandle(NULL),NULL,GetCommandLine(),SW_SHOWDEFAULT);
}


Resource IDs

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by apitabtest.rc

//

#define IDD_MAIN 101
#define IDD_PAGE_GENERAL 102
#define IDD_PAGE_OPTIONS 103
#define IDC_TAB 1000
#define IDC_EDIT1 1001
#define IDC_EDIT2 1002
#define IDC_RADIO1 1003
#define IDC_RADIO2 1004
#define IDC_RADIO3 1005
#define IDC_RADIO4 1006

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1007
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif


Resource Script

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////

// English (U.S.) resources


#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//


1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED



/////////////////////////////////////////////////////////////////////////////

//

// Dialog

//


IDD_MAIN DIALOG DISCARDABLE 0, 0, 308, 190
STYLE DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU |
WS_THICKFRAME
CAPTION "My App"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Tab1",IDC_TAB,"SysTabControl32",0x0,7,7,294,176
END

IDD_PAGE_GENERAL DIALOG DISCARDABLE 50, 50, 186, 94
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_EDIT1,72,22,107,14,ES_AUTOHSCROLL
EDITTEXT IDC_EDIT2,72,59,107,14,ES_AUTOHSCROLL
LTEXT "Static",IDC_STATIC,7,25,19,8
LTEXT "Static",IDC_STATIC,7,62,19,8
END

IDD_PAGE_OPTIONS DIALOG DISCARDABLE 50, 50, 186, 95
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Radio1",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,7,15,39,
10
CONTROL "Radio2",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,7,34,39,
10
CONTROL "Radio3",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,7,52,39,
10
CONTROL "Radio4",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,7,66,39,
10
END


/////////////////////////////////////////////////////////////////////////////

//

// DESIGNINFO

//


#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_MAIN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 301
VERTGUIDE, 20
VERTGUIDE, 290
TOPMARGIN, 7
BOTTOMMARGIN, 183
HORZGUIDE, 30
HORZGUIDE, 173
END

IDD_PAGE_GENERAL, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
VERTGUIDE, 72
TOPMARGIN, 7
BOTTOMMARGIN, 87
HORZGUIDE, 29
HORZGUIDE, 66
END

IDD_PAGE_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
END
#endif // APSTUDIO_INVOKED


#endif // English (U.S.) resources

/////////////////////////////////////////////////////////////////////////////




#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//



/////////////////////////////////////////////////////////////////////////////

#endif // not APSTUDIO_INVOKED



Hope that helps.

Share this post


Link to post
Share on other sites
Hey,

Im awake hehe, now to answer your questions.

Firstly,
I create my Dialog Box with a resource editor within MSVC. If you have a tab called FileV... icon near the bottom left of your compilers Workspace area, click on the one called Res... Now that should lead you to the resource items including the Dialog and all the components on the Dialog. Now in the Resource Editor I called the Dialog ''IDD_DIALOG'', the Tab Control ''IDC_TAB_CTRL'', and the Edit Box ''IDC_EDIT_SEL''. Now the code DialogBox() you see in the WinMain API is to show my dialog box from the resource as you can see we use the hInstance. Second parameter is to pull IDD_DIALOG out of the resource, third is GetDesktopWindow() and lastly is my Dialog Procedure for like controlling buttons and so forth.

Now, if you want your Tab Control to register anywhere on your dialog you will need to Initialize the Common Control. As you see in the Dialog Proc in WM_INITDIALOG, which simply means on dialog initialization, we initialized the Tab Control as you might see. We will also need the commctrl.h and comctl32.lib to properly execute this Dialog.

Then, I set the text on the Edit Box to show what Tab Number is currently selected is I used a code called SetDlgItemText() which paramaters stand for (HWND, IDCONTROL, string) so it sets your string to the IDCONTROL on your specific HWND. Pretty simple, heh. Now the whole strcpy() thing is appending a string to say "Tab Number: n" as n equals the current selected tab number. Now I make ''tabNumber = GetCurSel'' so I know which tab is selected with Tab starting with 0 ending with 2 since we have Three Tabs which are inserted by TabCtrl_InsertItem with the Tab Control handle and the item number it is assigned to.

1) You can display certain items in certain tabs but the way ive found it its not easy. The less tabs you have the easier it is. Now the way I do it is create a window with CreateWindow() and once you dont need it anymore you can remove the windows with DestroyWindow() I am going to write some more code on that with a demonstration of how to do it.

2) Yes you can alternate between the actual tab contents when the user changes the tabs as in above question you just use CreateWindow and DestroyWindow when you want to add stuff from one tab and delete it from the other and also I will still write some code on that.

Need anything else, im here.

- BlueDev

Share this post


Link to post
Share on other sites
OK. I worked through your examples, and I now see what they do. Before this, I had never seen resources, they are definitly a nifty way to take care of a lot of programming

However, I still have a big question. In your example Blue, you have a static text box, IDC_EDIT_SEL, that just sits there when you alternate between tabs and updates. Im going to need to remove and add a lot of buttons, text fields, and static text, so I guess my question is, how exactly do you do that? I assume it would be the createwindow/destroy window your talking about, Xiac? I guess like you said, that will be answered in your next example.

Also, is there anyway to manipulate all this information in a program where I do everything manually? (create main window, initialize everything, create tab controls manually, create tabs as child windows manually etc.) I think it would help me to know all the code behind the easy interface if I could learn it.

Thanks again for all the help, I cant wait to see your next example!

Share this post


Link to post
Share on other sites
Yes there is a way to do it all the manual way Instead of posting my next example ill rewrite it in plain Win32 with the dialog creation all in coding format so I will post it once im finished. Good Luck in the mean time.

- BlueDev



   BlueDev Net

Share this post


Link to post
Share on other sites
Yeah, thanks alot for the positive feedback Noods, the example should be done either Thursday or Friday if you dont mind.

- BlueDev



   BlueDev Net

[edited by - BlueDev on August 6, 2003 8:11:30 PM]

Share this post


Link to post
Share on other sites
Woohoo!!! I finally figured it out!!!

Thanks again for your example. From breaking it down, I was eventually able to create my own working code from it.

However, I now have another question

Everytime I switch tabs, I essentially destroy old child windows, and generate the proper ones. I plan to have a lot of items in each tab, so this method may prove to be a lot of coding. Is there any way to just destroy all current child windows, or even better, hide all current child windows?

Thanks again for everyones help

Share this post


Link to post
Share on other sites
I guess you could just move them back and forth on their "z"-axis to simulate one window over another. Or you can declare the last window hidden and unhide it when you need it.

Share this post


Link to post
Share on other sites
Possibly yeah alot of code but my example is done so please look at it. I made a special function called ''deleteWindows()'' which in there it removes all childs but nicely the hard way but also nicely condensed. Then I have another function which you can add too and add your own labels and edit boxes. If you need to know how to create more than just those two please let me know, I was just trying to get the example finished and working properly.

Download Code: Tab Example

Plus if you have anymore questions about this new code please feel free to ask. Also where the tabs switch and create/delete the windows are in a function called ''switchTabWindows()''. Please let me know what you think of it and if you have more questions. Good Luck!

- BlueDev

Share this post


Link to post
Share on other sites
Hey,

I just rewrote the Function.h header file that uses a much easier approach to deleting all the windows. So please take a look at it and if you have any questions about it feel free to ask.

Download Header: Functions.h

Hope this helps clear things up in your code!

- BlueDev


   BlueDev Net

[edited by - BlueDev on August 7, 2003 1:56:50 PM]