home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / GADGETWI.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  16.9 KB  |  745 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TGadgetWindow.
  6. //----------------------------------------------------------------------------
  7. #include <owl/owlpch.h>
  8. #include <owl/gadget.h>
  9. #include <owl/gadgetwi.h>
  10.  
  11. DEFINE_RESPONSE_TABLE1(TGadgetWindow, TWindow)
  12.   EV_WM_CTLCOLOR,
  13.   EV_WM_LBUTTONDOWN,
  14.   EV_WM_LBUTTONUP,
  15.   EV_WM_LBUTTONDBLCLK,
  16.   EV_WM_MOUSEMOVE,
  17.   EV_WM_SIZE,
  18.   EV_WM_SYSCOLORCHANGE,
  19. END_RESPONSE_TABLE;
  20.  
  21. static inline int HeightInPixels(int pointSize)
  22. {
  23.   TScreenDC  dc;
  24.   return MulDiv(-pointSize, dc.GetDeviceCaps(LOGPIXELSY), 72);
  25. }
  26.  
  27. TGadgetWindowFont::TGadgetWindowFont(int pointSize, bool bold, bool italic)
  28. :
  29.   TFont("MS Sans Serif", HeightInPixels(pointSize), 0, 0, 0,
  30.         bold ? FW_BOLD : FW_NORMAL,
  31.         uint8(VARIABLE_PITCH | FF_SWISS), uint8(italic))
  32. {
  33. }
  34.  
  35. TGadgetWindow::TGadgetWindow(TWindow*       parent,
  36.                              TTileDirection direction,
  37.                              TFont*         font,
  38.                              TModule*       module)
  39. :
  40.   TWindow(parent, 0, module)
  41. {
  42.   PRECONDITION(font);
  43.  
  44.   Attr.Style |= WS_BORDER;
  45.   Capture = 0;
  46.   AtMouse = 0;
  47.   Font = font;
  48.   Direction = direction;
  49.   if (Direction == Horizontal) {
  50.     ShrinkWrapWidth = false;
  51.     ShrinkWrapHeight = true;
  52.   }
  53.   else {
  54.     ShrinkWrapWidth = true;
  55.     ShrinkWrapHeight = false;
  56.   }
  57.   HintMode = PressHints;
  58.  
  59.   WideAsPossible = 0;  // number of gadgets with "WideAsPossible" set
  60.   DirtyLayout = true;
  61.   Gadgets = 0;
  62.   NumGadgets = 0;
  63.  
  64.   //
  65.   // compute the font height
  66.   //
  67.   TScreenDC   dc;
  68.   TEXTMETRIC  metrics;
  69.  
  70.   dc.SelectObject(*Font);
  71.   dc.GetTextMetrics(metrics);
  72.   FontHeight = metrics.tmHeight + metrics.tmExternalLeading;
  73.  
  74.   //
  75.   // choose a default height based on the height of the font plus room
  76.   // for a top and bottom border
  77.   //
  78.   Attr.H = FontHeight;
  79.  
  80.   if (Attr.Style & WS_BORDER)
  81.     Attr.H += 2 * GetSystemMetrics(SM_CYBORDER);
  82.  
  83.   SetBkgndColor(GetSysColor(COLOR_BTNFACE));
  84.   BkgndBrush = new TBrush(GetSysColor(COLOR_BTNFACE));
  85. }
  86.  
  87. TGadgetWindow::~TGadgetWindow()
  88. {
  89.   TGadget* gadget = Gadgets;
  90.  
  91.   while (gadget) {
  92.     TGadget*  tmp = gadget;
  93.  
  94.     gadget = gadget->Next;
  95.     delete tmp;
  96.   }
  97.  
  98.   delete Font;
  99.   delete BkgndBrush;
  100. }
  101.  
  102. void
  103. TGadgetWindow::EvSysColorChange()
  104. {
  105.   for (TGadget* g = Gadgets; g; g = g->NextGadget())
  106.     g->SysColorChange();
  107.   SetBkgndColor(GetSysColor(COLOR_BTNFACE));
  108.   delete BkgndBrush;
  109.   BkgndBrush = new TBrush(GetSysColor(COLOR_BTNFACE));
  110. }
  111.  
  112. bool
  113. TGadgetWindow::IdleAction(long idleCount)
  114. {
  115.   if (idleCount == 0) {
  116.     // See if we missed a mouse move & still need to send a MouseLeave to a
  117.     // gadget
  118.     //
  119.     if (AtMouse) {
  120.       TPoint crsPoint;
  121.       GetCursorPos(crsPoint);
  122.       if (WindowFromPoint(crsPoint) != HWindow)
  123.         HandleMessage(WM_MOUSEMOVE, 0, MAKELPARAM(-1,-1));  // nowhere
  124.     }
  125.  
  126.     // Let the gadgets do command enabling if they need to
  127.     //
  128.     for (TGadget* g = Gadgets; g; g = g->NextGadget())
  129.       g->CommandEnable();
  130.   }
  131.   return TWindow::IdleAction(idleCount);
  132. }
  133.  
  134. TGadget*
  135. TGadgetWindow::GadgetWithId(int id) const
  136. {
  137.   for (TGadget* g = Gadgets; g; g = g->NextGadget())
  138.     if (g->GetId() == id)
  139.       return g;
  140.  
  141.   return 0;
  142. }
  143.  
  144. void
  145. TGadgetWindow::SetShrinkWrap(bool shrinkWrapWidth, bool shrinkWrapHeight)
  146. {
  147.   ShrinkWrapWidth = shrinkWrapWidth;
  148.   ShrinkWrapHeight = shrinkWrapHeight;
  149. }
  150.  
  151. bool
  152. TGadgetWindow::GadgetSetCapture(TGadget& gadget)
  153. {
  154.   if (Capture) {
  155.     return false;
  156.   }
  157.   else {
  158.     Capture = &gadget;
  159.     SetCapture();
  160.     return true;
  161.   }
  162. }
  163.  
  164. void
  165. TGadgetWindow::GadgetReleaseCapture(TGadget& gadget)
  166. {
  167.   if (&gadget == Capture) {
  168.     Capture = 0;
  169.     ReleaseCapture();
  170.   }
  171. }
  172.  
  173. //
  174. // Simulate menu select & idle messages to our parent so that it can display
  175. // hint text the same way it does for menu commands
  176. //
  177. void
  178. TGadgetWindow::SetHintCommand(int id)
  179. {
  180.   if (Parent) {
  181.     if (id > 0)
  182.       Parent->HandleMessage(WM_MENUSELECT, id, 0);
  183.  
  184.     else
  185.       // Send a menuselect w/ flags==0xFFFF and hMenu==0 to indicate end
  186.       //
  187. #if defined(BI_PLAT_WIN32)
  188.       Parent->HandleMessage(WM_MENUSELECT, 0xFFFF0000, 0); // flags+item, hmenu
  189. #else
  190.       Parent->HandleMessage(WM_MENUSELECT, 0, 0x0000FFFFL);// item, hmenu+flags
  191. #endif
  192.  
  193.     Parent->HandleMessage(WM_ENTERIDLE, MSGF_MENU);
  194.   }
  195. }
  196.  
  197. void
  198. TGadgetWindow::SetMargins(TMargins& margins)
  199. {
  200.   Margins = margins;
  201.   LayoutSession();
  202. }
  203.  
  204. int
  205. TGadgetWindow::LayoutUnitsToPixels(int units)
  206. {
  207.   const long  UnitsPerEM = 8;
  208.  
  209.   return int((long(units) * FontHeight + UnitsPerEM / 2) / UnitsPerEM);
  210. }
  211.  
  212. void
  213. TGadgetWindow::GetMargins(TMargins& margins,
  214.                           int& left, int& right, int& top, int& bottom)
  215. {
  216.   switch (margins.Units) {
  217.     case TMargins::Pixels:
  218.       left = margins.Left;
  219.       top = margins.Top;
  220.       right = margins.Right;
  221.       bottom = margins.Bottom;
  222.       break;
  223.  
  224.     case TMargins::LayoutUnits:
  225.       left = LayoutUnitsToPixels(margins.Left);
  226.       top = LayoutUnitsToPixels(margins.Top);
  227.       right = LayoutUnitsToPixels(margins.Right);
  228.       bottom = LayoutUnitsToPixels(margins.Bottom);
  229.       break;
  230.  
  231.     case TMargins::BorderUnits:
  232.       int  cxBorder = GetSystemMetrics(SM_CXBORDER);
  233.       int  cyBorder = GetSystemMetrics(SM_CYBORDER);
  234.  
  235.       left = margins.Left * cxBorder;
  236.       top = margins.Top * cyBorder;
  237.       right = margins.Right * cxBorder;
  238.       bottom = margins.Bottom * cyBorder;
  239.       break;
  240.   }
  241. }
  242.  
  243. void
  244. TGadgetWindow::LayoutSession()
  245. {
  246.   if (HWindow)
  247.     InvalidateRect(TileGadgets());
  248. }
  249.  
  250. void
  251. TGadgetWindow::GetDesiredSize(TSize& size)
  252. {
  253.   int       left, right, top, bottom;
  254.   int       maxWidth = 0, maxHeight = 0;
  255.   TGadget*  lastGadget = 0;
  256.  
  257.   GetMargins(Margins, left, right, top, bottom);
  258.  
  259.   if (ShrinkWrapWidth || ShrinkWrapHeight) {
  260.     for (TGadget* gadget = Gadgets; gadget; gadget = gadget->Next) {
  261.       TSize  size;
  262.  
  263.       gadget->GetDesiredSize(size);
  264.  
  265.       if (size.cx > maxWidth)
  266.         maxWidth = size.cx;
  267.  
  268.       if (size.cy > maxHeight)
  269.         maxHeight = size.cy;
  270.     }
  271.  
  272.     //
  273.     // in some cases we need to actually tile the gadgets in order to tell how
  274.     // much room is needed
  275.     //
  276.     if (Direction == Horizontal && ShrinkWrapWidth ||
  277.         Direction == Vertical && ShrinkWrapHeight) {
  278.       TileGadgets();
  279.  
  280.       for (lastGadget = Gadgets; lastGadget && lastGadget->Next; lastGadget = lastGadget->Next)
  281.         ;
  282.     }
  283.   }
  284.  
  285.   if (!ShrinkWrapWidth)
  286.     size.cx = Attr.W;
  287.  
  288.   else if (Direction == Horizontal) {
  289.     size.cx = right;
  290.  
  291.     if (lastGadget)
  292.       size.cx += lastGadget->GetBounds().right;
  293.   }
  294.   else {
  295.     size.cx = left + right + maxWidth;
  296.  
  297.     if (Attr.Style & WS_BORDER)
  298.       size.cx += 2 * GetSystemMetrics(SM_CXBORDER);
  299.   }
  300.  
  301.   if (!ShrinkWrapHeight)
  302.     size.cy = Attr.H;
  303.  
  304.   else if (Direction == Vertical) {
  305.     size.cx = bottom;
  306.  
  307.     if (lastGadget)
  308.       size.cx += lastGadget->GetBounds().bottom;
  309.   }
  310.   else {
  311.     size.cy = top + bottom + maxHeight;
  312.  
  313.     if (Attr.Style & WS_BORDER)
  314.       size.cy += 2 * GetSystemMetrics(SM_CYBORDER);
  315.   }
  316. }
  317.  
  318. bool
  319. TGadgetWindow::Create()
  320. {
  321.   TSize  size;
  322.  
  323.   GetDesiredSize(size);
  324.  
  325.   if (ShrinkWrapWidth)
  326.     Attr.W = size.cx;
  327.  
  328.   if (ShrinkWrapHeight)
  329.     Attr.H = size.cy;
  330.  
  331.   bool r =  TWindow::Create();
  332.  
  333.   GetDesiredSize(size);
  334.   if ((ShrinkWrapWidth && Attr.W != size.cx) || (ShrinkWrapHeight &&  Attr.H != size.cy)) {
  335.     if (ShrinkWrapWidth)
  336.       Attr.W = size.cx;
  337.  
  338.     if (ShrinkWrapHeight)
  339.       Attr.H = size.cy;
  340.  
  341.     LayoutSession();
  342.   }
  343.  
  344.   return r;
  345. }
  346.  
  347. //
  348. // Set direction, & default shrink wrap flags. If already created, then also
  349. // adjust shrink wrap dimension & re-layout
  350. //
  351. void
  352. TGadgetWindow::SetDirection(TTileDirection direction)
  353. {
  354.   if (Direction != direction) {
  355.     Direction = direction;
  356.     if (Direction == Horizontal) {
  357.       ShrinkWrapWidth = false;
  358.       ShrinkWrapHeight = true;
  359.     }
  360.     else {
  361.       ShrinkWrapWidth = true;
  362.       ShrinkWrapHeight = false;
  363.     }
  364.     //
  365.     // Swap margin's X & Y axis
  366.     //
  367.     int t = Margins.Left; Margins.Left = Margins.Top; Margins.Top = t;
  368.     t = Margins.Right; Margins.Right = Margins.Bottom; Margins.Bottom = t;
  369.  
  370.     if (HWindow) {
  371.       TSize  size;
  372.       GetDesiredSize(size);
  373.  
  374.       if (ShrinkWrapWidth)
  375.         Attr.W = size.cx;
  376.  
  377.       if (ShrinkWrapHeight)
  378.         Attr.H = size.cy;
  379.  
  380.       LayoutSession();
  381.     }
  382.   }
  383. }
  384.  
  385. void
  386. TGadgetWindow::GetInnerRect(TRect& rect)
  387. {
  388.   int left, right, top, bottom;
  389.   GetMargins(Margins, left, right, top, bottom);
  390.  
  391.   rect.left = left;
  392.   rect.right = Attr.W - right;
  393.   rect.top = top;
  394.   rect.bottom = Attr.H - bottom;
  395.  
  396.   if (Attr.Style & WS_BORDER) {
  397.     rect.right -= 2 * GetSystemMetrics(SM_CYBORDER);
  398.     rect.bottom -= 2 * GetSystemMetrics(SM_CXBORDER);
  399.   }
  400. }
  401.  
  402. void
  403. TGadgetWindow::PositionGadget(TGadget*, TGadget*, TPoint&)
  404. {
  405. }
  406.  
  407. TRect
  408. TGadgetWindow::TileHorizontally()
  409. {
  410.   TRect  innerRect;
  411.   TRect  invalidRect;
  412.   int    width = 0;
  413.   int    x;
  414.  
  415.   GetInnerRect(innerRect);
  416.   invalidRect.SetEmpty();
  417.  
  418.   //
  419.   // first pass tally the width of all gadgets that don't have "WideAsPossible"
  420.   // set
  421.   //
  422.   // NOTE: we must also take into account any adjustments to the gadget spacing
  423.   //
  424.   for (TGadget* gadget = Gadgets; gadget; gadget = gadget->Next) {
  425.     if (!gadget->WideAsPossible) {
  426.       TSize   desiredSize;
  427.  
  428.       gadget->GetDesiredSize(desiredSize);
  429.       width += desiredSize.cx;
  430.     }
  431.  
  432.     if (gadget->Next) {
  433.       TPoint  spacing(0, 0);
  434.  
  435.       PositionGadget(gadget, gadget->Next, spacing);
  436.       width += spacing.x;
  437.     }
  438.   }
  439.  
  440.   //
  441.   // now tile all the gadgets
  442.   //
  443.   x = innerRect.left;
  444.   for (gadget = Gadgets; gadget; gadget = gadget->Next) {
  445.     TRect  bounds = gadget->Bounds;
  446.     TRect  originalBounds(bounds);
  447.     TSize  desiredSize;
  448.  
  449.     bounds.left = x;
  450.     gadget->GetDesiredSize(desiredSize);
  451.     bounds.top = innerRect.top + (innerRect.Height() - desiredSize.cy) / 2;
  452.     bounds.bottom = bounds.top + desiredSize.cy;
  453.  
  454.     if (gadget->WideAsPossible)
  455.       bounds.right = bounds.left + (innerRect.Width() - width) / WideAsPossible;
  456.  
  457.     else
  458.       bounds.right = bounds.left + desiredSize.cx;
  459.  
  460.     if (bounds != originalBounds) {
  461.       gadget->SetBounds(bounds);
  462.       invalidRect |= bounds;
  463.  
  464.       if (originalBounds.TopLeft() != TPoint(0, 0))
  465.         invalidRect |= originalBounds;
  466.     }
  467.     x += bounds.Width();
  468.  
  469.     if (gadget->Next) {
  470.       TPoint  origin(x, 0);
  471.  
  472.       PositionGadget(gadget, gadget->Next, origin);
  473.       x = origin.x;
  474.     }
  475.   }
  476.   return invalidRect;
  477. }
  478.  
  479. TRect
  480. TGadgetWindow::TileVertically()
  481. {
  482.   TRect  innerRect;
  483.   TRect  invalidRect;
  484.   int    y;
  485.  
  486.   GetInnerRect(innerRect);
  487.   invalidRect.SetEmpty();
  488.  
  489.   //
  490.   // now tile all the gadgets
  491.   //
  492.   y = innerRect.top;
  493.   for (TGadget* gadget = Gadgets; gadget; gadget = gadget->Next) {
  494.     TRect  bounds = gadget->Bounds;
  495.     TRect  originalBounds(bounds);
  496.     TSize  desiredSize;
  497.  
  498.     gadget->GetDesiredSize(desiredSize);
  499.     bounds.top = y;
  500.     bounds.bottom = bounds.top + desiredSize.cy;
  501.     bounds.left = innerRect.left + (innerRect.Width() - desiredSize.cx) / 2;
  502.     bounds.right = bounds.left + desiredSize.cx;
  503.  
  504.     if (bounds != originalBounds) {
  505.       gadget->SetBounds(bounds);
  506.       invalidRect |= bounds;
  507.  
  508.       if (originalBounds.TopLeft () != TPoint (0, 0))
  509.         invalidRect |= originalBounds;
  510.     }
  511.  
  512.     y += bounds.Height();
  513.  
  514.     if (gadget->Next) {
  515.       TPoint  origin(0, y);
  516.  
  517.       PositionGadget(gadget, gadget->Next, origin);
  518.       y = origin.y;
  519.     }
  520.   }
  521.   return invalidRect;
  522. }
  523.  
  524. TRect
  525. TGadgetWindow::TileGadgets()
  526. {
  527.   return (Direction == Horizontal) ? TileHorizontally() : TileVertically();
  528. }
  529.  
  530. void
  531. TGadgetWindow::GadgetChangedSize(TGadget&)
  532. {
  533.   LayoutSession();
  534. }
  535.  
  536. void
  537. TGadgetWindow::Insert(TGadget& gadget, TPlacement placement, TGadget* sibling)
  538. {
  539.   PRECONDITION(!gadget.Window);
  540.  
  541.   TGadget**  g = &Gadgets;
  542.  
  543.   if (sibling || placement == After) {
  544.     while (*g && *g != sibling)
  545.       g = &(*g)->Next;
  546.  
  547.     CHECK(*g == sibling);
  548.   }
  549.  
  550.   if (placement == After && *g)
  551.     g = &(*g)->Next;
  552.  
  553.   gadget.Next = *g;
  554.   *g = &gadget;
  555.  
  556.   gadget.Window = this;
  557.   NumGadgets++;
  558.   gadget.Inserted();
  559.  
  560.   if (gadget.WideAsPossible)
  561.     WideAsPossible++;
  562. }
  563.  
  564. //
  565. // remove a gadget from the gadget window's list
  566. //
  567. TGadget*
  568. TGadgetWindow::Remove(TGadget& gadget)
  569. {
  570.   if (gadget.Window != this || !Gadgets)
  571.     return 0;
  572.  
  573.   //
  574.   // handle head-of-list case
  575.   //
  576.   if (&gadget == Gadgets) {
  577.     Gadgets = Gadgets->Next;
  578.   }
  579.   //
  580.   // scan for gadget, looking one link ahead
  581.   //
  582.   else {
  583.     TGadget* g = Gadgets;
  584.  
  585.     while (g->Next && g->Next != &gadget)
  586.       g = g->Next;
  587.  
  588.     if (!g->Next)   // not found
  589.       return 0;
  590.  
  591.     g->Next = g->Next->Next;
  592.   }
  593.  
  594.   NumGadgets--;
  595.  
  596.   //
  597.   // re-adjust gadget now that it doesn't live in a window
  598.   //
  599.   if (gadget.WideAsPossible)
  600.     WideAsPossible--;
  601.   if (&gadget == AtMouse)
  602.     AtMouse = 0;
  603.   GadgetReleaseCapture(gadget);
  604.   gadget.Removed();
  605.   gadget.Window = 0;
  606.   gadget.Next = 0;
  607.   gadget.GetBounds() -= gadget.GetBounds().TopLeft();
  608.  
  609.   return &gadget;
  610. }
  611.  
  612. void
  613. TGadgetWindow::EvSize(uint sizeType, TSize& size)
  614. {
  615.   TWindow::EvSize(sizeType, size);
  616.  
  617.   if (DirtyLayout || WideAsPossible > 0) {
  618.     DirtyLayout = false;
  619.     TileGadgets();
  620.     Invalidate();
  621.   }
  622. }
  623.  
  624. //
  625. // Iterate thru the gadget list and paint each one.
  626. //
  627. void
  628. TGadgetWindow::PaintGadgets(TDC& dc, bool, TRect& rect)
  629. {
  630.   TPoint viewport = dc.GetViewportOrg();
  631.   for (TGadget* gadget = Gadgets; gadget; gadget = gadget->Next) {
  632.     if (gadget->Bounds.Touches(rect)) {
  633.       dc.SetViewportOrg((TPoint&)gadget->Bounds);
  634.  
  635.       if (gadget->Clip) {
  636.         dc.SaveDC();
  637.         dc.IntersectClipRect(gadget->Bounds);
  638.       }
  639.  
  640.       gadget->Paint(dc);
  641.  
  642.       if (gadget->Clip)
  643.         dc.RestoreDC();
  644.     }
  645.   }
  646.   dc.SetViewportOrg(viewport);
  647. }
  648.  
  649. void
  650. TGadgetWindow::Paint(TDC& dc, bool erase, TRect& rect)
  651. {
  652.   dc.SelectObject(*Font);
  653.   PaintGadgets(dc, erase, rect);
  654. }
  655.  
  656. //
  657. // Return gadget that a given window-relative point is in, 0 if none
  658. //
  659. TGadget*
  660. TGadgetWindow::GadgetFromPoint(TPoint& point) const
  661. {
  662.   for (TGadget* gadget = Gadgets; gadget; gadget = gadget->Next)
  663.     if (gadget->PtIn(point - *(TSize*)&gadget->Bounds.TopLeft()))
  664.       break;
  665.  
  666.   return gadget;
  667. }
  668.  
  669. HBRUSH
  670. TGadgetWindow::EvCtlColor(HDC hDC, HWND /*hWndChild*/, uint /*ctlType*/)
  671. {
  672.   ::SetBkColor(hDC, BkgndColor);
  673.   return HBRUSH(*BkgndBrush);
  674. }
  675.  
  676. //
  677. // Determine if the mouse down is in an enabled gadget, & if so pass it to
  678. // the gadget.
  679. //
  680. void
  681. TGadgetWindow::EvLButtonDown(uint modKeys, TPoint& point)
  682. {
  683.   TGadget* gadget = Capture ? Capture : GadgetFromPoint(point);
  684.  
  685.   if (gadget && (gadget->GetEnabled() || Capture))
  686.     gadget->LButtonDown(modKeys, point - *(TSize*)&gadget->Bounds.TopLeft());
  687.  
  688.   TWindow::EvLButtonDown(modKeys, point);
  689. }
  690.  
  691. //
  692. // Forward mouse ups to the gadget that has captures the mouse, if any, or
  693. // to the gadget at the mouse pos
  694. //
  695. void
  696. TGadgetWindow::EvLButtonUp(uint modKeys, TPoint& point)
  697. {
  698.   TGadget* gadget = Capture ? Capture : GadgetFromPoint(point);
  699.  
  700.   if (gadget && (gadget->GetEnabled() || Capture))
  701.     gadget->LButtonUp(modKeys, TPoint(point.x - gadget->Bounds.left,
  702.                                       point.y - gadget->Bounds.top));
  703.   TWindow::EvLButtonUp(modKeys, point);
  704. }
  705.  
  706. //
  707. // Pass double clicks thru as if they were just a second click, finish the
  708. // first click, & begin the second. Dn + Dbl + Up -> Dn + Up+Dn + Up
  709. //
  710. void
  711. TGadgetWindow::EvLButtonDblClk(uint modKeys, TPoint& point)
  712. {
  713.   EvLButtonUp(modKeys, point);
  714.   EvLButtonDown(modKeys, point);
  715. }
  716.  
  717. //
  718. // Forward mouse moves to the gadget that has captures the mouse, if any.
  719. // Otherwise checks for mouse entering & leaving gadgets
  720. //
  721. // Could enhance this by delaying mouse enter messages until mouse has been
  722. // in the same area for a while, or looking ahead in queue for mouse msgs.
  723. //
  724. void
  725. TGadgetWindow::EvMouseMove(uint modKeys, TPoint& point)
  726. {
  727.   if (Capture) {
  728.     Capture->MouseMove(modKeys, TPoint(point.x - Capture->Bounds.left,
  729.                                        point.y - Capture->Bounds.top));
  730.   }
  731.   else {
  732.     TGadget* gadget = GadgetFromPoint(point);
  733.     if (gadget != AtMouse) {
  734.       if (AtMouse)
  735.         AtMouse->MouseLeave(modKeys, TPoint(point.x - AtMouse->Bounds.left,
  736.                                             point.y - AtMouse->Bounds.top));
  737.       AtMouse = gadget;
  738.       if (AtMouse)
  739.         AtMouse->MouseEnter(modKeys, TPoint(point.x - AtMouse->Bounds.left,
  740.                                             point.y - AtMouse->Bounds.top));
  741.     }
  742.   }
  743.   TWindow::EvMouseMove(modKeys, point);
  744. }
  745.