SillyQuestions 0 Posted August 13 (edited) I am having issue with panels created once scrolling is needed the width is too wide. I was having another issue with placement incorrect, but I fixed that issue already. There also another issue when resizing the form messes up to the position of panels. unit Unit8; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.UITypes, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ToolWin, Vcl.ComCtrls, Vcl.ExtCtrls; type TForm8 = class(TForm) ScrollBox1: TScrollBox; ToolBar1: TToolBar; Button3: TButton; Button4: TButton; procedure Button3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button4Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form8: TForm8; implementation {$R *.dfm} var ScrollBox: TScrollBox; function GetInScrollBoxTopPos: integer; var I: integer; begin result := 0; for I := 0 to ScrollBox.ControlCount - 2 do if ScrollBox.Controls[I] is TPanel then result := result + TPanel(ScrollBox.Controls[I]).Height + 5; end; type TPanel160 = class panel: TPanel; constructor Create(AOwner: TComponent); end; type TPanel40 = class panel: TPanel; constructor Create(AOwner: TComponent); end; procedure TForm8.Button3Click(Sender: TObject); var panel : TPanel160; begin panel := TPanel160.Create(self) end; { TPanel160 } constructor TPanel160.Create(AOwner: TComponent); begin panel := TPanel.Create(AOwner); panel.Parent := ScrollBox; panel.Color := TColorRec.Red; panel.Caption := ''; panel.Height := 160; panel.Width := ScrollBox.Width - 20; panel.Top := GetInScrollBoxTopPos; panel.Left := 10; panel.Anchors := [akLeft, akRight]; end; { TPanel40 } constructor TPanel40.Create(AOwner: TComponent); begin panel := TPanel.Create(AOwner); panel.Parent := ScrollBox; panel.Color := TColorRec.Blue; panel.Caption := ''; panel.Height := 40; panel.Width := ScrollBox.Width - 20; panel.Top := GetInScrollBoxTopPos; panel.Left := 10; panel.Anchors := [akLeft, akRight]; end; procedure TForm8.Button4Click(Sender: TObject); var panel : TPanel40; begin panel := TPanel40.Create(self) end; procedure TForm8.FormCreate(Sender: TObject); begin ScrollBox := ScrollBox1 end; end. copy.zip Edited August 13 by SillyQuestions Share this post Link to post
PeterBelow 238 Posted August 13 Have you tried using scrollbox.clientwidth instead of scrollbox.width? Share this post Link to post
SillyQuestions 0 Posted August 13 4 hours ago, PeterBelow said: Have you tried using scrollbox.clientwidth instead of scrollbox.width? Yes, I not really sure what wrong. The width part is minor issue the biggest issue is how resizing the form display things. Share this post Link to post
David Schwartz 426 Posted August 14 It would help a lot if you'd explain the problem you're having. Looking at the code, I'm _guessing_ that you only have a single vertical list of panels on that scrollbox. However, I can't tell if you have horizontal scrolling active or not. Assuming you don't want the panels resized, then they should all have the same relative positioning. I'm doing something similar with some panels on a scrollbox that does not do horizontal scrolling. It put three across and unlimited rows. I have a list of things and I go through the list and display them like this: 1 ---- 2 ---- 3 4 ---- 5 ---- 6 7 ---- 8 ---- 9 . . . I have a row_count and col_count, and position them with a gutter above and to the left, and derive the Top and Left position of each one with simple math based on curr_row and curr_col that I track as I'm laying them down. I save the Top, Left, Height, and Width in the objects in the list. The Height and Width are always constant, but the Top and Left change based on whether I want to show or hide them based on filtering. I have no problem scrolling vertically. I don't want or need horizontal scrolling. And the form isn't sizeable. But there's no reason this approach shouldn't work. When the form size changes, check the dimensions and if the number per row changes, then hide then reset the panels on the scrollbox area to maximize the number you can have with the given gutter size you're using. (I'm using 20 for both, but you seem to be using 5 for Vertical and you're ignoring Horizontal.) But if there was a problem based on this code, I'd say it's because you're calculating the positions by deriving them by SUMMING things up while scanning through your list. If you do allow horizontal scrolling, then that's just not going to work. The summing approach you're using will ONLY work properly if there's JUST ONE COLUMN. If there are multiple columns, you're going to get a steadily growing gap between rows in increments of the panel.Height+5. That might be happening simply because you have horizontal scrolling enabled. You need to use indices and calculate the TOP and LEFT based on a panel's index, the number of columns and rows you have, the gutter size between them, and current row and column. Share this post Link to post
SillyQuestions 0 Posted August 14 Adjusting ScrollBox1.VertScrollBar.Range seems to fix issue. The other issue related to form resize is fix by just handling the on-size event. Share this post Link to post
SillyQuestions 0 Posted August 14 (edited) EDIT: For it still has issue if I add many panels then resize form to larger size then lesser size and scroll up all panels are moving downwards and there is empty space at the top. To try to be clearer I fill scrollbox with Tpanels, I expand window to full size scroll down then go back to normal window size, scroll up and nothing is above. The issue only happens if there enough Tpanels to cause scroll to be needed when window is expanded, and I scroll down before unexpanded. The window doesn't need to be fully expanded either just enough to cause the bigger window to need to scroll and scroll down then go back to smaller size and try scrolling up which is just empty. Edited August 14 by SillyQuestions Share this post Link to post
PeterBelow 238 Posted August 14 Try to not use anchors but set the new panel's Align to alTop instead. If you want vertical spacing set the panel's AlignWithMargin property to true and set its Margin.Bottom to the spacing you want and all other Margin members to 0. Share this post Link to post
Pat Foley 51 Posted August 14 Here's example of finger measure applied*. The example refactored your code into a mypanel. This code surfaces the numbers to aid in sizing. *finger measure ~ 13 mm grid layout size. I added a panel inside the ScrollBox unit Unit8; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.UITypes, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ToolWin, Vcl.ComCtrls, Vcl.ExtCtrls; type TmyPanel = class(TPanel) const // 96 dpi ~ 25.4 mm * 4 baseFinger = 96 div 2; baseFatFinger = 3 * 96 div 2; public TopOffset: Integer; Finger: Integer; class var UsedHeight: Integer; procedure Paint; override; procedure WMSIZE(var message: TWMSIZE); procedure SetUp(AParent: TWinControl; const AColor: TColor; const Offset: Integer; const AAlign: TAlign); end; TForm8 = class(TForm) ScrollBox1: TScrollBox; ToolBar1: TToolBar; Button3: TButton; Button4: TButton; Button1: TButton; Panel1: TPanel; procedure Button4Click(Sender: TObject); end; var Form8: TForm8; implementation {$R *.dfm} // Let's pass ScrollBox1 using ScrollBox in SetUp procedure parameter} //var // ScrollBox: TScrollBox; procedure TForm8.Button4Click(Sender: TObject); var panel : TmyPanel; TagNu: NativeInt; Prnt: TWinControl; Aln: TAlign; begin Prnt := panel1;//ScrollBox1; Aln := alTop;// alNone; panel := TmyPanel.Create(Self); TagNu := (Sender as TControl).Tag; Case Tagnu of 0: panel.SetUp(Prnt, clSkyBlue, 8, aln); 1: panel.SetUp(Prnt,clMoneyGreen, 4, aln); 2: panel.Setup(Prnt, clCream, 2, aln); End; end; { TmyPanel } // Note how only current numbers are used and top offset used for naming not used for scrolling! procedure TmyPanel.Paint; begin inherited; canvas.TextOut(10,10,format('%s class Top %d Rect.Top %d',[Name, UsedHeight, BoundsRect.Top])); end; procedure TmyPanel.SetUp(AParent: TWinControl; const AColor: TColor; const Offset: Integer; const AAlign: TAlign); begin Parent := AParent; self.Color := AColor; ParentBackground := False; // moved top to here to avoid firsttime flag // and when align = alNone sets panel top else // size the parent to fit with resize event finger := baseFinger; Top := UsedHeight + 2 * finger; Inc(UsedHeight, (Offset+1) * finger); TopOffset := UsedHeight; AParent.Height := TopOffset; Name := 'MyPanel'+'_'+ UsedHeight.ToString; Caption := '';//Name;// + ' ' + UseCount.ToString; Height := Offset * finger; Left := 2 * finger; Width := 200;//aParent.Width - 34 - Left; Align := AAlign; show; // if ScrollBox1.height > anOwner.Height div 2 then // begin // ScrollBox1.AutoSize := False; // ScrollBox1.Height := anOwner.Height div 2; // end; //e end; procedure TmyPanel.WMSIZE(var message: TWMSIZE); begin //Finger adjusted here finger := basefinger * {DPI/96} 1; end; end. Share this post Link to post