Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tab key issue in Tab Control in Win32 SDK

67 views
Skip to first unread message

Kavitesh Singh

unread,
Oct 5, 2008, 11:53:00 PM10/5/08
to
The original post is present at
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/9b170b5f-c4b9-4792-9205-2791aa2ab288/

I have got no solution so have repeated the post contents here. Would
appreciate if someone can help me out on this issue.

I am making simple tab control in visual studio 2005 express edition.

I do the following steps:-

1. I have a main dialog box made using resource editor with OK and Cancel
button.
2. On this i have made a tab contol by dragging it to the dialog box shape.
3. The tab control is used to display some options.
4. Inorder to display the different options i create a dialog box with
following parameters which will be child to the tab control
1. Border - None
2. Style - child
3. Title bar - false
5. I use this dialog box to display on the tab control using
CreateDialogParam() function.
6. The child dialog (in step 4) has some edit contols to have user input.
7. I want to ensure that user can use the TAB key to move between the
edit controls on the tab control and the OK and Cancel button of the main
dialog.
8. If i press the TAB key the control only switches between the OK and
Cancel button.

I have attached the full code including the resource file code. I hope some
one will help me troubleshoot the issue.

// TabControl_Win32.h code

#pragma once

#pragma comment(linker,"/manifestdependency:\"type='win32'
name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
processorArchitecture='x86' publicKeyToken='6595b64144ccf1df'
language='*'\"")
#pragma comment(lib,"comctl32.lib")

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

INT_PTR CALLBACK MainDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam);
BOOL CenterWindow(HWND hwnd);
void TabControlSetup(HWND hTabControl);
INT_PTR CALLBACK TabDialogOne(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM
lParam);
INT_PTR CALLBACK TabDialogTwo(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM
lParam);

// TabControl_Win32.cpp code


#include "TabControl_Win32.h"
#include "resource.h"

HINSTANCE hInstance =NULL;
HWND hMainDialog = NULL;
HWND hTabMainControl=NULL;
HWND hTabControlList[10];


//entry point
int WINAPI WinMain (HINSTANCE hInstan, HINSTANCE hPrevInstance, PSTR
szCmdLine, int iCmdShow)
{

MSG msg ;

InitCommonControls();
hInstanhInstance = hInstan;
//create dialog box
hMainDialog = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),
NULL, (DLGPROC)MainDlgProc);

if (hMainDialog == NULL)
{
// Notified your about the failure
MessageBox(NULL, TEXT("Application failed to load!"),
TEXT("Error"), MB_OK | MB_ICONEXCLAMATION);
// Set the return value
return FALSE;
}
else
{
ShowWindow (hMainDialog, SW_SHOW) ;
UpdateWindow(hMainDialog);
}

while (GetMessage (&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hMainDialog, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return (int)msg.wParam ;
}


INT_PTR CALLBACK MainDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_INITDIALOG:
hMainDialog = hwnd;
SetWindowText(hwnd,TEXT("Tab Control"));
CenterWindow(hwnd);
hTabMainControl = GetDlgItem(hwnd,IDC_TAB1);
TabControlSetup(hTabMainControl);
break;

case WM_NOTIFY:
{
NMHDR *nmhdr = NULL;
nmhdr = (NMHDR*)lParam;

if(hTabMainControl == nmhdr->hwndFrom)
{
switch(nmhdr->code)
{
case TCN_SELCHANGE:
{
switch(SendMessage(nmhdr->hwndFrom,(UINT)
TCM_GETCURFOCUS,0,0))
{
case 0:
{
ShowWindow (hTabControlList[1] , SW_HIDE) ;
ShowWindow (hTabControlList[0] , SW_SHOW) ;
UpdateWindow(hTabControlList[0] );
}
break;
case 1:
{
ShowWindow (hTabControlList[0] , SW_HIDE) ;
ShowWindow (hTabControlList[1] , SW_SHOW) ;
UpdateWindow(hTabControlList[1] );
}
break;
}

}
break;
}
}
}
break;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
break;
case IDCANCEL:
SendMessage(hwnd,WM_CLOSE,0,0);
break;

}
break;
}

case WM_CLOSE:
DestroyWindow(hTabControlList[0]);
DestroyWindow(hTabControlList[1]);
DestroyWindow(hwnd);
break;

case WM_DESTROY:
PostQuitMessage (0) ;
break;

}
return FALSE ;
}

