Positioning of custom list box item components in Delphi XE5, Firemonkey - delphi

I've customised the style of a Firmeonkey list box item in such a way that now it can consist of 4 TLables in it. Each of the lable has Alignment as alNone.
I'm setting position of each of them in my code whenever i need to add any item. I've observed that when my list has scroll bar and if first component is not visible (i.e. i've scrolled down enough) at that time if i re-add all the items again in list box, then the position of TLabels in first items (or items which are not shown) get distorted.
For setting positions I am using below code :
(tmpListBoxItem.FindStyleResource('txtCol2') As TLabel).Position.X :=
(tmpListBoxItem.FindStyleResource('txtCol2') As TLabel).Position.X + (tmpListBoxItem.FindStyleResource('txtCol2') As TLabel).Width;
Any suggesstions, how can i overcome this issue.
Regards,
Padam Jain

Firemonkey styles are repeatedly 'applied' and 'freed' as components appear and disappear from screen.
It is not enough to simply set properties of style objects once and expect those values to be remembered. What you need to do is either listen to the OnApplyStyleLookup event or override the ApplyStyle method of a custom component and use the same you have above to set the properties again.
This means you'll need somewhere to store the values you are going to set.
I would suggest for your situation that you subclass TListBoxItem so you can add suitable properties or fields and put your code in ApplyStyle.

Related

SendToBack TlistItemImage at design time or runtime in fireMonkey

In TlistView Dynamic appearance I added a few object appearanced to the item.
I have a TextObjectAppearence and an ImageObjectAppearence.
I want to set the image to be a background for the text meaning the text should be on top of the image.
I tried right-clicking on the image object and selecting SendToBack but it doesn't seem to work.
At run-time, there's also not any way to call ListItemImage.sendtoback etc.
what is the right way of doing it?
I've attached a screenshot of the two items overlapping...
The only way I found is to open fmx file in text mode and to move the various objects in the order needed (first is the deeper)

delphi stringgrid inplaceedit how to position and width of edit box in a cell that has a left/right justified checkbox

I have altered a D6 stringgrid to allow for left or right justified checkboxes to be displayed in the grid cells. When the stock inplace editor is called the edit box for receiving data starts at the beginning of the cell and its width covers the entire width of the cell (ie it fills the cell completely covering my checkboxes until repainted). How can I implement my own inplace editor and control the starting location of the editor and its width? Thanks in advance to all. Bill
TStringGrid does not natively support what you are asking for. The coordinates of the inplace editor are fixed to the entire cell bounds, as it was never designed to take user-defined cell controls into account.
When TStringGrid positions the editor, it calls CellRect() (which is not virtual) and passes the returned TRect to TInplaceEdit.Move() (which is not virtual), which calls TInplaceEditor.InternalMove() (which is private) to move the editor HWND to the specified coordinates and size using the Win32 API SetWindowPos() function.
The only way you will be able to change that logic is to either:
make a copy of Grids.pas and alter TStringGrid's source code, then add the modified file to your project (this only works if Runtime Packages are disabled).
use a hook/detour to redirect TInplaceEdit.Move() to a custom method where you can alter the content of the TRect before passing it to the original implementation.
Update: now that I think more about it, you might be able to derive a class from TInplaceEdit and override its virtual WndProc() method to calculate different position/size information when asked by the WM_GETMINMAXINFO or WM_WINDOWPOSCHANGING message. Or override its virtual BoundsChanged() method to reposition/resize the editor after the grid has positioned/sized the editor where it wants. Either way, you can override the virtual TStringGrid.CreateEditor() method to make the grid create an instance of your editor class.

FireMonkey grid with different controls in same column

What can you do if you want different cell controls in the same column of a grid in FireMonkey.
The cell control seems to belong to the column, but there are situations (like the property editor), where some rows need a checkbox while other rows need a combobox or an edit control.
Thanks in advance.
The following steps should get you up and running:
Create a style, add to it the controls you want to show (i.e. a TCheckbox, a TCombobox and a TEdit). Add these within a TLayout, and set each controls StyleName to something memorable.
In your cells ApplyStyle use FindStyleResource to extract the controls you added above using their StyleNames.
When the grid calls your cell's SetData method, you need to set the Visible property for each control so only the appropriate one is shown. If you can't determine this from the data passed in, add an event handler to the cell to get the data.
You'll need to sort out the keyboard handling, which gets pretty messy. If memory serves, you need to pass keys from the grid/cell to the control (or or is it trap movement keys from the controls and pass them to the grid? Sorry if I forget exact detail).
Sorry I can't give a more detailed answer, but covering this completely would take a whole series of blog posts.
Use a style - set the cell style when you set the cell data - then us the onapplystyle event to do anything clever you require with the newly styled cell.
This way you can add what controls you need to the style and then access the controls (to set events etc) with the onapplystyle.
Hint - FindStyleResource is your friend here :-)
I have also needed a property editor and looked for a way hosting different cell types in one column. Using different styles for each row may be a solution as suggested above, but since Firemonkey grid doesnt reserve any cell control for a specific row, each time the cell control would be shown on the row, the true style would be applied to it. This is not a big problem for a static property editor, however for a real grid which has got may rows and different cell types in each row a diferent strategy is needed. So I came up with a different solution, I considered cell type proxies between TColumn and cell controls, so that each cell proxy will reserve the cell controls that is responsible for. First of all, I have a new TColumn (TvariantColumn) which is responsible for the top strategy.
vColumn := TVariantColumn.Create(Self);
vColumn.Header := 'Variant Column';
vColumn.OnGetCellProxyIndex := GetCellProxyIndex;
Grid1.AddObject(vColumn);
Then create any proxies like
vColumn.NewCellProxy(TTextProxy);
vColumn.NewCellProxy(TColorComboProxy);
vColumn.NewCellProxy(TComboColorProxy);
You can also handle Proxy specific jobs after you create it, like
with TProgressProxy(vColumn.NewCellProxy(TProgressProxy)) do //4
begin
Min := 0;
Max := 100;
end;
with TPopUpProxy(vColumn.NewCellProxy(TPopupProxy)) do //5
begin
Items.Add('Istanbul');
Items.Add('Paris');
Items.Add('NewYork');
end;
I have blogged my method in my website and published a detailed article where you can find more about the subject.

