⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 paint.c

📁 <Win2k系统编程>源码.次数为国人自编,内容丰富,还是不错的.
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************\
*
*  MODULE:      PAINT.C
*
*  PURPOSE:     This is the module responsible for painting the SPINCUBE
*               custom control. When Paint() is called we retrieve a
*               pointer to a SPINCUBEINFO structure, and then use it's
*               current rotation & translation values to transform the
*               polyhedron described by gNormalizedVertices & gaiFacets.
*               Once we've transformed the vertices, we draw the
*               background, which consists of a grey rectangle and a few
*               black lines (a crass attempt to render a perspective
*               view into a "room"), on the offscreen bitmap associated
*               with the control (i.e. pSCI->hbmCompat). Then we walk the
*               facet list of the transformed polyhedron (gXformedVertices
*               & gaiFacets), drawing only those facets whose outward
*               normal faces us (again, drawing on pSCI->hbmCompat).
*               Finally, we BitBlt the appropriate rectangle from our
*               offscreen bitmap to the screen itself.
*
*               Drawing to the offscreen bitmap has two advantages over
*               drawing straight to the screen:
*
*                 1. The actual drawing the user sees consists of only
*                    a single BitBlt. Otherwise, the user would see us
*                    both erase the polyhedron in it's old position and
*                    draw it in it's new position (alot of flashing- not
*                    very smooth animation).
*
*                 2. When a spincube control with the SS_ERASE style
*                    is brought to the foreground, all it's contents
*                    i.e. the cube trails) are saved & can be re-Blted
*                    to the screen. Otherwise, all this info would be
*                    lost & there'd be a big blank spot in the middle
*                    of the control!
*
*               Interested persons should consult a text on 3 dimensional
*               graphics for more information (i.e. "Computer Graphics:
*               Principles and Practice", by Foley & van Dam).
*
*               Notes:
*
*               - A 3x2 tranformation matrix  is used instead of a  3x3
*                 matrix, since the transformed z-values aren't needed.
*                 (Normally these would be required for use in depth
*                 sorting  [for hidden surface removal], but  since we
*                 draw  only  a single convex polyhedron this  is not
*                 necessary.)
*
*               - A simplified perspective viewing transformation
*                 (which also  precludes the need for the transformed z
*                 coordinates). In a nutshell, the perspective  scale
*                 is as follows:
*
*                                    p' = S    x  p
*                                          per
*
*                 where:
*                        S    = WindowDepth /
*                         per      (WindowDepth + fCurrentZTranslation)
*
*                 (WindowDepth is  the greater of the  control's window
*                 height or window width.)
*
*
*  FUNCTIONS:   Paint()                         - the paint routine
*               TransformVertices()             - transforms vertices
*               ComputeRotationTransformation() - computes xformation
*                                                 based on current x, y
*                                                 and z rotation angles
*
\******************************************************************************/

#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include "spincube.h"
#include "paint.h"



/******************************************************************************\
*
*  FUNCTION:     Paint
*
*  INPUTS:       hwnd - Handle of the window to draw into.
*
*  COMMENTS:     Draws window background & a polyhedron in the window.
*
\******************************************************************************/

void Paint (HWND hwnd)
{
  PSPINCUBEINFO  pSCI;
  RECT           rect;
  int            i;
  LONG           lScaleFactor;
  PAINTSTRUCT    ps;
  HRGN           hrgnClip;
  HBRUSH         hBrush, hBrushSave;
  int            iX, iY, iCX, iCY;
  int            facetIndex, numPoints;
  POINT          polygn[MAX_POINTS_PER_FACET];
  POINT          vector1, vector2;
  COLORREF       acrColor[6] = { 0x0000ff, 0x00ff00, 0xff0000,
                                 0x00ffff, 0xff00ff, 0xffff00 };

  pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd, GWL_SPINCUBEDATA);

  BeginPaint (hwnd, &ps);

  if (memcmp((void *)&ps.rcPaint, (void *)&pSCI->rcCubeBoundary, sizeof(RECT))
      & !REPAINT_BKGND(pSCI))

  {
    //
    // We're not here because it's time to animate (i.e. this paint isn't
    //   the result of a WM_TIMER), so just do the Blt & blow out of here...
    //

    BitBlt (ps.hdc,
            ps.rcPaint.left,
            ps.rcPaint.top,
            ps.rcPaint.right - ps.rcPaint.left,
            ps.rcPaint.bottom - ps.rcPaint.top,
            pSCI->hdcCompat, ps.rcPaint.left,
            ps.rcPaint.top, SRCCOPY);

    EndPaint (hwnd, &ps);
    return;
  }


  //
  // The rectangle we get back is in Desktop coordinates, so we need to
  //   modify it to reflect coordinates relative to this window.
  //

  GetWindowRect (hwnd, &rect);

  rect.right  -= rect.left;
  rect.bottom -= rect.top;
  rect.left = rect.top = 0;


  //
  // Determine a "best fit" scale factor for our polyhedron
  //

  if (!(lScaleFactor = rect.right > rect.bottom ?
                       rect.bottom/12 : rect.right/12))

    lScaleFactor = 1;


  TransformVertices (hwnd, &rect, pSCI, lScaleFactor);


  //
  // Draw the window frame & background
  //
  // Note: The chances are that we are coming through here because we
  //   got a WM_TIMER message & it's time to redraw the cube to simulate
  //   animation. In that case all we want to erase/redraw is that small
  //   rectangle which bounded the polyhedron the last time. The less
  //   drawing that actually gets done the better, since we wnat to
  //   minimize the flicker on the screen. __BeginPaint__ is perfect for
  //   this because it causes all drawing outside of the invalid region
  //   to be "clipped" (no drawing is performed outside of the invalid
  //   region), and it also validates the invalid region.
  //

  if (DO_ERASE(hwnd) || REPAINT_BKGND(pSCI))
  {
    hrgnClip = CreateRectRgnIndirect (&ps.rcPaint);
    SelectClipRgn (pSCI->hdcCompat, hrgnClip);
    DeleteObject (hrgnClip);

    SelectObject (pSCI->hdcCompat, GetStockObject (GRAY_BRUSH));
    Rectangle    (pSCI->hdcCompat, (int)rect.left, (int)rect.top,
                  (int)rect.right, (int)rect.bottom);

    iX = (rect.right  - rect.left) / 4;
    iY = (rect.bottom - rect.top ) / 4;

    MoveToEx (pSCI->hdcCompat, (int)rect.left, (int)rect.top, NULL);
    LineTo   (pSCI->hdcCompat, (int)rect.left + iX, (int)rect.top + iY);
    LineTo   (pSCI->hdcCompat, (int)rect.left + iX, (int)rect.bottom - iY);
    LineTo   (pSCI->hdcCompat, (int)rect.left,      (int)rect.bottom);

    MoveToEx (pSCI->hdcCompat, (int)rect.right, (int)rect.top, NULL);
    LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.top + iY);
    LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.bottom- iY);
    LineTo   (pSCI->hdcCompat, (int)rect.right,      (int)rect.bottom);

    MoveToEx (pSCI->hdcCompat, (int)rect.left + iX,  (int)rect.top + iY, NULL);
    LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.top + iY);

    MoveToEx (pSCI->hdcCompat, (int)rect.left + iX,  (int)rect.bottom - iY, NULL);
    LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.bottom - iY);

    SelectClipRgn (pSCI->hdcCompat, NULL);

    pSCI->iOptions &= ~SPINCUBE_REPAINT_BKGND;
  }


  //
  // Draw the polyhedron. We'll walk through the facets list and compute
  //   the normal for each facet- if the normal has z > 0, then the facet
  //   faces us and we'll draw it. Note that this algorithim is ONLY valid
  //   for scenes with a single, convex polyhedron.
  //
  // Note: Use GetDC here because the above call to BeginPaint will
  //   probably not give us a DC with access to as much real estate as
  //   we'd like (we wouldn't be able to draw outside of the invalid
  //   region). We can party on the entire control window with the DC
  //   returned by GetDC.
  //

  for (i = 0, facetIndex = 0; i < NUMFACETS; i++)
  {
    vector1.x = gXformedVertices[gaiFacets[facetIndex + 1]].x -
                gXformedVertices[gaiFacets[facetIndex]].x;
    vector1.y = gXformedVertices[gaiFacets[facetIndex + 1]].y -
                gXformedVertices[gaiFacets[facetIndex]].y;
    vector2.x = gXformedVertices[gaiFacets[facetIndex + 2]].x -
                gXformedVertices[gaiFacets[facetIndex + 1]].x;
    vector2.y = gXformedVertices[gaiFacets[facetIndex + 2]].y -
                gXformedVertices[gaiFacets[facetIndex + 1]].y;

    for (numPoints = 0; gaiFacets[facetIndex] != -1; numPoints++, facetIndex++)
    {
      polygn[numPoints].x = gXformedVertices[gaiFacets[facetIndex]].x;
      polygn[numPoints].y = gXformedVertices[gaiFacets[facetIndex]].y;
    }

    facetIndex++; /* skip over the -1's in the facets list */
    if ((vector1.x*vector2.y - vector1.y*vector2.x) > 0)
    {
      hBrush     = CreateSolidBrush (acrColor[i]);
      hBrushSave = (HBRUSH) SelectObject (pSCI->hdcCompat, hBrush);

      Polygon (pSCI->hdcCompat, &polygn[0], numPoints);

      SelectObject (pSCI->hdcCompat, hBrushSave);
      DeleteObject (hBrush);
    }
  }

  iX  = pSCI->rcCubeBoundary.left < ps.rcPaint.left ?
        pSCI->rcCubeBoundary.left : ps.rcPaint.left;
  iY  = pSCI->rcCubeBoundary.top  < ps.rcPaint.top  ?
        pSCI->rcCubeBoundary.top  : ps.rcPaint.top;

  iCX = (pSCI->rcCubeBoundary.right > ps.rcPaint.right ?
         pSCI->rcCubeBoundary.right : ps.rcPaint.right) - iX;

  iCY = (pSCI->rcCubeBoundary.bottom > ps.rcPaint.bottom ?
         pSCI->rcCubeBoundary.bottom : ps.rcPaint.bottom) - iY;

  EndPaint (hwnd, &ps);

  ps.hdc = GetDC (hwnd);

  BitBlt (ps.hdc, iX, iY, iCX, iCY, pSCI->hdcCompat, iX, iY, SRCCOPY);

  ReleaseDC (hwnd, ps.hdc);

}



/******************************************************************************\
*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -