Thread: Tutorial or help about Tab control

  1. #1
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310

    Question Tutorial or help about Tab control

    Hi...

    I've read msdn's about how to use tab controls with dialogs...

    Does anyone know another tutorial about how to implement pages on tab controls?
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  2. #2
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Last time I did it I made a linked list of HWNDs and created a list for each page, traversing through the list to show and hide.

    But in hindsight, a better way might be to make everything on a page a child of a generic window and have an array of those instead, that way you don't need to go through reams of ShowWindow calls all the time whenever the tab control notifies you of a change.

  3. #3
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    ok...that part just, coded:
    Code:
    #include <windows.h>
    #include <commctrl.h>
    #include "resource.h"
    
    const int IDC_TABCONTROL = 1001;
    HWND hwnd_tab = NULL;
    
    INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch(uMsg)
    	{
    	case WM_INITDIALOG:
    		{
    			return true;
    		}
    	case WM_DESTROY:
    		{
    			return true;
    		}
    	case WM_CLOSE:
    		{
    			return true;
    		}
    	}
    	return false;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hTab;
    	static HINSTANCE hInstance;
    	switch (uMsg)
    	{
    	case WM_CREATE:
    		{
    			hInstance = LPCREATESTRUCT(lParam)->hInstance;
    
    			INITCOMMONCONTROLSEX iccx;
    			iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    			iccx.dwICC = ICC_TAB_CLASSES;
    			InitCommonControlsEx(&iccx);
    
    			RECT rc;
    			GetClientRect(hWnd, &rc);
    			hTab = CreateWindowEx(0, WC_TABCONTROL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, 0, 0, rc.right, rc.bottom, hWnd, HMENU(IDC_TABCONTROL), hInstance, 0);
    			SendMessage(hTab, WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 0);
    
    			TCITEM tci;
    			int i = 0;
    			tci.mask = TCIF_TEXT|TCIF_IMAGE;
    			tci.iImage = -1;
    			tci.pszText = "XML";
    			TabCtrl_InsertItem(hTab, ++i, &tci);
    
    			tci.pszText = "Output";
    			TabCtrl_InsertItem(hTab, ++i, &tci);
    			return 0;
    		}
    	case WM_SIZE:
    		{
    			RECT rc;
    			GetClientRect(hWnd, &rc);
    			TabCtrl_AdjustRect(hTab, false, &rc);
    			MoveWindow(hTab, 10, 10, LOWORD(lParam)-20, HIWORD(lParam)-20, true);
    			return 0;
    		}
    	case WM_NOTIFY:
    		{
    			LPNMHDR lpnmhdr = LPNMHDR(lParam);
    			switch(lpnmhdr->code)
    			{
    			case TCN_SELCHANGE:
    				{
    					int iSel = TabCtrl_GetCurSel(lpnmhdr->hwndFrom);
    					if (IsWindow(hwnd_tab))
    					{
    						DestroyWindow(hwnd_tab);
    					}
    					hwnd_tab = CreateDialog(hInstance, MAKEINTRESOURCE(101+iSel), hWnd, DlgProc);
    					RECT rc;
    					GetWindowRect(lpnmhdr->hwndFrom, &rc);
    					SetWindowPos(hwnd_tab, 0, rc.left+2, rc.top+24, (rc.right-rc.left)-4, (rc.bottom-rc.top)-26, SWP_NOZORDER | SWP_NOACTIVATE);
    					SetFocus(GetParent(lpnmhdr->hwndFrom));
    					break;
    				}
    			}
    			return 0;
    		}
    	case WM_COMMAND:
    		{
    			return 0;
    		}
    	case WM_CLOSE:
    		{
    			DestroyWindow(hWnd);
    			return 0;
    		}
    	case WM_DESTROY:
    		{
    			PostQuitMessage(0);
    			return 0;
    		}
    	}
    	return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    But now, I have another question: Is it possible to "lock" each dialog into the tab control? I mean, if I move my parent window, the current dialogbox keeps its position
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  4. #4
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    The problem is that your dialog resources are likely to be missing the WS_CHILD style, so they're treated as separate windows instead of part of the parent. I don't know if you can make dialogs WS_CHILD in the dialog editor but if not you would have to use SetWindowLong(hwnd_tab, GWL_STYLE, GetWindowLong(hwnd_tab, GWLSTYLE) | WS_CHILD) and SetWindowPos to update the dialog to the new style.

  5. #5
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Hi Smurf, I'm going to try it..

    1. coding.
    2. compiling
    3. testing
    4. failed: Is the same problem

    I open my Tab.rc and this is the generated code for each dialog:
    Code:
    IDD_DIALOG1 DIALOGEX 0, 0, 188, 90
    STYLE DS_SYSMODAL | DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | 
        WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
        LTEXT           "Dlg1",IDC_STATIC,22,18,15,8
    END
    
    IDD_DIALOG2 DIALOGEX 0, 0, 186, 90
    STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CHILD | WS_VISIBLE | 
        WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
        LTEXT           "Dlg2",IDC_STATIC,50,28,15,8
    END
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  6. #6
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Instead of having a list of windows for each page, create a window covering the entire client are for each page of the tab control then each button etc are children of this window. Hiding this window will also hide all its child windows.
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  7. #7
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Joelito, your code:
    Code:
    STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CHILD | WS_VISIBLE | 
        WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
    From the Win32 API:
    WS_POPUP Creates a pop-up window. This style cannot be used with the WS_CHILD style.
    You cannot WS_CHILD | WS_POPUP. (Makes no sense to do so.) Besides, if these are dialogs that are acting as pages in "tabs", it makes no sense to have WS_SYSMENU style either.

    Though personally I've had issues with using dialogs as tab pages. It works great, but using the tab key to switch focus seems to get stuck within the sub-dialog. You'll have to figure a way out of that one... I'm still working on it myself.

    This is doable; Nullsoft's Winamp does it. If you have WinAmp, check out their Preferences dialog: it's a great example. The main dialog has the close button, a treeview, and a sub-dialog for the current page. Many of the "option pages" have tab controls within that subdialog, and the tab controls use subdialogs. (That's a subdialog in a subdialog in a dialog box.) But between all these layers of controls, you can tab between them, in and out of subdialogs. (Though the tab controls themselves appear to not be tabstops. Shame.)
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  8. #8
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Ok, about Cactus_Hugger suggestion:

    I manage to the add some lines in my code:
    Code:
    case WM_NOTIFY:
    		{
    			LPNMHDR lpnmhdr = LPNMHDR(lParam);
    			switch(lpnmhdr->code)
    			{
    			case TCN_SELCHANGE:
    				{
    					int iSel = TabCtrl_GetCurSel(lpnmhdr->hwndFrom);
    					if (IsWindow(hPage))
    					{
    						DestroyWindow(hPage);
    					}
    					hPage = CreateDialog(hInstance, MAKEINTRESOURCE(101+iSel), hWnd, DlgProc);
    					RECT rc;
    					GetWindowRect(lpnmhdr->hwndFrom, &rc);
    
    					SetWindowLong(hPage, GWL_STYLE, WS_CHILD);
    					SetWindowLong(hPage, GWL_EXSTYLE, WS_EX_CONTROLPARENT);
    
    					SetWindowPos(hPage, 0, rc.left+2, rc.top+24, (rc.right-rc.left)-4, (rc.bottom-rc.top)-26, SWP_SHOWWINDOW|SWP_NOZORDER);
    					SetFocus(hWnd);
    					break;
    				}
    			}
    But, it keeps the current dialog in the same position
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  9. #9
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Try this:
    • Just set the STYLE resource definition in your dialog resource to WS_CHILD.
    • Make the tab control the dialog parent.
    • Move the SetWindowPos call for the dialog to the WM_INITDIALOG handler in the respective dialog procedure. Send a TCM_ADJUSTRECT message with the parent's ie the tab control's client dimensions and use that to provide the necessary dialog dimensions to SetWindowPos. If your dialog resource doesn't specify the WS_VISIBLE style bit then make sure you specify the SWP_SHOWWINDOW flag in your SetWindowPos call.
    • Lose the SetWindowLong calls in your TCN_SELCHANGE notification handler.

    If that fails to produce a satisfactory result then create a minimalist project that replicates the problem(s) and either post or attach that (include resource script and resource header).
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need a little help here about MFC and Tab Control stuff...
    By guitarist809 in forum Windows Programming
    Replies: 4
    Last Post: 09-19-2008, 10:36 AM
  2. Button handler
    By Nephiroth in forum Windows Programming
    Replies: 8
    Last Post: 03-12-2006, 06:23 AM
  3. Tab order in Tab Control
    By Halloko in forum Windows Programming
    Replies: 2
    Last Post: 05-08-2005, 11:08 PM
  4. tab control
    By tyouk in forum Windows Programming
    Replies: 6
    Last Post: 02-07-2005, 11:47 PM
  5. Disable a tab in control tab?
    By Iron Mike in forum Windows Programming
    Replies: 1
    Last Post: 07-23-2003, 10:50 AM