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 */ 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;
 * 1) define PAGE_COUNT (sizeof( nbpage ) / sizeof( NBPAGE ))
 * 2) define PAGE_FOO 0
 * 3) define PAGE_FOO2 1

/* 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; }  } }