Property Sheet Tab Control and TCS_VERTICAL Style 
Author Message
 Property Sheet Tab Control and TCS_VERTICAL Style

Hi,

I have to create an application that display a property sheet that have its
tabs on it left side.
I have implemented the CMyPropertySheet class that derive form
CPropertySheet class and it OnInitDialog method:

BOOL CMyPropertySheet::OnInitDialog()
{
     BOOL bResult = CPropertySheet::OnInitDialog();
     GetTabControl()->ModifyStyle(0, TCS_VERTICAL | TCS_MULTILINE, 0);
      return bResult;

Quote:
}

in order to put the tabs on the left size of the property sheet.

There are two problems :

- The tabs are not painted propertly until you click on one of them

- The tabs labels are not dispayed vertically.

Any help would be appreciated.

Thanks,

Vincent Marie



Mon, 20 Oct 2003 16:57:28 GMT  
 Property Sheet Tab Control and TCS_VERTICAL Style
Hi, Vincent!

Quote:

> Hi,

> I have to create an application that display a property sheet that have its
> tabs on it left side.
> I have implemented the CMyPropertySheet class that derive form
> CPropertySheet class and it OnInitDialog method:

> BOOL CMyPropertySheet::OnInitDialog()
> {
>      BOOL bResult = CPropertySheet::OnInitDialog();
>      GetTabControl()->ModifyStyle(0, TCS_VERTICAL | TCS_MULTILINE, 0);
>       return bResult;
> }
> in order to put the tabs on the left size of the property sheet.

> There are two problems :

> - The tabs are not painted propertly until you click on one of them

> - The tabs labels are not dispayed vertically.

> Any help would be appreciated.

> Thanks,

> Vincent Marie


Here's some sample code, it uses the styles TCS_VERTICAL|TCS_RIGHT but hopefully it will work with
your style goals too. I'm sorry that I don't have time right now to re-implement it. Anyway...

The trick is to get to the tab control before it is created, and for a propertysheet this is at the
DLGTEMPLATE[EX] level. Anyway, the propertysheet gives you access to this template via the
PropSheetProc function pointer in the PROPSHEETHEADER structure. So the first step is to derive a
class from CPropertySheet, and the second step is to add a member function declared like this...

    static int CALLBACK SheetCallBack(HWND, UINT, LPARAM);

The third step is to let the propertysheet know about it, and that you want to use it. So in your
CPropertySheet derived class's constructor(s), or somwhere else appropriate, you set up the
PROPSHEETHEADER...

    CMySheet::CMySheet()
    {
        m_psh.dwFlags |= PSH_USECALLBACK;
        m_psh.pfnCallback = &SheetCallBack;
        AddPage(&m_page1);
        ...
        AddPage(&m_page6);
    }

Next, just in case some version of the Win32 OS (although it is documented as only a DLGTEMPLATE)
uses a DLGTEMPLATEEX structure, you need to provide a typedef for it, and the DLGITEMTEMPLATEEX like
this...

    #pragma pack(push, 1)

    typedef struct {
        WORD    dlgVer;
        WORD    signature;
        DWORD  helpID;
        DWORD  exStyle;
        DWORD  style;
        WORD    cDlgItems;
        short  x;
        short  y;
        short  cx;
        short  cy;
    } DLGTEMPLATEEX, *LPDLGTEMPLATEEX;

    typedef struct
    {
        DWORD  helpID;
        DWORD  exStyle;
        DWORD  style;
        short  x;
        short  y;
        short  cx;
        short  cy;
        WORD   id;
    } DLGITEMTEMPLATEEX, *LPDLGITEMTEMPLATEEX;

#pragma pack(pop)

