home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_7 / 7.ddi / TDWEXMPL.ZIP / BCWDEMO.C next >
Encoding:
C/C++ Source or Header  |  1991-02-13  |  14.8 KB  |  528 lines

  1. /**********************************************************************
  2.  *          Copyright (c) 1991 by Borland International, Inc.         *
  3.  *                                                                    *
  4.  *                            BCWDEMO.C                               *
  5.  *                                                                    *
  6.  *  This program demonstrates how to write a simple Microsoft Windows *
  7.  *  graphics program in Turbo 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. #include <windows.h>
  15. #include "bcwdemo.h"
  16.  
  17. /*****************************************************
  18.  * FUNCTION PROTOTYPES
  19.  *****************************************************/
  20.  
  21. /*
  22.  * DoWMCommand processes WM_COMMAND messages.  WM_COMMAND
  23.  * is generated when the user selects something from the menu.
  24.  */
  25. int DoWMCommand(WORD wParam);
  26.  
  27. /*
  28.  * DoLButtonDown process WM_LBUTTONDOWN messages.  WM_LBUTTONDOWN
  29.  * is generated when the user presses the left mouse button.
  30.  */
  31. void DoLButtonDown(HWND hWnd,LONG lParam);
  32.  
  33. /*
  34.  * DoLButtonUp processes WM_LBUTTONUP messages.  WM_LBUTTONUP
  35.  * is generated when the user releases the left mouse button.
  36.  */
  37. void DoLButtonUp(HWND hWnd,LONG lParam);
  38.  
  39. /*
  40.  * DoMouseMove processes WM_MOUSEMOVE messages.  WM_MOUSEMOVE
  41.  * is generated when the user moves the mouse.
  42.  */
  43. void DoMouseMove(HWND hWnd,LONG lParam);
  44.  
  45. /*
  46.  * DoPaint processes WM_PAINT messages.  WM_PAINT is generated
  47.  * whenever UpdateWindow is called or another window is moved,
  48.  * revealing a portion of the window receiving this message.
  49.  */
  50. void DoPaint(HWND hWnd);
  51.  
  52. /*
  53.  * WndProc is the callback function (window proc)
  54.  * for the Simple Paint class of windows.
  55.  */
  56. long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG) ;
  57.  
  58. /*
  59.  * DrawShape draws a shape into a device context
  60.  * at a given location.
  61.  */
  62. void DrawShape(HDC hdc,int x,int y,int x2, int y2,int Shape,
  63.            int PenWidth,COLORREF PenColor,int Slope);
  64.  
  65. /***************************************************************
  66.  * Global Variables
  67.  ***************************************************************/
  68.  
  69. int CurrentShape = LINE;       /* Maintains the status of the shape
  70.                     * the user is drawing. Default is
  71.                     * to draw with a line.             */
  72.  
  73. int PenWidth = 3;           /* Maintains the current pen width.
  74.                     * Default width is medium.         */
  75.  
  76. COLORREF PenColor = RGB(255,0,0);  /* Maintains the current pen color.
  77.                     * Default color is red.            */
  78.  
  79.  
  80. /*
  81.  * Structure definition to track
  82.  * what shapes have been drawn.
  83.  */
  84. struct SSHAPE {
  85.     RECT     Points;       /* Location of the shape.           */
  86.     int     PenWidth,       /* Pen width for the shape.         */
  87.          theShape;       /* Shape this structure represents. */
  88.     COLORREF PenColor;       /* Color of the shape.              */
  89.     int     Slope;           /* Used to determine direction lines
  90.                     * should be drawn. If slope > 0 then
  91.                     * draw from UpperLeft to LowerRight.
  92.                     * Else draw from LowerLeft
  93.                     * to UpperRight.               */
  94. };
  95.  
  96. typedef struct SSHAPE SHAPE;
  97.  
  98. #define nPoints 100
  99. SHAPE thisShape[nPoints];       /* Array that stores the shapes
  100.                     * the user draws.              */
  101. int CurrentPoint = -1;           /* Indicates the number of shapes
  102.                     * the user has drawn.             */
  103.  
  104. /**********************************************************
  105.  * function WinMain
  106.  *    Standard WinMain function.
  107.  **********************************************************/
  108.  
  109. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  110.            LPSTR lpszCmdLine, int nCmdShow )
  111. {
  112.     WNDCLASS    wndClass;
  113.     MSG        msg;
  114.     HWND    hWnd;
  115.  
  116.     /*
  117.      * Register window class style if first
  118.      * instance of this program.
  119.      */
  120.     if ( !hPrevInstance )
  121.     {
  122.     wndClass.style        = CS_HREDRAW | CS_VREDRAW ;
  123.     wndClass.lpfnWndProc    = WndProc;
  124.     wndClass.cbClsExtra     = 0;
  125.     wndClass.cbWndExtra    = 0;
  126.     wndClass.hInstance     = hInstance;
  127.     wndClass.hIcon         = LoadIcon(NULL, "IDI_SIMPLEPAINT");
  128.     wndClass.hCursor    = LoadCursor(NULL, IDC_ARROW );
  129.     wndClass.hbrBackground    = GetStockObject(WHITE_BRUSH );
  130.     wndClass.lpszMenuName    = szAppName;
  131.     wndClass.lpszClassName    = szAppName;
  132.  
  133.     if (!RegisterClass(&wndClass))
  134.     return FALSE;
  135.     }
  136.  
  137.     /*
  138.      * Create and display the window.
  139.      */
  140.     hWnd = CreateWindow(szAppName,"Simple Paint",
  141.             WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,
  142.             CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
  143.  
  144.     ShowWindow(hWnd, nCmdShow);
  145.     UpdateWindow(hWnd);
  146.  
  147.     while (GetMessage(&msg, NULL, 0, 0))
  148.     {
  149.     TranslateMessage(&msg );
  150.     DispatchMessage(&msg );
  151.     }
  152.     return 0;
  153. }
  154.  
  155. /*******************************************************
  156.  * function WndProc
  157.  *    Handles all messages received by the window
  158.  *******************************************************/
  159.  
  160. long FAR PASCAL WndProc (HWND hWnd, unsigned Message,
  161.              WORD wParam, LONG lParam)
  162. {
  163.     switch(Message)
  164.     {
  165.     case WM_COMMAND:
  166.         return DoWMCommand(wParam);
  167.  
  168.     case WM_LBUTTONDOWN:
  169.         DoLButtonDown(hWnd,lParam);
  170.         break;
  171.  
  172.     case WM_LBUTTONUP:
  173.         DoLButtonUp(hWnd,lParam);
  174.         break;
  175.  
  176.     case WM_MOUSEMOVE:
  177.         DoMouseMove(hWnd,lParam);
  178.         break;
  179.  
  180.     case WM_PAINT:
  181.         DoPaint(hWnd);
  182.         break;
  183.  
  184.     case WM_DESTROY:
  185.         PostQuitMessage(0);
  186.         break;
  187.  
  188.     default:
  189.         return DefWindowProc(hWnd,Message,wParam,lParam);
  190.     }
  191.     return 0;
  192. }
  193.  
  194. /*****************************************************************
  195.  * function DrawShape
  196.  *
  197.  *    Draws the shape given by Shape parameter using PenWidth
  198.  *    and PenColor in the rectangle bounded by x,y,x2,y2.  The
  199.  *    Slope parameter is used with line shapes to determine if
  200.  *    lines should be drawn with a negative or positive slope.
  201.  *****************************************************************/
  202.  
  203. void DrawShape(HDC hdc, int x, int y, int x2, int y2, int Shape,
  204.            int PenWidth, COLORREF PenColor, int Slope)
  205. {
  206.     HANDLE    saveObject;
  207.     int        SaveROP;
  208.  
  209.     /*
  210.      * Create the proper pen for this shape.  Save the
  211.      * previously selected object from this DC.
  212.      */
  213.     saveObject = SelectObject(hdc, CreatePen(PS_SOLID,
  214.                          PenWidth,
  215.                          PenColor));
  216.     switch(Shape)
  217.     {
  218.     case LINE:
  219.         /*
  220.          *  Rectangles that save a shape's position must be stored
  221.          *  as upper-left and lower-right.  To draw a line from
  222.          *  upper-right to lower-left, the line must have a
  223.          *  negative slope.
  224.          */
  225.         if (Slope > 0)
  226.         {
  227.         MoveTo(hdc,x,y);
  228.         LineTo(hdc,x2,y2);
  229.         }
  230.         else
  231.         {
  232.         MoveTo(hdc,x,y2);
  233.         LineTo(hdc,x2,y);
  234.         }
  235.         break;
  236.  
  237.     case ELLIPSE:
  238.         Ellipse(hdc,x,y,x2,y2);
  239.         break;
  240.  
  241.     case RECTANGLE:
  242.         Rectangle(hdc,x,y,x2,y2);
  243.         break;
  244.     }
  245.     /*
  246.      *  Delete the currently selected object (the pen) and select
  247.      *    whatever object was currently selected when we entered
  248.      *    this routine.
  249.      */
  250.     DeleteObject(SelectObject(hdc,saveObject));
  251. }
  252.  
  253. /****************************************************************
  254.  * function DoPaint
  255.  *    Processes WM_PAINT messages.  WM_PAINT is generated
  256.  *    whenever UpdateWindow is called or another window is moved,
  257.  *    revealing a portion of the window receiving this message.
  258.  ****************************************************************/
  259.  
  260. void DoPaint(HWND hWnd)
  261. {
  262.     int        i,
  263.         saveROP;
  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.     ReleaseDC(hWnd,hdc);
  342.     EndPaint(hWnd,&ps);
  343. }
  344.  
  345.  
  346. /**********************************************************
  347.  * static variables oldx, oldy, mouseDown
  348.  *    Used to maintain both the state of the mouse position
  349.  *    and the button status between mouse messages.
  350.  **********************************************************/
  351.  
  352. static    oldx = -1, oldy = -1, mouseDown = 0;
  353.  
  354. /******************************************************************
  355.  * function DoLButtonDown
  356.  *    When the left button on the mouse is pressed, this routine
  357.  *    saves the origin of this shape, the current pen parameters,
  358.  *    and the current shape into the shapes array.  The mouse
  359.  *    button is also marked as pressed.
  360.  ******************************************************************/
  361.  
  362. void DoLButtonDown(HWND hWnd, LONG lParam)
  363. {
  364.     /*
  365.      * Redirect all subsequent mouse movements to this
  366.      * window until the mouse button is released.
  367.      */
  368.     SetCapture(hWnd);
  369.     oldy = thisShape[++CurrentPoint].Points.top = HIWORD(lParam);
  370.     oldx = thisShape[CurrentPoint].Points.left = LOWORD(lParam);
  371.     thisShape[CurrentPoint].theShape = CurrentShape;
  372.     thisShape[CurrentPoint].PenWidth = PenWidth;
  373.     thisShape[CurrentPoint].PenColor = PenColor;
  374.  
  375.     mouseDown = 1;
  376.  
  377. }
  378.  
  379. /******************************************************************
  380.  * function DoLButtonUp
  381.  *    When the Left mouse button is released, this routine
  382.  *    allows other windows to receive mouse messages and saves
  383.  *    the position of the mouse as the other corner of a bounding
  384.  *    rectangle for the shape.
  385.  ******************************************************************/
  386.  
  387. void DoLButtonUp(HWND hWnd, LONG lParam)
  388. {
  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)
  479. {
  480.     switch(wParam)
  481.     {
  482.     case MID_QUIT:
  483.         PostQuitMessage(0);
  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.