Easily Load and Manage Pages
By Samuel Audet
Last Modified: May 7, 2001 20:07:03 EDT.
The most annoying problem with Notebooks is the ability to directly communicate with the dialogs. However, this can be easily compensated through some simple functions and a nice structure, thanks to Rick Fishman for the great idea!
typedef struct _NBPAGE
{
PFNWP pfnwpDlg; /* Window procedure address for the dialog */
PSZ szStatusLineText; /* Text to go on status line */
PSZ szTabText; /* Text to go on major tab */
ULONG idDlg; /* ID of the dialog box for this page */
BOOL skip; /* skip this page (for major pages with minor pages) */
USHORT usTabType; /* BKA_MAJOR or BKA_MINOR */
ULONG ulPageId; /* notebook page ID */
HWND hwnd; /* set when page frame is loaded */
} NBPAGE, *PNBPAGE;
You make a global variable that initializes some of the values of that structure. For example:
NBPAGE nbpage[] =
{
{wpFoo, "Tab 1 of 4", "~Foo" , ID_FOO , FALSE, BKA_MAJOR, 0, 0},
{wpFoo2, "Tab 2 of 4", "Foo~2", ID_FOO2, FALSE, BKA_MAJOR, 0, 0},
}
/* some constants so that we don't have
to modify code if we add pages */
#define PAGE_COUNT (sizeof( nbpage ) / sizeof( NBPAGE ))
#define PAGE_FOO 0
#define PAGE_FOO2 1
Once this is filled, you can call createNotebook() and loadNotebookDlg() and voila! no hassle. Send messages to your controls using nbpage[PAGE_FOO].hwnd. Also, you can delay the calling of loadNotebookDlg() by trapping BKN_PAGESELECTEDPENDING and checking if NBPAGE.hwnd is valid to save initial loading time. Also, to skip major pages and show only minor pages, BKN_PAGESELECTEDPENDING does require some attention. See below for an example.
HWND createNotebook(HWND hwnd, NBPAGE *nbpage, ULONG pageCount)
{
HWND hwndNB;
int i;
/* create notebook, here if the warp 4 style doesn't show,
I am trying to minic it with the old style one */
hwndNB = WinCreateWindow( hwnd, WC_NOTEBOOK, NULL, WS_VISIBLE |
BKS_TABBEDDIALOG | /* BKS_BUTTONAREA | */ WS_GROUP | WS_TABSTOP |
/* needed for old style customizeable notebook */
BKS_BACKPAGESTR | BKS_MAJORTABTOP | BKS_ROUNDEDTABS |
BKS_STATUSTEXTCENTER | BKS_SPIRALBIND | BKS_TABTEXTLEFT,
0, 0, 0, 0, hwnd, HWND_TOP, FID_CLIENT, NULL, NULL );
if(!hwndNB) return FALSE;
/* change colors for old style notebook not to look ugly */
WinSendMsg(hwndNB, BKM_SETNOTEBOOKCOLORS, MPFROMLONG(SYSCLR_FIELDBACKGROUND),
MPFROMSHORT(BKA_BACKGROUNDPAGECOLORINDEX));
/* change tab width for old style notebook to something OK for most font size */
WinSendMsg(hwndNB, BKM_SETDIMENSIONS, MPFROM2SHORT(80,25),
MPFROMSHORT(BKA_MAJORTAB));
/* no minor */
WinSendMsg(hwndNB, BKM_SETDIMENSIONS, 0, MPFROMSHORT(BKA_MINORTAB));
for(i = 0; i < pageCount; i++)
{
nbpage[i].ulPageId = (LONG)WinSendMsg(hwndNB, BKM_INSERTPAGE, NULL,
MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | nbpage[i].usTabType),
BKA_LAST));
if ( !nbpage[i].ulPageId)
return FALSE;
if ( !WinSendMsg(hwndNB, BKM_SETSTATUSLINETEXT, MPFROMLONG(nbpage[i].ulPageId),
MPFROMP(nbpage[i].szStatusLineText)))
return FALSE;
if ( !WinSendMsg(hwndNB, BKM_SETTABTEXT, MPFROMLONG(nbpage[i].ulPageId),
MPFROMP(nbpage[i].szTabText)))
return FALSE;
if (!WinSendMsg( hwndNB, BKM_SETPAGEDATA, MPFROMLONG(nbpage[i].ulPageId),
MPFROMP(&nbpage[i])))
return FALSE;
}
/* return success (notebook window handle) */
return hwndNB;
}
BOOL loadNotebookDlg(HWND hwndNotebook, NBPAGE *nbpage, ULONG pageCount)
{
int i;
for(i = 0; i < pageCount; i++)
{
/* loading dialog page frame */
nbpage[i].hwnd = WinLoadDlg(hwndNotebook, hwndNotebook,
nbpage[i].pfnwpDlg, 0, nbpage[i].idDlg, NULL);
if(!nbpage[i].hwnd) return FALSE;
// WinSetPresParam(nbpage[i].hwnd, PP_FONTNAMESIZE, strlen(font)+1, font);
WinSendMsg(hwndNotebook, BKM_SETPAGEWINDOWHWND,
MPFROMLONG(nbpage[i].ulPageId), MPFROMHWND(nbpage[i].hwnd));
}
/* I want the focus on the notebook tab after load */
WinSetFocus(HWND_DESKTOP, hwndNotebook);
return TRUE;
}
In the client or main dialog window procedure, you will need something that looks like this:
/* received from the notebook window,
allows loading and refreshing of pages */
case WM_CONTROL:
{
switch(SHORT2FROMMP(mp1))
{
case BKN_PAGESELECTEDPENDING:
{
PAGESELECTNOTIFY *pageselect = PVOIDFROMMP(mp2);
/* get page window handle */
HWND FrameHwnd = HWNDFROMMR(WinSendMsg(pageselect->hwndBook,
BKM_QUERYPAGEWINDOWHWND,
MPFROMLONG(pageselect->ulPageIdNew), NULL));
NBPAGE *pagedata = PVOIDFROMMR(WinSendMsg(pageselect->hwndBook,
BKM_QUERYPAGEDATA,
MPFROMLONG(pageselect->ulPageIdNew), NULL));
if (!pagedata) return 0;
/* skip dummy (major) pages that we want
to skip to only show their minor pages */
if(pagedata->skip)
{
ULONG ulPageNext = (ULONG) WinSendMsg(pageselect->hwndBook,
BKM_QUERYPAGEID,
MPFROMLONG( pageselect->ulPageIdNew ),
MPFROM2SHORT( BKA_NEXT, 0 ) );
/* if the next page was the previously
viewed page, means the user is
going backward, so we show the previous page */
if(ulPageNext == pageselect->ulPageIdCur)
WinSendMsg(pageselect->hwndBook, BKM_TURNTOPAGE,
MPFROMLONG( (ULONG) WinSendMsg(pageselect->hwndBook,
BKM_QUERYPAGEID,
MPFROMLONG(pageselect->ulPageIdNew),
MPFROM2SHORT(BKA_PREV, 0))
), NULL);
/* else we want to show the next page */
else
WinSendMsg( pageselect->hwndBook,
BKM_TURNTOPAGE, MPFROMLONG(ulPageNext), NULL);
/* prevents the current page from showing at all */
pageselect->ulPageIdNew = 0;
break;
}
else if (!FrameHwnd)
loadNotebookDlg(pageselect->hwndBook, pagedata, 1);
return 0;
}
}
}