Lastly, you have to implement the above "SheetCallBack" (you can name it whatever you want)
function, something like so...

    int CALLBACK CMySheet::SheetCallBack(HWND hWnd, UINT msg, LPARAM lParam)
    {
        if (msg == PSCB_PRECREATE && AfxIsValidAddress((void*)lParam, 512))
        {
            union {
                DWORD dw;
                LPVOID Void;
                LPCSTR Char;
                LPCWSTR WChar;
                LPDLGTEMPLATE Template;
                LPDLGTEMPLATEEX TemplateEx;
                LPDLGITEMTEMPLATE Item;
                LPDLGITEMTEMPLATEEX ItemEx;
            } p = {lParam};

            while((p.Void = memchr(p.Void, 'S', (512-(p.dw - lParam)))) != NULL)
            {
                if (0 == wcscmp(p.WChar, L"SysTabControl32"))
                {
                    if (((LPDLGTEMPLATEEX)lParam)->signature != 0xFFFF)
                    {
                        p.dw -= sizeof(DLGITEMTEMPLATE);
                        p.Item->style |= (TCS_VERTICAL|TCS_RIGHT);
                    }
                    else
                    {
                        p.dw -= sizeof(DLGITEMTEMPLATEEX);
                        p.ItemEx->style |= (TCS_VERTICAL|TCS_RIGHT);
                    }
                    break;
                }
                p.Char++;
            }
        }
        return 0;
    }

And that's it in all of it's ungainly glory. I should point out that if you create a modless
CPropertySheet, MFC inserts it's own AfxPropSheetCallBack function in the default
CPropertySheet::Create function, so you may have to work with or around that.

HTH,

Jeff...
--
Please post all follow-ups to the newsgroup only.



Mon, 20 Oct 2003 19:30:56 GMT  
 Property Sheet Tab Control and TCS_VERTICAL Style
Thanks a lot Jeff for your prompt response!

I try your solution and it works properly,
However, in the mean time I found another solution ... maybe more simple:
the CMyPropertySheet::InitDialog method becames :

BOOL CMyPropertySheet::OnInitDialog()
{
 BOOL bResult = CPropertySheet::OnInitDialog();

 LOGFONT lfLogFont;
 CFont fFont;

 GetTabControl()->ModifyStyle(0, TCS_VERTICAL | TCS_MULTILINE, 0);

/* Turn the tabs label vertically */
 GetTabControl()->GetFont()->GetLogFont(&lfLogFont);
 lfLogFont.lfOrientation = 90;
 fFont.CreateFontIndirect(&lfLogFont);
 GetTabControl()->SetFont(&fFont);

/* Repaint properly the property sheet tabs */
 SetActivePage(GetActivePage());

 return bResult;

Quote:
}

Thanks again,
Vincent.


Quote:
> Hi, Vincent!




Quote:
> > Hi,

> > I have to create an application that display a property sheet that have
its
> > tabs on it left side.
> > I have implemented the CMyPropertySheet class that derive form
> > CPropertySheet class and it OnInitDialog method:

> > BOOL CMyPropertySheet::OnInitDialog()
> > {
> >      BOOL bResult = CPropertySheet::OnInitDialog();
> >      GetTabControl()->ModifyStyle(0, TCS_VERTICAL | TCS_MULTILINE, 0);
> >       return bResult;
> > }
> > in order to put the tabs on the left size of the property sheet.

> > There are two problems :

> > - The tabs are not painted propertly until you click on one of them

> > - The tabs labels are not dispayed vertically.

> > Any help would be appreciated.

> > Thanks,

> > Vincent Marie

> Here's some sample code, it uses the styles TCS_VERTICAL|TCS_RIGHT but

hopefully it will work with
Quote:
> your style goals too. I'm sorry that I don't have time right now to

re-implement it. Anyway...
Quote:

> The trick is to get to the tab control before it is created, and for a

propertysheet this is at the
Quote:
> DLGTEMPLATE[EX] level. Anyway, the propertysheet gives you access to this
template via the
> PropSheetProc function pointer in the PROPSHEETHEADER structure. So the

first step is to derive a
Quote:
> class from CPropertySheet, and the second step is to add a member function

declared like this...
Quote:

>     static int CALLBACK SheetCallBack(HWND, UINT, LPARAM);

> The third step is to let the propertysheet know about it, and that you

