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