home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / BORLAND TURBO / OWLSRC.PAK / UIFACE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  11.9 KB  |  414 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.11  $
  6. //
  7. // Implements TUIFace
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_UIHELPER_H)
  11. # include <owl/uihelper.h>
  12. #endif
  13. #if !defined(OWL_GDIOBJEC_H)
  14. # include <owl/gdiobjec.h>
  15. #endif
  16.  
  17. OWL_DIAGINFO;
  18.  
  19. const long RopPSDPxax = 0x00B8074AL;  //
  20. const long RopDSPDxax = 0x00E20746L;  //
  21.  
  22. //
  23. // Return a brush created using a hatched [checkerboard] pattern of the button
  24. // highlight color. This brush is commonly used for rendering 'indeterminate'
  25. // or 'mixed-value' appearances.
  26. //
  27. // NOTE: Automatically reconstructs the brush if the relevant system color
  28. //       changed during a session...
  29. //
  30. THatch8x8Brush&
  31. TUIFace::GetDitherBrush()
  32. {
  33.   static uint32 ditherColor = TColor::Sys3dHilight;
  34.   static THatch8x8Brush ditherBrush(THatch8x8Brush::Hatch11F1,
  35.                                     TColor::Sys3dFace,
  36.                                     TColor::Sys3dHilight);
  37.  
  38.   // Reconstruct the brush in case the system colors have changed
  39.   // since the brush was constructed
  40.   //
  41.   if (ditherColor != TColor::Sys3dHilight) {
  42.     ditherBrush.Reconstruct(THatch8x8Brush::Hatch11F1,
  43.                             TColor::Sys3dFace,
  44.                             TColor::Sys3dHilight);
  45.     ditherColor = TColor::Sys3dHilight;
  46.   }
  47.  
  48.   // Return ref. to static brush
  49.   //
  50.   return ditherBrush;
  51. }
  52.  
  53. //
  54. // Return a reference to a static monochrome bitmap. The optional TSize
  55. // pointer allows the routine to ensure that the bitmap is big enough for a
  56. // given use.
  57. //
  58. TBitmap&
  59. TUIFace::GetGlyphMask(const TSize& minSize)
  60. {
  61.   // Start off with no bitmap, allocate below with requested or default size
  62.   //
  63.   static TSize maskSize(0,0);      // Current mask size
  64.   static TPointer<TBitmap> maskBm; // Current mask bm
  65.  
  66.   // (Re)allocate mask bitmap if we need a bigger one
  67.   //
  68.   if (minSize.cx > maskSize.cx || minSize.cy > maskSize.cy) {
  69.     if (maskSize.cx < minSize.cx)
  70.       maskSize.cx = minSize.cx;
  71.     if (maskSize.cy < minSize.cy)
  72.       maskSize.cy = minSize.cy;
  73.     maskBm = new TBitmap(maskSize.cx, maskSize.cy, 1, 1, 0);
  74.   }
  75.   return *maskBm;
  76. }
  77.  
  78. //
  79. // Build a monochrome mask bitmap for the glyph that has 1's where color
  80. // Sys3dFace is and 0's everywhere else.
  81. //
  82. // NOTE: Assumes DC's are already setup - i.e. maskDC has the destination
  83. //       monochrome bitmap selected in it and glyphDC has the image selected
  84. //       in it..
  85. //
  86. void
  87. TUIFace::BuildMask(TDC& maskDC, const TPoint& maskDst, const TSize& maskSize,
  88.                    TDC& glyphDC, const TRect& glyphRect,
  89.                    const TColor& maskedColor)
  90. {
  91.   maskDC.PatBlt(0, 0, maskSize.cx, maskSize.cy, WHITENESS);
  92.   if (maskedColor != TColor::None) {
  93.     TColor bkColor = glyphDC.SetBkColor(TColor::Sys3dFace);
  94.     maskDC.BitBlt(maskDst.x, maskDst.y, glyphRect.Width(), glyphRect.Height(),
  95.                   glyphDC, glyphRect.left, glyphRect.top, SRCCOPY);
  96.     glyphDC.SetBkColor(bkColor);
  97.   }
  98. }
  99.  
  100. //
  101. // Paint onto a given DC withing a given rect using a monochrome BM in a dc as
  102. // a stencil and an arbitrary brush
  103. //
  104. void
  105. TUIFace::FillBackground(TDC& dc, TDC& maskDC, const TRect& dstRect,
  106.                         const TBrush& brush)
  107. {
  108.   dc.SelectObject(brush);
  109.   TColor txtClr = dc.SetTextColor(TColor::Black);
  110.   TColor bkClr = dc.SetBkColor(TColor::White);
  111.  
  112.   dc.BitBlt(dstRect, maskDC, TPoint(0, 0), RopDSPDxax);
  113.  
  114.   dc.SetTextColor(txtClr);
  115.   dc.SetBkColor(bkClr);
  116.   dc.RestoreBrush();
  117. }
  118.  
  119. //
  120. // Tiles the rectangle with a even dithered (checkerboard) pattern
  121. // maskDC determines the stencil area of dither
  122. //
  123. void
  124. TUIFace::DitherBackground(TDC& dc, TDC& maskDC, const TRect& dstRect)
  125. {
  126.   FillBackground(dc, maskDC, dstRect, GetDitherBrush());
  127. }
  128.  
  129. //
  130. // An extension to ::DrawText that draws etched text by writing twice, the
  131. // first one offset down & right in a light color, and the second not offset
  132. //
  133. int
  134. TUIFace::DrawTextEtched(TDC& dc, const char far* str, int count,
  135.                         const TRect& rect, uint16 format)
  136. {
  137.   TColor txtColor = dc.SetTextColor(TColor::Sys3dHilight);
  138.   int height = dc.DrawText(str, count, rect.OffsetBy(1, 1), format);
  139.  
  140.   if (!(format & DT_CALCRECT)) {
  141.     dc.SetTextColor(TColor::Sys3dShadow);
  142.     height = dc.DrawText(str, count, rect, format);
  143.   }
  144.   dc.SetTextColor(txtColor);
  145.   return height;
  146. }
  147.  
  148. //
  149. // Internal bitmap painting function
  150. //
  151. void
  152. TUIFace::PaintBm(const TBitmap& glyph, const TRect& glyphSrcRect,
  153.                  TDC& dc, const TRect& faceRect, const TPoint& dstPoint,
  154.                  TState state, bool pressed, bool fillFace,
  155.                  const TColor& maskColor, const TColor& fillColor)
  156. {
  157.   // Select our glyph in a working memory DC
  158.   //
  159.   TMemoryDC memDC(CONST_CAST(TBitmap&,glyph));
  160.   memDC.SetTextColor(TColor::Black);
  161.   memDC.SetBkColor(TColor::White);
  162.  
  163.   // Calculate the glyph's destination rect.
  164.   // Calculate the rect to fill in, depending on fill-face flag
  165.   //
  166.   TRect glyphDstRect(faceRect.TopLeft() + dstPoint, glyphSrcRect.Size());
  167.   glyphDstRect &= faceRect;
  168.   TRect fillRect(fillFace ? faceRect : glyphDstRect);
  169.   TPoint dstPt(dstPoint);
  170.  
  171.   // When the glyph is down, offset it's origin one pixel to the lower right.
  172.   // Make sure the glyph rect doesn't hang outside the face
  173.   //
  174.   if (pressed || state == Down) {
  175.     dstPt.Offset(1,1);
  176.     glyphDstRect.Offset(1,1);
  177.     glyphDstRect &= faceRect;
  178.   }
  179.   TSize glyphSize = glyphDstRect.Size(); // Get last in case it's clipped
  180.  
  181.   // Draw according the specified state
  182.   //
  183.   switch (state) {
  184.     case Normal: {
  185.       if (fillFace) {
  186.  
  187.         // Build mask of bitmap
  188.         //
  189.         TMemoryDC maskDC(GetGlyphMask(fillRect.Size()));
  190.         BuildMask(maskDC, dstPt, fillRect.Size(), memDC, glyphSrcRect, maskColor);
  191.  
  192.         // Fill background around mask with button face
  193.         //
  194.         TBrush btnFaceBr(TColor::Sys3dFace);
  195.         FillBackground(dc, maskDC, fillRect, btnFaceBr);
  196.       }
  197.  
  198.       dc.BitBlt(glyphDstRect, memDC, glyphSrcRect.TopLeft());
  199.       break;
  200.     }
  201.  
  202.     case Down: {
  203.       // Start with normal glyph
  204.       //
  205.       dc.BitBlt(glyphDstRect, memDC, glyphSrcRect.TopLeft(), SRCCOPY);
  206.  
  207.       // Build a mask of the glyph & dither the background around the glyph
  208.       //
  209.       TMemoryDC maskDC(GetGlyphMask(fillRect.Size()));
  210.       BuildMask(maskDC, dstPt, fillRect.Size(), memDC, glyphSrcRect, maskColor);
  211.       DitherBackground(dc, maskDC, fillRect);
  212.       break;
  213.     }
  214.  
  215.     case Indeterm: {
  216.       TMemoryDC maskDC(GetGlyphMask(fillRect.Size()));
  217.       BuildMask(maskDC, dstPt, fillRect.Size(), memDC, glyphSrcRect, maskColor);
  218.  
  219.       // Inactivate mask--convert the highlight color to 1's on existing
  220.       // mask
  221.       //
  222.       dc.SetBkColor(TColor::Sys3dHilight);
  223.       maskDC.BitBlt(glyphDstRect, memDC, glyphSrcRect.TopLeft(), SRCPAINT);
  224.  
  225.       // Fade the image by replacing the button text color with the button
  226.       // shadow color
  227.       //
  228.       TBrush  shadowBrush(TColor::Sys3dShadow);
  229.       dc.SelectObject(shadowBrush);
  230.       dc.BitBlt(fillRect, maskDC, TPoint(0,0), RopPSDPxax);
  231.  
  232.       // Dither the background everywhere except where the glyph is
  233.       //
  234.       DitherBackground(dc, maskDC, faceRect);
  235.       dc.RestoreBrush();
  236.       maskDC.RestoreBitmap();
  237.       break;
  238.     }
  239.  
  240.     case Disabled: {
  241.  
  242.       // Fill background..
  243.       //
  244.       dc.TextRect(fillFace ? faceRect : glyphDstRect, fillColor);
  245.  
  246.       TMemoryDC maskDC(GetGlyphMask(glyphSize));
  247.       BuildMask(maskDC, TPoint(0, 0), glyphSize, memDC, glyphSrcRect, maskColor);
  248.  
  249.       // Inactivate mask--convert the highlight color to 1's on existing mask
  250.       //
  251.       memDC.SetBkColor(TColor::Sys3dHilight);
  252.       maskDC.BitBlt(glyphSrcRect, memDC, TPoint(0,0), SRCPAINT);
  253.  
  254.       // Make the image look embossed - highlight color offset down and right
  255.       //
  256.       dc.SetTextColor(TColor::Black);
  257.       dc.SetBkColor(TColor::White);
  258.  
  259.       TBrush hiliteBrush(TColor::Sys3dHilight);
  260.       dc.SelectObject(hiliteBrush);
  261.       dc.BitBlt(glyphDstRect.left+1, glyphDstRect.top+1,
  262.                 glyphDstRect.Width()-1, glyphDstRect.Height()-1,
  263.                 maskDC, 0, 0, RopPSDPxax);
  264.       dc.RestoreBrush();
  265.  
  266.       // Fade the image by replacing the button text color with the button
  267.       // shadow color
  268.       //
  269.       TBrush shadowBrush(TColor::Sys3dShadow);
  270.       dc.SelectObject(shadowBrush);   // 0 -> shadow
  271.       dc.BitBlt(glyphDstRect, maskDC, TPoint(0, 0), RopPSDPxax);
  272.       dc.RestoreBrush();
  273.  
  274.       maskDC.RestoreBitmap();
  275.       break;
  276.     }
  277.     case Default: {
  278.       dc.BitBlt(glyphDstRect, memDC, TPoint(0,0));  
  279.       break;
  280.     }
  281.   }
  282. }
  283.  
  284. //
  285. //
  286. //
  287. void
  288. TUIFace::PaintText(const char far*, TDC&, const TRect&,
  289.                    const TPoint&, TState, bool)
  290. {
  291. }
  292.  
  293. //
  294. // Paint the face of a button onto a DC.
  295. // Assumes the entire bitmap is the face.
  296. //
  297. void
  298. TUIFace::Paint(TDC& dc, const TPoint& pt, TState state, bool pressed,
  299.                bool fillFace)
  300. {
  301.   if (Text)
  302.     PaintText(Text, dc, Rect, pt, state, fillFace);
  303.   else if (Bm)
  304.     PaintBm(*Bm, TRect(TPoint(0,0),Bm->Size()), dc, Rect, pt, state, pressed,
  305.             fillFace, BkgndColor, FillColor);
  306. }
  307.  
  308. //
  309. // Paint a portion of the source bitmap onto a DC.
  310. // This allows one bitmap to be the source for multiple TUIFaces.
  311. //
  312. void
  313. TUIFace::Paint(TDC& dc, const TRect& srcRect, const TPoint& pt, TState state,
  314.                bool pressed, bool fillFace)
  315. {
  316.   if (Text)
  317.     PaintText(Text, dc, Rect, pt, state, fillFace);
  318.   else if (Bm)
  319.     PaintBm(*Bm, srcRect, dc, Rect, pt, state, pressed,
  320.             fillFace, BkgndColor, FillColor);
  321. }
  322.  
  323. //
  324. // Encapsulates and emulate the 32-bit DrawState API.
  325. //
  326. #pragma warn -par  // most parameters unused in 16-bit build
  327. bool
  328. TUIFace::Draw(TDC& dc, HBRUSH hbr, LPARAM lp, WPARAM wp,
  329.               int x, int y, int cx, int cy, uint flags)
  330. {
  331. #if defined(BI_PLAT_WIN32)
  332.   static bool hasDrawState = true;
  333.  
  334.   // Try once to see if the API call is available. If not, do ourselves.
  335.   //
  336.   if (hasDrawState) {
  337.     if (::DrawState(dc, hbr, 0, lp, wp, x, y, cx, cy, flags))
  338.       return true;
  339.     if (::GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  340.       hasDrawState = false;  // No DrawState(). Don't try again, just emulate
  341.     else
  342.       return false;  // Some other error, just return
  343.   }
  344.  
  345.   return false;
  346. #else
  347.   uint type = flags & 0x000F;
  348. //  uint state= flags & 0xFFF0;
  349.  
  350.   switch (type) {
  351.     case DST_BITMAP:
  352.     case DST_ICON:
  353.     case DST_PREFIXTEXT:
  354.     case DST_TEXT:
  355.     default:
  356.       break;
  357.   }
  358.   return true;
  359. #endif
  360. }
  361. #pragma warn .par
  362.  
  363. //
  364. // Paint the mask onto a DC.
  365. //
  366. void
  367. TUIFace::PaintMaskBm(const TBitmap& glyph, TDC& dc, const TPoint& pt,
  368.                      const TColor& maskColor)
  369. {
  370.   // Create a DC to hold the image bitmap
  371.   //
  372.   TMemoryDC memDC;
  373.   memDC.SelectObject(glyph);
  374.  
  375.   // Create a DC to hold an "AND mask" of image and build the mask
  376.   //
  377.   TMemoryDC maskDC;
  378.   maskDC.SelectObject(GetGlyphMask(glyph.Size()));
  379.  
  380.   // Rectangle to hold mask of glyph
  381.   //
  382.   TRect  maskRect(TPoint(0,0), glyph.Size());
  383.  
  384.   // Build the mask
  385.   //
  386.   BuildMask(maskDC, TPoint(0, 0), glyph.Size(), memDC, maskRect, maskColor);
  387.  
  388.   // Make sure area under highlight color ends up fill color
  389.   //
  390.   // dc.TextRect(maskRect, FillColor);
  391.  
  392.   // Inactivate mask--convert the highlight color to 1's on existing mask
  393.   //
  394.   memDC.SetBkColor(TColor::Sys3dHilight);
  395.   maskDC.BitBlt(maskRect, memDC, maskRect.TopLeft(), SRCPAINT);
  396.  
  397.   dc.BitBlt(TRect(pt, maskRect.Size()), maskDC, TPoint(0,0));
  398. }
  399.  
  400. //
  401. // Paint the mask onto a DC.
  402. //
  403. void
  404. TUIFace::PaintMask(TDC& dc, const TPoint& pt)
  405. {
  406.   // ::DrawState()...
  407.  
  408.   if (Bm)
  409.     PaintMaskBm(*Bm, dc, pt, BkgndColor);
  410.   //else if (Text)
  411.   //  PaintMaskText(Text, dc, pt);
  412. }
  413.  
  414.