home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 4.ddi / TDWEXMPL.ZIP / BCWDEMO.C next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  15.0 KB  |  528 lines

  1. /**********************************************************************
  2.  *          Copyright (c) 1992 by Borland International, Inc.         *
  3.  *                                                                    *
  4.  *                            BCWDEMO.C                               *
  5.  *                                                                    *
  6.  *  This program demonstrates how to write a simple Microsoft Windows *
  7.  *  graphics program in Borland C++.  It's called Simple Paint and    *
  8.  *  provides three objects the user can draw, a line, an ellipse,     *
  9.  *  and a rectangle.  Simple Paint also provides the user with        *
  10.  *  three choices of line thicknesses and three choices of colors:    *
  11.  *  red, green, and black.                                            *
  12.  **********************************************************************/
  13.  
  14. #define STRICT
  15.  
  16. #include <windows.h>
  17. #include "bcwdemo.h"
  18.  
  19. /*****************************************************
  20.  * FUNCTION PROTOTYPES
  21.  *****************************************************/
  22.  
  23. /*
  24.  * DoWMCommand processes WM_COMMAND messages.  WM_COMMAND
  25.  * is generated when the user selects something from the menu.
  26.  */
  27. int DoWMCommand(WORD wParam, HWND hWnd);
  28.  
  29. /*
  30.  * DoLButtonDown process WM_LBUTTONDOWN messages.  WM_LBUTTONDOWN
  31.  * is generated when the user presses the left mouse button.
  32.  */
  33. void DoLButtonDown(HWND hWnd,LONG lParam);
  34.  
  35. /*
  36.  * DoLButtonUp processes WM_LBUTTONUP messages.  WM_LBUTTONUP
  37.  * is generated when the user releases the left mouse button.
  38.  */
  39. void DoLButtonUp(HWND hWnd,LONG lParam);
  40.  
  41. /*
  42.  * DoMouseMove processes WM_MOUSEMOVE messages.  WM_MOUSEMOVE
  43.  * is generated when the user moves the mouse.
  44.  */
  45. void DoMouseMove(HWND hWnd,LONG lParam);
  46.  
  47. /*
  48.  * DoPaint processes WM_PAINT messages.  WM_PAINT is generated
  49.  * whenever UpdateWindow is called or another window is moved,
  50.  * revealing a portion of the window receiving this message.
  51.  */
  52. void DoPaint(HWND hWnd);
  53.  
  54. /*
  55.  * WndProc is the callback function (window proc)
  56.  * for the Simple Paint class of windows.
  57.  */
  58. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  59.  
  60. /*
  61.  * DrawShape draws a shape into a device context
  62.  * at a given location.
  63.  */
  64. void DrawShape(HDC hdc,int x,int y,int x2, int y2,int Shape,
  65.            int PenWidth,COLORREF PenColor,int Slope);
  66.  
  67. /***************************************************************
  68.  * Global Variables
  69.  ***************************************************************/
  70.  
  71. int CurrentShape = LINE;           /* Maintains the status of the shape
  72.                     * the user is drawing. Default is
  73.                     * to draw with a line.             */
  74.  
  75. int PenWidth = 3;                  /* Maintains the current pen width.
  76.                     * Default width is medium.         */
  77.  
  78. COLORREF PenColor = RGB(255,0,0);  /* Maintains the current pen color.
  79.                     * Default color is red.            */
  80.  
  81.  
  82. /*
  83.  * Structure definition to track
  84.  * what shapes have been drawn.
  85.  */
  86. struct SSHAPE {
  87.     RECT     Points;           /* Location of the shape.           */
  88.     int      PenWidth,         /* Pen width for the shape.         */
  89.          theShape;         /* Shape this structure represents. */
  90.     COLORREF PenColor;         /* Color of the shape.              */
  91.     int      Slope;            /* Used to determine direction lines
  92.                     * should be drawn. If slope > 0 then
  93.                     * draw from UpperLeft to LowerRight.
  94.                     * Else draw from LowerLeft
  95.                     * to UpperRight.                   */
  96. };
  97.  
  98. typedef struct SSHAPE SHAPE;
  99.  
  100. #define nPoints 100
  101. SHAPE thisShape[nPoints];          /* Array that stores the shapes
  102.                     * the user draws.                 */
  103. int CurrentPoint = -1;             /* Indicates the number of shapes
  104.                     * the user has drawn.             */
  105.  
  106. /**********************************************************
  107.  * function WinMain
  108.  *    Standard WinMain function.
  109.  **********************************************************/
  110. #pragma argsused
  111. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  112.            LPSTR lpszCmdLine, int nCmdShow )
  113. {
  114.     WNDCLASS    wndClass;
  115.     MSG         msg;
  116.     HWND        hWnd;
  117.  
  118.     /*
  119.      * Register window class style if first
  120.      * instance of this program.
  121.      */
  122.     if ( !hPrevInstance )
  123.     {
  124.     wndClass.style          = CS_HREDRAW | CS_VREDRAW ;
  125.     wndClass.lpfnWndProc    = WndProc;
  126.     wndClass.cbClsExtra     = 0;
  127.     wndClass.cbWndExtra     = 0;
  128.     wndClass.hInstance      = hInstance;
  129.     wndClass.hIcon          = LoadIcon(hInstance, "IDI_SIMPLEPAINT");
  130.     wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW );
  131.     wndClass.hbrBackground  = GetStockObject(WHITE_BRUSH );
  132.     wndClass.lpszMenuName   = szAppName;
  133.     wndClass.lpszClassName  = szAppName;
  134.  
  135.     if (!RegisterClass(&wndClass))
  136.     return FALSE;
  137.     }
  138.  
  139.     /*
  140.      * Create and display the window.
  141.      */
  142.     hWnd = CreateWindow(szAppName,"Simple Paint",
  143.             WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,
  144.             CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
  145.  
  146.     ShowWindow(hWnd, nCmdShow);
  147.     UpdateWindow(hWnd);
  148.  
  149.     while (GetMessage(&msg, NULL, 0, 0))
  150.     {
  151.     TranslateMessage(&msg );
  152.     DispatchMessage(&msg );
  153.     }
  154.     return 0;
  155. }
  156.  
  157. /*******************************************************
  158.  * function WndProc
  159.  *    Handles all messages received by the window
  160.  *******************************************************/
  161.  
  162. LRESULT CALLBACK WndProc (HWND hWnd, UINT Message,
  163.              WPARAM wParam, LPARAM lParam)
  164. {
  165.     switch(Message)
  166.     {
  167.     case WM_COMMAND:
  168.         return DoWMCommand(wParam, hWnd);
  169.  
  170.     case WM_LBUTTONDOWN:
  171.         DoLButtonDown(hWnd,lParam);
  172.         break;
  173.  
  174.     case WM_LBUTTONUP:
  175.         DoLButtonUp(hWnd,lParam);
  176.         break;
  177.  
  178.     case WM_MOUSEMOVE:
  179.         DoMouseMove(hWnd,lParam);
  180.         break;
  181.  
  182.     case WM_PAINT:
  183.         DoPaint(hWnd);
  184.         break;
  185.  
  186.     case WM_DESTROY:
  187.         PostQuitMessage(0);
  188.         break;
  189.  
  190.     default:
  191.         return DefWindowProc(hWnd,Message,wParam,lParam);
  192.     }
  193.     return 0;
  194. }
  195.  
  196. /*****************************************************************
  197.  * function DrawShape
  198.  *
  199.  *    Draws the shape given by Shape parameter using PenWidth
  200.  *    and PenColor in the rectangle bounded by x,y,x2,y2.  The
  201.  *    Slope parameter is used with line shapes to determine if
  202.  *    lines should be drawn with a negative or positive slope.
  203.  *****************************************************************/
  204.  
  205. void DrawShape(HDC hdc, int x, int y, int x2, int y2, int Shape,
  206.            int PenWidth, COLORREF PenColor, int Slope)
  207. {
  208.     HANDLE      saveObject;
  209.  
  210.     /*
  211.      * Create the proper pen for this shape.  Save the
  212.      * previously selected object from this DC.
  213.      */
  214.     saveObject = SelectObject(hdc, CreatePen(PS_SOLID,
  215.                          PenWidth,
  216.                          PenColor));
  217.     switch(Shape)
  218.     {
  219.     case LINE:
  220.         /*
  221.          *  Rectangles that save a shape's position must be stored
  222.          *  as upper-left and lower-right.  To draw a line from
  223.          *  upper-right to lower-left, the line must have a
  224.          *  negative slope.
  225.          */
  226.         if (Slope > 0)
  227.         {
  228.         MoveTo(hdc,x,y);
  229.         LineTo(hdc,x2,y2);
  230.         }
  231.         else
  232.         {
  233.         MoveTo(hdc,x,y2);
  234.         LineTo(hdc,x2,y);
  235.         }
  236.         break;
  237.  
  238.     case ELLIPSE:
  239.         Ellipse(hdc,x,y,x2,y2);
  240.         break;
  241.  
  242.     case RECTANGLE:
  243.         Rectangle(hdc,x,y,x2,y2);
  244.         break;
  245.     }
  246.     /*
  247.      *  Delete the currently selected object (the pen) and select
  248.      *  whatever object was currently selected when we entered
  249.      *  this routine.
  250.      */
  251.     DeleteObject(SelectObject(hdc,saveObject));
  252. }
  253.  
  254. /****************************************************************
  255.  * function DoPaint
  256.  *    Processes WM_PAINT messages.  WM_PAINT is generated
  257.  *    whenever UpdateWindow is called or another window is moved,
  258.  *    revealing a portion of the window receiving this message.
  259.  ****************************************************************/
  260.  
  261. void DoPaint(HWND hWnd)
  262. {
  263.     int         i;
  264.  
  265.     HDC         hdc,
  266.         hMemDC;
  267.  
  268.     RECT        theRect,
  269.         destRect;
  270.  
  271.     HBITMAP     theBitmap;
  272.     PAINTSTRUCT ps;
  273.  
  274.     hdc = BeginPaint(hWnd,&ps);
  275.  
  276.     if (CurrentPoint >= 0)
  277.     {
  278.     /*
  279.      * Determine which rectangle on the window is invalid.
  280.      * If no rectangle is marked invalid, it will be a full
  281.      * window repaint.
  282.      */
  283.     GetUpdateRect(hWnd,&theRect,0);
  284.     if (IsRectEmpty(&theRect))
  285.         GetClientRect(hWnd,&theRect);
  286.  
  287.     /*
  288.      * Create a memory DC and bitmap the same
  289.      * size as the update rectangle.
  290.      */
  291.     hMemDC = CreateCompatibleDC(hdc);
  292.     theBitmap = CreateCompatibleBitmap(hdc,
  293.                        theRect.right-theRect.left,
  294.                        theRect.bottom-theRect.top);
  295.     SelectObject(hMemDC,theBitmap);
  296.  
  297.     /*
  298.      * Erase the memBitmap.
  299.      */
  300.     BitBlt(hMemDC, 0, 0,
  301.            theRect.right-theRect.left,
  302.            theRect.bottom-theRect.top,
  303.            hdc, 0, 0, SRCCOPY);
  304.  
  305.     /*
  306.      * Draw only those shapes that lie
  307.      * within the update rectangle.
  308.      */
  309.     for (i = 0; i <= CurrentPoint; ++i)
  310.     {
  311.         IntersectRect(&destRect, &thisShape[i].Points, &theRect);
  312.         if (!IsRectEmpty(&destRect))
  313.         DrawShape(hMemDC,
  314.               thisShape[i].Points.left-theRect.left,
  315.               thisShape[i].Points.top-theRect.top,
  316.               thisShape[i].Points.right-theRect.left,
  317.               thisShape[i].Points.bottom-theRect.top,
  318.               thisShape[i].theShape,thisShape[i].PenWidth,
  319.               thisShape[i].PenColor,thisShape[i].Slope);
  320.         /*
  321.          * Note that when drawing the shape, the shape's
  322.          * position was transformed so that the origin was
  323.          * at the upper-left corner of the update rectangle.
  324.          * This is the point (0,0) on the bitmap that will
  325.          * map onto (theRect.left,theRect.right).
  326.          */
  327.     }
  328.  
  329.     /*
  330.      * Finally, copy the bitmap onto the update rectangle.
  331.      */
  332.     BitBlt(hdc, theRect.left, theRect.top,
  333.            theRect.right-theRect.left,
  334.            theRect.bottom-theRect.top,
  335.            hMemDC, 0, 0, SRCCOPY);
  336.  
  337.     DeleteDC(hMemDC);
  338.     DeleteObject(theBitmap);
  339.     }
  340.  
  341.     EndPaint(hWnd,&ps);
  342. }
  343.  
  344.  
  345. /**********************************************************
  346.  * static variables oldx, oldy, mouseDown
  347.  *    Used to maintain both the state of the mouse position
  348.  *    and the button status between mouse messages.
  349.  **********************************************************/
  350.  
  351. static  oldx = -1, oldy = -1, mouseDown = 0;
  352.  
  353. /******************************************************************
  354.  * function DoLButtonDown
  355.  *    When the left button on the mouse is pressed, this routine
  356.  *    saves the origin of this shape, the current pen parameters,
  357.  *    and the current shape into the shapes array.  The mouse
  358.  *    button is also marked as pressed.
  359.  ******************************************************************/
  360.  
  361. void DoLButtonDown(HWND hWnd, LONG lParam)
  362. {
  363.     /*
  364.      * Redirect all subsequent mouse movements to this
  365.      * window until the mouse button is released.
  366.      */
  367.     SetCapture(hWnd);
  368.     oldy = thisShape[++CurrentPoint].Points.top = HIWORD(lParam);
  369.     oldx = thisShape[CurrentPoint].Points.left = LOWORD(lParam);
  370.     thisShape[CurrentPoint].theShape = CurrentShape;
  371.     thisShape[CurrentPoint].PenWidth = PenWidth;
  372.     thisShape[CurrentPoint].PenColor = PenColor;
  373.  
  374.     mouseDown = 1;
  375.  
  376. }
  377.  
  378. /******************************************************************
  379.  * function DoLButtonUp
  380.  *    When the Left mouse button is released, this routine
  381.  *    allows other windows to receive mouse messages and saves
  382.  *    the position of the mouse as the other corner of a bounding
  383.  *    rectangle for the shape.
  384.  ******************************************************************/
  385.  
  386. void DoLButtonUp(HWND hWnd, LONG lParam)
  387. {
  388.     if (mouseDown == 0) return;
  389.     ReleaseCapture();
  390.  
  391.     /*
  392.      * For rectangles to work with the IntersectRect function,
  393.      * they must be stored as left, top, right, bottom.
  394.      */
  395.     SetRect(&thisShape[CurrentPoint].Points,
  396.         min(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  397.         min(thisShape[CurrentPoint].Points.top, HIWORD(lParam)),
  398.         max(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  399.         max(thisShape[CurrentPoint].Points.top, HIWORD(lParam)));
  400.  
  401.     /*
  402.      * if the origin of the line has changed, it should be drawn
  403.      * from upper-right to lower left and therefore has negative
  404.      * slope.  Otherwise it will have positive slope.
  405.      */
  406.     if (CurrentShape == LINE)
  407.     thisShape[CurrentPoint].Slope =
  408.         thisShape[CurrentPoint].Points.left ==
  409.         LOWORD(lParam) ||
  410.         thisShape[CurrentPoint].Points.top ==
  411.         HIWORD(lParam) ?
  412.         -1 : 1;
  413.  
  414.     /*
  415.      * Mark this region on the window as
  416.      * needing redrawing and force an update.
  417.      */
  418.     InvalidateRect(hWnd, &thisShape[CurrentPoint].Points, 0);
  419.     UpdateWindow(hWnd);
  420.     mouseDown = 0;
  421.     oldx = -1;
  422.     oldy = -1;
  423. }
  424.  
  425. static int SaveROP;
  426.  
  427. /**********************************************************************
  428.  * function DoMouseMove
  429.  *    When the mouse is moved and the button is down, this function
  430.  *    draws the current shape.  It uses the Raster Operation NOTXORPEN
  431.  *    to draw the shape.  When this mode is used, drawing the
  432.  *    same image twice returns the image to its original state.
  433.  *    NOTXORPEN turns black on black white, black on white black
  434.  *    and white on white white.
  435.  **********************************************************************/
  436.  
  437. void DoMouseMove(HWND hWnd,LONG lParam)
  438. {
  439.     HDC hdc;
  440.  
  441.     if (mouseDown)
  442.     {
  443.     hdc = GetDC(hWnd);
  444.     /*
  445.      * Erase the old shape.
  446.      */
  447.     SaveROP = SetROP2(hdc,R2_NOTXORPEN);
  448.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  449.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  450.           thisShape[CurrentPoint].theShape,
  451.           thisShape[CurrentPoint].PenWidth,
  452.           thisShape[CurrentPoint].PenColor, 1);
  453.     /*
  454.      * At this point, the slope must be positive because
  455.      * the coordinates could not have been switched.
  456.      * The next step is to draw the new shape.
  457.      */
  458.  
  459.     oldx = LOWORD(lParam);
  460.     oldy = HIWORD(lParam);
  461.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  462.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  463.           thisShape[CurrentPoint].theShape,
  464.           thisShape[CurrentPoint].PenWidth,
  465.           thisShape[CurrentPoint].PenColor, 1);
  466.     SetROP2(hdc,SaveROP);
  467.     ReleaseDC(hWnd,hdc);
  468.     }
  469.  
  470. }
  471.  
  472. /*********************************************************************
  473.  * function DoWMCommand
  474.  *    When a menu item is selected, this function changes the current
  475.  *    state of shape selections to match the user's menu selection.
  476.  *******************************************************************/
  477.  
  478. int DoWMCommand(WORD wParam, HWND hWnd)
  479. {
  480.     switch(wParam)
  481.     {
  482.     case MID_QUIT:
  483.         DestroyWindow(hWnd);
  484.         break;
  485.  
  486.     case MID_LINE:
  487.         CurrentShape = LINE;
  488.         break;
  489.  
  490.     case MID_ELLIPSE:
  491.         CurrentShape = ELLIPSE;
  492.         break;
  493.  
  494.     case MID_RECTANGLE:
  495.         CurrentShape = RECTANGLE;
  496.         break;
  497.  
  498.     case MID_THIN:
  499.         PenWidth = 1;
  500.         break;
  501.  
  502.     case MID_REGULAR:
  503.         PenWidth = 3;
  504.         break;
  505.  
  506.     case MID_THICK:
  507.         PenWidth = 5;
  508.         break;
  509.  
  510.     case MID_RED:
  511.         PenColor = RGB(255,0,0);
  512.         break;
  513.  
  514.     case MID_GREEN:
  515.         PenColor = RGB(0,255,0);
  516.         break;
  517.  
  518.     case MID_BLACK:
  519.         PenColor = RGB(0,0,0);
  520.         break;
  521.  
  522.     default:
  523.         return 0;
  524.     }
  525.  
  526.     return 1;
  527. }
  528.