TListView Item Focus Theming

When using a TListView and themes are disabled in the Application, the focused and selected item appears something like this:
Notice in both images where the triangle is. The painted box for the item does not draw where the icon appears. In a TListBox the painted item fills the whole selected item.
How might I be able to get the icon part of the selected item to fill, just as it does with the text part?
I know TListBox renders like this, but I require the use of TListView for the Data property, also the TListView handles icons better via a TImageList.
Thanks.
You'll need to use the OnCustomDraw events of TListView. Within the event handler:
Determine if the item is selected
Determine if the control is focused
Draw the appropriate selection rectangle if the item is selected (grey if the control isn't selected, blue if it is)
Draw the text
Draw the image from the imagelist using TImageList.Draw
There are methods for doing these things, such as DrawText and FillRect.
Note that you can use TListBox rather than TListView if you'd rather. You indicated you need the Data property for items in the list, I'd assume to tie them up to your actual model objects. You can do this with anything that supports TStrings (such as TListBox.Items) using TStrings.Objects.

How to set the glyph for a toolbar button to blank?

I add a toolbar with some standard Delphi components to my application. Unfortunately, the stupid arrow is first glyph (does anyone even know what it is for?)
I would like to destroy it totally, or, at least, set itcs icon to blank, so that it blends in with the toolbar.
How can I do this?
I need some code which can be executed twice without causing an exception. Thanks
TToolButton gets its image from combining its ImageIndex property with the enclosing toolbar's Images property, which refers to a TImageList. To make a toolbar button have no image, assign ImageIndex := -1.
To remove the glyph from a TSpeedButton at design time, select the button, and then select the Glyph property in the Object Inspector. Press Del to clear the property. To do the same at run time, assign Button.Glyph := nil.
If you have a pre-made toolbar, such as TMediaPlayer or TDBNavigator, then you can't customize the buttons. They always show the arrow glyphs that are hard-coded in the control. You can choose to hide or show certain buttons, though. If you placed the control just to get a row of buttons and have no intention of using them to play media or navigate a database, then don't use that control. Just place a TPanel and put standalone buttons on it.

Resources