* * *

Author Topic: [SOLVED] TSpinEdit and TFloatSpinEdit: how to hide the 2 little arrow buttons?  (Read 1360 times)

Hartmut

  • Full Member
  • ***
  • Posts: 147
During the years I have written a couple of programs which contain a couple of TSpinEdit and TFloatSpinEdits. Mostly the 2 little arrow buttons made no sense so until Lazarus 1.6.2 it was no problem to hide them by the following code:

Code: Pascal  [Select]
  1. // In Lazarus 1.6.2 and older you don't see the 2 arrow buttons and because of this the input fields are smaller.
  2. // In Lazarus 1.8.0 and newer you don't see the 2 arrow buttons but the input fields are more wide.
  3.  
  4. unit Unit1;
  5.  
  6. {$mode objfpc}{$H+}
  7.  
  8. interface
  9.  
  10. uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Spin;
  11.  
  12. type
  13.  TForm1 = class(TForm)
  14.   SpinEdit1: TSpinEdit;
  15.   FloatSpinEdit1: TFloatSpinEdit;
  16.   procedure FormActivate(Sender: TObject);
  17.  private
  18.  public
  19.  end;
  20.  
  21. var Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. uses windows,Win32Proc;
  26.  
  27. {$R *.lfm}
  28.  
  29. procedure TForm1.FormActivate(Sender: TObject);
  30.    {disable the 2 arrow buttons of T[Float]SpinEdit}
  31.    begin
  32.    windows.ShowWindow(Win32Proc.GetWin32WindowInfo(
  33.                       SpinEdit1.Handle)^.UpDown, SW_HIDE);
  34.    windows.ShowWindow(Win32Proc.GetWin32WindowInfo(
  35.                       FloatSpinEdit1.Handle)^.UpDown, SW_HIDE);
  36.    end;
  37.  
  38. end.            

But in Lazarus 1.8.0 and 1.8.4 this solution does not work satisfying. Although the 2 arrow buttons are not visible, their space is drawn white (see attached screenshot):
a) this hides a part of the control, which is right to the T[Float]SpinEdit (so I would have to redisign all my old programs)
b) in this additionally white space you cannot enter a number. I entered "1234567890", which scrolled left automatically, keeping the additionally space empty (this looks curious).

Does somebody know a solution for Lazarus 1.8.4, that the additionally white space is not drawn?
What I do not want is to use TEdit, because it's to much trouble to handle MinValue and MaxValue and converting strings to numbers (with error handling) and vice versa.

I'm using Lazarus 1.8.4 on Windows 7 32 bit. Thanks a lot in advance.
« Last Edit: June 19, 2018, 01:54:47 pm by Hartmut »

jamie

  • Hero Member
  • *****
  • Posts: 773
I really don't think you can directly,...

however, you can implement your own Spin Edit using a TMASKEdit and keyboard events.

wp

  • Hero Member
  • *****
  • Posts: 4726
On palette "LazControls" there is an extended SpinEdit and FloatSpinEdit (SpinEditEx, FloatSpinEditEx), unit spinex - they are combined controls consisting of an edit and an UpDown. The UpDown is not visible directly outside because it is protected, but you can access is with the usual casting trick:
Code: Pascal  [Select]
  1. type
  2.   TMyFloatSpinEditEx = class(TFloatSpinEditEx);
  3.  
  4. procedure TForm1.CheckBox1Change(Sender: TObject);
  5. begin
  6.   TMyFloatSpinEditEx(FloatSpinEditEx1).Updown.Visible := Checkbox1.Checked;
  7. end;
When the UpDown is turned off this way the entire bounds of the control are available for editing.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3392
  • I like bugs.
On palette "LazControls" there is an extended SpinEdit and FloatSpinEdit (SpinEditEx, FloatSpinEditEx), unit spinex - they are combined controls consisting of an edit and an UpDown. The UpDown is not visible directly outside because it is protected, but you can access is with the usual casting trick:
I don't like those ugly tricks so in r58322 (Lazarus trunk) I extended the components with a property UpdownVisible. Please test.
I did not treat design time in any special way. Now it shows the UpDown part always at design time. Not sure why. They are hidden only at run time. If you want them hidden at design time, please feel free to improve it.

You could get almost the same behavior by using a MaskEdit + some extra coding, but SpinEditEx also supports arrow keys etc.

I don't know what changed the behavior of the original TSpinEdit which maps to a native control. Something in the layout system has changed.

wp

  • Hero Member
  • *****
  • Posts: 4726
I don't like those ugly tricks so in r58322 (Lazarus trunk) I extended the components with a property UpdownVisible. Please test.
I did not treat design time in any special way. Now it shows the UpDown part always at design time. Not sure why. They are hidden only at run time. If you want them hidden at design time, please feel free to improve it.
Thanks, great.

As for the designmode: when I create the Buddy in GroupedEdit TCustomAbstractGroupedEdit.CreateBuddy with parent Owner (not self) then designtime works. With an explicit destruction of the Buddy in TCustomAbstractGroupedEdit.Destroy there are no memory leaks. Are there any other disadvantages of the changed owner?
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3392
  • I like bugs.
As for the designmode: when I create the Buddy in GroupedEdit TCustomAbstractGroupedEdit.CreateBuddy with parent Owner (not self) then designtime works. With an explicit destruction of the Buddy in TCustomAbstractGroupedEdit.Destroy there are no memory leaks. Are there any other disadvantages of the changed owner?
I don't know. The components are made by Bart, maybe he can comment.

Hartmut

  • Full Member
  • ***
  • Posts: 147