void TabControlSetup(HWND hTabControl)
{
LRESULT lResult = 0;
TC_ITEM tcItem = {0};
RECT tabControlRect = {0};

tcItem.mask = TCIF_STATE|TCIF_TEXT;

tcItem.pszText = TEXT("Tab Control 1");
lResult = SendMessage(hTabControl,(UINT) TCM_INSERTITEM,0,(LPARAM)
&tcItem );
if(-1==lResult)
{
MessageBox(hTabControl,TEXT("TabControl Insert
failed"),TEXT("Error"),0);
return;
}

hTabControlList[0] =
CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD_TAB_PAGE_1), hTabControl,
(DLGPROC)TabDialogOne,0);
if (hTabControlList[0] == NULL)
{
// Notified your about the failure
MessageBox(NULL, TEXT("IDD_TAB_PAGE_1 failed to load!"),
TEXT("Error"), MB_OK | MB_ICONEXCLAMATION);
}
else
{
ShowWindow (hTabControlList[0] , SW_HIDE) ;
UpdateWindow(hTabControlList[0] );
}


tcItem.pszText = TEXT("Tab Control 2");
lResult = SendMessage(hTabControl,(UINT) TCM_INSERTITEM,1,(LPARAM)
&tcItem );
if(-1==lResult)
{
MessageBox(hTabControl,TEXT("TabControl Insert
failed"),TEXT("Error"),0);
return;
}

hTabControlList[1] =
CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD_TAB_PAGE_2), hTabControl,
(DLGPROC)TabDialogTwo,0);
if (hTabControlList[1] == NULL)
{
// Notified your about the failure
MessageBox(NULL, TEXT("IDD_TAB_PAGE_2 failed to load!"),
TEXT("Error"), MB_OK | MB_ICONEXCLAMATION);
}
else
{
ShowWindow (hTabControlList[1] , SW_HIDE) ;
UpdateWindow(hTabControlList[1] );
}


lResult = SendMessage(hTabControl,(UINT) TCM_SETCURSEL,0,0);
if(-1==lResult)
{
MessageBox(hTabControl,TEXT("TabControl Selection
failed"),TEXT("Error"),0);
return;
}
else
{
ShowWindow (hTabControlList[0] , SW_SHOW) ;
UpdateWindow(hTabControlList[0] );
}


}


INT_PTR CALLBACK TabDialogOne(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM
lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
break;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_TAB1_BUTTON1:
MessageBox(hwndDlg,TEXT("tab 1"),TEXT("Button"),0);
break;
}
break;
}
}
return FALSE ;


}


INT_PTR CALLBACK TabDialogTwo(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM
lParam)
{

switch (uMsg)
{
case WM_INITDIALOG:
break;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_TAB2_BUTTON1:
MessageBox(hwndDlg,TEXT("tab 2"),TEXT("Button"),0);
break;
}
break;
}

}
return FALSE ;


}

BOOL CenterWindow(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;

//make the window relative to its desktop
hwndParent = GetDesktopWindow();

GetWindowRect(hwnd, &rect);
GetWindowRect(hwndParent, &rectP);

width = rect.right - rect.left;
height = rect.bottom - rect.top;

x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;

screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);

//make sure that the dialog box never moves outside of
//the screen
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x + width > screenwidth) x = screenwidth - width;
if(y + height > screenheight) y = screenheight - height;

MoveWindow(hwnd, x, y, width, height, FALSE);
SetActiveWindow(hwnd);

return TRUE;
}

// resource.h code

#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define IDD_DIALOG1 100
#define IDD_TAB_PAGE_2 103
#define IDC_EDIT1 1000
#define IDC_TAB1 1000
#define IDC_TAB1_BUTTON1 1000
#define IDC_TAB2_BUTTON1 1001
#define IDC_EDIT2 1002
#define IDC_EDIT3 1003
#define IDD_TAB_PAGE_1 1033


// TabControl.rc code

// Generated by ResEdit 1.4.3
// Copyright (C) 2006-2008
// http://www.resedit.net

#include "resource.h"
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>


//
// Dialog resources
//
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
IDD_DIALOG1 DIALOGEX 0, 0, 273, 239
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_VISIBLE |
WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "Tahoma", 400, 0, 0
BEGIN
DEFPUSHBUTTON "OK", IDOK, 161, 217, 50, 14
PUSHBUTTON "Cancel", IDCANCEL, 216, 217, 50, 14
CONTROL "", IDC_TAB1, WC_TABCONTROL, 0, 2, 5, 264, 210
END

LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
IDD_TAB_PAGE_2 DIALOGEX 1, 13, 260, 195
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Tahoma", 400, 0, 0
BEGIN
GROUPBOX "Tab 2 page", IDC_STATIC, 15, 26, 216, 151
PUSHBUTTON "Tab 2", IDC_TAB2_BUTTON1, 145, 143, 63, 19
EDITTEXT IDC_EDIT1, 53, 45, 128, 14, ES_AUTOHSCROLL
EDITTEXT IDC_EDIT2, 53, 76, 128, 14, ES_AUTOHSCROLL
EDITTEXT IDC_EDIT3, 53, 109, 128, 14, ES_AUTOHSCROLL
END

LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
IDD_TAB_PAGE_1 DIALOGEX 1, 13, 260, 195
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Tahoma", 400, 0, 0
BEGIN
GROUPBOX "Tab 1 page", IDC_STATIC, 21, 30, 182, 116
PUSHBUTTON "Tab 1", IDC_TAB1_BUTTON1, 77, 74, 59, 27
END

