home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MSJV5-6.ZIP / FORM2.ZIP / VIEWER.C < prev    next >
C/C++ Source or Header  |  1990-11-01  |  20KB  |  789 lines

  1. /*
  2.  * FORM VIEWER - SOURCE CODE
  3.  *
  4.  * LANGUAGE      : Microsoft C 5.1
  5.  * MODEL         : medium
  6.  * ENVIRONMENT   : Microsoft Windows 3.00 SDK
  7.  * STATUS        : operational
  8.  *
  9.  *    Eikon Systems, Inc.
  10.  *    989 East Hillsdale Blvd, Suite 260
  11.  *    Foster City, California 94404
  12.  *
  13.  * 07/12/90 1.00 - Kevin P. Welch - initial creation.
  14.  *
  15.  */
  16.  
  17. #define NOCOMM
  18.  
  19. #include <windows.h>
  20. #include <memory.h>
  21. #include "viewer.h"
  22.  
  23. /* */
  24.  
  25. /*
  26.  * WinMain( hCrntInst, hPrevInst, lpszCmd, wCmdShow ) : VOID
  27.  *
  28.  *    hCrntInst      current instance handle
  29.  *    hPrevInst      previous instance handle
  30.  *    lpszCmd        current command line
  31.  *    wCmdShow       initial show window parameter
  32.  *
  33.  * This function is responsible for registering and creating the form
  34.  * viewer window.  Once the window has been created, messages
  35.  * are retrieved until the window is destroyed.
  36.  *
  37.  */
  38.  
  39. int PASCAL WinMain(
  40.    HANDLE      hCrntInst,
  41.    HANDLE      hPrevInst,
  42.    LPSTR       lpszCmd,
  43.    WORD        wCmdShow )
  44. {
  45.    /* local variables */
  46.    MSG         Msg;
  47.    HWND        hWnd;
  48.    WNDCLASS    WndClass;
  49.  
  50.    /* warning level 3 compatibility */
  51.    lpszCmd;
  52.    
  53.    /* define special window class */
  54.    memset( &WndClass, 0, sizeof(WNDCLASS) );
  55.  
  56.    WndClass.lpszClassName =   "Viewer";
  57.    WndClass.hInstance =       hCrntInst;
  58.    WndClass.lpfnWndProc =     ViewerWndFn;
  59.    WndClass.lpszMenuName =    "ViewerMenu";
  60.    WndClass.hbrBackground =   NULL;
  61.    WndClass.style =           CS_HREDRAW | CS_VREDRAW;
  62.    WndClass.hCursor =         LoadCursor( NULL, IDC_ARROW );
  63.    WndClass.hIcon =           LoadIcon( hCrntInst, "ViewerIcon" );
  64.  
  65.    /* register window class (if necessary) */
  66.    if ( (hPrevInst) || (RegisterClass(&WndClass)) ) {
  67.  
  68.       /* create main window */
  69.       hWnd = CreateWindow(
  70.             "Viewer",      
  71.             "Form Viewer - (untitled)",
  72.             VIEWER_STYLE,    
  73.             VIEWER_XPOS,     
  74.             VIEWER_YPOS,     
  75.             VIEWER_WIDTH,    
  76.             VIEWER_HEIGHT,   
  77.             (HWND)NULL,        
  78.             (HMENU)NULL,       
  79.             hCrntInst,         
  80.             (LPSTR)&WndClass
  81.          );
  82.  
  83.       /* continue if successful */
  84.       if ( hWnd ) {
  85.       
  86.          /* display main window */
  87.          ShowWindow( hWnd, wCmdShow );            
  88.  
  89.          /* process messages */
  90.          while ( GetMessage(&Msg,NULL,0,0) ) {
  91.             TranslateMessage( &Msg );
  92.             DispatchMessage( &Msg );
  93.          }
  94.  
  95.          /* normal exit */
  96.          return( Msg.wParam );  
  97.  
  98.       } else
  99.          WARNING( NULL, "Unable to create window!" );
  100.  
  101.    } else
  102.       WARNING( NULL, "Unable to register window!" );
  103.  
  104.    /* abnormal exit */
  105.    return( NULL );
  106.  
  107. }
  108.  
  109. /* */
  110.  
  111. /*
  112.  * ViewerWndFn( hWnd, wMessage, wParam, lParam ) : LONG
  113.  *
  114.  *    hWnd        window handle
  115.  *    wMessage    message number
  116.  *    wParam      additional message information
  117.  *    lParam      additional message information
  118.  *
  119.  * This window function processes all the messages related to the 
  120.  * form viewer window.  With the menu a new form can be loaded, and
  121.  * existing form edited or printed.
  122.  *
  123.  */
  124.  
  125. LONG FAR PASCAL ViewerWndFn(
  126.    HWND        hWnd,
  127.    WORD        wMsg,
  128.    WORD        wParam,
  129.    LONG        lParam )
  130. {
  131.    /* local variables */
  132.    LONG        lResult;    
  133.  
  134.    /* initialization */
  135.    lResult = FALSE;
  136.    
  137.    /* process each message */
  138.    switch( wMsg )
  139.       {
  140.    case WM_CREATE : /* window being created */
  141.       {
  142.          HWND     hWndEdit;
  143.          RECT     rcClient;
  144.  
  145.          /* retrieve client rectangle */
  146.          GetClientRect( hWnd, &rcClient );
  147.          
  148.          /* define property lists */
  149.          SET_EDIT( hWnd, NULL );
  150.          SET_FORM( hWnd, NULL );
  151.  
  152.          /* create edit child window */
  153.          hWndEdit = CreateWindow(
  154.                "Edit",      
  155.                "",
  156.                WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
  157.                   ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL,
  158.                -1,
  159.                -1,
  160.                rcClient.right+2,
  161.                rcClient.bottom+2,
  162.                hWnd,
  163.                1,       
  164.                INSTANCE(hWnd),         
  165.                NULL
  166.             );
  167.  
  168.          /* continue if successful */
  169.          if ( hWndEdit ) {
  170.             SET_EDIT( hWnd, hWndEdit );
  171.             EnableWindow( hWndEdit, FALSE );
  172.          } else {
  173.             WARNING( hWnd, "Unable to create edit window!" );
  174.             PostMessage( hWnd, WM_CLOSE, NULL, (LONG)NULL );
  175.          } 
  176.  
  177.       }
  178.       break;
  179.    case WM_SIZE : /* window being resized */
  180.       
  181.       /* resize edit window (if present) */
  182.       if ( GET_EDIT(hWnd) )
  183.          MoveWindow( 
  184.             GET_EDIT(hWnd),
  185.             -1, 
  186.             -1, 
  187.             LOWORD(lParam)+2,
  188.             HIWORD(lParam)+2,
  189.             TRUE
  190.          );
  191.  
  192.       break;
  193.    case WM_INITMENU : /* initialize menu */
  194.  
  195.       /* enable edit & print menus */
  196.       if ( GET_FORM(hWnd) ) {
  197.          EnableMenuItem( wParam, IDM_EDIT, MF_ENABLED );
  198.          EnableMenuItem( wParam, IDM_PRINT, MF_ENABLED );
  199.       } else {
  200.          EnableMenuItem( wParam, IDM_EDIT, MF_DISABLED|MF_GRAYED );
  201.          EnableMenuItem( wParam, IDM_PRINT, MF_DISABLED|MF_GRAYED );
  202.       }
  203.  
  204.       break;
  205.    case WM_COMMAND : /* window command */
  206.  
  207.       /* process message */
  208.       switch( wParam )
  209.          {
  210.       case IDM_OPEN :
  211.          
  212.          /* display open dialog box */
  213.          if ( Dialog(hWnd,"ViewerOpen",OpenDlgFn) )
  214.             SetFocus( GET_EDIT(hWnd) );
  215.  
  216.          break;
  217.       case IDM_EDIT :
  218.          {
  219.             HANDLE      hData;
  220.             HANDLE      hResult;
  221.             LPEDITFN    lpEditFn;
  222.  
  223.             /* retrieve text block */
  224.             hData = GetText( GET_EDIT(hWnd) );
  225.             if ( hData ) {
  226.    
  227.                /* pass data to form edit library function */
  228.                lpEditFn = GetProcAddress( GET_FORM(hWnd), FORM_EDIT );
  229.                hResult = (*lpEditFn)( hWnd, hData );
  230.  
  231.                /* redisplay updated information */
  232.                if ( hResult ) {
  233.                   SetText( GET_EDIT(hWnd), hResult );
  234.                   GlobalFree( hResult );
  235.                } 
  236.  
  237.                /* release initial data block */
  238.                GlobalFree( hData );
  239.  
  240.             } else
  241.                WARNING( hWnd, "Unable to retrieve text block!" );
  242.  
  243.          } 
  244.          break;
  245.       case IDM_PRINT :
  246.          {
  247.             HANDLE      hData;
  248.             HANDLE      hResult;
  249.             LPPRINTFN   lpPrintFn;
  250.  
  251.             /* retrieve edit data */
  252.             hData = GetText( GET_EDIT(hWnd) );
  253.             if ( hData ) {
  254.    
  255.                /* pass data to form print library function */
  256.                lpPrintFn = GetProcAddress( GET_FORM(hWnd), FORM_PRINT );
  257.                hResult = (*lpPrintFn)( hWnd, hData );
  258.  
  259.                /* release edit data */
  260.                GlobalFree( (hResult)?hResult:hData );
  261.  
  262.             } else
  263.                WARNING( hWnd, "Unable to retrieve text block!" );
  264.  
  265.          } 
  266.          break;
  267.       case IDM_EXIT :
  268.          PostMessage( hWnd, WM_CLOSE, NULL, (LONG)NULL );
  269.          break;
  270.       case IDM_ABOUT :
  271.          Dialog( hWnd, "ViewerAbout", AboutDlgFn );
  272.          break;
  273.       }
  274.    
  275.       break;
  276.    case WM_DESTROY : /* destroy window */
  277.       
  278.       /* free form library (if present) */
  279.       if ( GET_FORM(hWnd) )
  280.          FreeLibrary( GET_FORM(hWnd) );
  281.    
  282.       /* remove property lists */
  283.       REM_EDIT( hWnd );
  284.       REM_FORM( hWnd );
  285.    
  286.       /* die gracefully */
  287.       PostQuitMessage( 0 );
  288.  
  289.       break;
  290.    default : /* send to default */
  291.       lResult = DefWindowProc( hWnd, wMsg, wParam, lParam );
  292.       break;
  293.    }
  294.    
  295.    /* return normal result */
  296.    return( lResult );
  297.  
  298. }
  299.  
  300. /* */
  301.  
  302. /*
  303.  * OpenDlgFn( hDlg, wMsg, wParam, lParam ) : BOOL ;
  304.  *
  305.  *    hDlg           handle to dialog box
  306.  *    wMsg           message or event
  307.  *    wParam         word portion of message
  308.  *    lParam         long portion of message
  309.  *
  310.  * This function is responsible for enabling the user to
  311.  * open a new form library.
  312.  *
  313.  */
  314.  
  315. BOOL FAR PASCAL OpenDlgFn(
  316.    HWND        hDlg,
  317.    WORD        wMsg,
  318.    WORD        wParam,
  319.    LONG        lParam )
  320. {
  321.    /* local variables */
  322.    BOOL        bResult;
  323.  
  324.    /* initialization */
  325.    bResult = TRUE;
  326.  
  327.    /* process message */
  328.    switch( wMsg )
  329.       {
  330.    case WM_INITDIALOG :
  331.       CenterPopup( hDlg, GetParent(hDlg) );
  332.       break;
  333.    case WM_COMMAND :
  334.  
  335.       /* process sub-message */
  336.       switch( wParam )
  337.          {
  338.       case ID_FORM :
  339.          
  340.          /* enable or disable OK button */
  341.          if ( HIWORD(lParam) == EN_CHANGE ) 
  342.             EnableWindow(
  343.                GetDlgItem(hDlg,ID_OK),
  344.                SendMessage(
  345.                   GetDlgItem(hDlg,ID_FORM),
  346.                   WM_GETTEXTLENGTH,
  347.                   0,
  348.                   0L
  349.                ) ? TRUE : FALSE
  350.             ); 
  351.  
  352.          break;
  353.       case ID_OK :
  354.          {
  355.             HANDLE   hLib;
  356.             char     szLib[128];
  357.             char     szCaption[128];
  358.  
  359.             /* retrieve library name */
  360.             GetDlgItemText( hDlg, ID_FORM, szLib, sizeof(szLib) );
  361.  
  362.             /* attempt to load new library */
  363.             hLib = LoadLibrary( szLib );
  364.             if ( hLib >= 32 ) {
  365.  
  366.                /* update main window caption */
  367.                lstrcpy( szCaption, "Form Viewer - " );
  368.                lstrcat( szCaption, szLib );
  369.  
  370.                SetWindowText( PARENT(hDlg), szCaption );
  371.  
  372.                /* release old library */
  373.                if ( GET_FORM(PARENT(hDlg)) ) 
  374.                   FreeLibrary( GET_FORM(PARENT(hDlg)) );
  375.  
  376.                /* save library handle & activate edit window */
  377.                SET_FORM( PARENT(hDlg), hLib );
  378.                EnableWindow( GET_EDIT(PARENT(hDlg)), TRUE );
  379.                
  380.                /* close dialog box */
  381.                EndDialog( hDlg, TRUE );
  382.  
  383.             } 
  384.  
  385.          }
  386.          break;
  387.       case ID_CANCEL :
  388.  
  389.          /* return false */
  390.          EndDialog( hDlg, FALSE );
  391.  
  392.          break;
  393.       default :
  394.          bResult = FALSE;
  395.          break;
  396.       }
  397.  
  398.       break;
  399.    default :
  400.       bResult = FALSE;
  401.       break;
  402.    }
  403.  
  404.    /* return final result */
  405.    return( bResult );
  406.  
  407. }
  408.  
  409. /* */
  410.  
  411. /*
  412.  * AboutDlgFn( hDlg, wMsg, wParam, lParam ) : BOOL ;
  413.  *
  414.  *    hDlg           handle to dialog box
  415.  *    wMsg           message or event
  416.  *    wParam         word portion of message
  417.  *    lParam         long portion of message
  418.  *
  419.  * This function is responsible for processing all the messages
  420.  * that relate to the Viewer about dialog box. 
  421.  *
  422.  */
  423.  
  424. BOOL FAR PASCAL AboutDlgFn(
  425.    HWND        hDlg,
  426.    WORD        wMsg,
  427.    WORD        wParam,
  428.    LONG        lParam )
  429. {
  430.    /* local variables */
  431.    BOOL        bResult;
  432.  
  433.    /* warning level 3 compatibility */
  434.    lParam;
  435.  
  436.    /* initialization */
  437.    bResult = TRUE;
  438.  
  439.    /* process message */
  440.    switch( wMsg )
  441.       {
  442.    case WM_INITDIALOG :
  443.       CenterPopup( hDlg, GetParent(hDlg) );
  444.       break;
  445.    case WM_COMMAND :
  446.  
  447.       /* process sub-message */
  448.       if ( wParam == ID_OK )
  449.          EndDialog( hDlg, TRUE );
  450.       else
  451.          bResult = FALSE;
  452.  
  453.       break;
  454.    default :
  455.       bResult = FALSE;
  456.       break;
  457.    }
  458.  
  459.    /* return final result */
  460.    return( bResult );
  461.  
  462. }
  463.  
  464. /* */
  465.  
  466. /*
  467.  * GetText( hWnd ) : HANDLE;
  468.  *
  469.  *    hWnd           handle to edit control window
  470.  *
  471.  * This function allocates and retrieve a block of text data
  472.  * from a multi-line edit control.  Each text line is terminated
  473.  * with a single NULL character, and the last by two NULL characters.
  474.  *
  475.  * If a value of NULL is returned, it can be assumed that insufficient
  476.  * memory was available or an invalid window handle was provided.
  477.  *
  478.  * Note - this function assumes that the maximum text line length
  479.  * is 256 characters.
  480.  *
  481.  */
  482.  
  483. HANDLE FAR PASCAL GetText(
  484.    HWND        hWnd )
  485. {
  486.    /* local variables */
  487.    WORD        wLen;
  488.    WORD        wMax;
  489.    WORD        wLine;
  490.    HANDLE      hData;
  491.    DWORD       dwOld;
  492.    DWORD       dwNew;
  493.    LPSTR       lpData;
  494.    char        szData[256];
  495.  
  496.    /* initialization */
  497.    dwOld = 0;
  498.  
  499.    /* allocate space for data */
  500.    hData = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, dwOld+32 );
  501.    if ( hData ) {
  502.    
  503.       /* retrieve number of text lines */
  504.       wMax = (WORD)SendMessage( hWnd, EM_GETLINECOUNT, 0, (LONG)0 );
  505.  
  506.       /* process each text line */
  507.       for ( wLine=0; wLine<wMax; wLine++ ) {
  508.    
  509.          /* retrieve next text line (make null terminated) */
  510.          szData[0] = sizeof(szData) - 2;
  511.  
  512.          wLen = (WORD)SendMessage(
  513.                         hWnd, 
  514.                         EM_GETLINE, 
  515.                         wLine, 
  516.                         (LONG)(LPSTR)szData
  517.                      );
  518.  
  519.          szData[wLen] = NULL;
  520.  
  521.          /* continue if line not empty */
  522.          if ( wLen ) {
  523.  
  524.             /* calculate new memory block sizes */
  525.             dwNew = dwOld + wLen + 1;
  526.  
  527.             /* expand global buffer */
  528.             hData = GlobalReAlloc( hData, dwNew+32, NULL );
  529.             if ( hData ) {
  530.  
  531.                /* copy text string into global buffer */
  532.                lpData = GlobalLock( hData );
  533.                if ( lpData ) {
  534.                   lstrcpy( lpData+(WORD)dwOld, szData );
  535.                   GlobalUnlock( hData );
  536.                   dwOld = dwNew;
  537.                } 
  538.  
  539.             } 
  540.  
  541.          }
  542.          
  543.       }
  544.  
  545.       /* append final NULL character */
  546.       hData = GlobalReAlloc( hData, dwOld+32, NULL );
  547.       if ( hData ) {
  548.          lpData = GlobalLock( hData );
  549.          if ( lpData ) {
  550.             *(lpData+(WORD)dwOld) = NULL;
  551.             GlobalUnlock( hData );
  552.          }
  553.       }
  554.  
  555.    }
  556.  
  557.    /* return result */
  558.    return( hData );
  559.  
  560. }
  561.  
  562. /* */
  563.  
  564. /*
  565.  * SetText( hWnd, hData ) : HANDLE;
  566.  *
  567.  *    hWnd           handle to edit control
  568.  *    hData          handle to formatted data block
  569.  *
  570.  * This function erases the current contents of the edit control and
  571.  * displays the new text data block.  It is assumed that each line
  572.  * in the text block is terminated with a single NULL character and
  573.  * the last line by two NULL characters.
  574.  *
  575.  * If the function was successful, the original data block handle is
  576.  * returned.  If unsuccessful, a NULL handle is returned.
  577.  *
  578.  */
  579.  
  580. HANDLE FAR PASCAL SetText(
  581.    HWND        hWnd,
  582.    HANDLE      hData )
  583. {
  584.    /* local variables */
  585.    WORD        wLen;
  586.    HANDLE      hTemp;
  587.    DWORD       dwOld;
  588.    DWORD       dwNew;
  589.    LPSTR       lpData;
  590.    LPSTR       lpTemp;
  591.  
  592.    /* initialization */
  593.    dwOld = 0;
  594.    
  595.    /* allocate space for formatted data block */
  596.    hTemp = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, dwOld+32 );
  597.    if ( hTemp ) {
  598.  
  599.       /* copy text string into global buffer */
  600.       lpData = GlobalLock( hData );
  601.       if ( lpData ) {
  602.  
  603.          /* process each line in data block */
  604.          while ( *lpData ) {
  605.  
  606.             /* determine length of next string */
  607.             wLen = lstrlen(lpData);
  608.  
  609.             /* calculate new memory block sizes */
  610.             dwNew = dwOld + wLen + 2;
  611.  
  612.             /* expand temporary data block */
  613.             hTemp = GlobalReAlloc( hTemp, dwNew+32, NULL );
  614.             if ( hTemp ) {
  615.  
  616.                /* copy text string into global buffer */
  617.                lpTemp = GlobalLock( hTemp );
  618.                if ( lpTemp ) {
  619.                   lstrcpy( &lpTemp[(WORD)dwOld], lpData );
  620.                   lstrcpy( &lpTemp[(WORD)dwOld+wLen], "\r\n" );
  621.                   GlobalUnlock( hTemp );
  622.                   dwOld = dwNew;
  623.                } 
  624.  
  625.             } 
  626.  
  627.             /* move to next line */
  628.             lpData += wLen + 1;
  629.  
  630.          }
  631.  
  632.          /* unlock data block */
  633.          GlobalUnlock( hData );
  634.  
  635.       } 
  636.    
  637.       /* append final NULL character */
  638.       hTemp = GlobalReAlloc( hTemp, dwOld+32, NULL );
  639.       if ( hTemp ) {
  640.          lpTemp = GlobalLock( hTemp );
  641.          if ( lpTemp ) {
  642.             *(lpTemp+(WORD)dwOld) = NULL;
  643.             GlobalUnlock( hTemp );
  644.          }
  645.       }
  646.  
  647.       /* update edit control */
  648.       lpTemp = GlobalLock( hTemp );
  649.       if ( lpTemp ) {
  650.          SendMessage( hWnd, WM_SETTEXT, 0, (LONG)lpTemp );
  651.          GlobalUnlock( hTemp );
  652.       } 
  653.  
  654.       /* release temporary memory block */
  655.       GlobalFree( hTemp );
  656.  
  657.    }
  658.  
  659.    /* return result */
  660.    return( hData );
  661.  
  662. }
  663.  
  664. /* */
  665.  
  666. /*
  667.  * Dialog( hParentWnd, lpszTemplate, lpfnDlgProc ) : BOOL
  668.  *
  669.  *    hParentWnd        handle to parent window
  670.  *    lpszTemplate      dialog box template
  671.  *    lpfnDlgProc       dialog window function
  672.  *
  673.  * This utility function displays the specified dialog box, using the
  674.  * template provided.  It automatically makes a new instance of the
  675.  * dialog box function.  Note that this function will NOT work
  676.  * correctly if an invalid or NULL parent window handle is provided.
  677.  *
  678.  */
  679.  
  680. BOOL FAR PASCAL Dialog( hParentWnd, lpszTemplate, lpfnDlgProc )
  681.    HWND        hParentWnd;
  682.    LPSTR       lpszTemplate;
  683.    FARPROC     lpfnDlgProc;
  684. {
  685.    /* local variables */
  686.    BOOL           bResult;
  687.    FARPROC        lpProc;                 
  688.       
  689.    /* display palette dialog box */
  690.    lpProc = MakeProcInstance( lpfnDlgProc, INSTANCE(hParentWnd) );
  691.    bResult = DialogBox( INSTANCE(hParentWnd), lpszTemplate, hParentWnd, lpProc );
  692.    FreeProcInstance( lpProc );
  693.  
  694.    /* return result */
  695.    return( bResult );
  696.  
  697. }
  698.  
  699. /* */
  700.  
  701. /*
  702.  * CenterPopup( hWnd, hParentWnd ) : BOOL
  703.  *
  704.  *    hWnd              window handle
  705.  *    hParentWnd        parent window handle
  706.  *
  707.  * This routine centers the popup window in the screen or display
  708.  * using the window handles provided.  The window is centered over
  709.  * the parent if the parent window is valid.  Special provision
  710.  * is made for the case when the popup would be centered outside
  711.  * the screen - in this case it is positioned at the appropriate
  712.  * border.
  713.  *
  714.  */
  715.  
  716. BOOL FAR PASCAL CenterPopup( 
  717.       HWND     hWnd,
  718.       HWND     hParentWnd
  719.    )
  720. {
  721.    /* local variables */
  722.    int      xPopup;   
  723.    int      yPopup;   
  724.    int      cxPopup;  
  725.    int      cyPopup;  
  726.    int      cxScreen; 
  727.    int      cyScreen; 
  728.    int      cxParent; 
  729.    int      cyParent; 
  730.    RECT     rcWindow; 
  731.  
  732.    /* retrieve main display dimensions */
  733.    cxScreen = GetSystemMetrics( SM_CXSCREEN );
  734.    cyScreen = GetSystemMetrics( SM_CYSCREEN );
  735.  
  736.    /* retrieve popup rectangle  */
  737.    GetWindowRect( hWnd, (LPRECT)&rcWindow );
  738.  
  739.    /* calculate popup extents */
  740.    cxPopup = rcWindow.right - rcWindow.left;
  741.    cyPopup = rcWindow.bottom - rcWindow.top;
  742.  
  743.    /* calculate bounding rectangle */
  744.    if ( hParentWnd ) {
  745.  
  746.       /* retrieve parent rectangle */
  747.       GetWindowRect( hParentWnd, (LPRECT)&rcWindow );
  748.  
  749.       /* calculate parent extents */
  750.       cxParent = rcWindow.right - rcWindow.left;
  751.       cyParent = rcWindow.bottom - rcWindow.top;
  752.  
  753.       /* center within parent window */
  754.       xPopup = rcWindow.left + ((cxParent - cxPopup)/2);
  755.       yPopup = rcWindow.top + ((cyParent - cyPopup)/2);
  756.  
  757.       /* adjust popup x-location for screen size */
  758.       if ( xPopup+cxPopup > cxScreen )
  759.          xPopup = cxScreen - cxPopup;
  760.  
  761.       /* adjust popup y-location for screen size */
  762.       if ( yPopup+cyPopup > cyScreen )
  763.          yPopup = cyScreen - cyPopup;
  764.  
  765.    } else {
  766.  
  767.       /* center within entire screen */
  768.       xPopup = (cxScreen - cxPopup) / 2;
  769.       yPopup = (cyScreen - cyPopup) / 2;
  770.  
  771.    }
  772.  
  773.    /* move window to new location & display */
  774.    MoveWindow(
  775.       hWnd,
  776.       ( xPopup > 0 ) ? xPopup : 0,
  777.       ( yPopup > 0 ) ? yPopup : 0,
  778.       cxPopup,
  779.       cyPopup,
  780.       TRUE
  781.    );
  782.  
  783.    /* normal return */
  784.    return( TRUE );
  785.  
  786. }
  787.  
  788.  
  789.