home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_12 / 2n12032b < prev    next >
Text File  |  1991-08-20  |  12KB  |  495 lines

  1. /**********************************************************
  2.            File Name: NTFY_BOX.C
  3.        Expanded Name: Notify Box
  4.          Description: Library of functions for displaying
  5.                       a notification box or window.  An
  6.                       important requirment to use these
  7.                       functions is too export the window
  8.                       callback function NotifyBoxProc.
  9.                       This function name must be added to
  10.                       the EXPORTS section of the linker
  11.                       definition file.
  12.         Program List: 
  13. Global Function List: NotifyBox
  14.                       NotifyBoxCreate
  15.                       NotifyBoxDestroy
  16.                       NotifyBoxProc
  17. Static Function List: get_num_notify_text_lines
  18.     Local Macro List: NOTIFY_BOX_WIDTH
  19.                       NOTIFY_BOX_MAX_NUM_LINES
  20.                       NOTIFY_BOX_WND_CLASS_NAME
  21.          Global Data: 
  22.          Static Data: g_lpText
  23.          Portability: MS Windows, Any memory model,
  24.                       Any windows compatable C Compiler
  25. **********************************************************/
  26.  
  27. /* MS Windows */
  28. #include <windows.h>
  29.  
  30. /* Own */
  31. #include <ntfy_box.h>
  32.  
  33. #define NOTIFY_BOX_WIDTH 40
  34. #define NOTIFY_BOX_MAX_NUM_LINES 20
  35. #define NOTIFY_BOX_WND_CLASS_NAME "NotifyWndClassName"
  36.  
  37. /* Prototype for window proc callback funciton */
  38. LONG FAR PASCAL NotifyBoxProc( HWND hWnd,
  39.         unsigned int iMessage, WORD wParam,
  40.         LONG lParam );
  41.  
  42. /* Prototypes for static functions */
  43. static int NEAR get_num_notify_text_lines( LPSTR lpText,
  44.         int Width );
  45.  
  46. /* Modual level global variables */
  47. static LPSTR g_lpText;
  48.  
  49. /* Multi modual global variables */
  50. extern HANDLE G_hInstance;
  51.  
  52. /**********************************************************
  53.        Name: NotifyBox
  54.  Parameters: hWndParent - handle of parent window
  55.              lpText - text to display in notify box
  56.              lpCaption - caption text for notify box
  57.      Return: zero if error
  58.              nonzero if notify box is created or destroyed
  59.              successfully
  60. Description: Creates and displays a notfiy box with the
  61.              specified text and caption.  The notify box
  62.              is displayed in the center of the parent
  63.              window.  If a notify box already exists, the
  64.              previous notify box is destroyed.
  65. **********************************************************/
  66. int FAR NotifyBox( HWND hWndParent, LPSTR lpText,
  67.         LPSTR lpCaption, HANDLE hInstanceParent )
  68.     {
  69.  
  70.     int status = TRUE;
  71.  
  72.     static HWND l_hWndNotify = NULL;
  73.  
  74.     if ( l_hWndNotify == NULL )
  75.         {
  76.  
  77.         l_hWndNotify = NotifyBoxCreate( hWndParent,
  78.                 lpText, lpCaption, hInstanceParent );
  79.  
  80.         if ( l_hWndNotify == NULL )
  81.             {
  82.             status = FALSE;
  83.             }
  84.  
  85.         }   /* if l_hWndNotify */
  86.     else
  87.         {
  88.  
  89.         status = NotifyBoxDestroy( l_hWndNotify );
  90.  
  91.         if ( status == TRUE )
  92.             {
  93.             l_hWndNotify = NULL;
  94.             }
  95.  
  96.         }   /* else */
  97.  
  98.     return ( status );
  99.  
  100.     }   /* function NotifyBox */
  101.  
  102.  
  103. /**********************************************************
  104.        Name: NotifyBoxCreate
  105.  Parameters: hWndParent - handle of parent window
  106.              lpText - text to display in notify box
  107.              lpCaption - caption text for notify box
  108.      Return: handle of notify box window (NULL if error)
  109. Description: Creates and displays a notfiy box with the
  110.              specified text and caption.  The notify box
  111.              is displayed in the center of the parent
  112.              window.
  113. **********************************************************/
  114. HWND FAR NotifyBoxCreate( HWND hWndParent, LPSTR lpText,
  115.         LPSTR lpCaption, HANDLE hInstanceParent )
  116.     {
  117.  
  118.     BOOL NullWndParentFlag = FALSE;
  119.  
  120.     HDC hDc;
  121.  
  122.     HWND hWndNotify;
  123.  
  124.     RECT Rect;
  125.  
  126.     short int
  127.         TextHeight,
  128.         TextWidth,
  129.         WindowWidth,
  130.         NumberOfLines,
  131.         WindowHeight,
  132.         WindowXPos,
  133.         WindowYPos;
  134.  
  135.     TEXTMETRIC TextMetrics;
  136.  
  137.     WNDCLASS WndClass;
  138.  
  139.     if ( hWndParent == NULL )
  140.         {
  141.  
  142.         /* Check for a valid instance handle */
  143.         if ( hInstanceParent == NULL )
  144.             {
  145.             MessageBox( hWndParent,
  146.                     "Invalid parent instance handle.\n"
  147.                     "Unable to create NotifyBox.",
  148.                     NULL,
  149.                     MB_OK | MB_ICONEXCLAMATION );
  150.             return ( FALSE );
  151.             }   /* if hInstanceParent */
  152.  
  153.         hWndParent = GetDesktopWindow();
  154.         NullWndParentFlag = TRUE;
  155.  
  156.         }   /* if hWndParent */
  157.     else
  158.         {
  159.         hInstanceParent =
  160.                 GetWindowWord( hWndParent,
  161.                 GWW_HINSTANCE );
  162.         }   /* else */
  163.  
  164.     /* Register the window class
  165.     ** Note registering is no big
  166.     ** deal - RegisterClass()
  167.     ** just fails. */
  168.     if ( NullWndParentFlag == TRUE )
  169.         {
  170.         WndClass.style = 0;
  171.         }
  172.     else
  173.         {
  174.         WndClass.style = CS_PARENTDC;
  175.         }
  176.     WndClass.lpfnWndProc  = NotifyBoxProc;
  177.     WndClass.cbClsExtra = 0;
  178.     WndClass.cbWndExtra = 0;
  179.     WndClass.hInstance = hInstanceParent;
  180.     WndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  181.     WndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
  182.     WndClass.hbrBackground = COLOR_WINDOW + 1;
  183.     WndClass.lpszMenuName = NULL;
  184.     WndClass.lpszClassName = NOTIFY_BOX_WND_CLASS_NAME;
  185.     RegisterClass( &WndClass );
  186.  
  187.     /* Calculate the required size of the window */
  188.     if ( hWndParent == NULL )
  189.         {
  190.         /* If there is no parent window use the windows
  191.         ** desktop */
  192.         hWndParent = GetDesktopWindow();
  193.         }
  194.     hDc = GetDC( hWndParent );
  195.     GetTextMetrics( hDc, &TextMetrics );
  196.     TextHeight = TextMetrics.tmHeight +
  197.             TextMetrics.tmExternalLeading;
  198.     TextWidth = TextMetrics.tmAveCharWidth;
  199.     WindowWidth = TextWidth * ( NOTIFY_BOX_WIDTH + 2 );
  200.     WindowWidth += 2 * GetSystemMetrics( SM_CXBORDER );
  201.     NumberOfLines = get_num_notify_text_lines( lpText,
  202.             NOTIFY_BOX_WIDTH );
  203.     WindowHeight = ( NumberOfLines + 2 ) * TextHeight;
  204.     WindowHeight += GetSystemMetrics( SM_CYCAPTION ) +
  205.             2 * GetSystemMetrics( SM_CYBORDER );
  206.     ReleaseDC( hWndParent, hDc );
  207.     
  208.     /* Calculate the location of the window */
  209.     GetWindowRect( hWndParent, &Rect );
  210.  
  211.     /* Calculate X position */
  212.     WindowXPos = Rect.left +
  213.             ( Rect.right - Rect.left ) / 2;
  214.     WindowXPos -= WindowWidth / 2;
  215.     if ( WindowXPos < 0 )
  216.         {
  217.         WindowXPos = 0;
  218.         }
  219.  
  220.     /* Calculate Y position */
  221.     WindowYPos = Rect.top +
  222.             ( Rect.bottom - Rect.top ) / 2;
  223.     WindowYPos -= WindowHeight / 2;
  224.     if ( WindowYPos < 0 )
  225.         {
  226.         WindowYPos = 0;
  227.         }
  228.  
  229.     if ( NullWndParentFlag == TRUE )
  230.         {
  231.         hWndParent = NULL;
  232.         }
  233.  
  234.     /* Create the window */
  235.     hWndNotify = CreateWindow(
  236.             NOTIFY_BOX_WND_CLASS_NAME,
  237.             lpCaption,
  238.             WS_OVERLAPPED | WS_BORDER,
  239.             WindowXPos,
  240.             WindowYPos,
  241.             WindowWidth,
  242.             WindowHeight,
  243.             hWndParent,
  244.             NULL,
  245.             hInstanceParent,
  246.             NULL );
  247.  
  248.     if ( hWndNotify != NULL )
  249.         {
  250.  
  251.         hDc = GetDC( hWndNotify );
  252.  
  253.         /* Set the colors of the text. */
  254.         SetTextColor( hDc,
  255.                 GetSysColor( COLOR_WINDOWTEXT ) );
  256.         SetBkColor( hDc,
  257.                 GetSysColor( COLOR_WINDOW ) );
  258.  
  259.         /* Copy text pointer into static data
  260.         ** to pass it into the window proc */
  261.         g_lpText = lpText;
  262.  
  263.         /* Display and paint the window */
  264.         ShowWindow( hWndNotify, SW_SHOW );
  265.         UpdateWindow( hWndNotify );
  266.  
  267.         ReleaseDC( hWndNotify, hDc );
  268.  
  269.         }   /* if hWndNotify */
  270.  
  271.     return ( hWndNotify );
  272.  
  273.     }   /* function NotifyBoxCreate */
  274.  
  275.  
  276. /**********************************************************
  277.        Name: NotifyBoxDestroy
  278.  Parameters: hWndNotify - handle of notify box window to
  279.              destroy
  280.      Return: nonzero - notify box window was NULL or
  281.              successfully destroyed
  282.              zero - notify box was not destroyed
  283. Description: Removes a notify box window from the display.
  284. **********************************************************/
  285. BOOL FAR NotifyBoxDestroy( HWND hWndNotify )
  286.     {
  287.  
  288.     if ( hWndNotify != NULL )
  289.         {
  290.         return ( DestroyWindow( hWndNotify ) );
  291.         }
  292.  
  293.     return ( TRUE );
  294.  
  295.     }    /* function NotifyBoxDestroy */
  296.  
  297.  
  298. /**********************************************************
  299.        Name: NotfifyBoxProc
  300.  Parameters: hWndNotify 
  301.      Return: 
  302. Description: Windows callback function.
  303. **********************************************************/
  304. LONG FAR PASCAL NotifyBoxProc( HWND hWnd,
  305.         unsigned int iMessage, WORD wParam,
  306.         LONG lParam )
  307.     {
  308.     
  309.     if ( iMessage == WM_PAINT )
  310.         {
  311.  
  312.         BOOL FinishedFlag = FALSE;
  313.  
  314.         int
  315.             Char,
  316.             Line;
  317.  
  318.         char Buffer[NOTIFY_BOX_WIDTH + 1];
  319.  
  320.         LPSTR lpCurrent;
  321.  
  322.         PAINTSTRUCT PaintStruct;
  323.  
  324.         TEXTMETRIC TextMetrics;
  325.  
  326.         lpCurrent = g_lpText;
  327.  
  328.         BeginPaint( hWnd, &PaintStruct );
  329.  
  330.         GetTextMetrics( PaintStruct.hdc, &TextMetrics );
  331.  
  332.         /* Set the colors of the text to defaults. */
  333.         SetTextColor( PaintStruct.hdc,
  334.                 GetSysColor( COLOR_WINDOWTEXT ) );
  335.         SetBkColor( PaintStruct.hdc,
  336.                 GetSysColor( COLOR_WINDOW ) );
  337.  
  338.         /* Print out the text line by line */
  339.         for ( Line = 0; Line < NOTIFY_BOX_MAX_NUM_LINES;
  340.                 Line++ )
  341.             {
  342.  
  343.             for ( Char = 0; Char < NOTIFY_BOX_WIDTH;
  344.                     Char++ )
  345.                 {
  346.  
  347.                 if ( ( lpCurrent[Char] == '\n' ) ||
  348.                         ( lpCurrent[Char] == '\0' ) )
  349.                     {
  350.                     Buffer[Char] = '\0';
  351.                     if ( lpCurrent[Char] == '\0' )
  352.                         {
  353.                         /* Hit end of string */
  354.                         FinishedFlag = TRUE;
  355.                         }
  356.                     lpCurrent = &lpCurrent[Char + 1];
  357.                     break;
  358.                     }
  359.  
  360.                 Buffer[Char] = lpCurrent[Char];
  361.  
  362.                 }   /* for Char */
  363.  
  364.             if ( Char == NOTIFY_BOX_WIDTH )
  365.                 {
  366.                 /* Do word wrap */
  367.                 for ( ; Char >= 0; Char-- )
  368.                     {
  369.                     if ( lpCurrent[Char] == ' ' )
  370.                         {
  371.                         Buffer[Char] = '\0';
  372.                         lpCurrent =
  373.                                 &lpCurrent[Char + 1];
  374.                         break;
  375.                         }   /* if lpCurrent */
  376.                     }   /* for */
  377.                 }   /* if Char */
  378.  
  379.             if ( Char == -1 )
  380.                 {
  381.                 /* Failure could not word wrap */
  382.                 return ( 0L );
  383.                 }
  384.             else
  385.                 {
  386.  
  387.                 int Row;
  388.  
  389.                 /* Print out the text */
  390.  
  391.                 Row = ( Line + 1 ) *
  392.                         ( TextMetrics.tmHeight +
  393.                         TextMetrics.tmExternalLeading );
  394.  
  395.                 TextOut( PaintStruct.hdc,
  396.                         2 * TextMetrics.tmAveCharWidth,
  397.                         Row, Buffer,
  398.                         (int)lstrlen( Buffer ) );
  399.  
  400.                 }   /* else */
  401.  
  402.             if ( FinishedFlag == TRUE )
  403.                 {
  404.                 break;
  405.                 }
  406.  
  407.             }   /* for Line */
  408.  
  409.         return ( 0L );
  410.  
  411.         }   /* if iMessage */
  412.  
  413.     return ( DefWindowProc( hWnd, iMessage, wParam,
  414.             lParam ) );
  415.  
  416.     }   /* function NotifyBoxProc */
  417.  
  418.  
  419. /**********************************************************
  420.        Name: get_num_notify_text_lines
  421.  Parameters: lpText - text to process
  422.              Width - maximum number of characters in a line
  423.      Return: The number of lines or -1 if error.
  424. Description: Does simple word wrap of text and calculates
  425.              the number of lines that fit in a window of
  426.              specified width in characters.
  427. **********************************************************/
  428. static int NEAR get_num_notify_text_lines( LPSTR lpText,
  429.         int Width )
  430.     {
  431.  
  432.     LPSTR lpCurrent;
  433.  
  434.     int
  435.         Char,
  436.         Line;
  437.         
  438.     if ( ( lpText == NULL ) || ( *lpText == '\0' ) )
  439.         {
  440.         /* Bad input string */
  441.         return ( 0 );
  442.         }
  443.  
  444.     lpCurrent = lpText;
  445.  
  446.     for ( Line = 0; Line < NOTIFY_BOX_MAX_NUM_LINES;
  447.             Line++ )
  448.         {
  449.  
  450.         for ( Char = 0; Char < Width; Char++ )
  451.             {
  452.  
  453.             if ( lpCurrent[Char] == '\0' )
  454.                 {
  455.                 /* Hit the end of the string */
  456.                 return ( Line + 1 );
  457.                 }
  458.  
  459.             if ( lpCurrent[Char] == '\n' )
  460.                 {
  461.                 /* Hit a new line */
  462.                 lpCurrent = &lpCurrent[Char + 1];
  463.                 break;
  464.                 }
  465.  
  466.             }   /* for Char */
  467.  
  468.         if ( Char == Width )
  469.             {
  470.  
  471.             /* Exceeded the maximum width
  472.             ** search backwards for a space. */
  473.             for ( ; Char >= 0; Char-- )
  474.                 {
  475.                 if ( lpCurrent[Char] == ' ' )
  476.                     {
  477.                     lpCurrent = &lpCurrent[Char + 1];
  478.                     break;
  479.                     }
  480.                 }
  481.  
  482.             if ( Char == -1 )
  483.                 {
  484.                 /* Failure - no space found */
  485.                 return ( -1 );
  486.                 }
  487.  
  488.             }   /* if Char */
  489.  
  490.         }   /* for Line */
  491.  
  492.     return ( Line );
  493.  
  494.     }   /* function get_num_notify_text_lines */
  495.