home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgmon.zip / notebook.c < prev    next >
C/C++ Source or Header  |  1993-07-27  |  40KB  |  940 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  notebook.c             AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-21-93                                           *
  5.  *                                                                   *
  6.  * MODULE DESCRIPTION:                                               *
  7.  *                                                                   *
  8.  *  Part of the 'DRGDROP' drag/drop sample program.                  *
  9.  *                                                                   *
  10.  *  Main module for the notebook code. Each dialog will have its own *
  11.  *  source module. Those modules can be looked upon as being owned   *
  12.  *  by this one, much as the notebook owns the dialogs on its pages. *
  13.  *                                                                   *
  14.  * NOTES:                                                            *
  15.  *                                                                   *
  16.  * FUNCTIONS CALLABLE BY OTHER MODULES:                              *
  17.  *                                                                   *
  18.  *   bookSetup                                                       *
  19.  *                                                                   *
  20.  *                                                                   *
  21.  * HISTORY:                                                          *
  22.  *                                                                   *
  23.  *  07-21-93 - Program coded.                                        *
  24.  *                                                                   *
  25.  *  Rick Fishman                                                     *
  26.  *  Code Blazers, Inc.                                               *
  27.  *  4113 Apricot                                                     *
  28.  *  Irvine, CA. 92720                                                *
  29.  *  CIS ID: 72251,750                                                *
  30.  *                                                                   *
  31.  *                                                                   *
  32.  *********************************************************************/
  33.  
  34. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  35.  
  36. /*********************************************************************/
  37. /*------- Include relevant sections of the OS/2 header files --------*/
  38. /*********************************************************************/
  39.  
  40. #define  INCL_DOSERRORS
  41. #define  INCL_DOSRESOURCES
  42. #define  INCL_GPILCIDS
  43. #define  INCL_GPIPRIMITIVES
  44. #define  INCL_WINDIALOGS
  45. #define  INCL_WINERRORS
  46. #define  INCL_WINFRAMEMGR
  47. #define  INCL_WININPUT
  48. #define  INCL_WINSHELLDATA
  49. #define  INCL_WINSTDBOOK
  50. #define  INCL_WINSTDCNR
  51. #define  INCL_WINSTDDRAG
  52. #define  INCL_WINSYS
  53. #define  INCL_WINWINDOWMGR
  54.  
  55. /*********************************************************************/
  56. /*----------------------------- INCLUDES ----------------------------*/
  57. /*********************************************************************/
  58.  
  59. #include <os2.h>
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #include "drgdrop.h"
  64.  
  65. /*********************************************************************/
  66. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  67. /*********************************************************************/
  68.  
  69. #define TAB_CX_MARGIN            14  // Margin around text in tab
  70. #define TAB_CY_MARGIN            10  // Margin around text in tab
  71.  
  72. #define BOOK_TITLE               "DrgDrop Settings"
  73.  
  74. #define FRAME_FLAGS             (FCF_TASKLIST  | FCF_TITLEBAR  | FCF_SYSMENU | \
  75.                                  FCF_MINBUTTON | FCF_SIZEBORDER)
  76.  
  77. /*********************************************************************/
  78. /*---------------------------- STRUCTURES ---------------------------*/
  79. /*********************************************************************/
  80.  
  81. typedef struct _PAGECONSTANTS       // PER-PAGE CONSTANTS
  82. {
  83.     PFNWP   pfnwpDlg;               // Window procedure address for the dialog
  84.     PSZ     szStatusLineText;       // Text to go on status line
  85.     PSZ     szTabText;              // Text to go on the tab
  86.     ULONG   idPage;                 // Page id
  87.     ULONG   idDlg;                  // ID of the dialog box for this page
  88.  
  89. } PAGECONSTANTS, *PPAGECONSTANTS;
  90.  
  91. /*********************************************************************/
  92. /*----------------------- FUNCTION PROTOTYPES -----------------------*/
  93. /*********************************************************************/
  94.  
  95. BOOL CreateNotebookWindow( HWND hwndParent );
  96. BOOL SetUpPage           ( HPS hps, PPAGECONSTANTS pPgConsts, int *pcxTab,
  97.                            int *pcxPage, int *pcyPage );
  98. BOOL GetDialogDimensions ( ULONG idDlg, PLONG pCx, PLONG pCy );
  99. BOOL SetFramePos         ( HWND hwndFrame, int cxPage, int cyPage );
  100. BOOL ControlMsg          ( HWND hwndFrame, USHORT usControl, USHORT usEvent,
  101.                            MPARAM mp2 );
  102. void SetNBPage           ( HWND hwndFrame, PPAGESELECTNOTIFY ppsn );
  103. HWND LoadAndAssociate    ( HWND hwndFrame, PPAGEDATA pPageData,
  104.                            PPAGESELECTNOTIFY ppsn );
  105. void TurnToPage          ( ULONG idRequestedPage );
  106. void FreeResources       ( void );
  107.  
  108. FNWP wpNBFrame;
  109.  
  110. /*********************************************************************/
  111. /*------------------------ GLOBAL VARIABLES -------------------------*/
  112. /*********************************************************************/
  113.  
  114. PAGECONSTANTS PgConsts[] =    // CONSTANT PAGE DATA
  115. {
  116.     { wpDragInfo, "DragInfo Setup",        "~DragInfo", NBPID_DRAGINFO,
  117.       IDD_DRAGINFO },
  118.  
  119.     { wpRMF,      "RMF Setup",             "~RMF",      NBPID_RMF,
  120.       IDD_RMF },
  121.  
  122.     { wpReply,    "Message Reply Options", "R~eplies",  NBPID_REPLY,
  123.       IDD_REPLY },
  124.  
  125.     { wpMisc,     "Miscellaneous Options", "~Misc",     NBPID_MISC,
  126.       IDD_MISC }
  127. };
  128.  
  129. #define PAGE_COUNT (sizeof( PgConsts ) / sizeof( PAGECONSTANTS ))
  130.  
  131. PFNWP pfnwpFrame;                  // Original frame winproc
  132.  
  133. /*********************************************************************/
  134. /*--------------------------- bookSetup -----------------------------*/
  135. /*                                                                   */
  136. /*  CREATE THE SETTINGS NOTEBOOK IF NOT ALREADY CREATED              */
  137. /*                                                                   */
  138. /*  PARMS: id of page to turn to                                     */
  139. /*                                                                   */
  140. /*  NOTES:                                                           */
  141. /*                                                                   */
  142. /*  RETURNS: frame window handle                                     */
  143. /*                                                                   */
  144. /*-------------------------------------------------------------------*/
  145. /*********************************************************************/
  146. HWND bookSetup( ULONG idInitialPage )
  147. {
  148.     HWND hwndFrame;
  149.  
  150.     if( hwndBook )
  151.     {
  152.         hwndFrame = PARENT( hwndBook );
  153.  
  154.         // For some reason it is necessary to restore the notebook before
  155.         // setting the frame as the active window if the frame is being
  156.         // restored from a minimized state.
  157.  
  158.         WinSetWindowPos( hwndBook, NULLHANDLE, 0, 0, 0, 0,
  159.                          SWP_SHOW | SWP_RESTORE );
  160.         WinSetWindowPos( hwndFrame, NULLHANDLE, 0, 0, 0, 0,
  161.                          SWP_SHOW | SWP_RESTORE | SWP_ACTIVATE );
  162.     }
  163.     else
  164.     {
  165.         FRAMECDATA fcdata;
  166.  
  167.         memset( &fcdata, 0, sizeof fcdata );
  168.         fcdata.cb            = sizeof( FRAMECDATA );
  169.         fcdata.flCreateFlags = FRAME_FLAGS;
  170.         fcdata.idResources   = ID_NBFRAME;
  171.  
  172.         hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL, WS_ANIMATE,
  173.                                      0, 0, 0, 0, NULLHANDLE, HWND_TOP,
  174.                                      ID_NBFRAME, &fcdata, NULL );
  175.         if( hwndFrame )
  176.         {
  177.             pfnwpFrame = WinSubclassWindow( hwndFrame, wpNBFrame );
  178.             if( pfnwpFrame )
  179.                 if( CreateNotebookWindow( hwndFrame ) )
  180.                     WinSetWindowText( hwndFrame, BOOK_TITLE );
  181.                 else
  182.                 {
  183.                     WinDestroyWindow( hwndFrame );
  184.                     hwndFrame = NULLHANDLE;
  185.                 }
  186.             else
  187.             {
  188.                 WinDestroyWindow( hwndFrame );
  189.                 Msg( "bookSetup WinSubclassWindow RC(%X)", HWNDERR(hwndFrame) );
  190.                 hwndFrame = NULLHANDLE;
  191.             }
  192.         }
  193.         else
  194.             Msg( "bookSetup WinCreateWindow of frame window RC(%X)", HABERR(0));
  195.     }
  196.  
  197.     if( hwndBook )
  198.         TurnToPage( idInitialPage );
  199.  
  200.     return hwndFrame;
  201. }
  202.  
  203. /**********************************************************************/
  204. /*----------------------- bookRefreshDlgInfo -------------------------*/
  205. /*                                                                    */
  206. /*  REFRESH THE GLOBAL DLGINFO STRUCTURE.                             */
  207. /*                                                                    */
  208. /*  PARMS: nothing                                                    */
  209. /*                                                                    */
  210. /*  NOTES:                                                            */
  211. /*                                                                    */
  212. /*  RETURNS: nothing                                                  */
  213. /*                                                                    */
  214. /*--------------------------------------------------------------------*/
  215. /**********************************************************************/
  216. void bookRefreshDlgInfo()
  217. {
  218.     USHORT usNext = BKA_FIRST;
  219.     ULONG  ulPageId = 0;
  220.     HWND   hwndDlg;
  221.  
  222.     if( !hwndBook )
  223.         return;
  224.  
  225.     // Enumerate through all the pages of the notebook so we can gain access
  226.     // to their page data to free their resources.
  227.  
  228.     for( ; ; )
  229.     {
  230.         ulPageId = (ULONG) WinSendMsg( hwndBook, BKM_QUERYPAGEID,
  231.                                        MPFROMLONG( ulPageId ),
  232.                                        MPFROM2SHORT( usNext, 0 ) );
  233.         if( !ulPageId )
  234.             break;
  235.  
  236.         usNext = BKA_NEXT;
  237.  
  238.         if( ulPageId == (ULONG) BOOKERR_INVALID_PARAMETERS )
  239.             Msg( "bookRefreshDlgInfo QUERYPAGEID RC(%X)", HWNDERR( hwndBook ) );
  240.  
  241.         hwndDlg = (HWND) WinSendMsg( hwndBook, BKM_QUERYPAGEWINDOWHWND,
  242.                                      MPFROMLONG( ulPageId ), NULL );
  243.  
  244.         if( hwndDlg != (HWND) BOOKERR_INVALID_PARAMETERS && hwndDlg )
  245.             WinSendMsg( hwndDlg, UM_DUMP_DLGINFO, NULL, NULL );
  246.     }
  247. }
  248.  
  249. /**********************************************************************/
  250. /*----------------------- CreateNotebookWindow -----------------------*/
  251. /*                                                                    */
  252. /*  CREATE THE NOTEBOOK WINDOW                                        */
  253. /*                                                                    */
  254. /*  PARMS: frame window handle                                        */
  255. /*                                                                    */
  256. /*  NOTES:                                                            */
  257. /*                                                                    */
  258. /*  RETURNS: TRUE or FALSE if successful or not                       */
  259. /*                                                                    */
  260. /*--------------------------------------------------------------------*/
  261. /**********************************************************************/
  262. BOOL CreateNotebookWindow( HWND hwndFrame )
  263. {
  264.     BOOL fSuccess = TRUE;
  265.  
  266.     // Make the notebook's id FID_CLIENT so we don't need a client window. This
  267.     // will make the notebook automatically size with the frame window and
  268.     // eliminate the need for a client window.
  269.  
  270.     hwndBook = WinCreateWindow( hwndFrame, WC_NOTEBOOK, NULL,
  271.                 BKS_BACKPAGESBR | BKS_MAJORTABRIGHT | BKS_ROUNDEDTABS |
  272.                 BKS_STATUSTEXTCENTER | BKS_SPIRALBIND | WS_VISIBLE,
  273.                 0, 0, 0, 0, hwndFrame, HWND_TOP, FID_CLIENT, NULL, NULL );
  274.  
  275.     if( hwndBook )
  276.     {
  277.         int          i, cxTab = 0, cyTab = 0, cxPage = 0, cyPage = 0;
  278.         FONTMETRICS  fm;
  279.         HPS          hps = WinGetPS( hwndBook );
  280.  
  281.         if( GpiQueryFontMetrics( hps, sizeof fm, &fm ) )
  282.         {
  283.             cyTab = fm.lMaxBaselineExt;
  284.  
  285.             // Set the page background color to grey so it is the same as
  286.             // a dialog box.
  287.  
  288.             if( !WinSendMsg( hwndBook, BKM_SETNOTEBOOKCOLORS,
  289.                              MPFROMLONG( SYSCLR_FIELDBACKGROUND ),
  290.                              MPFROMSHORT( BKA_BACKGROUNDPAGECOLORINDEX ) ) )
  291.                 Msg( "BKM_SETNOTEBOOKCOLRS (BACKPAGE) RC(%X)",
  292.                      HWNDERR( hwndBook ) );
  293.  
  294.             // Set the tab background color to grey so it is the same as
  295.             // the page background. Note that the page packground also
  296.             // dictates the color of the foreground tab (the one attached
  297.             // to the top page). We want to make the background of all the
  298.             // tabs to be the same color.
  299.  
  300.             if( !WinSendMsg( hwndBook, BKM_SETNOTEBOOKCOLORS,
  301.                              MPFROMLONG( SYSCLR_FIELDBACKGROUND ),
  302.                              MPFROMSHORT( BKA_BACKGROUNDMAJORCOLORINDEX ) ) )
  303.                 Msg( "BKM_SETNOTEBOOKCOLRS (BACKTAB) RC(%X)",
  304.                      HWNDERR( hwndBook ) );
  305.  
  306.             // Insert all the pages into the notebook and configure them.
  307.             // The dialog boxes will also be loaded now. Also, the width and
  308.             // height of the biggest dialog will be passed back as well as the
  309.             // width of the widest tab text.
  310.  
  311.             for( i = 0; i < PAGE_COUNT && fSuccess; i++ )
  312.                 fSuccess = SetUpPage( hps, &PgConsts[ i ], &cxTab, &cxPage,
  313.                                       &cyPage );
  314.  
  315.             if( fSuccess )
  316.             {
  317.                 // Set the tab height and width based on the biggest bitmap.
  318.  
  319.                 WinSendMsg( hwndBook, BKM_SETDIMENSIONS,
  320.                             MPFROM2SHORT( cxTab + TAB_CX_MARGIN,
  321.                                           cyTab + TAB_CY_MARGIN ),
  322.                             MPFROMSHORT( BKA_MAJORTAB ) );
  323.  
  324.                 // Set the minor tab height/width to zero so we get rid of the
  325.                 // bottom part of the notebook.
  326.  
  327.                 WinSendMsg( hwndBook, BKM_SETDIMENSIONS,
  328.                             MPFROM2SHORT( 0, 0 ), MPFROMSHORT( BKA_MINORTAB ) );
  329.  
  330.                 fSuccess = SetFramePos( hwndFrame, cxPage, cyPage );
  331.                 if( !fSuccess )
  332.                     WinDestroyWindow( hwndBook );
  333.             }
  334.             else
  335.                 WinDestroyWindow( hwndBook );
  336.         }
  337.         else
  338.         {
  339.             fSuccess = FALSE;
  340.             WinDestroyWindow( hwndBook );
  341.             Msg( "CreateNBWindow GpiQuery..Metrics RC(%X)", HWNDERR(hwndBook) );
  342.         }
  343.  
  344.         WinReleasePS( hps );
  345.     }
  346.     else
  347.     {
  348.         fSuccess = FALSE;
  349.         Msg( "CreateNotebookWindow WinCreateWindow RC(%X)",HWNDERR(hwndFrame));
  350.     }
  351.  
  352.     return fSuccess;
  353. }
  354.  
  355. /**********************************************************************/
  356. /*----------------------------- SetUpPage ----------------------------*/
  357. /*                                                                    */
  358. /*  SET UP A NOTEBOOK PAGE AND LOAD ITS DIALOG.                       */
  359. /*                                                                    */
  360. /*  PARMS: Notebook's presentation space handle,                      */
  361. /*         pointer to constants for this page,                        */
  362. /*         address of tab width variable,                             */
  363. /*         address of page width variable,                            */
  364. /*         address of page height variable                            */
  365. /*                                                                    */
  366. /*  NOTES:                                                            */
  367. /*                                                                    */
  368. /*  RETURNS: TRUE or FALSE if successful or not                       */
  369. /*                                                                    */
  370. /*--------------------------------------------------------------------*/
  371. /**********************************************************************/
  372. BOOL SetUpPage( HPS hps, PPAGECONSTANTS pPgConsts, int *pcxTab, int *pcxPage,
  373.                 int *pcyPage )
  374. {
  375.     BOOL      fSuccess = TRUE;
  376.     ULONG     ulPageId;
  377.     PPAGEDATA pPageData;
  378.  
  379.     // Insert a page into the notebook. Specify that it is to have status text
  380.     // and the window associated with each page will be automatically sized by
  381.     // the notebook according to the size of the page.
  382.  
  383.     ulPageId = (ULONG) WinSendMsg( hwndBook, BKM_INSERTPAGE, NULL,
  384.                                    MPFROM2SHORT( BKA_MAJOR | BKA_STATUSTEXTON |
  385.                                    BKA_AUTOPAGESIZE, BKA_LAST ) );
  386.  
  387.     if( ulPageId )
  388.     {
  389.         POINTL aptl[ TXTBOX_COUNT ];
  390.  
  391.         pPageData = (PPAGEDATA) malloc( sizeof( PAGEDATA ) );
  392.  
  393.         if( pPageData )
  394.         {
  395.             memset( pPageData, 0, sizeof *pPageData );
  396.             pPageData->cb       = sizeof *pPageData;
  397.             pPageData->pfnwpDlg = pPgConsts->pfnwpDlg;
  398.             pPageData->idDlg    = pPgConsts->idDlg;
  399.             pPageData->idPage   = pPgConsts->idPage;
  400.  
  401.             // Insert a pointer to this page's info into the space available
  402.             // in each page (its PAGE DATA that is available to the application).
  403.  
  404.             fSuccess = (BOOL) WinSendMsg( hwndBook, BKM_SETPAGEDATA,
  405.                                           MPFROMLONG( ulPageId ),
  406.                                           MPFROMP( pPageData ) );
  407.  
  408.             // Set the text into the status line.
  409.  
  410.             if( fSuccess )
  411.             {
  412.                 fSuccess = (BOOL) WinSendMsg( hwndBook, BKM_SETSTATUSLINETEXT,
  413.                                        MPFROMP( ulPageId ),
  414.                                        MPFROMP( pPgConsts->szStatusLineText ) );
  415.  
  416.                 if( fSuccess )
  417.                     fSuccess = (BOOL) WinSendMsg( hwndBook, BKM_SETTABTEXT,
  418.                                        MPFROMP( ulPageId ),
  419.                                        MPFROMP( pPgConsts->szTabText ) );
  420.  
  421.                 else
  422.                     Msg( "BKM_SETSTATUSLINETEXT RC(%X)", HWNDERR( hwndBook ) );
  423.             }
  424.             else
  425.                 Msg( "BKM_SETPAGEDATA RC(%X)", HWNDERR( hwndBook ) );
  426.  
  427.             if( fSuccess )
  428.             {
  429.                 // Get the size, in pixels, of the tab text for this page. If
  430.                 // it is longer than the currently longest text, set it as the
  431.                 // new longest text.
  432.  
  433.                 if( GpiQueryTextBox( hps, strlen( pPgConsts->szTabText ),
  434.                                    pPgConsts->szTabText, TXTBOX_COUNT, aptl ) )
  435.                 {
  436.                     if( aptl[ TXTBOX_CONCAT ].x > *pcxTab )
  437.                         *pcxTab = aptl[ TXTBOX_CONCAT ].x;
  438.                 }
  439.                 else
  440.                 {
  441.                     fSuccess = FALSE;
  442.                     Msg( "SetUpPage GpiQueryTextBox RC(%X)", HWNDERR( hwndBook ) );
  443.                 }
  444.             }
  445.         }
  446.         else
  447.         {
  448.             fSuccess = FALSE;
  449.             Msg( "Out of memory in SetUpPage!" );
  450.         }
  451.     }
  452.     else
  453.     {
  454.         fSuccess = FALSE;
  455.         Msg( "SetUpPage BKM_INSERTPAGE RC(%X)", HWNDERR( hwndBook ) );
  456.     }
  457.  
  458.     if( fSuccess )
  459.     {
  460.         LONG cx, cy;
  461.  
  462.         // Keep an ongoing count of the widest and tallest dialog
  463.         // dimensions needed for an optimal notebook size.
  464.  
  465.         if( GetDialogDimensions( pPgConsts->idDlg, &cx, &cy ) )
  466.         {
  467.             if( cx > *pcxPage )
  468.                 *pcxPage = cx;
  469.             if( cy > *pcyPage )
  470.                 *pcyPage = cy;
  471.         }
  472.     }
  473.  
  474.     return fSuccess;
  475. }
  476.  
  477. /**********************************************************************/
  478. /*------------------------ GetDialogDimensions -----------------------*/
  479. /*                                                                    */
  480. /*  RETURN THE WIDTH AND HEIGHT OF A DIALOG BOX.                      */
  481. /*                                                                    */
  482. /*  PARMS: dialog box id,                                             */
  483. /*         address of the width,                                      */
  484. /*         address of the height                                      */
  485. /*                                                                    */
  486. /*  NOTES:                                                            */
  487. /*                                                                    */
  488. /*  RETURNS: TRUE or FALSE if successful or not                       */
  489. /*                                                                    */
  490. /*--------------------------------------------------------------------*/
  491. /**********************************************************************/
  492. BOOL GetDialogDimensions( ULONG idDlg, PLONG pCx, PLONG pCy )
  493. {
  494.     BOOL         fSuccess = TRUE;
  495.     APIRET       rc;
  496.     PDLGTEMPLATE pDlgTemplate = NULL;
  497.  
  498.     rc = DosGetResource( 0, RT_DIALOG, idDlg, (PPVOID) &pDlgTemplate );
  499.  
  500.     if( !rc )
  501.     {
  502.         PDLGTITEM pDlgItem;
  503.  
  504.         // Get offset to the item table
  505.  
  506.         pDlgItem = (PDLGTITEM) ((PBYTE) pDlgTemplate + pDlgTemplate->offadlgti);
  507.  
  508.         *pCx = (LONG) pDlgItem->cx;
  509.         *pCy = (LONG) pDlgItem->cy;
  510.     }
  511.     else
  512.     {
  513.         fSuccess = FALSE;
  514.         Msg( "DosGetResource for id %u RC(%X)", idDlg, HWNDERR( hwndBook ) );
  515.     }
  516.  
  517.     return fSuccess;
  518. }
  519.  
  520. /**********************************************************************/
  521. /*---------------------------- SetFramePos ---------------------------*/
  522. /*                                                                    */
  523. /*  SET THE FRAME ORIGIN AND SIZE.                                    */
  524. /*                                                                    */
  525. /*  PARMS: frame window handle,                                       */
  526. /*         width of the widest page,                                  */
  527. /*         height of the tallest page                                 */
  528. /*                                                                    */
  529. /*  NOTES:                                                            */
  530. /*                                                                    */
  531. /*  RETURNS: TRUE or FALSE if successful or not                       */
  532. /*                                                                    */
  533. /*--------------------------------------------------------------------*/
  534. /**********************************************************************/
  535. BOOL SetFramePos( HWND hwndFrame, int cxPage, int cyPage )
  536. {
  537.     BOOL  fSuccess;
  538.     RECTL rcl;
  539.  
  540.     // Calculate the size of the notebook from the size of the page.
  541.  
  542.     rcl.xLeft   = 0;
  543.     rcl.yBottom = 0;
  544.     rcl.xRight  = cxPage;
  545.     rcl.yTop    = cyPage;
  546.  
  547.     // Convert size from dialog units to pixels.
  548.  
  549.     WinMapDlgPoints( HWND_DESKTOP, (PPOINTL) &rcl, 2, TRUE );
  550.  
  551.     fSuccess = (BOOL) WinSendMsg( hwndBook, BKM_CALCPAGERECT,
  552.                                   MPFROMP( &rcl ), MPFROMLONG( FALSE ) );
  553.     if( fSuccess )
  554.     {
  555.         // Calculate the size of the frame from the size of the notebook
  556.  
  557.         fSuccess = (BOOL) WinSendMsg( PARENT( hwndBook ),
  558.                                       WM_CALCFRAMERECT,
  559.                                       MPFROMP( &rcl ), MPFROMLONG( FALSE ) );
  560.         if( fSuccess )
  561.         {
  562.             LONG cxDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
  563.             LONG cyDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
  564.  
  565.             // BKM_CALCPAGERECT and WM_CALCFRAMERECT take the x,y into
  566.             // consideration when they do their work so we need to
  567.             // calculate the actual cx and cy based upon its results. Keep
  568.             // in mind we are only working with width and height at this
  569.             // time.
  570.  
  571.             rcl.xRight = rcl.xRight - rcl.xLeft;
  572.             rcl.yTop   = rcl.yTop - rcl.yBottom;
  573.  
  574.             // Now do the x and y origin. Put the notebook in the middle of the
  575.             // screen.
  576.  
  577.             rcl.xLeft   = (cxDesktop - rcl.xRight) / 2;
  578.             rcl.yBottom = (cyDesktop - rcl.yTop) / 2;
  579.  
  580.             // Adjust cx,cy for new x,y. Until now it was assumed that the
  581.             // origin was 0,0.
  582.  
  583.             rcl.xRight += (rcl.xLeft - 1);
  584.             rcl.yTop   += (rcl.yBottom - 1);
  585.         }
  586.     }
  587.  
  588.     if( fSuccess )
  589.         fSuccess = WinSetWindowPos( hwndFrame, NULLHANDLE,
  590.                                     rcl.xLeft, rcl.yBottom,
  591.                                     (rcl.xRight - rcl.xLeft) + 1,
  592.                                     (rcl.yTop - rcl.yBottom) + 1,
  593.                                SWP_SIZE | SWP_SHOW | SWP_MOVE | SWP_ACTIVATE );
  594.  
  595.     return fSuccess;
  596. }
  597.  
  598. /**********************************************************************/
  599. /*----------------------------- wpNBFrame ----------------------------*/
  600. /*                                                                    */
  601. /*  SUBCLASSED FRAME WINDOW PROCEDURE                                 */
  602. /*                                                                    */
  603. /*  PARMS: standard window proc parms                                 */
  604. /*                                                                    */
  605. /*  NOTES:                                                            */
  606. /*                                                                    */
  607. /*  RETURNS: message result                                           */
  608. /*                                                                    */
  609. /*--------------------------------------------------------------------*/
  610. /**********************************************************************/
  611. MRESULT EXPENTRY wpNBFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  612. {
  613.     switch( msg )
  614.     {
  615.         case WM_CONTROL:
  616.  
  617.             if( ControlMsg( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ),
  618.                             mp2 ) )
  619.                 return 0;
  620.             else
  621.                 break;
  622.  
  623.         // You need to process the SC_CLOSE WM_SYSCOMMAND message instead of
  624.         // WM_CLOSE when working with frame windows.
  625.  
  626.         case WM_SYSCOMMAND:
  627.             if( SHORT1FROMMP( mp1 ) == SC_CLOSE )
  628.             {
  629.                 WinDestroyWindow( hwnd );
  630.  
  631.                 // Don't let the WM_QUIT message through
  632.  
  633.                 return 0;
  634.             }
  635.  
  636.             break;
  637.  
  638.         // The Notebook prevents the Accelerator key processing from working
  639.         // correctly so we must do another kludge. Here we close the window if
  640.         // the user hit the F3 key.
  641.         case WM_TRANSLATEACCEL:
  642.         {
  643.             PQMSG  pQmsg = (PQMSG) mp1;
  644.             USHORT fsFlags = SHORT1FROMMP( pQmsg->mp1 );
  645.  
  646.             if( !(fsFlags & (KC_CTRL | KC_SHIFT | KC_ALT | KC_CHAR)) &&
  647.                 (fsFlags & KC_KEYUP) &&
  648.                 (SHORT2FROMMP( pQmsg->mp2 ) == VK_F3) )
  649.             {
  650.                 WinDestroyWindow( hwnd );
  651.                 return (MRESULT) TRUE;
  652.             }
  653.             else
  654.                 return FALSE;
  655.         }
  656.  
  657.         case WM_DESTROY:
  658.             FreeResources();
  659.             break;
  660.     }
  661.  
  662.     return pfnwpFrame( hwnd, msg, mp1, mp2 );
  663. }
  664.  
  665. /**********************************************************************/
  666. /*---------------------------- ControlMsg ----------------------------*/
  667. /*                                                                    */
  668. /*  PROCESS A WM_CONTROL MESSAGE FROM THE NOTEBOOK.                   */
  669. /*                                                                    */
  670. /*  PARMS: frame window handle,                                       */
  671. /*         control id,                                                */
  672. /*         control event code,                                        */
  673. /*         2nd message parameter from WM_CONTROL message              */
  674. /*                                                                    */
  675. /*  NOTES:                                                            */
  676. /*                                                                    */
  677. /*  RETURNS: TRUE  - message was processed                            */
  678. /*           FALSE - message was not processed                        */
  679. /*                                                                    */
  680. /*--------------------------------------------------------------------*/
  681. /**********************************************************************/
  682. BOOL ControlMsg( HWND hwndFrame, USHORT usControl, USHORT usEvent, MPARAM mp2 )
  683. {
  684.     BOOL fProcessed = FALSE;
  685.  
  686.     switch( usControl )
  687.     {
  688.         case FID_CLIENT:
  689.  
  690.             switch( usEvent )
  691.             {
  692.                 case BKN_PAGESELECTED:
  693.                     SetNBPage( hwndFrame, (PPAGESELECTNOTIFY) mp2 );
  694.                     fProcessed = TRUE;
  695.                     break;
  696.             }
  697.  
  698.             break;
  699.     }
  700.  
  701.     return fProcessed;
  702. }
  703.  
  704. /**********************************************************************/
  705. /*---------------------------- SetNBPage -----------------------------*/
  706. /*                                                                    */
  707. /*  SET UP THE NEW TOP PAGE IN THE NOTEBOOK CONTROL.                  */
  708. /*                                                                    */
  709. /*  PARMS: frame window handle,                                       */
  710. /*         pointer to the PAGESELECTNOTIFY struct                     */
  711. /*                                                                    */
  712. /*  NOTES:                                                            */
  713. /*                                                                    */
  714. /*  RETURNS: nothing                                                  */
  715. /*                                                                    */
  716. /*--------------------------------------------------------------------*/
  717. /**********************************************************************/
  718. void SetNBPage( HWND hwndFrame, PPAGESELECTNOTIFY ppsn )
  719. {
  720.     HWND hwndDlg;
  721.  
  722.     // Get a pointer to the page information that is associated with this page.
  723.     // It was stored in the page's PAGE DATA in the SetUpPage function.
  724.  
  725.     PPAGEDATA pPageData = (PPAGEDATA) WinSendMsg( ppsn->hwndBook,
  726.                                         BKM_QUERYPAGEDATA,
  727.                                         MPFROMLONG( ppsn->ulPageIdNew ), NULL );
  728.  
  729.     if( !pPageData )
  730.         return;
  731.     else if( pPageData == (PPAGEDATA) BOOKERR_INVALID_PARAMETERS )
  732.     {
  733.         Msg( "SetNBPage QUERYPAGEDATA RC(%X)", HWNDERR( ppsn->hwndBook ) );
  734.         return;
  735.     }
  736.  
  737.     hwndDlg = (HWND) WinSendMsg( ppsn->hwndBook, BKM_QUERYPAGEWINDOWHWND,
  738.                                  MPFROMLONG( ppsn->ulPageIdNew ), NULL );
  739.  
  740.     if( hwndDlg == (HWND) BOOKERR_INVALID_PARAMETERS )
  741.         Msg( "SetNBPage QUERYPAGEHWND RC(%X)", HWNDERR( ppsn->hwndBook ) );
  742.     else if( !hwndDlg )
  743.     {
  744.         // It is time to load this dialog because the user has flipped pages
  745.         // to a page that hasn't yet had the dialog associated with it.
  746.  
  747.         hwndDlg = LoadAndAssociate( hwndFrame, pPageData, ppsn );
  748.     }
  749.  
  750.     if( hwndDlg )
  751.     {
  752.         // Set focus to the first control in the dialog. This is not
  753.         // automatically done by the notebook.
  754.  
  755.         WinSetFocus( HWND_DESKTOP, WinWindowFromID( hwndDlg,
  756.                                                     pPageData->idFocus ) );
  757.     }
  758. }
  759.  
  760. /**********************************************************************/
  761. /*------------------------- LoadAndAssociate -------------------------*/
  762. /*                                                                    */
  763. /*  LOAD A DIALOG BOX AND ASSOCIATE IT WITH A NOTEBOOK PAGE.          */
  764. /*                                                                    */
  765. /*  PARMS: frame window handle,                                       */
  766. /*         pointer to the PAGEDATA structure for this page,           */
  767. /*         pointer to the PAGESELECTNOTIFY struct                     */
  768. /*                                                                    */
  769. /*  NOTES:                                                            */
  770. /*                                                                    */
  771. /*  RETURNS: Dialog box window handle                                 */
  772. /*                                                                    */
  773. /*--------------------------------------------------------------------*/
  774. /**********************************************************************/
  775. HWND LoadAndAssociate( HWND hwndFrame, PPAGEDATA pPageData,
  776.                        PPAGESELECTNOTIFY ppsn )
  777. {
  778.     HWND hwndDlg = WinLoadDlg( hwndFrame, ppsn->hwndBook, pPageData->pfnwpDlg,
  779.                                0, pPageData->idDlg, NULL );
  780.  
  781.     if( hwndDlg )
  782.     {
  783.         // Allow the dialog to give us its initial focus id.
  784.  
  785.         pPageData->idFocus = (ULONG) WinSendMsg( hwndDlg, UM_GET_FOCUS_ID,
  786.                                                  NULL, NULL );
  787.         // Associate the dialog with the page.
  788.  
  789.         if( WinSendMsg( ppsn->hwndBook, BKM_SETPAGEWINDOWHWND,
  790.                         MPFROMP( ppsn->ulPageIdNew ),
  791.                         MPFROMLONG( hwndDlg ) ) )
  792.             WinSetWindowPtr( hwndDlg, QWL_USER, pPageData );
  793.         else
  794.         {
  795.             WinDestroyWindow( hwndDlg );
  796.             hwndDlg = NULLHANDLE;
  797.             Msg( "LoadAndAssociate SETPAGEWINDOWHWND RC(%X)",
  798.                  HWNDERR( ppsn->hwndBook ) );
  799.         }
  800.     }
  801.     else
  802.         Msg( "LoadAndAssociate WinLoadDlg RC(%X)", HWNDERR( hwndBook ) );
  803.  
  804.     return hwndDlg;
  805. }
  806.  
  807. /*********************************************************************/
  808. /*--------------------------- TurnToPage ----------------------------*/
  809. /*                                                                   */
  810. /*  TURN TO THE SPECIFIED PAGE OF THE NOTEBOOK                       */
  811. /*                                                                   */
  812. /*  PARMS: identifier for the page to turn to                        */
  813. /*                                                                   */
  814. /*  NOTES:                                                           */
  815. /*                                                                   */
  816. /*  RETURNS: nothing                                                 */
  817. /*                                                                   */
  818. /*-------------------------------------------------------------------*/
  819. /*********************************************************************/
  820. void TurnToPage( ULONG idRequestedPage )
  821. {
  822.     USHORT    usNext = BKA_FIRST;
  823.     ULONG     ulPageId = 0;
  824.     PPAGEDATA pPageData;
  825.  
  826.     // Enumerate through all the pages of the notebook so we can gain access
  827.     // to their page data to find the page we're looking for.
  828.  
  829.     for( ; ; )
  830.     {
  831.         ulPageId = (ULONG) WinSendMsg( hwndBook, BKM_QUERYPAGEID,
  832.                                        MPFROMLONG( ulPageId ),
  833.                                        MPFROM2SHORT( usNext, 0 ) );
  834.  
  835.         if( !ulPageId )
  836.             break;
  837.  
  838.         usNext = BKA_NEXT;
  839.  
  840.         if( ulPageId == (ULONG) BOOKERR_INVALID_PARAMETERS )
  841.         {
  842.             Msg( "TurnToPage QUERYPAGEID RC(%X)", HWNDERR( hwndBook ) );
  843.             break;
  844.         }
  845.  
  846.         // If the caller requested the first page in the notebook, we're done.
  847.         // Note that NBPID_FIRST is our own id value (look in our header).
  848.  
  849.         if( idRequestedPage == NBPID_FIRST )
  850.             break;
  851.  
  852.         // Get a pointer to the page information that is associated with this
  853.         // page. It was stored in the page's PAGE DATA in the SetUpPage
  854.         // function.
  855.  
  856.         pPageData = (PPAGEDATA) WinSendMsg( hwndBook, BKM_QUERYPAGEDATA,
  857.                                             MPFROMLONG( ulPageId ), NULL );
  858.  
  859.         if( !pPageData || pPageData == (PPAGEDATA) BOOKERR_INVALID_PARAMETERS )
  860.         {
  861.             Msg( "TurnToPage QUERYPAGEDATA RC(%X)", HWNDERR( hwndBook ) );
  862.             break;
  863.         }
  864.         else
  865.             if( pPageData->idPage == idRequestedPage )
  866.                 break;
  867.     }
  868.  
  869.     if( !WinSendMsg( hwndBook, BKM_TURNTOPAGE, MPFROMLONG( ulPageId ), NULL ) )
  870.         Msg( "TurnToPage BKM_TURNTOPAGE RC(%X)", HWNDERR( hwndBook ) );
  871. }
  872.  
  873. /**********************************************************************/
  874. /*--------------------------- FreeResources --------------------------*/
  875. /*                                                                    */
  876. /*  FREE THE RESOURCES ALLOCATED FOR THE NOTEBOOK.                    */
  877. /*                                                                    */
  878. /*  PARMS: nothing                                                    */
  879. /*                                                                    */
  880. /*  NOTES:                                                            */
  881. /*                                                                    */
  882. /*  RETURNS: nothing                                                  */
  883. /*                                                                    */
  884. /*--------------------------------------------------------------------*/
  885. /**********************************************************************/
  886. void FreeResources()
  887. {
  888.     USHORT    usNext = BKA_FIRST;
  889.     ULONG     ulPageId = 0;
  890.     PPAGEDATA pPageData;
  891.     HWND      hwndDlg;
  892.  
  893.     // Enumerate through all the pages of the notebook so we can gain access
  894.     // to their page data to free their resources.
  895.  
  896.     for( ; ; )
  897.     {
  898.         ulPageId = (ULONG) WinSendMsg( hwndBook, BKM_QUERYPAGEID,
  899.                                        MPFROMLONG( ulPageId ),
  900.                                        MPFROM2SHORT( usNext, 0 ) );
  901.  
  902.         if( !ulPageId )
  903.             break;
  904.  
  905.         usNext = BKA_NEXT;
  906.  
  907.         if( ulPageId == (ULONG) BOOKERR_INVALID_PARAMETERS )
  908.             Msg( "FreeResources QUERYPAGEID RC(%X)", HWNDERR( hwndBook ) );
  909.  
  910.         // Get a pointer to the page information that is associated with this
  911.         // page. It was stored in the page's PAGE DATA in the SetUpPage
  912.         // function.
  913.  
  914.         pPageData = (PPAGEDATA) WinSendMsg( hwndBook, BKM_QUERYPAGEDATA,
  915.                                             MPFROMLONG( ulPageId ), NULL );
  916.  
  917.         if( !pPageData || pPageData == (PPAGEDATA) BOOKERR_INVALID_PARAMETERS )
  918.             Msg( "FreeResources QUERYPAGEDATA RC(%X)", HWNDERR( hwndBook ) );
  919.         else
  920.             free( pPageData );
  921.  
  922.         hwndDlg = (HWND) WinSendMsg( hwndBook, BKM_QUERYPAGEWINDOWHWND,
  923.                                      MPFROMLONG( ulPageId ), NULL );
  924.  
  925.         if( hwndDlg != (HWND) BOOKERR_INVALID_PARAMETERS && hwndDlg )
  926.         {
  927.             WinSendMsg( hwndDlg, UM_DUMP_DLGINFO, NULL, NULL );
  928.             WinDestroyWindow( hwndDlg );
  929.         }
  930.     }
  931.  
  932.     SaveDlgInfo( ANCHOR( hwndBook ) );
  933.  
  934.     hwndBook = NULLHANDLE;
  935. }
  936.  
  937. /*********************************************************************
  938.  *                      E N D   O F   S O U R C E                    *
  939.  *********************************************************************/
  940.