Leslie Milburn

unread,
Oct 6, 2008, 7:17:15 AM10/6/08
to
"Kavitesh Singh" <Kavite...@discussions.microsoft.com> wrote in message
news:953FC776-D4E1-46CC...@microsoft.com...

If you were using CreateWindowEx() for the main window then you could use
the
Window Style WS_EX_CONTROLPARENT which theorectically would then include
controls on child windows in the tab sequence.

HTH
Leslie.


Kavitesh Singh

unread,
Oct 7, 2008, 2:40:01 AM10/7/08
to
Well i am using CreateDialogParam for creating dialog box which have been
modelled in resource editor.

Now what i did was - I used the WS_EX_CONTROLPARENT using SetWindowLong
function for the parent tree control and also the 2 child dialog box in tab
control. The tab controls are working fine now but the problem is: I cant use
Tab key to navigate in pages. For example i would like to swtich from tab-1
to tab-2 using TAB. I tried WS_TABSTOP but it behaves erratically.

Also i didnt understand why i need to out WS_EX_CONTROLPARENT for all the
tab control along with 2 child dialogs. I thought only tab control required
this style.

MSDN states: WS_EX_CONTROLPARENT: The window itself contains child windows
that should take part in dialog box navigation. If this style is specified,
the dialog manager recurses into children of this window when performing
navigation operations such as handling the TAB key, an arrow key, or a
keyboard mnemonic.

Leslie Milburn

unread,
Oct 13, 2008, 8:55:31 PM10/13/08
to
Hi,

WS_EX_CONTROLPARENT should be set on any Window that contains Child Windows,
I do not think it should be applied to controls themselves (ie the Tree
control).

With regards navigating the Tab control itself, TAB is not used to change
the current tab - it makes no sense because then how do you tab into the
actual controls themselves. Try CTRL - TAB and if you have programmed it
correctly, the current tab should change. Take a look at one of the standard
Windows dialogs - such as System Properties to see what I mean.

Leslie.

"Kavitesh Singh" <Kavite...@discussions.microsoft.com> wrote in message

news:94054437-6DF4-44B0...@microsoft.com...

Kavitesh Singh

unread,
Oct 14, 2008, 7:29:01 AM10/14/08
to
The tab control is embedded into a Dialog Box. The tab-control dialog boxes
are child to tab control and not the main dialog box. I hope this is correct
way of creating tab control. The child-dialog box have control like
editbox/list box etc. The main dialog box also has OK/CANCEL button.

I have few observations:
1. To implement basic tab functions i have to use WS_EX_CONTROLPARENT
setting for tab control and child dialog box. If i comment the setting from
child-dialog box i cannot navigate using tab for child tab dialog box.

2. If i comment all WS_EX_CONTROLPARENT for both tab and child-dialog and
keep it for just the main dialog Box. I can use tab to navigate OK/CANCEL
button and also switch the tabs using arrow key.
SetWindowLongPtr(hwnd,GWL_EXSTYLE,WS_EX_CONTROLPARENT);

3. But is do this and change the settings for tabcontrol also then it doesnt
work.

Leslie:
You are right that CTRL+TAB should be used to switch tabs - actually i
wanted some key to use for navigation. I mean like the tab and arrow
combination which work currently partially. I didnt do anything in code for
that though.

For having the CTRL+TAB function right now i think the work around for me
would to manually trap that message and switch tabs. Because i cant find
where the problem in my code is :( :(

Leslie Milburn

unread,
Oct 16, 2008, 9:08:05 AM10/16/08
to

"Kavitesh Singh" <Kavite...@discussions.microsoft.com> wrote in message
news:F66F7D66-AA14-4C06...@microsoft.com...

> The tab control is embedded into a Dialog Box. The tab-control dialog
> boxes
> are child to tab control and not the main dialog box. I hope this is
> correct
> way of creating tab control. The child-dialog box have control like
> editbox/list box etc. The main dialog box also has OK/CANCEL button.

It is my understanding that the Parent Dialog Box should have
WS_EX_CONTROLPARENT not the tab control itself (at least thats how I read
it). It could be that you also need that Window style on the child windows
as well, but I am pretty sure it should *not* be on the Tab Control -
remember this is just a standard control, its nothing special at all really.

> You are right that CTRL+TAB should be used to switch tabs - actually i
> wanted some key to use for navigation. I mean like the tab and arrow
> combination which work currently partially. I didnt do anything in code
> for
> that though.

I am not sure what you actually require, but to use NON-standard key
combinations for common controls is not a good idea and can only lead to
confusion for the End-User.

> For having the CTRL+TAB function right now i think the work around for me
> would to manually trap that message and switch tabs. Because i cant find
> where the problem in my code is :( :(

Well if CTRL-TAB works then you can subclass the Tab control and intercept
the message (if you really must).

Leslie.


0 new messages