Recent

Author Topic: Possible Bug in TTrackbar (win7-x64)?  (Read 5325 times)

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #15 on: September 03, 2019, 06:59:00 pm »
ok. Undid the change in trunk, it was a bad idea.

feds

  • New Member
  • *
  • Posts: 33
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #16 on: September 03, 2019, 09:59:21 pm »
This is off-topic, but I want to add a comment because I think that you are misunderstanding the meaning of the property "Frequency" here. Really, this property is named in a misleading way: in common sense, the word "frequency" implies: "High frequency -> many ticks". But it's the other way round: "High frequency --> less ticks"! The default parameters of a TrackBar have Max = 10 and Frequecy = 1 --> there are 10 intervals (or: 11 ticks). Now set the Frequeny higher to 2 - now we have LESS intervals (5, or 6 ticks). Therefore, the property should be understood as "TickIntervals"

Your calculation "tickRange / Width" is wrong because it calculates the number of intervals. You should do: "tickRange / Count" instead to determine the "Frequency" value.

Learning is never off-topic. Thanks for your effort :)

I understand the frequency in the meaning of frequent or repeated.  I.e. taking the default trackbar [0..10] and frequency:=5 gives me only one bar in the middle.
The trackbar makes a tick every 5 steps. Is this wrong?

But indeed, i was calculating the intervals when the widths is to small to show all ticks.
 
My major point was to keep the range (min/max) intact because i assume possible bugs when changing this (i.e. increasing min in a lighting controller would keep the lamps glowing).

Hence the idea was to put as much as possible of the required ticks into the available width (wich was assumed to be acceptable small).
 
Moreover i was not aware that there is a count anywhere around.  Hence i take (simply) the width to create the frequency. Or as you call it tick-intervall (much better name btw.)

