home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / NBLOAD.ZIP / NBLOAD.C < prev    next >
Text File  |  1993-01-02  |  46KB  |  1,087 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  nbload.c               AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  10-18-92                                           *
  5.  *                                                                   *
  6.  * HOW TO RUN THIS PROGRAM:                                          *
  7.  *                                                                   *
  8.  *  Just enter NBLOAD on the command line.                           *
  9.  *                                                                   *
  10.  *   Arguments:                                                      *
  11.  *                                                                   *
  12.  *       0 - Load dialogs on demand                                  *
  13.  *       1 - Use a timer                                             *
  14.  *       2 - Load them at startup                                    *
  15.  *                                                                   *
  16.  *                                                                   *
  17.  * MODULE DESCRIPTION:                                               *
  18.  *                                                                   *
  19.  *  Only module for NBLOAD.EXE, a program that builds on the source  *
  20.  *  code of NBBASE.EXE. It attempts to demonstrate the perceived     *
  21.  *  load time of NBBASE.EXE using 3 methods of loading the dialog    *
  22.  *  boxes that will be associated with notebook pages:               *
  23.  *                                                                   *
  24.  *    1. Delay loading them until they are needed.                   *
  25.  *    2. Set a timer that on a timer interval goes thru the list of  *
  26.  *       dialogs that need to be loaded. If it finds one that hasn't *
  27.  *       yet been loaded, load it. This technique also uses number 2 *
  28.  *       because the dialog will be loaded if the user requests it   *
  29.  *       and it hasn't been loaded and the timer hasn't yet loaded   *
  30.  *       it.                                                         *
  31.  *    3. Load them all at startup of the Notebook.                   *
  32.  *                                                                   *
  33.  * NOTES:                                                            *
  34.  *                                                                   *
  35.  *  This program is strictly a sample and should be treated as such. *
  36.  *  There is nothing real-world about it and the dialogs that it     *
  37.  *  uses do nothing useful. It is meant solely to see the differences*
  38.  *  of loading Notebook dialogs using various techniques.            *
  39.  *                                                                   *
  40.  *  I hope this code proves useful for other PM programmers. The     *
  41.  *  more of us the better!                                           *
  42.  *                                                                   *
  43.  * HISTORY:                                                          *
  44.  *                                                                   *
  45.  *  10-18-92 - Program coded                                         *
  46.  *  12-04-92 - Brought up to spec for changes in NBBASE              *
  47.  *                                                                   *
  48.  *  Rick Fishman                                                     *
  49.  *  Code Blazers, Inc.                                               *
  50.  *  4113 Apricot                                                     *
  51.  *  Irvine, CA. 92720                                                *
  52.  *  CIS ID: 72251,750                                                *
  53.  *                                                                   *
  54.  *********************************************************************/
  55.  
  56. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  57.  
  58. /*********************************************************************/
  59. /*------- Include relevant sections of the OS/2 header files --------*/
  60. /*********************************************************************/
  61.  
  62. #define  INCL_GPILCIDS
  63. #define  INCL_GPIPRIMITIVES
  64. #define  INCL_WINDIALOGS
  65. #define  INCL_WINERRORS
  66. #define  INCL_WINFRAMEMGR
  67. #define  INCL_WINMESSAGEMGR
  68. #define  INCL_WINSTDBOOK
  69. #define  INCL_WINSYS
  70. #define  INCL_WINTIMER
  71. #define  INCL_WINWINDOWMGR
  72.  
  73. /**********************************************************************/
  74. /*----------------------------- INCLUDES -----------------------------*/
  75. /**********************************************************************/
  76.  
  77. #include <os2.h>
  78. #include <stdio.h>
  79. #include <stdarg.h>
  80. #include <stdlib.h>
  81. #include <string.h>
  82. #include "nbload.h"
  83.  
  84. /*********************************************************************/
  85. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  86. /*********************************************************************/
  87.  
  88. #define USAGE_MSG             "Usage: NBLOAD [0 1 2]\n\n"                    \
  89.                               "0 - Load dialogs on demand (default)\n"       \
  90.                               "1 - Load dialogs on a timer\n"                \
  91.                               "2 - Load all dialogs at startup"
  92.  
  93. #define FRAME_FLAGS           (FCF_TASKLIST | FCF_TITLEBAR   | FCF_SYSMENU | \
  94.                                FCF_MINMAX   | FCF_SIZEBORDER | FCF_ICON)
  95.  
  96. #define TAB_WIDTH_MARGIN      10   // Padding for the width of a notebook tab
  97. #define TAB_HEIGHT_MARGIN     6    // Padding for the height of a notebook tab
  98. #define DEFAULT_NB_TAB_HEIGHT 16   // Default if Gpi calls fail
  99.  
  100. #define FRAME_X               10   // In dialog units!
  101. #define FRAME_Y               10   // In dialog units!
  102. #define FRAME_CX              275  // In dialog units!
  103. #define FRAME_CY              210  // In dialog units!
  104.  
  105. #define LOAD_ON_DEMAND        0    // Constants for commandline value
  106. #define LOAD_BY_TIMER         1
  107. #define LOAD_AT_STARTUP       2
  108. #define LOAD_MAX_VALUE        LOAD_AT_STARTUP
  109.  
  110. #define TIMER_INTERVAL        1000 // 1 second timer interval if LOAD_BY_TIMER
  111.  
  112. /**********************************************************************/
  113. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  114. /**********************************************************************/
  115.  
  116.        INT  main             ( INT argc, CHAR **argv );
  117. static BOOL Init             ( INT argc, CHAR **argv );
  118. static BOOL TurnToFirstPage  ( HWND hwndClient );
  119. static BOOL SetFramePos      ( HWND hwndFrame );
  120. static BOOL CreateNotebook   ( HWND hwndClient );
  121. static BOOL SetUpPage        ( HWND hwndNB, INT iArrayIndex );
  122. static BOOL SetTabDimensions ( HWND hwndNB );
  123. static INT  GetStringSize    ( HPS hps, HWND hwndNB, PSZ szString);
  124. static BOOL ControlMsg       ( USHORT usCtl, USHORT usEvent, MPARAM mp2);
  125. static VOID SetNBPage        ( PPAGESELECTNOTIFY ppsn );
  126. static VOID CheckDialogs     ( HWND hwndClient );
  127. static HWND LoadAndAssociate ( HWND hwndNB, ULONG ulPageId, PNBPAGE pnbp );
  128. static VOID Msg              ( PSZ szFormat, ... );
  129.  
  130. FNWP wpClient, wpPage;
  131.  
  132. /**********************************************************************/
  133. /*------------------------ GLOBAL VARIABLES --------------------------*/
  134. /**********************************************************************/
  135.  
  136. INT iLoadType;       // Way to load dialogs - can be modified by cmdline parm
  137.  
  138. NBPAGE nbpage[] =    // INFORMATION ABOUT NOTEBOOK PAGES (see NBLOAD.H)
  139. {
  140.     { wpPage,      "Page 1",  "Page ~1",  IDD_PAGE1,  EF_1,  FALSE, BKA_MAJOR },
  141.     { (PFNWP) NULL,"Page 2",  "Page ~2",  0,          0,     TRUE,  BKA_MAJOR },
  142.     { wpPage,      "Page 2A", "Page 2~A", IDD_PAGE2A, EF_2A, FALSE, BKA_MINOR },
  143.     { wpPage,      "Page 2B", "Page 2~B", IDD_PAGE2B, EF_2B, FALSE, BKA_MINOR },
  144.     { wpPage,      "Page 3",  "Page ~3",  IDD_PAGE3,  EF_3,  FALSE, BKA_MAJOR },
  145.     { (PFNWP) NULL,"Page 4",  "Page ~4",  0,          0,     TRUE,  BKA_MAJOR },
  146.     { wpPage,      "Page 4A", "Page ~4A", IDD_PAGE4A, EF_4A, FALSE, BKA_MINOR },
  147.     { wpPage,      "Page 4B", "Page ~4B", IDD_PAGE4B, EF_4B, FALSE, BKA_MINOR },
  148.     { wpPage,      "Page 4C", "Page ~4C", IDD_PAGE4C, EF_4C, FALSE, BKA_MINOR },
  149.     { wpPage,      "Page 4D", "Page ~4D", IDD_PAGE4D, EF_4D, FALSE, BKA_MINOR },
  150.     { wpPage,      "Page 5",  "Page ~5",  IDD_PAGE5,  EF_5,  FALSE, BKA_MAJOR },
  151.     { (PFNWP) NULL,"Page 6",  "Page ~6",  0,          0,     TRUE,  BKA_MAJOR },
  152.     { wpPage,      "Page 6A", "Page ~6A", IDD_PAGE6A, EF_6A, FALSE, BKA_MINOR },
  153.     { wpPage,      "Page 6B", "Page ~6B", IDD_PAGE6B, EF_6B, FALSE, BKA_MINOR },
  154.     { wpPage,      "Page 6C", "Page ~6C", IDD_PAGE6C, EF_6C, FALSE, BKA_MINOR },
  155.  
  156.     { wpPage,"Page 7 (1 of 4)","Page ~7", IDD_PAGE71, EF_71, FALSE, BKA_MAJOR },
  157.     { wpPage,"Page 7 (2 of 4)",NULL,      IDD_PAGE72, EF_72, FALSE, 0 },
  158.     { wpPage,"Page 7 (3 of 4)",NULL,      IDD_PAGE73, EF_73, FALSE, 0 },
  159.     { wpPage,"Page 7 (4 of 4)",NULL,      IDD_PAGE74, EF_74, FALSE, 0 }
  160. };
  161.  
  162. #define PAGE_COUNT (sizeof( nbpage ) / sizeof( NBPAGE ))
  163.  
  164. /**********************************************************************/
  165. /*------------------------------- main -------------------------------*/
  166. /*                                                                    */
  167. /*  PROGRAM ENTRYPOINT                                                */
  168. /*                                                                    */
  169. /*  INPUT: commandline                                                */
  170. /*                                                                    */
  171. /*  1.                                                                */
  172. /*                                                                    */
  173. /*  OUTPUT: nothing                                                   */
  174. /*                                                                    */
  175. /*--------------------------------------------------------------------*/
  176. /**********************************************************************/
  177. INT main( INT argc, CHAR **argv )
  178. {
  179.     BOOL  fSuccess;
  180.     HAB   hab;
  181.     HMQ   hmq;
  182.     HWND  hwndFrame, hwndClient;
  183.     QMSG  qmsg;
  184.     ULONG flFrame = FRAME_FLAGS;
  185.  
  186.     // This macro is defined for the debug version of the C Set/2 Memory
  187.     // Management routines. Since the debug version writes to stderr, we
  188.     // send all stderr output to a debuginfo file. Look in MAKEFILE to see how
  189.     // to enable the debug version of those routines.
  190.  
  191. #ifdef __DEBUG_ALLOC__
  192.     freopen( DEBUG_FILENAME, "w", stderr );
  193. #endif
  194.  
  195.     hab = WinInitialize( 0 );
  196.  
  197.     if( hab )
  198.         hmq = WinCreateMsgQueue( hab, 0 );
  199.     else
  200.     {
  201.         WinAlarm( HWND_DESKTOP, WA_ERROR );
  202.  
  203.         (void) fprintf( stderr, "WinInitialize failed!" );
  204.     }
  205.  
  206.     if( hmq )
  207.     {
  208.         // CS_CLIPCHILDREN so the client doesn't need to paint the area covered
  209.         // by the notebook. CS_SIZEREDRAW so the notebook gets sized correctly
  210.         // the first time the Frame/Client get drawn.
  211.  
  212.         fSuccess = WinRegisterClass( hab, NOTEBOOK_WINCLASS, wpClient,
  213.                                      CS_CLIPCHILDREN | CS_SIZEREDRAW, 0 );
  214.         if( !fSuccess )
  215.             Msg( "WinRegisterClass RC(%X)", HABERR( hab ) );
  216.     }
  217.     else
  218.     {
  219.         WinAlarm( HWND_DESKTOP, WA_ERROR );
  220.  
  221.         (void) fprintf( stderr, "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
  222.     }
  223.  
  224.     if( fSuccess && Init( argc, argv ) )
  225.         hwndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &flFrame,
  226.                                         NOTEBOOK_WINCLASS, NULL, 0, NULLHANDLE,
  227.                                         ID_NBWINFRAME, &hwndClient );
  228.  
  229.     if( hwndFrame )
  230.     {
  231.         // If the TURNTOPAGE is sent during WM_CREATE processing, the dialog
  232.         // box for page 1 won't be visible.
  233.  
  234.         fSuccess = TurnToFirstPage( hwndClient );
  235.  
  236.         if( fSuccess )
  237.             fSuccess = SetFramePos( hwndFrame );
  238.  
  239.         if( fSuccess )
  240.             WinSetWindowText( hwndFrame, PROGRAM_TITLE );
  241.     }
  242.  
  243.     if( hwndFrame )
  244.     {
  245.         while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  246.             WinDispatchMsg( hab, &qmsg );
  247.  
  248.         WinDestroyWindow( hwndFrame );
  249.     }
  250.  
  251.     if( hmq )
  252.         WinDestroyMsgQueue( hmq );
  253.  
  254.     if( hab )
  255.         WinTerminate( hab );
  256.  
  257. #ifdef __DEBUG_ALLOC__
  258.     _dump_allocated( -1 );
  259. #endif
  260.  
  261.     return 0;
  262. }
  263.  
  264. /**********************************************************************/
  265. /*-------------------------------- Init ------------------------------*/
  266. /*                                                                    */
  267. /*  PERFORM PROGRAM INITIALIZATION                                    */
  268. /*                                                                    */
  269. /*  INPUT: commandline                                                */
  270. /*                                                                    */
  271. /*  1.                                                                */
  272. /*                                                                    */
  273. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  274. /*                                                                    */
  275. /*--------------------------------------------------------------------*/
  276. /**********************************************************************/
  277. static BOOL Init( INT argc, CHAR **argv )
  278. {
  279.     BOOL fSuccess = TRUE;
  280.  
  281.     if( argc > 1 )
  282.         iLoadType = atoi( argv[ 1 ] );
  283.  
  284.     if( iLoadType > LOAD_MAX_VALUE )
  285.     {
  286.         fSuccess = FALSE;
  287.  
  288.         Msg( USAGE_MSG );
  289.     }
  290.  
  291.     return fSuccess;
  292. }
  293.  
  294. /**********************************************************************/
  295. /*----------------------------- wpClient -----------------------------*/
  296. /*                                                                    */
  297. /*  CLIENT WINDOW PROCEDURE                                           */
  298. /*                                                                    */
  299. /*  INPUT: window proc params                                         */
  300. /*                                                                    */
  301. /*  1.                                                                */
  302. /*                                                                    */
  303. /*  OUTPUT: retcode from processing message                           */
  304. /*                                                                    */
  305. /*--------------------------------------------------------------------*/
  306. /**********************************************************************/
  307. MRESULT EXPENTRY wpClient( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  308. {
  309.     switch( msg )
  310.     {
  311.         case WM_CREATE:
  312.  
  313.             // Don't create the window if notebook creation fails
  314.  
  315.             if( !CreateNotebook( hwnd ) )
  316.                 return (MRESULT) TRUE;
  317.  
  318.             break;
  319.  
  320.  
  321.         case WM_SIZE:
  322.  
  323.             // Size the notebook with the client window
  324.  
  325.             WinSetWindowPos( WinWindowFromID( hwnd, ID_NB ), 0, 0, 0,
  326.                              SHORT1FROMMP( mp2 ), SHORT2FROMMP( mp2 ),
  327.                              SWP_SIZE | SWP_SHOW );
  328.  
  329.             break;
  330.  
  331.  
  332.         case WM_ERASEBACKGROUND:
  333.  
  334.             // Paint the client in the default background color
  335.  
  336.             return (MRESULT) TRUE;
  337.  
  338.  
  339.         case WM_CONTROL:
  340.  
  341.             if( ControlMsg( SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ), mp2 ) )
  342.                 return 0;
  343.             else
  344.                 break;
  345.  
  346.  
  347.         case WM_TIMER:
  348.  
  349.             // See if any dialogs need to be loaded
  350.  
  351.             CheckDialogs( hwnd );
  352.  
  353.             break;
  354.  
  355.  
  356.         case WM_DESTROY:
  357.  
  358.             if( iLoadType == LOAD_BY_TIMER )
  359.                 WinStopTimer( ANCHOR( hwnd ), hwnd, 1 );
  360.  
  361.             break;
  362.     }
  363.  
  364.     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  365. }
  366.  
  367. /**********************************************************************/
  368. /*------------------------- TurnToFirstPage --------------------------*/
  369. /*                                                                    */
  370. /*  TURN TO THE FIRST PAGE IN THE NOTEBOOK.                           */
  371. /*                                                                    */
  372. /*  INPUT: client window handle                                       */
  373. /*                                                                    */
  374. /*  1.                                                                */
  375. /*                                                                    */
  376. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  377. /*                                                                    */
  378. /*--------------------------------------------------------------------*/
  379. /**********************************************************************/
  380. static BOOL TurnToFirstPage( HWND hwndClient )
  381. {
  382.     HWND  hwndNB = WinWindowFromID( hwndClient, ID_NB );
  383.     ULONG ulFirstPage;
  384.     BOOL  fSuccess = TRUE;
  385.  
  386.     ulFirstPage = (ULONG) WinSendMsg( hwndNB, BKM_QUERYPAGEID, NULL,
  387.                                       MPFROM2SHORT( BKA_FIRST, BKA_MAJOR ) );
  388.  
  389.     if( ulFirstPage )
  390.     {
  391.         fSuccess = (ULONG) WinSendMsg( hwndNB, BKM_TURNTOPAGE,
  392.                                        MPFROMLONG( ulFirstPage ), NULL );
  393.  
  394.         if( !fSuccess )
  395.             Msg( "TurnToFirstPage BKM_TURNTOPAGE RC(%X)", HWNDERR( hwndNB ) );
  396.     }
  397.     else
  398.     {
  399.         fSuccess = FALSE;
  400.  
  401.         Msg( "TurnToFirstPage BKM_QUERYPAGEID RC(%X)", HWNDERR( hwndNB ) );
  402.     }
  403.  
  404.     return fSuccess;
  405. }
  406.  
  407. /**********************************************************************/
  408. /*---------------------------- SetFramePos ---------------------------*/
  409. /*                                                                    */
  410. /*  SET THE FRAME ORIGIN AND SIZE.                                    */
  411. /*                                                                    */
  412. /*  INPUT: frame window handle                                        */
  413. /*                                                                    */
  414. /*  1.                                                                */
  415. /*                                                                    */
  416. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  417. /*                                                                    */
  418. /*--------------------------------------------------------------------*/
  419. /**********************************************************************/
  420. static BOOL SetFramePos( HWND hwndFrame )
  421. {
  422.     BOOL   fSuccess;
  423.     POINTL aptl[ 2 ];
  424.  
  425.     // Convert origin and size from dialog units to pixels. We need to do this
  426.     // because dialog boxes are automatically sized to the display. Since the
  427.     // notebook contains these dialogs it must size itself accordingly so the
  428.     // dialogs fit in the notebook.
  429.  
  430.     aptl[ 0 ].x = FRAME_X;
  431.     aptl[ 0 ].y = FRAME_Y;
  432.     aptl[ 1 ].x = FRAME_CX;
  433.     aptl[ 1 ].y = FRAME_CY;
  434.  
  435.     fSuccess = WinMapDlgPoints( HWND_DESKTOP, aptl, 2, TRUE );
  436.  
  437.     if( fSuccess )
  438.     {
  439.         fSuccess = WinSetWindowPos( hwndFrame, NULLHANDLE,
  440.                                aptl[ 0 ].x, aptl[ 0 ].y, aptl[ 1 ].x, aptl[ 1 ].y,
  441.                                SWP_SIZE | SWP_MOVE | SWP_SHOW | SWP_ACTIVATE );
  442.  
  443.         if( !fSuccess )
  444.             Msg( "SetFramePos WinSetWindowPos RC(%X)", HWNDERR( hwndFrame ) );
  445.     }
  446.     else
  447.         Msg( "WinMapDlgPoints RC(%X)", HWNDERR( hwndFrame ) );
  448.  
  449.     return fSuccess;
  450. }
  451.  
  452. /**********************************************************************/
  453. /*-------------------------- CreateNotebook --------------------------*/
  454. /*                                                                    */
  455. /*  CREATE THE NOTEBOOK WINDOW                                        */
  456. /*                                                                    */
  457. /*  INPUT: client window handle                                       */
  458. /*                                                                    */
  459. /*  1.                                                                */
  460. /*                                                                    */
  461. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  462. /*                                                                    */
  463. /*--------------------------------------------------------------------*/
  464. /**********************************************************************/
  465. static BOOL CreateNotebook( HWND hwndClient )
  466. {
  467.     BOOL fSuccess = TRUE;
  468.     HWND hwndNB;
  469.     INT  i;
  470.  
  471.     // Create the notebook. Its parent and owner will be the client window.
  472.     // Its pages will show on the bottom right of the notebook. Its major tabs
  473.     // will be on the right and they will be rounded. The status text will be
  474.     // centered. Its binding will be spiraled rather than solid. The tab text
  475.     // will be left-justified.
  476.  
  477.     hwndNB = WinCreateWindow( hwndClient, WC_NOTEBOOK, NULL,
  478.                 BKS_BACKPAGESBR | BKS_MAJORTABRIGHT | BKS_ROUNDEDTABS |
  479.                 BKS_STATUSTEXTCENTER | BKS_SPIRALBIND | BKS_TABTEXTLEFT |
  480.                 WS_GROUP | WS_TABSTOP | WS_VISIBLE,
  481.                 0, 0, 0, 0, hwndClient, HWND_TOP, ID_NB, NULL, NULL );
  482.  
  483.     if( hwndNB )
  484.     {
  485.         // Set the page background color to grey so it is the same as a dlg box.
  486.  
  487.         if( !WinSendMsg( hwndNB, BKM_SETNOTEBOOKCOLORS,
  488.                          MPFROMLONG( SYSCLR_FIELDBACKGROUND ),
  489.                          MPFROMSHORT( BKA_BACKGROUNDPAGECOLORINDEX ) ) )
  490.             Msg( "BKM_SETNOTEBOOKCOLORS failed! RC(%X)", HWNDERR( hwndClient ));
  491.  
  492.         if( !SetTabDimensions( hwndNB ) )
  493.             fSuccess = FALSE;
  494.  
  495.         // Insert all the pages into the notebook and configure them. The dialog
  496.         // boxes are not going to be loaded and associated with those pages yet.
  497.  
  498.         for( i = 0; i < PAGE_COUNT && fSuccess; i++ )
  499.             fSuccess = SetUpPage( hwndNB, i );
  500.     }
  501.     else
  502.     {
  503.         fSuccess = FALSE;
  504.  
  505.         Msg( "Notebook creation failed! RC(%X)", HWNDERR( hwndClient ) );
  506.     }
  507.  
  508.     if( fSuccess && iLoadType == LOAD_BY_TIMER )
  509.     {
  510.         fSuccess = WinStartTimer( ANCHOR( hwndClient ), hwndClient, 1,
  511.                                   TIMER_INTERVAL );
  512.  
  513.         if( !fSuccess )
  514.             Msg( "WinStartTimer failed! RC(%X)", HWNDERR( hwndClient ) );
  515.     }
  516.  
  517.     return fSuccess;
  518. }
  519.  
  520. /**********************************************************************/
  521. /*----------------------------- SetUpPage ----------------------------*/
  522. /*                                                                    */
  523. /*  SET UP A NOTEBOOK PAGE.                                           */
  524. /*                                                                    */
  525. /*  INPUT: window handle of notebook control,                         */
  526. /*         index into nbpage array                                    */
  527. /*                                                                    */
  528. /*  1.                                                                */
  529. /*                                                                    */
  530. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  531. /*                                                                    */
  532. /*--------------------------------------------------------------------*/
  533. /**********************************************************************/
  534. static BOOL SetUpPage( HWND hwndNB, INT iPage )
  535. {
  536.     BOOL  fSuccess = TRUE;
  537.     ULONG ulPageId;
  538.  
  539.     // Insert a page into the notebook and store it in the array of page data.
  540.     // Specify that it is to have status text and the window associated with
  541.     // each page will be automatically sized by the notebook according to the
  542.     // size of the page.
  543.  
  544.     ulPageId = (ULONG) WinSendMsg( hwndNB, BKM_INSERTPAGE, NULL,
  545.                             MPFROM2SHORT( nbpage[ iPage ].usTabType |
  546.                                           BKA_STATUSTEXTON | BKA_AUTOPAGESIZE,
  547.                                           BKA_LAST ) );
  548.  
  549.     if( ulPageId )
  550.     {
  551.         // Insert a pointer to this page's info into the space available
  552.         // in each page (its PAGE DATA that is available to the application).
  553.  
  554.         fSuccess = (BOOL) WinSendMsg( hwndNB, BKM_SETPAGEDATA,
  555.                                       MPFROMLONG( ulPageId ),
  556.                                       MPFROMP( &nbpage[ iPage ] ) );
  557.  
  558.         // Set the text into the status line.
  559.  
  560.         if( fSuccess )
  561.         {
  562.             fSuccess = (BOOL) WinSendMsg( hwndNB, BKM_SETSTATUSLINETEXT,
  563.                                           MPFROMP( ulPageId ),
  564.                         MPFROMP( nbpage[ iPage ].szStatusLineText ) );
  565.  
  566.             if( !fSuccess )
  567.                 Msg( "BKM_SETSTATUSLINETEXT RC(%X)", HWNDERR( hwndNB ) );
  568.         }
  569.         else
  570.             Msg( "BKM_SETPAGEDATA RC(%X)", HWNDERR( hwndNB ) );
  571.  
  572.         // Set the text into the tab for this page.
  573.  
  574.         if( fSuccess )
  575.         {
  576.             if( nbpage[ iPage ].usTabType )
  577.                 fSuccess = (BOOL) WinSendMsg( hwndNB, BKM_SETTABTEXT,
  578.                                          MPFROMP( ulPageId ),
  579.                                          MPFROMP( nbpage[ iPage ].szTabText ) );
  580.  
  581.             if( fSuccess )
  582.             {
  583.                 // If the user wanted us to load all dialogs at startup time,
  584.                 // do it.
  585.  
  586.                 if( iLoadType == LOAD_AT_STARTUP && nbpage[iPage].idDlg )
  587.                     if( !LoadAndAssociate( hwndNB, ulPageId, nbpage + iPage ) )
  588.                         fSuccess = FALSE;
  589.             }
  590.             else
  591.                 Msg( "BKM_SETTABTEXT RC(%X)", HWNDERR( hwndNB ) );
  592.         }
  593.     }
  594.     else
  595.     {
  596.         fSuccess = FALSE;
  597.  
  598.         Msg( "BKM_INSERTPAGE RC(%X)", HWNDERR( hwndNB ) );
  599.     }
  600.  
  601.     return fSuccess;
  602. }
  603.  
  604. /**********************************************************************/
  605. /*-------------------------- SetTabDimensions ------------------------*/
  606. /*                                                                    */
  607. /*  SET THE DIMENSIONS OF THE NOTEBOOK TABS.                          */
  608. /*                                                                    */
  609. /*  INPUT: window handle of notebook control                          */
  610. /*                                                                    */
  611. /*  1.                                                                */
  612. /*                                                                    */
  613. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  614. /*                                                                    */
  615. /*--------------------------------------------------------------------*/
  616. /**********************************************************************/
  617. static BOOL SetTabDimensions( HWND hwndNB )
  618. {
  619.     BOOL         fSuccess = TRUE;
  620.     HPS          hps = WinGetPS( hwndNB );
  621.     FONTMETRICS  fm;
  622.     INT          i, iSize, iLongestMajText = 0, iLongestMinText = 0;
  623.  
  624.     if( !hps )
  625.     {
  626.         Msg( "SetTabDimensions WinGetPS RC(%X)", HWNDERR( hwndNB ) );
  627.  
  628.         return FALSE;
  629.     }
  630.  
  631.     (void) memset( &fm, 0, sizeof( FONTMETRICS ) );
  632.  
  633.     // Calculate the height of a tab as the height of an average font character
  634.     // plus a margin value.
  635.  
  636.     if( GpiQueryFontMetrics( hps, sizeof( FONTMETRICS ), &fm ) )
  637.         fm.lMaxBaselineExt += (TAB_HEIGHT_MARGIN * 2);
  638.     else
  639.     {
  640.         fm.lMaxBaselineExt = DEFAULT_NB_TAB_HEIGHT + (TAB_HEIGHT_MARGIN * 2);
  641.  
  642.         Msg( "SetTabDimensions GpiQueryFontMetrics RC(%X)", HWNDERR( hwndNB ) );
  643.     }
  644.  
  645.     // Calculate the longest tab text for both the MAJOR and MINOR pages
  646.  
  647.     for( i = 0; i < PAGE_COUNT; i++ )
  648.     {
  649.         if( nbpage[ i ].usTabType )
  650.         {
  651.             iSize = GetStringSize( hps, hwndNB, nbpage[ i ].szTabText );
  652.  
  653.             if( nbpage[ i ].usTabType == BKA_MAJOR )
  654.             {
  655.                 if( iSize > iLongestMajText )
  656.                     iLongestMajText = iSize;
  657.             }
  658.             else
  659.             {
  660.                 if( iSize > iLongestMinText )
  661.                     iLongestMinText = iSize;
  662.             }
  663.         }
  664.     }
  665.  
  666.     WinReleasePS( hps );
  667.  
  668.     // Add a margin amount to the longest tab text
  669.  
  670.     if( iLongestMajText )
  671.         iLongestMajText += TAB_WIDTH_MARGIN;
  672.  
  673.     if( iLongestMinText )
  674.         iLongestMinText += TAB_WIDTH_MARGIN;
  675.  
  676.     // Set the tab dimensions for the MAJOR and MINOR pages. Note that the
  677.     // docs as of this writing say to use BKA_MAJOR and BKA_MINOR in mp2 but
  678.     // you really need BKA_MAJORTAB and BKA_MINORTAB.
  679.  
  680.     if( iLongestMajText )
  681.     {
  682.         fSuccess = (BOOL) WinSendMsg( hwndNB, BKM_SETDIMENSIONS,
  683.                     MPFROM2SHORT( iLongestMajText, (SHORT)fm.lMaxBaselineExt ),
  684.                     MPFROMSHORT( BKA_MAJORTAB ) );
  685.  
  686.         if( !fSuccess )
  687.             Msg( "BKM_SETDIMENSIONS(MAJOR) RC(%X)", HWNDERR( hwndNB ) );
  688.     }
  689.  
  690.     if( fSuccess && iLongestMinText )
  691.     {
  692.         fSuccess = (BOOL) WinSendMsg( hwndNB, BKM_SETDIMENSIONS,
  693.                     MPFROM2SHORT( iLongestMinText, (SHORT)fm.lMaxBaselineExt ),
  694.                     MPFROMSHORT( BKA_MINORTAB ) );
  695.  
  696.         if( !fSuccess )
  697.             Msg( "BKM_SETDIMENSIONS(MINOR) RC(%X)", HWNDERR( hwndNB ) );
  698.     }
  699.  
  700.     return fSuccess;
  701. }
  702.  
  703. /**********************************************************************/
  704. /*-------------------------- GetStringSize ---------------------------*/
  705. /*                                                                    */
  706. /*  GET THE SIZE IN PIXELS OF A STRING.                               */
  707. /*                                                                    */
  708. /*  INPUT: presentation space handle,                                 */
  709. /*         notebook window handle,                                    */
  710. /*         pointer to string                                          */
  711. /*                                                                    */
  712. /*  1.                                                                */
  713. /*                                                                    */
  714. /*  OUTPUT: nothing                                                   */
  715. /*                                                                    */
  716. /*--------------------------------------------------------------------*/
  717. /**********************************************************************/
  718. static INT GetStringSize( HPS hps, HWND hwndNB, PSZ szString )
  719. {
  720.     POINTL aptl[ TXTBOX_COUNT ];
  721.  
  722.     // Get the size, in pixels, of the string passed.
  723.  
  724.     if( !GpiQueryTextBox( hps, strlen( szString ), szString, TXTBOX_COUNT,
  725.                           aptl ) )
  726.     {
  727.         Msg( "GetStringSize GpiQueryTextBox RC(%X)", HWNDERR( hwndNB ) );
  728.  
  729.         return 0;
  730.     }
  731.     else
  732.         return aptl[ TXTBOX_CONCAT ].x;
  733. }
  734.  
  735. /**********************************************************************/
  736. /*---------------------------- ControlMsg ----------------------------*/
  737. /*                                                                    */
  738. /*  THE ENTRY DIALOG PROC GOT A WM_CONTROL MESSAGE.                   */
  739. /*                                                                    */
  740. /*  INPUT: client window handle,                                      */
  741. /*         control id,                                                */
  742. /*         control event code,                                        */
  743. /*         2nd message parameter from WM_CONTROL message              */
  744. /*                                                                    */
  745. /*  1.                                                                */
  746. /*                                                                    */
  747. /*  OUTPUT: nothing                                                   */
  748. /*                                                                    */
  749. /*--------------------------------------------------------------------*/
  750. /**********************************************************************/
  751. static BOOL ControlMsg( USHORT usControl, USHORT usEvent, MPARAM mp2 )
  752. {
  753.     BOOL fProcessed = FALSE;
  754.  
  755.     switch( usControl )
  756.     {
  757.         case ID_NB:
  758.  
  759.             switch( usEvent )
  760.             {
  761.                 case BKN_PAGESELECTED:
  762.  
  763.                     // A new page has been selected by the user. If the dialog
  764.                     // box needs to be loaded, load it and associate it with
  765.                     // the new page.
  766.  
  767.                     SetNBPage( (PPAGESELECTNOTIFY) mp2 );
  768.  
  769.                     fProcessed = TRUE;
  770.  
  771.                     break;
  772.             }
  773.  
  774.             break;
  775.     }
  776.  
  777.     return fProcessed;
  778. }
  779.  
  780. /**********************************************************************/
  781. /*---------------------------- SetNBPage -----------------------------*/
  782. /*                                                                    */
  783. /*  SET THE TOP PAGE IN THE NOTEBOOK CONTROL.                         */
  784. /*                                                                    */
  785. /*  INPUT: pointer to the PAGESELECTNOTIFY struct                     */
  786. /*                                                                    */
  787. /*  1.                                                                */
  788. /*                                                                    */
  789. /*  OUTPUT: nothing                                                   */
  790. /*                                                                    */
  791. /*--------------------------------------------------------------------*/
  792. /**********************************************************************/
  793. static VOID SetNBPage( PPAGESELECTNOTIFY ppsn )
  794. {
  795.     HWND hwndDlg;
  796.  
  797.     // Get a pointer to the page information that is associated with this page.
  798.     // It was stored in the page's PAGE DATA in the SetUpPage function.
  799.  
  800.     PNBPAGE pnbp = (PNBPAGE) WinSendMsg( ppsn->hwndBook, BKM_QUERYPAGEDATA,
  801.                                         MPFROMLONG( ppsn->ulPageIdNew ), NULL );
  802.  
  803.     if( !pnbp )
  804.         return;
  805.     else if( pnbp == (PNBPAGE) BOOKERR_INVALID_PARAMETERS )
  806.     {
  807.         Msg( "SetNBPage BKM_QUERYPAGEDATA Invalid page id" );
  808.  
  809.         return;
  810.     }
  811.  
  812.     // If this is a BKA_MAJOR page and it is what this app terms a 'parent'
  813.     // page, that means when the user selects this page we actually want to go
  814.     // to its first MINOR page. So in effect the MAJOR page is just a dummy page
  815.     // that has a tab that acts as a placeholder for its MINOR pages. If the
  816.     // user is using the left arrow to scroll thru the pages and they hit this
  817.     // dummy MAJOR page, that means they have already been to its MINOR pages in
  818.     // reverse order. They would now expect to see the page before the dummy
  819.     // MAJOR page, so we skip the dummy page. Otherwise the user is going the
  820.     // other way and wants to see the first MINOR page associated with this
  821.     // 'parent' page so we skip the dummy page and show its first MINOR page.
  822.  
  823.     if( pnbp->fParent )
  824.     {
  825.         ULONG ulPageFwd, ulPageNew;
  826.  
  827.         ulPageFwd = (ULONG) WinSendMsg( ppsn->hwndBook, BKM_QUERYPAGEID,
  828.                                         MPFROMLONG( ppsn->ulPageIdNew ),
  829.                                         MPFROM2SHORT( BKA_NEXT, BKA_MINOR ) );
  830.  
  831.         // If this is true, the user is going in reverse order
  832.  
  833.         if( ulPageFwd == ppsn->ulPageIdCur )
  834.             ulPageNew = (ULONG) WinSendMsg( ppsn->hwndBook, BKM_QUERYPAGEID,
  835.                                             MPFROMLONG( ppsn->ulPageIdNew ),
  836.                                             MPFROM2SHORT(BKA_PREV, BKA_MAJOR) );
  837.         else
  838.             ulPageNew = ulPageFwd;
  839.  
  840.         if( ulPageNew == (ULONG) BOOKERR_INVALID_PARAMETERS )
  841.             Msg( "SetNBPage BKM_QUERYPAGEID Invalid page specified" );
  842.         else if( ulPageNew )
  843.             if( !WinSendMsg( ppsn->hwndBook, BKM_TURNTOPAGE,
  844.                              MPFROMLONG( ulPageNew ), NULL ) )
  845.                 Msg( "BKM_TURNTOPAGE RC(%X)", HWNDERR( ppsn->hwndBook ) );
  846.     }
  847.     else
  848.     {
  849.         hwndDlg = (HWND) WinSendMsg( ppsn->hwndBook, BKM_QUERYPAGEWINDOWHWND,
  850.                                      MPFROMLONG( ppsn->ulPageIdNew ), NULL );
  851.  
  852.         if( hwndDlg == (HWND) BOOKERR_INVALID_PARAMETERS )
  853.         {
  854.             hwndDlg = NULLHANDLE;
  855.  
  856.             Msg( "SetNBPage BKM_QUERYPAGEWINDOWHWND Invalid page specified" );
  857.         }
  858.         else if( !hwndDlg )
  859.  
  860.             // It is time to load this dialog because the user has flipped pages
  861.             // to a page that hasn't yet had the dialog associated with it.
  862.  
  863.             hwndDlg = LoadAndAssociate( ppsn->hwndBook, ppsn->ulPageIdNew,
  864.                                         pnbp );
  865.     }
  866.  
  867.     // Set focus to the first control in the dialog. This is not automatically
  868.     // done by the notebook.
  869.  
  870.     if( !pnbp->fParent && hwndDlg )
  871.         if( !WinSetFocus( HWND_DESKTOP,
  872.                           WinWindowFromID( hwndDlg, pnbp->idFocus ) ) )
  873.         {
  874.             // Bug in 2.0! Developers left some debug code in there!
  875.  
  876.             USHORT usErr = HWNDERR( ppsn->hwndBook );
  877.  
  878.             if( usErr != PMERR_WIN_DEBUGMSG )
  879.                 Msg( "SetNBPage WinSetFocus RC(%X)", usErr );
  880.         }
  881.  
  882.     return;
  883. }
  884.  
  885. /**********************************************************************/
  886. /*-------------------------- CheckDialogs ----------------------------*/
  887. /*                                                                    */
  888. /*  LOAD A DIALOG IF NOT ALL ARE LOADED YET.                          */
  889. /*                                                                    */
  890. /*  INPUT: client window handle                                       */
  891. /*                                                                    */
  892. /*  1.                                                                */
  893. /*                                                                    */
  894. /*  OUTPUT: nothing                                                   */
  895. /*                                                                    */
  896. /*--------------------------------------------------------------------*/
  897. /**********************************************************************/
  898. static VOID CheckDialogs( HWND hwndClient )
  899. {
  900.     HWND   hwndDlg, hwndNB = WinWindowFromID( hwndClient, ID_NB );
  901.     ULONG  ulPageId = 1;
  902.     USHORT usWhat = BKA_FIRST;
  903.  
  904.     // Enumerate thru all pages looking for the first one that hasn't yet
  905.     // been associated with an hwnd.
  906.  
  907.     while( ulPageId )
  908.     {
  909.         ulPageId = (ULONG) WinSendMsg( hwndNB, BKM_QUERYPAGEID,
  910.                                MPFROMLONG( ulPageId ),
  911.                                MPFROM2SHORT( usWhat, 0 ) );
  912.  
  913.         if( ulPageId == (ULONG) BOOKERR_INVALID_PARAMETERS )
  914.         {
  915.             ulPageId = 0;
  916.  
  917.             Msg( "CheckDialogs BKM_QUERYPAGEID Invalid page specified" );
  918.  
  919.             break;
  920.         }
  921.         else if( ulPageId )
  922.         {
  923.             hwndDlg = (HWND) WinSendMsg( hwndNB, BKM_QUERYPAGEWINDOWHWND,
  924.                                          MPFROMLONG( ulPageId ), NULL );
  925.  
  926.             if( hwndDlg == (HWND) BOOKERR_INVALID_PARAMETERS )
  927.             {
  928.                 Msg( "CheckDialogs QUERYPAGEWNDHWND Invalid page specified" );
  929.  
  930.                 ulPageId = 0;
  931.  
  932.                 break;
  933.             }
  934.             else if( !hwndDlg )
  935.             {
  936.                 PNBPAGE pnbp = WinSendMsg( hwndNB, BKM_QUERYPAGEDATA,
  937.                                            MPFROMLONG( ulPageId ), NULL );
  938.  
  939.                 if( pnbp == (PNBPAGE) BOOKERR_INVALID_PARAMETERS )
  940.                 {
  941.                     Msg( "CheckDialogs QUERYPAGEDATA Invalid page specified" );
  942.  
  943.                     ulPageId = 0;
  944.  
  945.                     break;
  946.                 }
  947.                 else if( pnbp && pnbp->idDlg )
  948.                 {
  949.                     hwndDlg = LoadAndAssociate( hwndNB, ulPageId, pnbp );
  950.  
  951.                     if( !hwndDlg )
  952.                         ulPageId = 0;
  953.  
  954.                     break;
  955.                 }
  956.             }
  957.         }
  958.  
  959.         usWhat = BKA_NEXT;
  960.     }
  961.  
  962.     // If all pages have been loaded, stop the timer
  963.  
  964.     if( !ulPageId )
  965.         WinStopTimer( ANCHOR( hwndClient ), hwndClient, 1 );
  966.  
  967.     return;
  968. }
  969.  
  970. /**********************************************************************/
  971. /*----------------------- LoadAndAssociate ---------------------------*/
  972. /*                                                                    */
  973. /*  LOAD THE DIALOG BOX AND ASSOCIATE IT WITH A NOTEBOOK PAGE.        */
  974. /*                                                                    */
  975. /*  INPUT: notebook window handle,                                    */
  976. /*         page id to associate dialog with,                          */
  977. /*         pointer to info related this page                          */
  978. /*                                                                    */
  979. /*  1.                                                                */
  980. /*                                                                    */
  981. /*  OUTPUT: Dialog box window handle                                  */
  982. /*                                                                    */
  983. /*--------------------------------------------------------------------*/
  984. /**********************************************************************/
  985. static HWND LoadAndAssociate( HWND hwndNB, ULONG ulPageId, PNBPAGE pnbp )
  986. {
  987.     HWND hwndDlg, hwndClient = PARENT( hwndNB );
  988.  
  989.     hwndDlg = WinLoadDlg( hwndClient, hwndClient, pnbp->pfnwpDlg, 0,
  990.                           pnbp->idDlg, NULL );
  991.  
  992.     if( hwndDlg )
  993.     {
  994.         // Associate the dialog with the page.
  995.  
  996.         if( !WinSendMsg( hwndNB, BKM_SETPAGEWINDOWHWND,
  997.                          MPFROMP( ulPageId ), MPFROMLONG( hwndDlg ) ) )
  998.         {
  999.             WinDestroyWindow( hwndDlg );
  1000.  
  1001.             hwndDlg = NULLHANDLE;
  1002.  
  1003.             Msg( "BKM_SETPAGEWINDOWHWND RC(%X)", HWNDERR( hwndNB ));
  1004.         }
  1005.     }
  1006.     else
  1007.         Msg( "WinLoadDlg RC(%X)", HWNDERR( hwndNB ) );
  1008.  
  1009.     return hwndDlg;
  1010. }
  1011.  
  1012. /**********************************************************************/
  1013. /*------------------------------ wpPage ------------------------------*/
  1014. /*                                                                    */
  1015. /*  WINDOW PROCEDURE FOR ALL DIALOGS                                  */
  1016. /*                                                                    */
  1017. /*  INPUT: window handle, message id, message parameter 1 and 2.      */
  1018. /*                                                                    */
  1019. /*  1.                                                                */
  1020. /*                                                                    */
  1021. /*  OUTPUT: return code                                               */
  1022. /*--------------------------------------------------------------------*/
  1023. /**********************************************************************/
  1024. MRESULT EXPENTRY wpPage( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1025. {
  1026.     switch( msg )
  1027.     {
  1028.         case WM_COMMAND:
  1029.  
  1030.             return 0;
  1031.     }
  1032.  
  1033.     return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  1034. }
  1035.  
  1036. /**********************************************************************/
  1037. /*------------------------------- Msg --------------------------------*/
  1038. /*                                                                    */
  1039. /*  DISPLAY A MESSAGE TO THE USER.                                    */
  1040. /*                                                                    */
  1041. /*  INPUT: a message in printf format with its parms                  */
  1042. /*                                                                    */
  1043. /*  1. Format the message using vsprintf.                             */
  1044. /*  2. Sound a warning sound.                                         */
  1045. /*  3. Display the message in a message box.                          */
  1046. /*                                                                    */
  1047. /*  OUTPUT: nothing                                                   */
  1048. /*                                                                    */
  1049. /*--------------------------------------------------------------------*/
  1050. /**********************************************************************/
  1051.  
  1052. #define MESSAGE_SIZE 1024
  1053.  
  1054. VOID Msg( PSZ szFormat,... )
  1055. {
  1056.     PSZ     szMsg;
  1057.     va_list argptr;
  1058.  
  1059.     if( (szMsg = (PSZ) malloc( MESSAGE_SIZE )) == NULL )
  1060.     {
  1061.         DosBeep( 1000, 1000 );
  1062.  
  1063.         return;
  1064.     }
  1065.  
  1066.     va_start( argptr, szFormat );
  1067.  
  1068.     vsprintf( szMsg, szFormat, argptr );
  1069.  
  1070.     va_end( argptr );
  1071.  
  1072.     szMsg[ MESSAGE_SIZE - 1 ] = 0;
  1073.  
  1074.     (void) WinAlarm( HWND_DESKTOP, WA_WARNING );
  1075.  
  1076.     (void) WinMessageBox(  HWND_DESKTOP, HWND_DESKTOP, szMsg,
  1077.                            PROGRAM_TITLE, 1, MB_OK | MB_MOVEABLE );
  1078.  
  1079.     free( szMsg );
  1080.  
  1081.     return;
  1082. }
  1083.  
  1084. /************************************************************************
  1085.  *                      E N D   O F   S O U R C E                       *
  1086.  ************************************************************************/
  1087.