home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / BUTTONGA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  17.6 KB  |  712 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
  3. //   source\owl\buttonga.cpp
  4. //   Implementation of class TButtonGadget.
  5. //----------------------------------------------------------------------------
  6. #include <owl\owlpch.h>
  7. #include <owl\buttonga.h>
  8. #include <owl\gadgetwi.h>
  9. #include <owl\celarray.h>
  10.  
  11. //
  12. // make the monochrome bitmap large enough to hold any possible bitmap
  13. //
  14. #define GLYPH_MASK_WIDTH   128
  15. #define GLYPH_MASK_HEIGHT  128
  16. const long RopPSDPxax = 0x00B8074AL;  //
  17. const long RopDSPDxax = 0x00E20746L;  // 
  18.  
  19. //----------------------------------------------------------------------------
  20.  
  21. //
  22. // Mini 8x8 monochrome checkerboard dither brush class
  23. //
  24. class TDitherBrush : public TBrush {
  25.   public:
  26.     TDitherBrush();
  27.     void     Reconstruct();
  28.   private:
  29.     static HBRUSH CreateBrush();
  30. };
  31.  
  32. TDitherBrush::TDitherBrush()
  33.   : TBrush(CreateBrush(), AutoDelete)
  34. {
  35.   OBJ_REF_ADD(Handle, Brush);
  36. }
  37.  
  38. //
  39. // (re) constructs the dither brush with current system button colors
  40. //
  41. void
  42. TDitherBrush::Reconstruct()
  43. {
  44.   if (Handle)
  45.     ::DeleteObject(Handle);
  46.   Handle = CreateBrush();
  47. }
  48.  
  49. HBRUSH
  50. TDitherBrush::CreateBrush()
  51. {
  52.   TDib dib(8, 8, 2, DIB_RGB_COLORS);
  53.   unsigned char HUGE* bits = (unsigned char HUGE*)dib.GetBits();
  54.   memset(bits, 0, 8*sizeof(DWORD));
  55.   bits[0 * sizeof(DWORD)] = 0xAA;
  56.   bits[2 * sizeof(DWORD)] = 0xAA;
  57.   bits[4 * sizeof(DWORD)] = 0xAA;
  58.   bits[6 * sizeof(DWORD)] = 0xAA;
  59.   bits[1 * sizeof(DWORD)] = 0x55;
  60.   bits[3 * sizeof(DWORD)] = 0x55;
  61.   bits[5 * sizeof(DWORD)] = 0x55;
  62.   bits[7 * sizeof(DWORD)] = 0x55;
  63.   dib.SetColor(0, GetSysColor(COLOR_BTNFACE));
  64.   dib.SetColor(1, GetSysColor(COLOR_BTNHIGHLIGHT));
  65.  
  66.   HBRUSH Handle;
  67.   #if defined(__WIN32__)
  68.     Handle = ::CreateDIBPatternBrushPt((LPVOID)dib.GetInfo(), dib.Usage());
  69.     if (!Handle && ::GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  70.       Handle = ::CreateDIBPatternBrush(dib, dib.Usage());
  71.   #else
  72.     Handle = ::CreateDIBPatternBrush(dib, dib.Usage());
  73.   #endif
  74.  
  75.   CheckValid(Handle);
  76.   return Handle;
  77. }
  78.  
  79. //----------------------------------------------------------------------------
  80.  
  81. //
  82. // local 'class' vars
  83. //
  84. static TDitherBrush ditherBrush;
  85. static TBitmap      glyphMask(GLYPH_MASK_WIDTH, GLYPH_MASK_HEIGHT, 1, 1, 0);
  86.  
  87. //
  88. // command enabler for button gadgets
  89. //
  90. class _OWLCLASS TButtonGadgetEnabler : public TCommandEnabler {
  91.   public:
  92.     TButtonGadgetEnabler(HWND hWndReceiver, TButtonGadget* g)
  93.       : TCommandEnabler(g->GetId(), hWndReceiver) {
  94.       gadget = g;
  95.     }
  96.  
  97.     //
  98.     // override member functions of TCommandEnabler
  99.     //
  100.     void  Enable(BOOL);
  101.     void  SetText(LPCSTR);
  102.     void  SetCheck(int);
  103.  
  104.   protected:
  105.     TButtonGadget*  gadget;
  106. };
  107.  
  108. void
  109. TButtonGadgetEnabler::Enable(BOOL enable)
  110. {
  111.   TCommandEnabler::Enable(enable);
  112.   gadget->SetEnabled(enable);
  113. }
  114.  
  115. void
  116. TButtonGadgetEnabler::SetText(LPCSTR)
  117. {
  118.   #pragma warn -ccc
  119.   CHECK(FALSE);
  120.   #pragma warn .ccc
  121. }
  122.  
  123. void
  124. TButtonGadgetEnabler::SetCheck(int state)
  125. {
  126.   gadget->SetButtonState(TButtonGadget::TState(state));
  127. }
  128.  
  129. TButtonGadget::TButtonGadget(TResId bmpResId,
  130.                              int    id,
  131.                              TType  type,
  132.                              BOOL   enabled,
  133.                              TState state,
  134.                              BOOL   repeat)
  135.   : TGadget(id, Plain)
  136. {
  137.   ResId = bmpResId.IsString() ? strnewdup(bmpResId) : (char far*)bmpResId;
  138.   CelArray = 0;
  139.   BitmapOrigin.x = BitmapOrigin.y = 0;
  140.   Type = type;
  141.   Repeat = repeat;
  142.   TrackMouse = TRUE;
  143.   State = state;
  144.   NotchCorners = TRUE;
  145.   Pressed = FALSE;
  146.   SetEnabled(enabled);
  147.   SetShadowStyle(DoubleShadow);
  148.   SetAntialiasEdges(TRUE);
  149. }
  150.  
  151. TButtonGadget::~TButtonGadget()
  152. {
  153.   delete CelArray;
  154.   if (ResId.IsString())
  155.     delete (char far*)ResId;
  156. }
  157.  
  158. void
  159. TButtonGadget::SetShadowStyle(TShadowStyle shadowStyle)
  160. {
  161.   TBorders  borders;
  162.  
  163.   ShadowStyle = shadowStyle;
  164.   borders.Left = borders.Top = 2;
  165.   borders.Right = borders.Bottom = ShadowStyle + 1;
  166.   SetBorders(borders);
  167. }
  168.  
  169. void
  170. TButtonGadget::CommandEnable()
  171. {
  172.   //
  173.   // Can't post here since a ptr to a temp is passed
  174.   //
  175.   Window->Parent->HandleMessage(
  176.     WM_COMMAND_ENABLE,
  177.     0,
  178.     (LPARAM)&TButtonGadgetEnabler(*Window->Parent, this)
  179.   );
  180. }
  181.  
  182. void
  183. TButtonGadget::SysColorChange()
  184. {
  185.   ditherBrush.Reconstruct();
  186.   BuildCelArray();
  187. }
  188.  
  189. void
  190. TButtonGadget::CheckExclusively()
  191. {
  192.   if (State != Down) {
  193.     if (Window) {
  194.       TGadget*        g = Window->FirstGadget();
  195.       TButtonGadget*  first = 0;
  196.       TButtonGadget*  last = this;
  197.  
  198.       //
  199.       // look for the start of the group in which the receiver is located
  200.       //
  201.       while (g != this) {
  202.         if (((TButtonGadget*)g)->Type != Exclusive)
  203.           first = 0;
  204.  
  205.         else if (!first)
  206.           first = (TButtonGadget*)g;
  207.  
  208.         g = g->NextGadget();
  209.       }
  210.  
  211.       //
  212.       // look for the end of the group in which the receiver is located
  213.       //
  214.       while (last->NextGadget()) {
  215.         if (((TButtonGadget*)last->NextGadget())->Type != Exclusive)
  216.           break;
  217.  
  218.         else
  219.           last = (TButtonGadget*)last->NextGadget();
  220.       }
  221.  
  222.       if (!first)
  223.         first = this;
  224.  
  225.       while (TRUE) {
  226.         if (first->State == Down) {
  227.           first->State = Up;
  228.           first->Invalidate();
  229.           first->Update();
  230.         }
  231.  
  232.         if (first == last)
  233.           break;
  234.  
  235.         first = (TButtonGadget*)first->NextGadget();
  236.       }
  237.     }
  238.  
  239.     State = Down;
  240.   }
  241. }
  242.  
  243. void
  244. TButtonGadget::SetButtonState(TState state)
  245. {
  246.   if (state != State) {
  247.     if (Type == Exclusive && state == Down)
  248.       CheckExclusively();
  249.  
  250.     State = state;
  251.     Invalidate();
  252.     Update();
  253.   }
  254. }
  255.  
  256. void
  257. TButtonGadget::SetBounds(TRect& bounds)
  258. {
  259.   TRect  innerRect;
  260.   TSize  bitmapSize = CelArray->CelSize();
  261.  
  262.   TGadget::SetBounds(bounds);
  263.  
  264.   //
  265.   // center the glyph within the inner bounds
  266.   //
  267.   GetInnerRect(innerRect);
  268.  
  269.   BitmapOrigin.x = innerRect.left + (innerRect.Width() - bitmapSize.cx) / 2;
  270.   BitmapOrigin.y = innerRect.top + (innerRect.Height() - bitmapSize.cy) / 2;
  271. }
  272.  
  273. void
  274. TButtonGadget::GetDesiredSize(TSize& size)
  275. {
  276.   TGadget::GetDesiredSize(size);
  277.  
  278.   if (!CelArray)
  279.     BuildCelArray();
  280.  
  281.   size += CelArray->CelSize();
  282. }
  283.  
  284. //
  285. // determines the parts of "r1" that do not lie within "r2"
  286. //
  287. // returns the resulting number of rectangles which will be in the
  288. // range "0 .. 4" inclusive
  289. //
  290. UINT
  291. Subtract(TRect& r1, TRect& r2, TRect result[4])
  292. {
  293.   if (!r1.Touches(r2)) {
  294.     result[0] = r1;
  295.     return 1;
  296.  
  297.   } else {
  298.     UINT  i = 0;
  299.  
  300.     if (r2.top > r1.top) {
  301.       result[i].left = r1.left;
  302.       result[i].top = r1.top;
  303.       result[i].right = r1.right;
  304.       result[i].bottom = r2.top;
  305.       i++;
  306.     }
  307.  
  308.     if (r2.bottom < r1.bottom) {
  309.       result[i].left = r1.left;
  310.       result[i].top = r2.bottom;
  311.       result[i].right = r1.right;
  312.       result[i].bottom = r1.bottom;
  313.       i++;
  314.     }
  315.  
  316.     if (r2.left > r1.left) {
  317.       result[i].left = r1.left;
  318.       result[i].top = max(r1.top, r2.top);
  319.       result[i].right = r2.left;
  320.       result[i].bottom = min(r1.bottom, r2.bottom);
  321.       i++;
  322.     }
  323.  
  324.     if (r2.right < r1.right) {
  325.       result[i].left = r2.right;
  326.       result[i].top = max(r1.top, r2.top);
  327.       result[i].right = r1.right;
  328.       result[i].bottom = min(r1.bottom, r2.bottom);
  329.       i++;
  330.     }
  331.     return i;
  332.   }
  333. }
  334.  
  335. //
  336. // build a monochrome mask bitmap for the glyph that has 1's where
  337. // COLOR_BTNFACE is and 0's everywhere else. assumes glyphDC is already setup
  338. //
  339. static void
  340. BuildMask(TDC& maskDC, TRect& maskRect, TDC& glyphDC, TRect& glyphRect)
  341. {
  342.   maskDC.PatBlt(0, 0, maskRect.Width(), maskRect.Height(), WHITENESS);
  343.   glyphDC.SetBkColor(GetSysColor(COLOR_BTNFACE));  // btnface to white
  344.   maskDC.BitBlt(maskRect.left, maskRect.top, glyphRect.Width(), glyphRect.Height(),
  345.                 glyphDC, glyphRect.left, glyphRect.top, SRCCOPY);
  346. }
  347.  
  348. //
  349. // tiles the rectangle with a even dithered (checkerboard) pattern
  350. //
  351. // maskDC determines the stencil area of dither
  352. //
  353. static void
  354. DitherBackground(TDC& dc, TDC& maskDC, TRect& rect)
  355. {
  356.   dc.SelectObject(HBRUSH(ditherBrush));
  357.  
  358.   dc.SetTextColor(RGB(0, 0, 0));      // 0 to black
  359.   dc.SetBkColor(RGB(255, 255, 255));  // 1 to white
  360.  
  361.   dc.BitBlt(rect, maskDC, TPoint(0, 0), RopDSPDxax);
  362. }
  363.  
  364. //
  365. // virtual function responsible for supplying glyphdib. Can be overriden to
  366. // get dib from elsewhere, cache it, map colors differently, etc.
  367. //
  368. TDib*
  369. TButtonGadget::GetGlyphDib()
  370. {
  371.   TDib* glyph = new TDib(*Window->GetModule(), ResId);
  372.   glyph->MapUIColors(
  373.     TDib::MapFace | TDib::MapText | TDib::MapShadow | TDib::MapHighlight
  374.   );
  375.   return glyph;
  376. }
  377.  
  378. //
  379. // virtual function responsible for releasing glyph dib as needed based on how
  380. // GetGlyphDib() got it (if different from new/delete).
  381. //
  382. void
  383. TButtonGadget::ReleaseGlyphDib(TDib* glyph)
  384. {
  385.   delete glyph;
  386. }
  387.  
  388. //
  389. // Build the CelArray member using the resource bitmap as the base glyph
  390. // CelArray may contain an existing cel array that should be deleted if
  391. // replaced
  392. //
  393. void
  394. TButtonGadget::BuildCelArray()
  395. {
  396.   //
  397.   // Get the base glyph as a dib, & map the colors to current SysColors.
  398.   //
  399.   TDib*  glyph = GetGlyphDib();
  400.   TSize  celSize = glyph->Size();
  401.  
  402.   //
  403.   // Create a TCelArray if we don't already have one, else use existing one.
  404.   //
  405.   if (!CelArray) {
  406.     TBitmap*   bitmap = new TBitmap(TScreenDC(), celSize.cx*CelsTotal,
  407.                                     celSize.cy);
  408.     CelArray = new TCelArray(bitmap, CelsTotal);
  409.   }
  410.   
  411.   TMemoryDC maskDC;
  412.   maskDC.SelectObject(glyphMask);
  413.   TRect maskRect(0,0, celSize.cx, celSize.cy);
  414.  
  415.   TMemoryDC celDC;
  416.   celDC.SelectObject(*CelArray);
  417.   
  418.   //
  419.   // CelArray[CelNormal]: normal appearance, blit directly from the glyph dib
  420.   //
  421.   TRect nrmlCelRect = CelArray->CelRect(CelNormal);
  422.   celDC.StretchDIBits(nrmlCelRect, maskRect, *glyph);
  423.   
  424.   ReleaseGlyphDib(glyph);
  425.  
  426.   //
  427.   // CelArray[CelDisabled]: disabled variant of glyph
  428.   //
  429.   TRect celRect = CelArray->CelRect(CelDisabled);
  430.  
  431.   //
  432.   // make sure area under highlight color ends up face color
  433.   //
  434.   BuildMask(maskDC, maskRect, celDC, nrmlCelRect);
  435.   celDC.TextRect(celRect, GetSysColor(COLOR_BTNFACE));
  436.  
  437.   //
  438.   // inactivate mask--convert the highlight color to 1's on existing mask
  439.   //
  440.   celDC.SetBkColor(GetSysColor(COLOR_BTNHIGHLIGHT));
  441.   maskDC.BitBlt(maskRect, celDC, nrmlCelRect.TopLeft(), SRCPAINT);
  442.  
  443.   //
  444.   // make the image look embossed--highlight color offset down & right
  445.   //
  446.   celDC.SetTextColor(RGB(0, 0, 0));  // 0 to black
  447.   celDC.SetBkColor(RGB(255, 255, 255));  // 1 to white
  448.  
  449.   TBrush  hiliteBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
  450.   celDC.SelectObject(hiliteBrush);  // 0 -> highlight color
  451.   celDC.BitBlt(celRect.left + 1, celRect.top + 1,
  452.                celRect.Width() - 1, celRect.Height() - 1,
  453.                maskDC, 0, 0, RopPSDPxax);
  454.  
  455.   //
  456.   // fade the image by replacing the button text color with the button
  457.   // shadow color
  458.   //
  459.   TBrush  shadowBrush(GetSysColor(COLOR_BTNSHADOW));
  460.   celDC.SelectObject(shadowBrush);  // 0 -> shadow
  461.   celDC.BitBlt(celRect, maskDC, TPoint(0, 0), RopPSDPxax);
  462.  
  463.   //
  464.   // CelArray[CelIndeterm]: Indeterminate variant of glyph
  465.   //
  466.   celRect = CelArray->CelRect(CelIndeterm);
  467.  
  468.   //
  469.   // fade the image by replacing the button text color with the button
  470.   // shadow color
  471.   //
  472.   celDC.SelectObject(shadowBrush);  // 0 -> shadow
  473.   celDC.BitBlt(celRect, maskDC, TPoint(0, 0), RopPSDPxax);
  474.  
  475.   //
  476.   // dither the background everywhere except where the glyph is
  477.   //
  478.   DitherBackground(celDC, maskDC, celRect);
  479.  
  480.   //
  481.   // CelArray[CelDown]: Down (but not Pressed) variant of glyph
  482.   //
  483.   celRect = CelArray->CelRect(CelDown);
  484.   celDC.BitBlt(celRect, celDC, CelArray->CelRect(CelNormal).TopLeft(), SRCCOPY);
  485.  
  486.   //
  487.   // dither the background everywhere except where the glyph is
  488.   //
  489.   BuildMask(maskDC, maskRect, celDC, celRect);
  490.   DitherBackground(celDC, maskDC, celRect);
  491.  
  492.   maskDC.RestoreBitmap();
  493.   celDC.RestoreBitmap();
  494.   celDC.RestoreBitmap();
  495.   celDC.RestoreBrush();
  496. }
  497.  
  498. //
  499. //
  500. //
  501. void
  502. TButtonGadget::Paint(TDC& dc)
  503. {
  504.   int     cxBorder = GetSystemMetrics(SM_CXBORDER);
  505.   int     cyBorder = GetSystemMetrics(SM_CYBORDER);
  506.   TPoint  bitmapOrigin = BitmapOrigin;
  507.   TRect   innerRect(cxBorder, cyBorder,
  508.                     Bounds.Width()-cxBorder, Bounds.Height()-cyBorder);
  509.  
  510.   PaintBorder(dc);  // Assumes Plain border--other styles will be overpainted
  511.  
  512.   TBrush  faceBrush(GetSysColor(COLOR_BTNFACE));
  513.   TBrush  hiliteBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
  514.   TBrush  shadowBrush(GetSysColor(COLOR_BTNSHADOW));
  515.  
  516.   //
  517.   // draw top and left
  518.   //
  519.   int shadow = Pressed && Type != Command ? 2 : 1;
  520.   dc.SelectObject(Pressed || State == Down ? shadowBrush : hiliteBrush);
  521.   dc.PatBlt(innerRect.left, innerRect.top,
  522.             innerRect.Width(), shadow * cyBorder, PATCOPY);
  523.   dc.PatBlt(innerRect.left, innerRect.top,
  524.             shadow * cxBorder, innerRect.Height(), PATCOPY);
  525.  
  526.   if (Pressed || State == Down) {
  527.     innerRect.left += shadow * cxBorder;
  528.     innerRect.top += shadow * cyBorder;
  529.  
  530.   } else {
  531.     int  i = 0;
  532.  
  533.     //
  534.     // draw right and bottom
  535.     //
  536.     dc.SelectObject(shadowBrush);
  537.     innerRect.bottom -= cyBorder;
  538.     innerRect.right -= cxBorder;
  539.  
  540.     while (TRUE) {
  541.       dc.PatBlt(innerRect.left, innerRect.bottom,
  542.                 innerRect.Width() + cxBorder, cyBorder, PATCOPY);
  543.       dc.PatBlt(innerRect.right, innerRect.top,
  544.                 cxBorder, innerRect.Height(), PATCOPY);
  545.  
  546.       if (++i == ShadowStyle)
  547.         break;
  548.  
  549.       innerRect.Inflate(-cxBorder, -cyBorder);
  550.     }
  551.   }
  552.  
  553.   if (NotchCorners || AntialiasEdges && State == Up && !Pressed) {
  554.     dc.SelectObject(faceBrush);
  555.     
  556.     if (NotchCorners) {
  557.       dc.PatBlt(0, 0, cxBorder, cyBorder);
  558.       dc.PatBlt(Bounds.Width() - cxBorder, 0, cxBorder, cyBorder);
  559.       dc.PatBlt(0, Bounds.Height() - cyBorder, cxBorder, cyBorder);
  560.       dc.PatBlt(Bounds.Width() - cxBorder, Bounds.Height() - cyBorder,
  561.                 cxBorder, cyBorder);
  562.     }
  563.     if (AntialiasEdges && State == Up && !Pressed) {
  564.       TRect edge(0, 0, Bounds.Width(), Bounds.Height());
  565.       for (int i = 0; i <= shadow; i++) {
  566.         edge.Inflate(-cxBorder,-cyBorder);
  567.         dc.PatBlt(edge.right-cxBorder, edge.top, cxBorder, cyBorder);
  568.         dc.PatBlt(edge.left, edge.bottom-cyBorder, cxBorder, cyBorder);
  569.       }
  570.     }
  571.     dc.RestoreBrush();
  572.   }
  573.  
  574.   //
  575.   // adjust the bitmap origin based on the state
  576.   //
  577.   if (Pressed || State == Down)
  578.     bitmapOrigin.Offset(shadow * cxBorder, shadow * cyBorder);
  579.   TRect  bitmapRect(bitmapOrigin, CelArray->CelSize());
  580.  
  581.   TMemoryDC celDC;
  582.   celDC.SelectObject(*CelArray);
  583.  
  584.   //
  585.   // blit the appropriate cel at the calculated origin
  586.   //
  587.   if (!GetEnabled() || State == Indeterminate) {
  588.     if (!GetEnabled())
  589.       dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelDisabled).TopLeft());
  590.  
  591.     else //(State == Indeterminate)
  592.       dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelIndeterm).TopLeft());
  593.  
  594.   } else {
  595.     TRect dirtyRects[4];
  596.     int   numRects = Subtract(innerRect, bitmapRect, dirtyRects);
  597.     if (numRects) {
  598.       dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
  599.       while (numRects--)
  600.         dc.TextRect(dirtyRects[numRects]);
  601.     }
  602.     if (State == Down && !Pressed)
  603.       dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelDown).TopLeft());
  604.     else //(State == Up || Pressed)
  605.       dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelNormal).TopLeft());
  606.   }
  607.  
  608.   celDC.RestoreBitmap();
  609.   dc.RestoreBrush();
  610. }
  611.  
  612. void
  613. TButtonGadget::Invalidate()
  614. {
  615.   TRect  r(0, 0, Bounds.Width(), Bounds.Height());
  616.  
  617.   r.Inflate(-GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
  618.   InvalidateRect(r, FALSE);
  619. }
  620.  
  621. //
  622. // Begin button pressed state, repaint & enter menuselect state
  623. //
  624. void
  625. TButtonGadget::BeginPressed(TPoint&)
  626. {
  627.   Pressed = TRUE;
  628.   Invalidate();
  629.   Update();
  630.   if (Window->GetHintMode() == TGadgetWindow::PressHints)
  631.     Window->SetHintCommand(GetId());
  632. }
  633.  
  634. //
  635. // Cancel pressed state, repaint & end menuselect state
  636. //
  637. void
  638. TButtonGadget::CancelPressed(TPoint&)
  639. {
  640.   Pressed = FALSE;
  641.   Invalidate();
  642.   Update();
  643.   if (Window->GetHintMode() == TGadgetWindow::PressHints)
  644.     Window->SetHintCommand(-1);
  645. }
  646.  
  647. void
  648. TButtonGadget::Activate(TPoint& pt)
  649. {
  650.   switch (Type) {
  651.     case Exclusive:
  652.       if (State != Down)
  653.         CheckExclusively();
  654.       break;
  655.  
  656.     case NonExclusive:
  657.       State = State == Up ? Down : Up;
  658.       break;
  659.   }
  660.  
  661.   CancelPressed(pt);
  662.  
  663.   if (!(Type == Exclusive && State != Down))
  664.     Window->Parent->PostMessage(WM_COMMAND, GetId());
  665. }
  666.  
  667. void
  668. TButtonGadget::LButtonDown(UINT modKeys, TPoint& pt)
  669. {
  670.   TGadget::LButtonDown(modKeys, pt);
  671.   BeginPressed(pt);
  672. }
  673.  
  674. void
  675. TButtonGadget::MouseMove(UINT modKeys, TPoint& pt)
  676. {
  677.   TGadget::MouseMove(modKeys, pt);
  678.  
  679.   BOOL  hit = PtIn(pt);
  680.   if (Pressed) {
  681.     if (!hit)
  682.       CancelPressed(pt);
  683.  
  684.   } else if (hit) {
  685.     BeginPressed(pt);
  686.   }
  687. }
  688.  
  689. void
  690. TButtonGadget::MouseEnter(UINT modKeys, TPoint& pt)
  691. {
  692.   TGadget::MouseEnter(modKeys, pt);
  693.   if (Window->GetHintMode() == TGadgetWindow::EnterHints)
  694.     Window->SetHintCommand(GetId());
  695. }
  696.  
  697. void
  698. TButtonGadget::MouseLeave(UINT modKeys, TPoint& pt)
  699. {
  700.   TGadget::MouseLeave(modKeys, pt);
  701.   if (Window->GetHintMode() == TGadgetWindow::EnterHints)
  702.     Window->SetHintCommand(-1);
  703. }
  704.  
  705. void
  706. TButtonGadget::LButtonUp(UINT modKeys, TPoint& pt)
  707. {
  708.   TGadget::LButtonUp(modKeys, pt);
  709.   if (Pressed)
  710.     Activate(pt);
  711. }
  712.