want to use it. So in your
Quote:
> CPropertySheet derived class's constructor(s), or somwhere else

appropriate, you set up the
Quote:
> PROPSHEETHEADER...

>     CMySheet::CMySheet()
>     {
>         m_psh.dwFlags |= PSH_USECALLBACK;
>         m_psh.pfnCallback = &SheetCallBack;
>         AddPage(&m_page1);
>         ...
>         AddPage(&m_page6);
>     }

> Next, just in case some version of the Win32 OS (although it is documented

as only a DLGTEMPLATE)
Quote:
> uses a DLGTEMPLATEEX structure, you need to provide a typedef for it, and

the DLGITEMTEMPLATEEX like

- Show quoted text -

Quote:
> this...

>     #pragma pack(push, 1)

>     typedef struct {
>         WORD    dlgVer;
>         WORD    signature;
>         DWORD  helpID;
>         DWORD  exStyle;
>         DWORD  style;
>         WORD    cDlgItems;
>         short  x;
>         short  y;
>         short  cx;
>         short  cy;
>     } DLGTEMPLATEEX, *LPDLGTEMPLATEEX;

>     typedef struct
>     {
>         DWORD  helpID;
>         DWORD  exStyle;
>         DWORD  style;
>         short  x;
>         short  y;
>         short  cx;
>         short  cy;
>         WORD   id;
>     } DLGITEMTEMPLATEEX, *LPDLGITEMTEMPLATEEX;

> #pragma pack(pop)

> Lastly, you have to implement the above "SheetCallBack" (you can name it
whatever you want)
> function, something like so...

>     int CALLBACK CMySheet::SheetCallBack(HWND hWnd, UINT msg, LPARAM
lParam)
>     {
>         if (msg == PSCB_PRECREATE && AfxIsValidAddress((void*)lParam,
512))
>         {
>             union {
>                 DWORD dw;
>                 LPVOID Void;
>                 LPCSTR Char;
>                 LPCWSTR WChar;
>                 LPDLGTEMPLATE Template;
>                 LPDLGTEMPLATEEX TemplateEx;
>                 LPDLGITEMTEMPLATE Item;
>                 LPDLGITEMTEMPLATEEX ItemEx;
>             } p = {lParam};

>             while((p.Void = memchr(p.Void, 'S', (512-(p.dw - lParam)))) !=
NULL)
>             {
>                 if (0 == wcscmp(p.WChar, L"SysTabControl32"))
>                 {
>                     if (((LPDLGTEMPLATEEX)lParam)->signature != 0xFFFF)
>                     {
>                         p.dw -= sizeof(DLGITEMTEMPLATE);
>                         p.Item->style |= (TCS_VERTICAL|TCS_RIGHT);
>                     }
>                     else
>                     {
>                         p.dw -= sizeof(DLGITEMTEMPLATEEX);
>                         p.ItemEx->style |= (TCS_VERTICAL|TCS_RIGHT);
>                     }
>                     break;
>                 }
>                 p.Char++;
>             }
>         }
>         return 0;
>     }

> And that's it in all of it's ungainly glory. I should point out that if

you create a modless

- Show quoted text -

Quote:
> CPropertySheet, MFC inserts it's own AfxPropSheetCallBack function in the
default
> CPropertySheet::Create function, so you may have to work with or around
that.

> HTH,

> Jeff...
> --
> Please post all follow-ups to the newsgroup only.



Mon, 20 Oct 2003 21:06:29 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Tab Control and Property Sheet

2. Property Sheets and Tab Control

3. Property Sheets and Tab Control

4. Tab control VS. Property sheet

5. Tab and property sheets control...

6. Property sheet with no tab control?

7. Subclass tab control in property sheet?

8. Tab Controls and Property Sheets

9. Tab Control or Property Sheet?

10. Property Sheets v/s Tabbed Control

11. TAB Controls or Property SHeet/Pages?

12. moving tab control in a property sheet

 

 
Powered by phpBB® Forum Software