home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 April / Chip_1997-04_cd.bin / prezent / cb / data.z / SPIN.CPP < prev    next >
C/C++ Source or Header  |  1997-01-16  |  12KB  |  483 lines

  1. //---------------------------------------------------------------------------
  2. // Borland C++Builder
  3. // Copyright (c) 1987, 1997 Borland International Inc.  All Rights Reserved.
  4. //---------------------------------------------------------------------------
  5. #if !defined (REGISTER_ALL_CONTROLS)
  6.   #include "spin.h"
  7. #else
  8.   #include "spin\spin.h"
  9. #endif
  10. //#pragma resource "*.res"   //IDE links .res automatically for components
  11.  
  12. //---------------------------------------------------------------------------
  13. namespace Spin {
  14. void __fastcall Register()
  15. {
  16.   TComponentClass classes[2] = {__classid(TSpinButton),
  17.                                 __classid(TSpinEdit)};
  18.   RegisterComponents("Samples",
  19.                      classes,
  20.                      (sizeof(classes)/sizeof(classes[0])) - 1);
  21. }
  22. } //end namespace
  23.  
  24. //---------------------------------------------------------------------------
  25. // TSpinButton
  26.  
  27. __fastcall TSpinButton::TSpinButton(TComponent *AOwner)
  28.                       : TWinControl(AOwner)
  29. {
  30.   (((ControlStyle >> csAcceptsControls)
  31.                   >> csSetCaption)
  32.                   << csFramed)
  33.                   << csOpaque;
  34.  
  35.   FUpButton = CreateButton();
  36.   FDownButton = CreateButton();
  37.   UpGlyph = NULL;
  38.   DownGlyph = NULL;
  39.  
  40.   Width = 20;
  41.   Height = 25;
  42.   FFocusedButton = FUpButton;
  43. }
  44.  
  45. TTimerSpeedButton *__fastcall TSpinButton::CreateButton(void)
  46. {
  47.   TTimerSpeedButton * Result;
  48.  
  49.   Result = new TTimerSpeedButton((TComponent *) this);
  50.   Result->OnClick = BtnClick;
  51.   Result->OnMouseDown = BtnMouseDown;
  52.   Result->Visible = True;
  53.   Result->Enabled = True;
  54.   Result->TimeBtnState << tbAllowTimer;
  55.   Result->NumGlyphs = 1;
  56.   Result->Parent = this;
  57.  
  58.   return Result;
  59. }
  60.  
  61. void __fastcall TSpinButton::AdjustSize(int &W, int &H)
  62. {
  63.   if ((FUpButton == NULL) || (ComponentState.Contains(csLoading)))
  64.      return;
  65.  
  66.   if (W < 15)
  67.       W = 15;
  68.  
  69.   FUpButton->SetBounds (0, 0, W, H / 2);
  70.   FDownButton->SetBounds (0, FUpButton->Height - 1, W, H - FUpButton->Height + 1);
  71. }
  72.  
  73. void __fastcall TSpinButton::SetBounds(int ALeft, int ATop, int AWidth, int AHeight)
  74. {
  75.   int W, H;
  76.  
  77.   W = AWidth;
  78.   H = AHeight;
  79.   AdjustSize (W, H);
  80.   TWinControl::SetBounds (ALeft, ATop, W, H);
  81. }
  82.  
  83. void __fastcall TSpinButton::WMSize(TWMSize &Message)
  84. {
  85.   int W, H;
  86.  
  87.   // check for minimum size
  88.   W = Width;
  89.   H = Height;
  90.   AdjustSize (W, H);
  91.  
  92.   if ((W != Width) || (H != Height))
  93.       TWinControl::SetBounds(Left, Top, W, H);
  94.  
  95.   Message.Result = 0;
  96. }
  97.  
  98. void __fastcall TSpinButton::WMSetFocus(TWMSetFocus &Message)
  99. {
  100.   FFocusedButton->TimeBtnState << tbFocusRect;
  101.   FFocusedButton->Invalidate();
  102. }
  103.  
  104. void __fastcall TSpinButton::WMKillFocus(TWMKillFocus &Message)
  105. {
  106.   FFocusedButton->TimeBtnState >> tbFocusRect;
  107.   FFocusedButton->Invalidate();
  108. }
  109.  
  110. void __fastcall TSpinButton::KeyDown(Word &Key,  TShiftState Shift)
  111. {
  112.   switch (Key) {
  113.     case VK_UP:
  114.           SetFocusBtn (FUpButton);
  115.           FUpButton->Click();
  116.           break;
  117.     case VK_DOWN:
  118.           SetFocusBtn (FDownButton);
  119.           FDownButton->Click();
  120.           break;
  121.     case VK_SPACE:
  122.         FFocusedButton->Click();
  123.   }
  124. }
  125.  
  126. void __fastcall TSpinButton::BtnMouseDown(TObject *Sender, TMouseButton Button,
  127.                                        TShiftState Shift, int X, int Y)
  128. {
  129.   if (Button == mbLeft) {
  130.     SetFocusBtn ((TTimerSpeedButton*) Sender);
  131.     if((FFocusControl != NULL) && ( FFocusControl->TabStop ) &&
  132.       (FFocusControl->CanFocus()) && (GetFocus() != FFocusControl->Handle))
  133.             FFocusControl->SetFocus();
  134.     else if (TabStop && (GetFocus() != Handle) && CanFocus() )
  135.       SetFocus();
  136.   }
  137. }
  138.  
  139. void __fastcall TSpinButton::BtnClick(TObject *Sender)
  140. {
  141.   if (Sender == FUpButton) {
  142.     if (FOnUpClick != NULL)
  143.         FOnUpClick(this);
  144.   }
  145.   else
  146.     if (FOnDownClick != NULL)
  147.        FOnDownClick(this);
  148. }
  149.  
  150. void __fastcall TSpinButton::SetFocusBtn(TTimerSpeedButton *Btn)
  151. {
  152.   if (TabStop && CanFocus() &&  (Btn != FFocusedButton)) {
  153.     FFocusedButton->TimeBtnState >> tbFocusRect;
  154.     FFocusedButton = Btn;
  155.     if (GetFocus() == Handle) {
  156.        FFocusedButton->TimeBtnState << tbFocusRect;
  157.        Invalidate();
  158.     }
  159.   }
  160. }
  161.  
  162. void __fastcall TSpinButton::WMGetDlgCode(TWMNoParams &Message)
  163. {
  164.   Message.Result = DLGC_WANTARROWS;
  165. }
  166.  
  167. void __fastcall TSpinButton::Loaded(void)
  168. {
  169.  
  170.   int W, H;
  171.  
  172.   W = Width;
  173.   H = Height;
  174.   AdjustSize (W, H);
  175.  
  176.   if ((W != Width) || (H != Height))
  177.     TWinControl::SetBounds(Left, Top, W, H);
  178. }
  179.  
  180. Graphics::TBitmap *__fastcall TSpinButton::GetUpGlyph(void)
  181. {
  182.   Graphics::TBitmap * Result;
  183.  
  184.   Result = FUpButton->Glyph;
  185.   return Result;
  186. }
  187.  
  188. void __fastcall TSpinButton::SetUpGlyph(Graphics::TBitmap *Value)
  189. {
  190.   if (Value != NULL)
  191.     FUpButton->Glyph = Value;
  192.   else {
  193.     FUpButton->Glyph->Handle = LoadBitmap((void*) HInstance, "SpinUp");
  194.     FUpButton->NumGlyphs = 1;
  195.     FUpButton->Invalidate();
  196.   }
  197. }
  198.  
  199. Graphics::TBitmap *__fastcall TSpinButton::GetDownGlyph(void)
  200. {
  201.   Graphics::TBitmap * Result;
  202.  
  203.   Result = FDownButton->Glyph;
  204.   return Result;
  205. }
  206.  
  207. void __fastcall TSpinButton::SetDownGlyph(Graphics::TBitmap *Value)
  208. {
  209.   if (Value != NULL)
  210.     FDownButton->Glyph = Value;
  211.   else {
  212.     FDownButton->Glyph->Handle = LoadBitmap((void*)HInstance, "SpinDown");
  213.     FDownButton->NumGlyphs = 1;
  214.     FDownButton->Invalidate();
  215.   }
  216. }
  217.  
  218. // TSpinEdit
  219.  
  220. __fastcall TSpinEdit::TSpinEdit(TComponent *AOwner) : TCustomEdit(AOwner)
  221. {
  222.   FButton = new TSpinButton(this);
  223.  
  224.   FButton->Width = 15;
  225.   FButton->Height = 17;
  226.   FButton->Visible = True;
  227.   FButton->Parent = this;
  228.   FButton->FocusControl = this;
  229.   FButton->OnUpClick = UpClick;
  230.   FButton->OnDownClick = DownClick;
  231.   Text = "0";
  232.   ControlStyle >> csSetCaption;
  233.   FIncrement = 1;
  234.   FEditorEnabled = True;
  235. }
  236.  
  237. __fastcall TSpinEdit::~TSpinEdit(void)
  238. {
  239.   FButton = NULL;
  240. }
  241.  
  242. void __fastcall TSpinEdit::GetChildren(TGetChildProc Proc)
  243. {
  244. }
  245.  
  246. void __fastcall TSpinEdit::KeyDown(Word &Key,  TShiftState Shift)
  247. {
  248.   if (Key == VK_UP)
  249.     UpClick (this);
  250.   else if (Key == VK_DOWN)
  251.          DownClick (this);
  252.   TCustomEdit::KeyDown(Key, Shift);
  253. }
  254.  
  255. void __fastcall TSpinEdit::KeyPress(Char& Key)
  256. {
  257.   if (!IsValidChar(Key)) {
  258.     Key = 0;
  259.     MessageBeep(0);
  260.   }
  261.   if (Key != 0)
  262.     TCustomEdit::KeyPress(Key);
  263. }
  264.  
  265. bool __fastcall TSpinEdit::IsValidChar(Char Key)
  266. {
  267.   bool Result;
  268.   if(((Key == DecimalSeparator)       ||
  269.       (Key == '+')                    ||
  270.       (Key == '-')                    ||
  271.      ((Key >= '0') && (Key <= '9')))  ||
  272.      ((Key < 0x32) && (Key != Char(VK_RETURN))))
  273.    Result = True;
  274.  
  275.   if (!(FEditorEnabled) &&
  276.       Result &&
  277.       ((Key >= 0x32) ||
  278.        (Key == Char(VK_BACK)) ||
  279.        (Key == Char(VK_DELETE))))
  280.     Result = False;
  281.   return Result;
  282. }
  283.  
  284. void __fastcall TSpinEdit::CreateParams(TCreateParams &Params)
  285. {
  286.   TCustomEdit::CreateParams(Params);
  287.   //Params->Style &= ~WS_BORDER;
  288.   Params.Style |=  ES_MULTILINE || WS_CLIPCHILDREN;
  289. }
  290.  
  291. void __fastcall TSpinEdit::CreateWnd()
  292. {
  293.   TCustomEdit::CreateWnd();
  294.   SetEditRect();
  295. }
  296.  
  297. void __fastcall TSpinEdit::SetEditRect(void)
  298. {
  299.   TRect Loc;
  300.  
  301.   SendMessage(Handle, EM_GETRECT, 0, long(&Loc));
  302.   Loc.Bottom = ClientHeight + 1;  // +1 is workaround for windows paint bug
  303.   Loc.Right = ClientWidth - FButton->Width - 2;
  304.   Loc.Top = 0;
  305.   Loc.Left = 0;
  306.   SendMessage(Handle, EM_SETRECTNP, 0, long(&Loc));
  307.   SendMessage(Handle, EM_GETRECT, 0, long(&Loc));  // debug
  308. }
  309.  
  310. void __fastcall TSpinEdit::WMSize(TWMSize &Message)
  311. {
  312.   int MinHeight;
  313.  
  314.   MinHeight = GetMinHeight();
  315.     // text edit bug: if size to less than minheight, then edit ctrl does
  316.     //  not display the text
  317.   if (Height < MinHeight)
  318.     Height = MinHeight;
  319.   else if (FButton != NULL) {
  320.     if (NewStyleControls)
  321.       FButton->SetBounds(Width - FButton->Width - 5, 0, FButton->Width, Height - 5);
  322.     else FButton->SetBounds (Width - FButton->Width, 0, FButton->Width, Height);
  323.     SetEditRect();
  324.   };
  325. }
  326.  
  327. int __fastcall TSpinEdit::GetMinHeight(void)
  328. {
  329.   HDC DC;
  330.   HFONT SaveFont;
  331.   int I, Result;
  332.   TTextMetric SysMetrics, Metrics;
  333.  
  334.   DC = GetDC(NULL);
  335.   GetTextMetrics(DC, &SysMetrics);
  336.   SaveFont = SelectObject(DC, Font->Handle);
  337.   GetTextMetrics(DC, &Metrics);
  338.   SelectObject(DC, SaveFont);
  339.   ReleaseDC(0, DC);
  340.   I = SysMetrics.tmHeight;
  341.   if (I > Metrics.tmHeight)
  342.     I = Metrics.tmHeight;
  343.  
  344.   Result = Metrics.tmHeight + I / 4 + GetSystemMetrics(SM_CYBORDER) * 4 + 2;
  345.   return Result;
  346. }
  347.  
  348. void __fastcall TSpinEdit::UpClick(TObject *Sender)
  349. {
  350.   if (ReadOnly)
  351.     MessageBeep(0);
  352.   else Value += FIncrement;
  353. }
  354.  
  355. void __fastcall TSpinEdit::DownClick(TObject *Sender)
  356. {
  357.   if (ReadOnly)
  358.     MessageBeep(0);
  359.   else
  360.     Value -= FIncrement;
  361. }
  362.  
  363. void __fastcall TSpinEdit::WMPaste(TWMNoParams &Message)
  364. {
  365.   if (!FEditorEnabled || ReadOnly)
  366.     return;
  367. }
  368.  
  369. void __fastcall TSpinEdit::WMCut(TWMNoParams &Message)
  370. {
  371.   if (!FEditorEnabled || ReadOnly)
  372.     return;
  373. }
  374.  
  375. void __fastcall TSpinEdit::CMExit(TWMNoParams &Message)
  376. {
  377.   if (CheckValue (Value) != Value)
  378.     SetValue (Value);
  379. }
  380.  
  381. long __fastcall TSpinEdit::GetValue(void)
  382. {
  383.   long Result;
  384.   try {
  385.     Result = Text.ToInt();
  386.     }
  387.   catch(...) {
  388.     Result = FMinValue;
  389.   }
  390.   return Result;
  391. }
  392.  
  393. void __fastcall TSpinEdit::SetValue(long NewValue)
  394. {
  395.   Text = AnsiString((int)CheckValue(NewValue));
  396. }
  397.  
  398. long __fastcall TSpinEdit::CheckValue(long NewValue)
  399. {
  400.   long Result;
  401.   Result = NewValue;
  402.   if (FMaxValue != FMinValue) {
  403.     if (NewValue < FMinValue)
  404.       Result = FMinValue;
  405.     else if (NewValue > FMaxValue)
  406.       Result = FMaxValue;
  407.   }
  408.   return Result;
  409. }
  410.  
  411. void __fastcall TSpinEdit::CMEnter(TWMNoParams &Message)
  412. {
  413.   if (AutoSelect && !(ControlState.Contains(csLButtonDown)))
  414.     SelectAll();
  415. }
  416.  
  417. // TTimerSpeedButton
  418.  
  419.  __fastcall TTimerSpeedButton::TTimerSpeedButton(TComponent *AOwner) :
  420.                                TSpeedButton(AOwner) { }
  421.  
  422. __fastcall TTimerSpeedButton::~TTimerSpeedButton()
  423. {
  424.   if (FRepeatTimer != NULL)
  425.     delete FRepeatTimer;
  426. }
  427.  
  428. void __fastcall TTimerSpeedButton::MouseDown(TMouseButton Button,  TShiftState Shift,
  429.                           int X, int Y)
  430. {
  431.   TSpeedButton::MouseDown (Button, Shift, X, Y);
  432.  
  433.   if (FTimeBtnState.Contains(tbAllowTimer))
  434.   {
  435.     if (FRepeatTimer == NULL)
  436.       FRepeatTimer = new TTimer(this);
  437.  
  438.     FRepeatTimer->OnTimer = TimerExpired;
  439.     FRepeatTimer->Interval = InitRepeatPause;
  440.     FRepeatTimer->Enabled  = True;
  441.   };
  442. }
  443.  
  444. void __fastcall TTimerSpeedButton::MouseUp(TMouseButton Button,  TShiftState Shift,
  445.                                     int X, int Y)
  446. {
  447.   TSpeedButton::MouseUp (Button, Shift, X, Y);
  448.   if (FRepeatTimer != NULL)
  449.     FRepeatTimer->Enabled  = false;
  450. }
  451.  
  452. void __fastcall TTimerSpeedButton::TimerExpired(TObject *Sender)
  453. {
  454.   FRepeatTimer->Interval = RepeatPause;
  455.   if ((FState == bsDown) && MouseCapture) {
  456.     try {
  457.       Click();
  458.     }
  459.     catch(...) {
  460.       FRepeatTimer->Enabled = false;
  461.       throw;
  462.     }
  463.   }
  464. }
  465.  
  466. void __fastcall TTimerSpeedButton::Paint(void)
  467. {
  468.   TRect R;
  469.  
  470.   TSpeedButton::Paint();
  471.   if (FTimeBtnState.Contains(tbFocusRect)) {
  472.     R.Left = 0;
  473.     R.Top = 0;
  474.     R.Right = Width;
  475.     R.Bottom = Height;
  476.     InflateRect(&RECT(R), -3, -3);
  477.     if (FState == bsDown)
  478.       OffsetRect(&RECT(R), 1, 1);
  479.     DrawFocusRect(Canvas->Handle, &RECT(R));
  480.   }
  481. }
  482.  
  483.