I have a problem I am unable to solve even though I spend long time trying to do it.
I usually use GridPanels to align controls on forms. It has, however, an annoying bug. When the GridPanel align mode is alClient and I maximize its parent window, the GridPanel adjusts to the new size of that window, however, the controls laying on the grid do not. They stay in the same position they were before window resize.
It happens only at the first window's maximization. If the window is first resized manually, everyting is OK. I think the grid adjusts its child controls after the second resize event (??).
What to to do make GridPanel work properly if it comes to this bug? It might be enough to send a message to it (but what message?), I do not know. I tried to use Realign, Refresh etc., but they did not help.
Thanks for your help in advance,
Mariusz.
Ah, I've had similar issues as well. It might be related to a resizing problem in the VCL. You might want to try the fix by Andreas Hausladen. It seems to work for me in most of the cases.
Changing the width / invalidating the control doesn't work for me (something changed with recent versions of RAD Studio?).
Anyway a similar, simple workaround along that line is:
procedure TForm1.FormResize(Sender: TObject);
begin
GridPanel1.ControlCollection.BeginUpdate;
GridPanel1.ControlCollection.EndUpdate;
end;
I found one trick.
in OnResize event of parent of gridpanel, change gridpanel's width by 1 pixel.
then gridPanel will notice size changed, then rearrange sub-controls in gridpanel..
sample is below..
procedure TForm1.FormResize(Sender: TObject);
begin
GridPanel1.Width := GridPanel1.Width - 1; // subtract 1
GridPanel1.Width := GridPanel1.Width + 1; // recover width by adding 1
end;
I have had this error too, on several projects. I'm not sure how I solved this (it was on projects for my previous employer, I don't have access to this source code anymore). I think I had te redraw / refresh that parent frame or form on which the GridPanel was placed.
on the resize of the owner call GridPanel.Invalidate.
I didn't test it. I hope it's work.
Related
I have only one form in my application, where I insert a frame accordingly the user action.
This form is inserted in a TScrollBox, since it sometimes has a width bigger than the screen/window.
I have one or more TListViews on the frame, and many TEdits.
When running the application and opening any frame, one or more TListView are not filled in. By debug I see the data is pulled from the SQL. TEdits are filled in. Moving the SQL cursors gets all TEdits updated accordingly.
The closing this frame and opening again (or any other) then it start showing the data on the TListView.
I have not found any correlation that make sense. Apparently there is some kind of initialization missing. Not all TListView are empty, in some frames I have 4 or 5 of them and it show 2 with data, the others are empty.
EDIT: I have changed the title of this question, since I have noted that the problem seems not be related to the LiveBindings primarly, but seems to be related to some kind of initialization of the TListView on other lists.
I made a new test and see that TTreeView is also having the same problem, showing totally out of order the data, only at first time. If I previouslly opens something else it works fine, if I close and open the frame with the TTreeview the second time is ok.
In this image I show the TreeView messed:
It should not have all that spaces and some of the nodes are overlapped.
My application has only one form, and everything are frames that are created as parent of a TScrollBox.
With Delphi XE5 the issues of TScrollBox were many, I had to upgrade to XE6.
Many things start working with XE6, however there is still a little problem with TScrollBox:
There is a need to call ApplyStyleLookup, after the frame is inserted and parented to the scroll, to make the initialization. That makes the TListView and TTreeView works fine since the very first time.
constructor TFrameBase.Create(AOwner: TComponent);
begin
inherited;
Align := TAlignLayout.Left;
Parent := AOwner as TFmxObject;
if (AOwner is TScrollBox) then
(AOwner as TScrollBox).ApplyStyleLookup;
end;
This is my frame constructor. This fixed all the problems.
I have three buttons placed at the right on my form. The buttons' anchor property parameters akTop, akRight are set to true, the other ones left to false so that the buttons always remain at the right side near the boarder when the form is resized. Then I set the form's WindowState property to wsMaximized so that it covers the whole screen when run at start-up. But when I start the application the buttons are closer to the middle rather than on the right. But when I resize the form at design-time everything seems to work just fine.
Here are some snapshots to show you exactly what I mean:
At design-time:
At run-time:
Please, explain what I'm doing wrong and how to fix this so that it works as intended.
This looks like the buttons are being created with their designed positions, the form is then set to Maximized, then the anchor properties are set or put in place.
In design time the anchors are already set and so that’s why you see them move as you want. To prove my theory on this make the form much smaller, run the application and notice that the items are in their smaller design time locations.
An easy fix to get what you want. Keep the Window state at wsNormal and on FormShow (which occurs after Create) do this:
procedure TForm1.FormShow(Sender: TObject);
begin
self.WindowState := wsMaximized;
end;
You will see the results you want.
I have seen your answer in one of those tutorials. But realy dont remember was which one. You can watch all videos, even you will learn more things. it will not time waste all the way.
Link: Learn Delphi TV
Also you can try something like below if you are lazy enough to watch videos. Put this code in form resize:
buttoncreate.left := panel.width - (buttoncreate.width + buttonedit.width + buttondelete.width);
buttonedit.left := panel.width - (buttonedit.width + buttondelete.width);
buttondelete.left := panel.width - buttondelete.width;
Please help me with my question.
I have TreeView and Frames, how can I shift them if I click on an item of TreeView?
Is it better to use PageControl (PageControl1.Pages[i].TabVisible := false;) instead of Frames or Frames fit better?
Thank you very much!
To answer your first question "how to ... using a TreeView?" : Implement the OnChange event of the TreeView. The node parameter refers to the newly selected item.
About your second question "Should I use Frames or a PageControl?" : Well, one does not exclude the other and you perfectly can use both. Indeed, I advice to do so when you use the contents of such a TabPage multiple times. In those cases, place the Frame with Align = alClient on your TabPage.
Frames are usefull to design an arbitrary reusable container. For instance: you could set the same FrameType on every Page of the PageControl, assuming they all look the same but each working with different data.
Another possible minor advantage of using frames is not to get confused about all the controls on the TabPages.
But if every TabPage is unique in terms of visual style or control layout, then it's perfectly ok to not use frames and design the pages on the PageControl directly.
And about the shifting part: I don't exactly understand what you want to accomplish by setting the visibility of a tab, but shifting to another page (depending entirely on your implementation) based on the node could be as simple as:
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
PageControl1.ActivePageIndex := Node.Index;
end;
Is there a way how to enable scroll bars in disabled TMemo component ? I want let the users scroll the content even if the control's Enabled property is set to False.
I know about the possible workaround with ReadOnly and color changes like in disabled state, but this would help me a lot.
Thanks in advance :)
A control can be disabled or enabled, but not half dis- and half enabled. (And, for the nit-pickers amongst us, I think no hack should make it so :-), for the reason given below).
Using ReadOnly is the easiest solution. Be mindful though with the color changes to not make the control look disabled. That would also be very confusing for the user with regard to recognizing enabled/disabled controls. It would be better to make it look like a scrollable multi-line label. That usually is done by setting the (background) color equal to the color of its parent.
Haven't used the solution suggested and linked by #HalloDu, but that looks like a good alternative.
Well, it is not exactly, what you want, but the effect is the same. Look at this article where an ViewOnly Property for WinControls is implemented, which I found quite useful over the years. LINK
That's not perfect way but it works :
Use ScrollBar comp. adjacent to Memo.
procedure TForm9.FormCreate(Sender: TObject);
begin
Memo1.ScrollBars := ssNone;
ScrollBar1.Min := 0;
ScrollBar1.Max := Memo1.Lines.Count div (Memo1.Height div 13);//13 is height of a line in memo
end;
procedure TForm9.ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
begin
if ScrollCode in [scPageDown, scLineDown] then
SendMessage(Memo1.Handle, WM_VSCROLL, SB_PAGEDOWN,0)
else if ScrollCode in [scPageUp, scLineUp] then
SendMessage(Memo1.Handle, WM_VSCROLL, SB_PAGEUP,0);
end;
There is a way.
Place entire TMemo inside a TScrollBox.
When you fill the memo with text, adjust the height and width to accommodate the size of the text (that's another question but I'm sure it can be done)
I have an application that uses a frame extensively and needs to hide/show certain buttons depending on which form is active at the time. In order to keep the buttons neat and organized appropriately, I have put them on panels and show or hide the panels as needed for each form. My problem is when each form is initially created, the panels on the frame are out of order even though I am explicitly telling them which order to put themselves into. After I hide and re-show the form, the panels are in the correct order. Any suggestions on how to keep them in the proper order from the very beginning?
Instead of giving the panels explicit positions, try giving them alignments. They tend to stick better than way, and they do a better job of resizing if you resize the form.
You can also try using a stackpanel (or was it flowpanel?) as parent for the panels. Then you will have a order instead of a position to manipulate.
Maybe you can have a look at the DevExpress LAyoutControl? It helps us creating interfaces that always look good, no matter if we show or hide certain groups / panels. It even allows for run-time customization of the interface, if you want that!
You may try to organize them by coordinates i.e.: setting Top and Left. Unless your panels are aligned, this will always work (but it takes bit lot of work).
I had this problem and I found that the solution was to do this in FormCreate (or in a CMShowingChanged method of your frame):
MyPanel1.Align := alNone;
MyPanel2.Align := alNone;
MyPanel1.Align := alBottom;
MyPanel2.Align := alBottom;
Restore in the order that you need - this seemed to sort out the order visually.