Unfortunally it still does not do the job. Too bad  :(

Regards
Feds

BrunoK

  • Sr. Member
  • ****
  • Posts: 452
  • Retired programmer
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #17 on: September 04, 2019, 04:53:52 pm »
I don't think anything can be done to correct the large memory usage.

Have found a C# problem that describes (the answer) what seems to also happen in Lazarus.
https://www.oipapio.com/question-1739276

Here after a little project  that feds could try. (Without any warranty ...)
Code: Pascal  [Select][+][-]
  1. object Form1: TForm1
  2.   Left = 880
  3.   Height = 115
  4.   Top = 173
  5.   Width = 320
  6.   Caption = 'Form1'
  7.   ClientHeight = 115
  8.   ClientWidth = 320
  9.   OnShow = FormShow
  10.   LCLVersion = '2.1.0.0'
  11.   object TrackBar1: TTrackBar
  12.     Left = 104
  13.     Height = 32
  14.     Top = 56
  15.     Width = 208
  16.     Frequency = 64000
  17.     LineSize = 2
  18.     Max = 100
  19.     Min = -100
  20.     OnChange = TrackBar1Change
  21.     PageSize = 1
  22.     Position = 0
  23.     ScalePos = trBottom
  24.     Anchors = [akTop, akLeft, akRight]
  25.     OnResize = TrackBar1Resize
  26.     TabOrder = 0
  27.   end
  28.   object LabeledEdit1: TLabeledEdit
  29.     Left = 8
  30.     Height = 23
  31.     Top = 56
  32.     Width = 80
  33.     EditLabel.Height = 15
  34.     EditLabel.Width = 80
  35.     EditLabel.Caption = 'Volume [0..10]'
  36.     EditLabel.ParentColor = False
  37.     TabOrder = 1
  38.     Text = 'vol.'
  39.     OnChange = LabeledEdit1Change
  40.   end
  41. end
Code: Pascal  [Select][+][-]
  1. unit frmTrackBar;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. // https://forum.lazarus.freepascal.org/index.php/topic,46606.0.html?PHPSESSID=70njdrempm7i7uc0r6t25vg7l5
  6.  
  7. // Similar problem in C#
  8. //  https://www.oipapio.com/question-1739276
  9.  
  10.  
  11. interface
  12.  
  13. uses
  14.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls,
  15.   ExtCtrls;
  16.  
  17. type
  18.  
  19.   TVolumeChanger = (vcNone, vcText, vcTrack, vcTrackResize);
  20.  
  21.   { TForm1 }
  22.  
  23.   TForm1 = class(TForm)
  24.     LabeledEdit1: TLabeledEdit;
  25.     TrackBar1: TTrackBar;
  26.     procedure FormShow(Sender: TObject);
  27.     procedure LabeledEdit1Change(Sender: TObject);
  28.     procedure TrackBar1Change(Sender: TObject);
  29.     procedure TrackBar1Resize(Sender: TObject);
  30.   private
  31.     procedure SetVolume(AValue: Real);
  32.   private
  33.     FVolume : Real;
  34.     FVolumeChanger : TVolumeChanger;
  35.     procedure UpdateTrackBarFreq(aTrackBar : TTrackBar; aGraduation : integer = 10);
  36.     property Volume : Real read FVolume write SetVolume;
  37.   public
  38.  
  39.   end;
  40.  
  41. var
  42.   Form1: TForm1;
  43.  
  44. implementation
  45.  
  46. {$R *.lfm}
  47.  
  48. uses
  49.   Windows;
  50.  
  51. procedure TForm1.FormShow(Sender: TObject);
  52. begin
  53.   TrackBar1.Min := 0;
  54.   TrackBar1.Max := TrackBar1.Width;
  55.   TrackBar1.OnChange(TrackBar1);
  56.   UpdateTrackBarFreq(TrackBar1);
  57. end;
  58.  
  59. procedure TForm1.LabeledEdit1Change(Sender: TObject);
  60. var
  61.   lVolume : real;
  62. begin
  63.   if FVolumeChanger <> vcNone then
  64.     Exit;
  65.   FVolumeChanger := vcText;
  66.   if TryStrToFloat(LabeledEdit1.Text, lVolume) then
  67.     Volume := lVolume;
  68.   FVolumeChanger := vcNone;
  69. end;
  70.  
  71. procedure TForm1.TrackBar1Change(Sender: TObject);
  72. begin
  73.   if FVolumeChanger <> vcNone then
  74.     Exit;
  75.   FVolumeChanger := vcTrack;
  76.   Volume := TrackBar1.Position / TrackBar1.Frequency;
  77.   LabeledEdit1.Text := Format('%.2g', [Volume]);
  78.   FVolumeChanger := vcNone;
  79. end;
  80.  
  81. procedure TForm1.TrackBar1Resize(Sender: TObject);
  82. var
  83.   lOldVolume : real;
  84. begin
  85.   if FVolumeChanger <> vcNone then
  86.     Exit;
  87.   lOldVolume := Volume;
  88.   FVolumeChanger := vcTrackResize;
  89.   TrackBar1.Max := TrackBar1.Width;
  90.   UpdateTrackBarFreq(TrackBar1);
  91.   TrackBar1.Position := Trunc(FVolume * TrackBar1.Frequency);
  92.   FVolumeChanger := vcNone;
  93. end;
  94.  
  95. procedure TForm1.SetVolume(AValue: Real);
  96. begin
  97.   if FVolume=AValue then
  98.     Exit;
  99.   FVolume:=AValue;
  100.   TrackBar1.Position := Trunc(FVolume * TrackBar1.Frequency);
  101. end;
  102.  
  103. procedure TForm1.UpdateTrackBarFreq(aTrackBar : TTrackBar; aGraduation : integer = 10);
  104. var
  105.   lFreq : integer;
  106. begin
  107.   lFreq := (aTrackBar.Max -  aTrackBar.Min) div (aGraduation-1);
  108.   TrackBar1.max := lFreq * 10;
  109.   TrackBar1.Frequency:=lFreq;
  110. end;

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #18 on: September 04, 2019, 05:25:04 pm »
So what to do?

Restrict the windows version to the maximum for max to 10.000 and write some words about it in the doc.

Or write a totaly new owner drawn trackbar for windows.

Or any other ideas?

Btw As far as I know the value for min is not allowed to be negative due to M$ docs.

Winni

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #19 on: September 04, 2019, 05:52:39 pm »
interesting, But I think there  must be a better way for this, like hooking the TrackBar's window procedure and control the cycling there to restrict the number of calls.

 Has anyone yet investigated the Message Que for a flood? Windows provides a PeekMessage where by you can remove all messages found. This appears to be a flooding problem or maybe there is some Application.ProcessMessages in the loop of the LCL code.


The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #20 on: September 04, 2019, 05:55:29 pm »
Here is another, less destructive workaround than before. Like the previous one it switches to "no ticks" style when the range is greater than some critical value, 100,000 this time. But now it operates in the Windows widgetset only and does not modify properties persistently.

Of course, something like Max = 200000 and Frequency = 20000 (10 intervals) still breaks existing code because the Ticks are hidden now. But that's life... If this really is a problem the user can rescale the values to bring Max below 100000.

Open Win32WSComCtrls.pp from (lazarus)\lcl\interfaces\win32 and replace the method ApplyChanges by the following code:
Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSTrackBar.ApplyChanges(const ATrackBar: TCustomTrackBar);
  2. var
  3.   wHandle: HWND;
  4.   NewStyle: integer;
  5. const
  6.   StyleMask = TBS_AUTOTICKS or TBS_NOTICKS or TBS_VERT or TBS_TOP or TBS_BOTH or
  7.     TBS_ENABLESELRANGE or TBS_REVERSED;
  8.   TickStyleStyle: array[TTickStyle] of DWORD = (TBS_NOTICKS, TBS_AUTOTICKS, 0);
  9.   OrientationStyle: array[TTrackBarOrientation] of DWORD = (TBS_HORZ, TBS_VERT);
  10.   TickMarksStyle: array[TTickMark] of DWORD = (TBS_BOTTOM, TBS_TOP, TBS_BOTH);
  11.   SelRangeStyle: array[Boolean] of DWORD = (0, TBS_ENABLESELRANGE);
  12.   ReversedStyle: array[Boolean] of DWORD = (0, TBS_REVERSED);
  13. begin
  14.   with ATrackBar do
  15.   begin
  16.     { cache handle }
  17.     wHandle := Handle;
  18.     if Max - Min > 100000 then                                    // <---- new
  19.       NewStyle := TickStyleStyle[tsNone]                          // <--- new
  20.     else
  21.       NewStyle := TickStyleStyle[TickStyle];                      // <--- new
  22.     NewStyle := NewStyle or OrientationStyle[Orientation] or      // <--- modified
  23.                 TickMarksStyle[TickMarks] or SelRangeStyle[ShowSelRange] or ReversedStyle[Reversed];
  24.     UpdateWindowStyle(wHandle, NewStyle, StyleMask);
  25.     Windows.SendMessage(wHandle, TBM_SETRANGEMAX, Windows.WPARAM(True), Max);
  26.     Windows.SendMessage(wHandle, TBM_SETRANGEMIN, Windows.WPARAM(True), Min);
  27.     if Reversed then
  28.       Windows.SendMessage(wHandle, TBM_SETPOS, Windows.WPARAM(True), Max + Min - Position)
  29.     else
  30.       Windows.SendMessage(wHandle, TBM_SETPOS, Windows.WPARAM(True), Position);
  31.     Windows.SendMessage(wHandle, TBM_SETLINESIZE, 0, LineSize);
  32.     Windows.SendMessage(wHandle, TBM_SETPAGESIZE, 0, PageSize);
  33.     Windows.SendMessage(wHandle, TBM_SETTICFREQ, Frequency, 0);
  34.     if ((SelStart = 0) and (SelEnd = 0)) or not ShowSelRange then
  35.       Windows.SendMessage(wHandle, TBM_CLEARSEL, Windows.WPARAM(True), 0)
  36.     else
  37.     begin
  38.       Windows.SendMessage(wHandle, TBM_SETSELSTART, Windows.WParam(False), SelStart);
  39.       Windows.SendMessage(wHandle, TBM_SETSELEND, Windows.WParam(True), SelEnd)
  40.     end;
  41.   end;
  42. end;

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #21 on: September 04, 2019, 06:23:01 pm »
But that gives you an empty tick line?

btw, this effects the Designer too if you set the value high in it.

Wouldn't it be better to simply draw a solid line for values where there isn't enough pixels?

 This would mean doing your own drawing but it's better than what we have now  :o
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #22 on: September 04, 2019, 07:17:34 pm »
We got a natural visible threshold  value:

The linewidth of the ticks is 1.
Between two ticks there should be a gap with the minimum of 1.
So our threshold is component.width div 2. (Ok, a little bit less)

If the number of ticks is greater than this value, divide by 2 in a loop until it fits.

That would be an easy solution.

Winni

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #23 on: September 04, 2019, 07:33:48 pm »
Added bug 36046 with patch. Test it, please.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #24 on: September 04, 2019, 07:52:09 pm »
We got a natural visible threshold  value:

The linewidth of the ticks is 1.
Between two ticks there should be a gap with the minimum of 1.
So our threshold is component.width div 2. (Ok, a little bit less)

If the number of ticks is greater than this value, divide by 2 in a loop until it fits.

That would be an easy solution.

Winni
What do you want to do? Alter the Frequency value? This will not work because it's Max which causes the trouble: Set Max := MaxInt and Frequency := MaxInt div 2, and the issue will still be there although there are only 3 ticks to be drawn. Alter the Max value? That's a no-go because it directly affects the visual position of the slider.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #25 on: September 04, 2019, 07:57:23 pm »
Added bug 36046 with patch. Test it, please.
Yes, it's like what I posted in reply #20. However I would put less emphasis on Delphi compatibility and increase the limiting value to 100,000 or even 1,000,000 because it reduces the chance of a conflict as noted by winni in reply #4.

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #26 on: September 04, 2019, 08:20:55 pm »
Yes, it's like what I posted in reply #20. However I would put less emphasis on Delphi compatibility and increase the limiting value to 100,000 or even 1,000,000 because it reduces the chance of a conflict as noted by winni in reply #4.
The number 10000 was chosen as the maximum resolution in pixels. To draw tics often than pixel pointless.
Detail conflict please.

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #27 on: September 04, 2019, 08:29:55 pm »
I think it is more logical to restrain the Frequency to the width of the control?

so if the range value exceeds the control's width in pixels it should automatically adjust the frequency for a proper fit.

 I just ran some test here and it does not effect any code that I can see, it actually works perfectly because I still get my graph bar even with high values.

 So basically this..

  If TrackBar.Width < Range / Frequency Then Frequency := Range / TrackBar.Width;

 To me that is a better choice because at least you still get a tick bar and it does not flood the message que with notifications when updating the ticks

 Can you please put in a Option in the properties to select which way to adjust the conditions  for
large values?

The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #28 on: September 04, 2019, 08:36:55 pm »
Detail conflict please.
In the code of reply #4
Code: Pascal  [Select][+][-]
  1. trackbar.Min        := 0;
  2. trackbar.Max        := 50000;
  3. trackbar.Frequency  := 5000;
we have 10 intervals (= 50000/5000) - this means: 11 ticks. And this is what is displayed by the LCL Trackbar. But with your patch there are no more ticks because Max is > 10000.

Suppose the trackbar represents the number of iterations in some software calculation. Ideally the user does not think about readjustment these numbers to the usable range below 10000 in your patch. The longer he can use direct numbers the better. Therefore I'd increase the limit value beyond which ticks are turned off.

On the other hand, the trackbar ticks are rather useless because they are not labeled. So maybe, my comment added just too much noise...

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Possible Bug in TTrackbar (win7-x64)?
« Reply #29 on: September 04, 2019, 08:44:48 pm »
A Proper patch would be to simply calculate the Frequency to limit the drawing ticks automatically.

I do have one app that uses that control for a file pointer and it does get big at times but I would really love to not loose the bar looks even though it's useless there because I have other graphics around it.

 P.S.
   I have had slowness in some apps using this control before and never investigated the cause, now I think that is it.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018