Thanks a lot to all for your help. For today I will use the solution from wp, because it's easy to implement and works from Lazarus 1.8.0 on. As soon as the next Lazarus release will come out, I will switch to the new solution from JuhaManninen.

A little Problem did I have with Runtime Error 219 in line
Code: Pascal  [Select]
  1. TMyFloatSpinEditEx(FloatSpinEditEx1).Updown.Visible:=Checkbox1.Checked;
because mostly I have Compiler Option -CR active. I could solve this with {$OBJECTCHECKS OFF}.
But, if possible, I would set {$OBJECTCHECKS} after this in it's previous state like:

Code: Pascal  [Select]
  1. type TMySpinEditEx = class(TSpinEditEx);
  2.      TMyFloatSpinEditEx = class(TFloatSpinEditEx);
  3.  
  4. procedure TForm1.CheckBox1Change(Sender: TObject);
  5.    begin
  6. {$UNDEF XYZ}
  7. {$IFOPT OBJECTCHECKS} // does not compile
  8.    {$DEFINE XYZ}
  9. {$ENDIF}
  10.  
  11. {$OBJECTCHECKS OFF}
  12.    TMyFloatSpinEditEx(FloatSpinEditEx1).Updown.Visible:=Checkbox1.Checked;
  13.    TMySpinEditEx(SpinEditEx1).Updown.Visible:=Checkbox1.Checked;
  14. {$IFDEF XYZ}
  15.    {$OBJECTCHECKS ON}
  16. {$ENDIF}
  17.    end;
     
But the compiler says 'Illegal compiler switch "OBJECTCHECKS"' in line 7. Does anybody have another idea of setting {$OBJECTCHECKS} in it's previous state? Thanks in advance.

wp

  • Hero Member
  • *****
  • Posts: 4726
Better to use {$PUSH} and {$POP} here:
https://www.freepascal.org/docs-html/prog/progsu63.html#x70-690001.2.63 and
https://www.freepascal.org/docs-html/prog/progsu62.html#x69-680001.2.62

Code: Pascal  [Select]
  1. {$PUSH}
  2.   {$OBJECTCHECKS OFF}
  3.    TMyFloatSpinEditEx(FloatSpinEditEx1).Updown.Visible:=Checkbox1.Checked;
  4.    TMySpinEditEx(SpinEditEx1).Updown.Visible:=Checkbox1.Checked;
  5. {$POP}
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Hartmut

  • Full Member
  • ***
  • Posts: 147
Phantastic! Thank you very much again for your valuable help. This is a great forum...

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 197
As for the designmode: when I create the Buddy in GroupedEdit TCustomAbstractGroupedEdit.CreateBuddy with parent Owner (not self) then designtime works. With an explicit destruction of the Buddy in TCustomAbstractGroupedEdit.Destroy there are no memory leaks. Are there any other disadvantages of the changed owner?

If you mean:
Code: [Select]
Result := GetBuddyClassType.Create(Parent);
then, yes. Never do this. I let you to think about the reasons as an exercise.
« Last Edit: June 19, 2018, 02:28:52 pm by Ondrej Pokorny »

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 197
Re: TSpinEdit and TFloatSpinEdit: how to hide the 2 little arrow buttons?
« Reply #10 on: June 19, 2018, 02:25:16 pm »
Quote from: JuhaManninen link=topic=41589.msg288985#msg288985
If you want them hidden at design time, please feel free to improve it.

Please fix this or don't publish the property (move it to the public section). Published properties should work in design-time as well.

wp

  • Hero Member
  • *****
  • Posts: 4726
Re: TSpinEdit and TFloatSpinEdit: how to hide the 2 little arrow buttons?
« Reply #11 on: June 19, 2018, 03:10:16 pm »
[...] when I create the Buddy in GroupedEdit TCustomAbstractGroupedEdit.CreateBuddy with parent Owner (not self) [...]

If you mean:
Code: [Select]
Result := GetBuddyClassType.Create(Parent);
then, yes. Never do this. I let you to think about the reasons as an exercise.
Damned typos! I mean: "with owner Owner", i.e.
Code: Pascal  [Select]
  1. function TCustomAbstractGroupedEdit.CreateBuddy: TControl;
  2. begin
  3.   // current:
  4.   Result := GetBuddyClassType.Create(Self);
  5.   // my change:
  6.   Result := GetBuddyClassType.Create(Owner);
  7. end;
Create(Parent) is nonsense of course, because  the Edit does not necessariliy have a parent at this moment. But why does visibilitiy of the Buddy depend on the "Owner", i. e. on the component which destroys it? I would expect visibility to depend on the Parent (and this is probably the reason for my typo).
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 197
Re: TSpinEdit and TFloatSpinEdit: how to hide the 2 little arrow buttons?
« Reply #12 on: June 19, 2018, 03:24:56 pm »
Code: Pascal  [Select]
  1. function TCustomAbstractGroupedEdit.CreateBuddy: TControl;
  2. begin
  3.   // current:
  4.   Result := GetBuddyClassType.Create(Self);
  5.   // my change:
  6.   Result := GetBuddyClassType.Create(Owner);
  7. end;

This is a no-go for a container component as well. Internal components may not be listed in the form's Components[] list (the XYZ.Components[] lists all components that have the Owner set to XYZ).

Bart

  • Hero Member
  • *****
  • Posts: 3012
    • Bart en Mariska's Webstek
The component is called T(Float)SpinEditEx for a reason: it has spinbuttons.
If you want the ability to remove those, please construct a derived class from it and do it there.

Bart

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus