I am trying to add custom behavior to a TExpander. Basically what I am trying to acheive is the following:
I've got multiple TExpanders on my form. When the user expands one of these TExpanders, all the other TExpanders should be minimized.
The easiest way to do this is to handle the OnResize event for the TExpander, and then in that event, check the IsExpanded property of each of the other TExpander panels and set them to False.
Related
I installed the new Delphi 10.2.2 Tokyo and started to move my projects over to it.
I found the following strange behavior in a Windows desktop application.
I have a Form with a size of 700x545. To prevent the user from resizing it, I use the OnCanResize event and set the Resize parameter to False.
In the OnCreate event, I set the desired Width/Height values. With Delphi 10.0 Seattle, it works well, but in 10.2.2 the size is set to 340x220 instead.
Obviously, it is set before the OnCreate event, because my changes in the OnCreate event are ignored, maybe because of my OnCanResize event.
In design time, I find the correct values in the Object Inspector.
Any ideas?
When a Form object is created, its underlying window can (and usually is) created during DFM streaming, before the OnCreate event is fired. So, it is possible for the Form to want to perform resize operations before you are ready for them. This has always been a possibility in all versions of Delphi, it is not new behavior in Tokyo.
If you are going to use the Form's OnCanResize event, you should make sure the Form object is fully constructed and initialized before you start setting the event's Resize parameter to False. For instance, add a Boolean member to your Form class and set it to True in the OnCreate event, then have the OnCanResize event set the Resize parameter to the opposite value of that Boolean.
Alternatively, instead of using the OnCanResize event, consider using the Form's Contraints property instead, or simply set the Form's BorderStyle property to a non-resizable style, like bsSingle or bsDialog. Either way will allow you to resize the Form in code while preventing the user from resizing the Form manually.
Te difference between Seattle and 10.2.2 is following:
the oncanresize event is called twice before the oncreate event is called. The source comes from a TControl (i could not find out what control), the caller seems for me the ScaleforCurrentDPI procedure. In Seattle the oncanresize is never called before finishing the oncreate event.
For me it sounds like a bug when a onformdosomething event can be called before the oncreate event.
I use a frame that is shown by calling TPopup.Popup(true); method. If the frame contains a button with the ModalResult property set (to, for example, mrOK) it closes automatically when clicked by the user. But I need to close the frame in an OnClick event of a TListBox in it.
Frame does not have Close method.
I would like to avoid using message posting to the parent form as it might cause future problems when the application is ported to Android as well as I would prefer not to declare the OnClick event handler for the Frame.ListBox in the parent Form because the frame might be shown by several different forms and it will worsen the quality of parent Form code making it heavy and difficult to read.
I would highly appreciate suggestions how to do this.
I found the following way out. I call
(GetParentComponent as TPopup).IsOpen:=false;
When you inherit from TPopUp like explained here (How to make my own dialog component from Firemonkey TPopUp?) then you can call ClosePopup when an event is trigerred in your frame.
I am trying to add a custom color to a TColorBox control. I've added the control to my form and for the Style property, set cbCustomColor to True. For the OnGetColors event, I have the following code:
procedure TfrmAbout.GetColors(Sender: TCustomColorBox; Items: TStrings);
begin
ShowMessage('GetColors has been triggered');
Items.AddObject('clWebSnow',TObject(clWebSnow));
Items.AddObject('MyOrange',TObject(Rgb(255,128,0)));
end;
I don't see the messagebox or the colors appearing in the dropdown. Is there anything else I need to do in order to get this to work?
You need to include the cbCustomColors option to the Style property to enable adding of your own custom colors instead. The cbCustomColor option only includes the item, which allows you to select a custom color.
In order to get this to work I did have to follow #Sertac's suggestion. On FormCreate, I fired a procedure that removed the [cbCustomColors] then added them back in, for each TColorBox.
I could not find another suitable work around or figure out why GetColors was not firing when it should.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why don’t child controls of a TStringGrid work properly?
I have a TStringGrid of variable length, and one column has a TComboBox to alter the data inside. I have made its parent the TStringGrid so that if it is scrolled down I can use the position of the selected rectangle inside the StringGrid.
The problem has arisen because I need to fire an OnChange event: The issue is that when its parent is StringGrid, the only way to fire the OnChange event seems to be using the keyboard events, and selecting its items will not fire the event. I have also tried to redeclare the OnChange event after changing the parent and the OnClick event (which doesn't fire whatsoever).
I'm not really sure why this is occurring but it defintely seems to be a problem with the parent being a TStringGrid.
It is common problem for controls with Parent = TStringGrid.
Look at the solution here
On my main form I have a TPanel containing buttons that act as a toolbar. I want to clone/copy this toolbar and the buttons and their functionality to a second form.
Cloning the menu was simple using newmenu.merge(mainmenu). That was an excellent shortcut to duplicating a Tmainmenu.
But I am at a loss on how to easily duplicate my toolbar without having to manually assign the events and keep a timer to compare and track which buttons are enabled and disabled in comparison to the real mainmenu on the main form. Depending on what the application is doing the main toolbar buttons will be enabled and disabled at various times.
Any ideas here? Thanks for any suggestions or tips to make this easier.
Duplicating the controls
In the Form Designer, select the panel and press Ctrl+C to copy it and all its children to the clipboard. Go to the second form and press Ctrl+V to paste.
If you're still working on the design and want to keep it consistent between both forms, then create a TFrame and design your toolbar layout there. Then put an instance of that frame on both your forms. Changes to the frame design will be reflected in the forms.
See Working with frames in the help.
Making sure both sets of buttons are enabled consistently
Create a data module. Put a TActionList on it. Add an action to it for each button on your main form. Assign event handlers to the actions' OnUpdate events. In them, set the actions' Enabled properties. Finally, assign each button's Action property to refer to the corresponding action object. The buttons will automatically get enabled and disabled with the actions. No timer required.
Furthermore, you can handle the actions' OnExecute events, too. Clear each button's OnClick property, and then move the button's OnClick code into the corresponding action's OnExecute handler. It will automatically get called when you click the button, even though the OnClick property is empty.
When you assign the Caption or Hint property of a TAction, the corresponding properties of any associated controls also change. Likewise for images, if the control supports them. Actions can be assigned to menu items, too.
See Using action lists in the help.
Acting like a toolbar
Just use TToolbar. That's what it's for.
Or, once you're used to actions, put a TActionManager in your project and use it with TActionToolbar and TActionMainMenuBar. See Organizing actions for toolbars and menus in the help.
Are the buttons attached to actions? If so, you can use the OnUpdate event of the TActionList to specify what should and should not be enabled. If not, it isn't too much work to convert to using actions.
If you go this route to convert to using a ActionList, consider putting the ActionList in a datamodule where different units and forms could reference it.
You can Use ClipBoard Object For Copy Your Panel.
Clipboard.SetComponent(Panel1);
Clipboard.GetComponent(Form2,GroupBox1);