home *** CD-ROM | disk | FTP | other *** search
/ Windoware / WINDOWARE_1_6.iso / source / winfern / winfern.c < prev    next >
C/C++ Source or Header  |  1991-04-22  |  20KB  |  684 lines

  1. /*
  2. ╔════════════════════════════════════════════════════════════════════════════╗
  3. ║                                                                            ║
  4. ║  Product:     Fractal Fern Generator                                       ║
  5. ║  Version:     1.0                                                          ║
  6. ║                                                                            ║
  7. ║  Source:      WINFERN.C                                                    ║
  8. ║  Revison:     1.0                                                          ║
  9. ║  Description: Fractal Fern Generator based on code from the "Fractal       ║
  10. ║               Programming in C" book by a very qualified author            ║
  11. ║               (who's name I don't remember since I wrote this a year ago   ║
  12. ║               and have since packed the book away somewhere)               ║
  13. ║  Group:       Generator code                                               ║
  14. ║                                                                            ║
  15. ║  Author:      René Schuchter, TouchGo(tm) Studios                          ║
  16. ║                                                                            ║
  17. ║  Date:        April 22, 1991  (BBS version)                                ║
  18. ║                                                                            ║
  19. ║  This code is placed in the public domain. Any issues of copyright related ║
  20. ║  to using these examples from "Fractals Prograamming in C" for commercial  ║
  21. ║  or other purposes is the sole responsibility of the person using this     ║
  22. ║  code.                                                                     ║
  23. ║                                                                            ║
  24. ║  This notice MUST remain with any versions of this code ditributed on a    ║
  25. ║  BBS.                                                                      ║
  26. ║                                                                            ║
  27. ║  The folowing files should be included with any distributed version:       ║
  28. ║                                                                            ║
  29. ║     WINFERN.EXE                                                            ║
  30. ║     WINFERN.C                                                              ║
  31. ║     WINFERN.H                                                              ║
  32. ║     WINFERN.RC                                                             ║
  33. ║     WINFERN.DEF                                                            ║
  34. ║     WINFERN.ICO                                                            ║
  35. ║     WFABOUT.BMP                                                            ║
  36. ║     WFABOUT.RL4  (4 bpp RLE of original BMP )                              ║
  37. ║     WINFERN                                                                ║
  38. ║                                                                            ║
  39. ║  For any questions or comments I can be reached at (916) 739-0100.         ║
  40. ║                                                                            ║
  41. ╚════════════════════════════════════════════════════════════════════════════╝
  42. */
  43.  
  44. #include <windows.h>
  45. #include <stdlib.h>
  46. #include <math.h>
  47. #include "winfern.h"
  48.  
  49. char   szAppName[] = "Fractal Fern Generator v1.0",
  50.        szMsg[ 256 ];
  51. DWORD  dwFernColors[ 4 ] = { RGB( 255,   0,   0 ),
  52.                              RGB(   0, 255,   0 ),
  53.                              RGB(   0,   0, 255 ),
  54.                              RGB( 255, 255,   0 ) };
  55. HANDLE hInst;
  56. HWND   hWndAbout;
  57.  
  58. int PASCAL WinMain(
  59.    HANDLE hInstance,
  60.    HANDLE hPrevInstance,
  61.    LPSTR  lpszCmdLine,
  62.    int    nCmdShow )
  63. {
  64.    HWND     hWnd;
  65.    MSG      msg;
  66.    WNDCLASS wndclass;
  67.  
  68.    if ( hPrevInstance )
  69.  
  70.       return FALSE;
  71.  
  72.    hInst = hInstance;
  73.  
  74.    wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  75.    wndclass.lpfnWndProc   = WndProc;
  76.    wndclass.cbClsExtra    = 0;
  77.    wndclass.cbWndExtra    = 0;
  78.    wndclass.hInstance     = hInst;
  79.    wndclass.hIcon         = LoadIcon( hInst, "WFIcon" );
  80.    wndclass.hCursor       = LoadCursor( NULL, IDC_ARROW );
  81.    wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
  82.    wndclass.lpszMenuName  = (LPSTR)"WFMenu";
  83.    wndclass.lpszClassName = szAppName;
  84.  
  85.    if ( !RegisterClass( &wndclass ) )
  86.  
  87.       return FALSE;
  88.  
  89.    wndclass.lpfnWndProc   = AboutWndProc;
  90.    wndclass.hIcon         = NULL;
  91.    wndclass.hCursor       = LoadCursor( NULL, IDC_ARROW );
  92.    wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
  93.    wndclass.lpszMenuName  = NULL;
  94.    wndclass.lpszClassName = "ABOUTCLASS";
  95.  
  96.    if ( !RegisterClass( &wndclass ) )
  97.  
  98.       return FALSE;
  99.  
  100.    hWnd = CreateWindow( szAppName,  /* Class */
  101.                         szAppName,  /* Title */
  102.                         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  103.                         CW_USEDEFAULT,
  104.                         0,
  105.                         CW_USEDEFAULT,
  106.                         0,
  107.                         NULL,
  108.                         NULL,
  109.                         hInst,
  110.                         NULL );
  111.  
  112.    ShowWindow( hWnd, nCmdShow );
  113.  
  114.    UpdateWindow( hWnd );
  115.  
  116.    while ( GetMessage( &msg, NULL, 0, 0 ) )
  117.    {
  118.       TranslateMessage( &msg );
  119.  
  120.       DispatchMessage( &msg );
  121.    }
  122.  
  123.    return msg.wParam;
  124. }
  125.  
  126. long FAR PASCAL WndProc(
  127.    HWND hWnd,
  128.    WORD wMessage,
  129.    WORD wParam,
  130.    LONG lParam )
  131. {
  132.    HDC         hDC;
  133.    PAINTSTRUCT ps;
  134.  
  135.    switch ( wMessage )
  136.    {
  137.       case WM_COMMAND:
  138.  
  139.          switch ( wParam )
  140.          {
  141.             case IDM_DRAW:
  142.  
  143.                InvalidateRect( hWnd, NULL, TRUE );
  144.  
  145.                UpdateWindow( hWnd );
  146.  
  147.                DrawFern( hWnd, RGB( 255, 0, 0 ) );
  148.                
  149.                break;
  150.  
  151.             case IDM_DRAW3D:
  152.  
  153.                InvalidateRect( hWnd, NULL, TRUE );
  154.  
  155.                UpdateWindow( hWnd );
  156.  
  157.                Draw3DFern( hWnd, 4, dwFernColors );
  158.                
  159.                break;
  160.  
  161.             case IDM_ABOUT:
  162.  
  163.                About( hWnd );
  164.  
  165.                break;
  166.          }
  167.  
  168.          break;
  169.  
  170.       case WM_PAINT:
  171.  
  172.          hDC = BeginPaint( hWnd, &ps );
  173.  
  174.          EndPaint( hWnd, &ps );
  175.  
  176.          break;
  177.  
  178.       case WM_DESTROY:
  179.  
  180.          PostQuitMessage( 0 );
  181.  
  182.          break;
  183.  
  184.       default:
  185.  
  186.          return DefWindowProc( hWnd, wMessage, wParam, lParam );
  187.    }
  188.  
  189.    return 0L;
  190. }
  191.  
  192. void NEAR PASCAL DrawFern(
  193.    HWND  hWnd,
  194.    DWORD dwColor )
  195. {
  196.    double  a[ 4 ],
  197.            b[ 4 ],
  198.            c[ 4 ],
  199.            d[ 4 ],
  200.            e[ 4 ],
  201.            f[ 4 ],
  202.            newx,
  203.            dXScreenVGARatio,
  204.            dYScreenVGARatio,
  205.            x,
  206.            y;
  207.    HCURSOR hCursor;
  208.    HDC     hDC;
  209.    int     i,
  210.            j,
  211.            k,
  212.            nClientWidth,
  213.            nClientHeight,
  214.            nXScreenSize,
  215.            nYScreenSize,
  216.            p[ 4 ],
  217.            px,
  218.            py,
  219.            xoffset,
  220.            xscale,
  221.            yoffset,
  222.            yscale;
  223.    RECT    rRect;
  224.  
  225.    /* constants optimized for VGA
  226.    */
  227.  
  228.    #define convert(x,y)   {x = (x + 319);  y = (175 - ((93*y) >> 7));}
  229.  
  230.    hCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  231.  
  232.    a[0] = (double)0.0;  a[1] = (double) 0.2;  a[2] = (double)-0.15; a[3] = (double) 0.85;
  233.    b[0] = (double)0.0;  b[1] = (double)-0.26; b[2] = (double) 0.28; b[3] = (double) 0.04;
  234.    c[0] = (double)0.0;  c[1] = (double) 0.23; c[2] = (double) 0.26; c[3] = (double)-0.04;
  235.  
  236.    d[0] = (double)0.16; d[1] = (double) 0.22; d[2] = (double) 0.24; d[3] = (double) 0.85;
  237.    e[0] = (double)0.0;  e[1] = (double) 0.0;  e[2] = (double) 0.0;  e[3] = (double) 0.0;
  238.    f[0] = (double)0.0;  f[1] = (double) 0.2;  f[2] = (double) 0.2;  f[3] = (double) 0.2;
  239.  
  240.    p[0] = 328;  p[1] = 2621;  p[2] = 4915;
  241.  
  242.    GetClientRect( hWnd, &rRect );
  243.  
  244.    nClientWidth  = rRect.right  - rRect.left + 1;
  245.    nClientHeight = rRect.bottom - rRect.top  + 1;
  246.  
  247.    nXScreenSize = GetSystemMetrics( SM_CXSCREEN );
  248.    nYScreenSize = GetSystemMetrics( SM_CYSCREEN );
  249.  
  250.    dXScreenVGARatio = (double)nXScreenSize / (double)640;
  251.    dYScreenVGARatio = (double)nYScreenSize / (double)480;
  252.  
  253.    xscale = (int)( (double)300 * dXScreenVGARatio );
  254.    yscale = (int)( (double)300 * dYScreenVGARatio );
  255.  
  256.    xoffset = (int)( (double) -50 * dXScreenVGARatio );
  257.    yoffset = (int)( (double)-180 * dYScreenVGARatio );
  258.  
  259.    x = (double)0.0;
  260.    y = (double)0.0;
  261.  
  262.    /* image offset for centering optimzed manually for VGA
  263.       so adjust offset constants ( 16 and 6 ) for screen size
  264.    */
  265.  
  266.    hDC = GetDC( hWnd );
  267.  
  268.    SetMapMode( hDC, MM_ANISOTROPIC );
  269.  
  270.    SetWindowOrg( hDC, -(int)( (double)( nXScreenSize / 16 ) *
  271.                        pow( (double)dXScreenVGARatio, (double)2.0 ) ),
  272.                       -(int)( (double)( nYScreenSize /  6 ) *
  273.                        pow( (double)dYScreenVGARatio, (double)2.0 ) ) );
  274.  
  275.    SetWindowExt( hDC, nXScreenSize, nYScreenSize );
  276.  
  277.    SetViewportExt( hDC, nClientWidth, nClientHeight );
  278.  
  279.    for ( i = 1; i <= 10000; i++ )
  280.    {
  281.       j = rand();
  282.  
  283.       k = ( j < p[0] ) ? 0 : ( ( j < p[1] ) ? 1 : ( ( j < p[2] ) ? 2 : 3 ) );
  284.  
  285.       newx = ( ( a[k] * x ) + ( b[k] * y ) + e[k] );
  286.  
  287.       y = ( ( c[k] * x ) + ( d[k] * y ) + f[k] );
  288.  
  289.       x = newx;
  290.  
  291.       px = (int)( x * (double)xscale ) + xoffset;
  292.  
  293.       py = (int)( y * (double)yscale ) + yoffset;
  294.  
  295.       if ( ( px >= -( nXScreenSize / 2 ) ) &&
  296.            ( px < ( nXScreenSize / 2 ) )   &&
  297.            ( py >= -( nYScreenSize / 2 ) ) &&
  298.            ( py < ( nYScreenSize / 2 ) ) )
  299.       {
  300.          convert( px, py);
  301.  
  302.          SetPixel( hDC, px, py, dwColor );
  303.       }
  304.    }
  305.  
  306.    ReleaseDC( hWnd, hDC );
  307.  
  308.    SetCursor( hCursor );
  309. }
  310.  
  311. void NEAR PASCAL Draw3DFern(
  312.    HWND  hWnd,
  313.    int   nFernCount,
  314.    DWORD *dwColor )
  315. {
  316.    #define MAX_FERN_COUNT 4
  317.  
  318.    static double alpha[ MAX_FERN_COUNT ] = { (double)30.0,
  319.                                              (double)45.0,
  320.                                              (double)15.0,
  321.                                              (double)95.0 },
  322.                  beta[ MAX_FERN_COUNT ] =  { (double)115.0,
  323.                                              (double)105.0,
  324.                                              (double)70.0,
  325.                                              (double)40.0 },
  326.                  gamma[ MAX_FERN_COUNT ] = { (double)25.0,
  327.                                              (double)70.0,
  328.                                              (double)20.0,
  329.                                              (double)-30.0 };
  330.  
  331.    double  a[ 4 ],
  332.            b[ 4 ],
  333.            c[ 4 ],
  334.            d[ 4 ],
  335.            e[ 4 ],
  336.            f[ 4 ],
  337.            g[ 4 ],
  338.            h[ 4 ],
  339.            m[ 4 ],
  340.            n[ 4 ],
  341.            q[ 4 ],
  342.            r[ 4 ],
  343.            ca,
  344.            cb,
  345.            cg,
  346.            sa,
  347.            sb,
  348.            sg,
  349.            x,
  350.            y,
  351.            z,
  352.            dXScreenVGARatio,
  353.            dYScreenVGARatio,
  354.            newx,
  355.            newy,
  356.            vx,
  357.            vy;
  358.    HCURSOR hCursor;
  359.    HDC     hDC;
  360.    int     i,
  361.            j,
  362.            k,
  363.            index,
  364.            nClientWidth,
  365.            nClientHeight,
  366.            nXScreenSize,
  367.            nYScreenSize,
  368.            xscale,
  369.            yscale,
  370.            xoffset,
  371.            yoffset,
  372.            p[ 4 ],
  373.            px,
  374.            py;
  375.    RECT    rRect;
  376.             
  377.    /* constants optimized for VGA
  378.    */
  379.  
  380.    #define convert(x,y)   {x = (x + 319);  y = (175 - ((93*y) >> 7));}
  381.  
  382.    hCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  383.  
  384.    a[0] = (double)0.0;  a[1] = (double) 0.83; a[2] = (double) 0.22;  a[3] = (double)-0.22;
  385.    b[0] = (double)0.0;  b[1] = (double) 0.0;  b[2] = (double)-0.023; b[3] = (double) 0.23;
  386.    c[0] = (double)0.0;  c[1] = (double) 0.0;  c[2] = (double) 0.0;   c[3] = (double) 0.0;
  387.    d[0] = (double)0.0;  d[1] = (double) 0.0;  d[2] = (double) 0.24;  d[3] = (double) 0.24;
  388.    e[0] = (double)0.18; e[1] = (double) 0.86; e[2] = (double) 0.22;  e[3] = (double) 0.22;
  389.    f[0] = (double)0.0;  f[1] = (double) 0.1;  f[2] = (double) 0.0;   f[3] = (double) 0.0;
  390.    g[0] = (double)0.0;  g[1] = (double) 0.0;  g[2] = (double) 0.0;   g[3] = (double) 0.0;
  391.    h[0] = (double)0.0;  h[1] = (double)-0.12; h[2] = (double) 0.0;   h[3] = (double) 0.0;
  392.    m[0] = (double)0.0;  m[1] = (double) 0.84; m[2] = (double) 0.32;  m[3] = (double) 0.32;
  393.    n[0] = (double)0.0;  n[1] = (double) 0.0;  n[2] = (double) 0.0;   n[3] = (double) 0.0;
  394.    q[0] = (double)0.0;  q[1] = (double) 1.62; q[2] = (double) 0.82;  q[3] = (double) 0.82;
  395.    r[0] = (double)0.0;  r[1] = (double) 0.0;  r[2] = (double) 0.0;   r[3] = (double) 0.0;
  396.  
  397.    p[0] = 328; p[1] = 27879 ; p[2] = 30173;
  398.  
  399.    GetClientRect( hWnd, &rRect );
  400.  
  401.    nClientWidth  = rRect.right  - rRect.left + 1;
  402.    nClientHeight = rRect.bottom - rRect.top  + 1;
  403.  
  404.    nXScreenSize = GetSystemMetrics( SM_CXSCREEN );
  405.    nYScreenSize = GetSystemMetrics( SM_CYSCREEN );
  406.  
  407.    dXScreenVGARatio = (double)nXScreenSize / (double)640;
  408.    dYScreenVGARatio = (double)nYScreenSize / (double)480;
  409.  
  410.    xscale = (int)( (double)40 * dXScreenVGARatio );
  411.    yscale = (int)( (double)50 * dYScreenVGARatio );
  412.  
  413.    xoffset = (int)( (double)  60 * dXScreenVGARatio );
  414.    yoffset = (int)( (double)-180 * dYScreenVGARatio );
  415.  
  416.    /* image offset for centering optimzed manually for VGA
  417.       so adjust offset constants ( 16 and 6 ) for screen size
  418.    */
  419.  
  420.    hDC = GetDC( hWnd );
  421.  
  422.    SetMapMode( hDC, MM_ANISOTROPIC );
  423.  
  424.    SetWindowOrg( hDC, -(int)( (double)( nXScreenSize / 16 ) *
  425.                        pow( (double)dXScreenVGARatio, (double)2.0 ) ),
  426.                       -(int)( (double)( nYScreenSize /  6 ) *
  427.                        pow( (double)dYScreenVGARatio, (double)2.0 ) ) );
  428.  
  429.    SetWindowExt( hDC, nXScreenSize, nYScreenSize );
  430.  
  431.    SetViewportExt( hDC, nClientWidth, nClientHeight );
  432.  
  433.    for ( index = 0; index < nFernCount && index < MAX_FERN_COUNT; index++ )
  434.    {
  435.       ca = cos( alpha[ index ] * (double)0.0174533 );
  436.       cb = cos( beta[ index ]  * (double)0.0174533 );
  437.       cg = cos( gamma[ index ] * (double)0.0174533 );
  438.       sa = sin( alpha[ index ] * (double)0.0174533 );
  439.       sb = sin( beta[ index ]  * (double)0.0174533 );
  440.       sg = sin( gamma[ index ] * (double)0.0174533 );
  441.  
  442.       x = (double)0.0;
  443.       y = (double)0.0;
  444.       z = (double)0.0;
  445.  
  446.       for ( i = 1; i <= 10000; i++ )
  447.       {
  448.          j = rand();
  449.  
  450.          k = ( j < p[0] ) ? 0 : ( ( j < p[1] ) ? 1 : ( ( j < p[2] ) ? 2 : 3 ) );
  451.  
  452.          newx = ( a[k] * x ) + ( b[k] * y ) + ( c[k] * z ) + n[k];
  453.          newy = ( d[k] * x ) + ( e[k] * y ) + ( f[k] * z ) + q[k];
  454.  
  455.          z = g[k] * x + h[k] * y + m[k] * z + r[k];
  456.  
  457.          x = newx;
  458.          y = newy;
  459.  
  460.          vx = ( x * ca ) + ( y * cb ) + ( z * cg );
  461.  
  462.          px = (int)( ( vx * (double)xscale ) + (double)xoffset );
  463.  
  464.          vy = ( x * sa ) + ( y * sb ) + ( z * sg );
  465.  
  466.          py = (int)( ( vy * (double)yscale ) + (double)yoffset );
  467.  
  468.          if ( ( px >= -( nXScreenSize / 2 ) ) &&
  469.               ( px < ( nXScreenSize / 2 ) )   &&
  470.               ( py >= -( nYScreenSize / 2 ) ) &&
  471.               ( py < ( nYScreenSize / 2 ) ) )
  472.          {
  473.             convert( px, py );
  474.  
  475.             SetPixel( hDC, px, py, dwColor[ index ] );
  476.          }
  477.       }
  478.    }
  479.  
  480.    ReleaseDC( hWnd, hDC );
  481.  
  482.    SetCursor( hCursor );
  483. }
  484.  
  485. BOOL NEAR PASCAL About(
  486.    HWND hWndParent )
  487. {
  488.    BITMAP  Bitmap;
  489.    char    szAboutName[ MAXIMAGENAMELEN + 1 ];
  490.    HBITMAP hbmAboutImage;
  491.    int     nAboutHeight,
  492.            nAboutWidth;
  493.    POINT   ptAbout;
  494.    RECT    rRectClient;
  495.  
  496.    if ( hWndAbout )
  497.  
  498.       return TRUE;
  499.  
  500.    lstrcpy( szAboutName, "ABOUT" );
  501.  
  502.    if ( NULL == ( hbmAboutImage = LoadBitmap( hInst, szAboutName ) ) )
  503.    {
  504.       MessageBox( hWndParent, "Could not load about image", szAppName, MB_OK );
  505.  
  506.       return FALSE;
  507.    }
  508.  
  509.    GetObject( hbmAboutImage, 16, (LPSTR)&Bitmap);
  510.  
  511.    DeleteObject( hbmAboutImage );
  512.  
  513.    nAboutWidth  = Bitmap.bmWidth + 2;
  514.    nAboutHeight = Bitmap.bmHeight + 2 + GetSystemMetrics( SM_CYCAPTION );
  515.  
  516.    GetClientRect( hWndParent, &rRectClient );
  517.  
  518.    ptAbout.x = ( ( rRectClient.right  - rRectClient.left + 1 ) / 2 ) -
  519.                ( nAboutWidth  / 2 );
  520.  
  521.    ptAbout.y = ( ( rRectClient.bottom - rRectClient.top  + 1 ) / 2 ) -
  522.                ( nAboutHeight / 2 );
  523.  
  524.    ptAbout.x    = max( ptAbout.x,    0 );
  525.    ptAbout.y    = max( ptAbout.y,    0 );
  526.    nAboutWidth  = max( nAboutWidth,  0 );
  527.    nAboutHeight = max( nAboutHeight, 0 );
  528.  
  529.    hWndAbout = CreateWindow( "ABOUTCLASS",
  530.                              "About Fractal Fern Generator",
  531.                              WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_VISIBLE,
  532.                              ptAbout.x,
  533.                              ptAbout.y,
  534.                              nAboutWidth,
  535.                              nAboutHeight,
  536.                              hWndParent,
  537.                              NULL,
  538.                              hInst,
  539.                              NULL );
  540.  
  541.    if ( !hWndAbout )
  542.    {
  543.       MessageBox( hWndParent, "Could not create about window", szAppName, MB_OK );
  544.  
  545.          return FALSE;
  546.    }
  547.  
  548.    return TRUE;
  549. }
  550.  
  551. long FAR PASCAL AboutWndProc(
  552.    HWND hWnd,
  553.    WORD wMessage,
  554.    WORD wParam,
  555.    LONG lParam )
  556. {
  557.    static BOOL    bOkButtonShowing = FALSE;
  558.    static char    szAboutName[ MAXIMAGENAMELEN + 1 ],
  559.                   szOKText[ 4 ] = "&OK";
  560.    static HWND    hBtnAbout;
  561.  
  562.    BITMAP         Bitmap;
  563.    BOOL           bShowImage;
  564.    HBITMAP        hbmAboutImage,
  565.                   hbmOld;
  566.    HDC            hDC,
  567.                   hDCMem;
  568.    PAINTSTRUCT    ps;
  569.  
  570.    switch ( wMessage )
  571.    {
  572.       case WM_CREATE:
  573.  
  574.          lstrcpy( szAboutName, "ABOUT" );
  575.  
  576.          bOkButtonShowing = FALSE;
  577.  
  578.          break;
  579.  
  580.       case WM_PAINT:
  581.  
  582.          hDC = BeginPaint( hWnd, &ps );
  583.  
  584.          if ( NULL == ( hbmAboutImage = LoadBitmap( hInst, szAboutName ) ) )
  585.          {
  586.             bShowImage = FALSE;
  587.  
  588.             MessageBox( hWnd, "Could not load about image", szAppName, MB_OK );
  589.          }
  590.          else
  591.          {
  592.             bShowImage = TRUE;
  593.  
  594.             hDCMem = CreateCompatibleDC( hDC );
  595.  
  596.             hbmOld = SelectObject( hDCMem, hbmAboutImage );
  597.  
  598.             GetObject( hbmAboutImage, 16, (LPSTR)&Bitmap);
  599.  
  600.             BitBlt( hDC,
  601.                     0,
  602.                     0,
  603.                     Bitmap.bmWidth,
  604.                     Bitmap.bmHeight, 
  605.                     hDCMem,
  606.                     0,
  607.                     0,
  608.                     SRCCOPY );
  609.  
  610.             SelectObject( hDCMem, hbmOld );
  611.  
  612.             DeleteDC( hDCMem );
  613.  
  614.             DeleteObject( hbmAboutImage );
  615.  
  616.             if ( !bOkButtonShowing )
  617.             {
  618.                hBtnAbout = CreateWindow( "button",
  619.                                          szOKText,
  620.                                          WS_CHILD | WS_VISIBLE,
  621.                                          309,
  622.                                          284,
  623.                                          100,
  624.                                          34,
  625.                                          hWnd,
  626.                                          IDC_ABOUTOK,
  627.                                          hInst,
  628.                                          NULL );
  629.  
  630.                SetFocus( hBtnAbout );
  631.  
  632.                bOkButtonShowing = TRUE;
  633.             }
  634.             else
  635.  
  636.                SetFocus( hBtnAbout );
  637.          }
  638.  
  639.          EndPaint( hWnd, &ps );
  640.  
  641.          break;
  642.  
  643.       case WM_COMMAND:
  644.  
  645.          switch ( wParam )
  646.          {
  647.             case IDC_ABOUTOK:
  648.  
  649.                PostMessage( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L );
  650.  
  651.                break;
  652.          }
  653.  
  654.          if ( hBtnAbout )
  655.  
  656.             SetFocus( hBtnAbout );
  657.  
  658.          break;
  659.  
  660.       case WM_DESTROY:
  661.  
  662.          if ( hBtnAbout )
  663.          {
  664.             DestroyWindow( hBtnAbout );
  665.  
  666.             hBtnAbout = 0;
  667.  
  668.             bOkButtonShowing = FALSE;
  669.          }
  670.  
  671.          hWndAbout = 0;
  672.  
  673.          break;
  674.  
  675.       default:
  676.  
  677.          return DefWindowProc( hWnd, wMessage, wParam, lParam );
  678.    }
  679.  
  680.    return 0L;
  681. }
  682.  
  683.  
  684.