Why is the ampersand missing in Firemonkey combo? - delphi

When you create a Delphi project and add a combobox and set ComboBox1.Items.Add('Zebra & Zulu') it shows "Zebra & Zulu" when you dropdown the list. Perfect.
When you create a Firemonkey project and add a comboxbox or comboedit and set ComboBox1.Items.Add('Zebra & Zulu') or ComboEdit1.Items.Add('Zebra & Zulu') it shows "Zebra Zulu" (no ampersand shows) when you dropdown the list. However, when you select it using the comboedit the text field part shows "Zebra & Zulu". Just weird.
Now there is a work around (sort of) but to me it is questionable. Add a second ampersand and the dropdown list shows the ampersand. However, adding the second ampersand shows up on the comboedit text field part. Bad.
My question is can you force these combo controls dropdown list to show the ampersand? And why is the ampersand missing in the first place?

This seems to be inbuilt behaviour that is likely leftover from the VCL's accelerator key handling. There does not seem to be a way to modify this behaviour with styles or options :
procedure TTextControl.DoChanged;
var
TextStr: string;
begin
if Assigned(FITextSettings) then
FITextSettings.TextSettings.BeginUpdate;
try
if Assigned(FITextSettings) then
FITextSettings.TextSettings.Assign(ResultingTextSettings);
TextStr := DelAmp(Text); // **! Here deleting ampersands unconditionally
if Assigned(FTextObject) then
begin
UpdateTextObject(FTextObject, TextStr);
// ... etc - method continues
One workaround is to use the unicode full-width ampersand :
ComboBox1.Items.Add('Zebra & Zulu');
Obviously not appealing for a number of reasons.
From the code above, this naturally affects all FMX TTextControls - even a TLabel, for example, will not display an ampersand when assigned :
Label1.Text := 'Zebra & Zulu';
Even in a VCL application, for interest, this:
Label1.Caption := 'Zebra & Zulu';
will render as
Zebra _Zulu
Although a VCL TComboBox will correctly render an item with a single ampersand...
This is an open QC, albeit one that does not appear in any hurry of being addressed :
http://qc.embarcadero.com/wc/qcmain.aspx?d=122564

Related

How can I use ALL system registered themes/styles in my Delphi App?

With Vcl.Themes.TStyleManager.StyleNames, I have access to just the style names enabled in the project options (Application/Appearance).
How can I list all of the style names registered in the system, and make it active in Delphi 11?
This is how I fill a TComboBox with the available styles:
procedure FillComboboxWithStyles;
var
stylename: string;
begin
for stylename in TStyleManager.StyleNames do
CBVclStyles.Items.Add(stylename);
end;
To activate a certain style you fill TStyleManager.SetStyle(const Name: string) with the stylename. For example the selected one from the TComboBox.
if (CBVclStyles.ItemIndex >= 0) then
TStyleManager.SetStyle(CBVclStyles.Items[CBVclStyles.ItemIndex])
else
;// handle a non-selected style
Don't forget Vcl.Themes in your uses.
You can include the style files (*.vsf from C:\Program Files (x86)\Embarcadero\Studio\22.0\Redist\styles\vcl with 22.0 marking your RAD Studio version) along with (externally from) your .EXE and then iterate over them when you fill your ComboBox. Then manually load the style from the file with TStyleManager.LoadFromFile when selected.
This will also allow your user to add his own style files to the setup.
This, I believe, is what the IDE does (except that it reads the list directly from the folder, since there's no "installation" of a style other than making the file available in a recognized location).

TListView truncate hints when using styles

I have a problem with TListView when using Application styles.
Sometimes the hints are truncated. It depends on spaces and length of words in the string.
For example:
'1518 ZL Danovy doklad odeslany' is truncated
'1518ZLDaňový doklad odeslaný' ' is OK
This is happening in Delphi 10.2.1! In Delphi XE7, it was all OK! So I think it must be some kind of bug in this version.
Is there any way of fixing it, or a workaround?
ScreenShot of problem:
Simple project:
https://www.dropbox.com/s/q30i9vlejt1vst7/ListViewTest.7z?dl=0
Things I tried:
removing the LVS_EX_INFOTIP flag (with ViewStyle.vsIcon not working):
ListView_SetExtendedListViewStyle(
ListView1.Handle,
ListView_GetExtendedListViewStyle(LV.Handle) and not LVS_EX_INFOTIP
);
Removing the style from TListView as here:
How to disable VCL styles in Delphi

Insert values on Windows Dialog from Delphi Dialog

I want to know if there's a way to insert, for example, a FilePath in a DialogBox opened by Windows itself, but inserted from a Delphi variable to the Windows Dialog? Something like, click on an Upload button in any website that does open the File Explorer Dialog, and in Delphi send the value of the Path to the File Explorer of Website.
PS : I already have the code to get his HWND handle.
I don't know if this is possible, or is there's a way to do it.
Edit : A Select File from the site, what I want is simply to input the FilePath of this site by an app variable in Delphi.
Variants
If you know that dialog window's handle already then there are at least 2 variants:
finding the control by going through the children hierarchy, using FindWindowEx()
relying on the dialog template's IDs, using GetDlgItem()
Both may work out great, but are at the same time fragile, since the dialog window's structure (as per its controls and IDs) can change even by Service Packs already, let alone entire Windows versions. My experience here is from Win2000 up to Win7 and on those systems it worked.
Dialog versions
What you posted as screenshot is the "Vista" version of the dialog; the older "Win95" version is identical in terms of accessing the "filename" ComboBox.
The old one is typical for having the buttons ("open" and "cancel") in one row. Older software might still use these, but your web browser most likely not:
The one since Vista has its buttons in one line and is notable of featuring a full folder pane:
But both pictures show that the control layout is the same: a ComboBoxEx32 is a direct child of the window, having its own child(s). So we can use the same code for both versions.
Code
var
hDialog, hCbx32, hCbx, hEdit, hFilename: HWND;
sText: String;
begin
hDialog:= 9568854; // Dialog window, class "32770"
sText:= 'M:\my\filename.ext'; // What should be set
// Variant #1: finding the control by parents and childs.
// Luckily both the old dialog up to XP and the new dialog
// since Vista do not differ as per the filename ComboBox.
hCbx32:= FindWindowEx( hDialog, 0, 'ComboBoxEx32', nil ); // Most likely the 3rd child control
hCbx:= FindWindowEx( hCbx32, 0, 'ComboBox', nil ); // Actual ComboBox inside that
hEdit:= FindWindowEx( hCbx, 0, 'Edit', nil ); // Edit control inside ComboBox
SendMessage( hEdit, WM_SETTEXT, 0, LPARAM(PChar(sText)) );
// Variant #2: using dialog template IDs, which haven't
// changed since XP with one of its Service Packs. However,
// tested with Win7 only.
hFilename:= GetDlgItem( hDialog, $47C ); // "cmb13", found at least in XP SP3
if hFilename= 0 then hFilename:= GetDlgItem( hDialog, $480 ); // "edt1" = Maybe prior to XP without any SP
SendMessage( hFilename, WM_SETTEXT, 0, LPARAM(PChar(sText)) );
end;
One of both variants should do already. Successfully tested on Win7x64
using Paint's "Open" command for the Vista dialog version, and
one of my older program's "Open" command for the Win95 dialog version:
the text in the filename's ComboBox was set as expected.

How to refresh child objects in desktop testing with TestComplete

There is a desktop window, which has more tabs, and some tabs include a text editor.
The editor buttons have the following mapping on the first tab (simplified here):
Window.PageControl.Tab1.Editor.Panel.Button1
Window.PageControl.Tab1.Editor.Panel.Button2 and so on.
The editor buttons have the following mapping on the second tab (simplified here):
Window.PageControl.Tab2.Editor.Panel.Button1
Window.PageControl.Tab2.Editor.Panel.Button2 and so on.
(Sometimes the Editor and other objects between Editor and Panel are cached and their mapping is not stable.)
I wrote a test which checks the functions of the text editor in the following way:
Window.PageControl.TabIndex := 1;
editor_test;
Window.PageControl.TabIndex := 2;
editor_test;
The editor_test looks like:
Window.PageControl.Refresh;
lprops := ['FullName','WndClass'];
lvals := ['*Panel', 'TWPToolPanel'];
ltarget := Aliases.(application name).Find(lprops,lvals,20,true);
ltarget.Button1.Click;
ltarget.Button2.Click...
editor_test properly works on any single tab of the window. Although, when I try to run the editor_test more times in one test, the test fails after changing tab, because it searches the buttons on the previous tab.
I tried Refresh and RefreshMappingInfo methods on the common parent object of the tabs (see above), but they doesn't help.
(The names and number of tabs can change in the window depending on the conditions.)
Is there any other way to clear cached mapping tree during test run? Is there any mistake in the concept?
Thank you in advance for any suggestion!
The solution was to complement the editor test in the following way:
lprops := ['FullName','WndClass', 'VisibleOnScreen'];
lvals := ['*Panel', 'TWPToolPanel', true];
Using this, TestComplete does not recognize editor buttons on inactive tabs of the window, which happened in the original scenario.

Error loading txt files to synedit

I'm trying to load the text from a text file to a synmemo by using
procedure TForm1.btn7Click(Sender: TObject);
begin
if dlgOpen1.Execute then
synm1.Lines.LoadFromFile(dlgOpen1.Files.Text);
end;
But as soon as I select a file i get this error:
Cannot open file "C:\Users\adria\Desktop\New Text Document.txt
". The filename, directory name, or volume label syntax is incorrect.
Component: https://github.com/TurboPack/SynEdit
The problem is in the use of the Files property of the dialog to access the selected filename.
The Files property is a list of strings intended for use when you have enabled multiple selection in the dialog and need to process more than one filename selected by the user.
The Text property of string list returns a formatted representation of all entries in that list with each entry delimited by an EOL character (or characters).
You might expect that where only a single file is involved that this Textproperty would contain only the name of that file. But in fact it also includes an EOL character. i.e. the filename you are trying to open by using this technique is actually:
'C:\Users\adria\Desktop\New Text Document.txt'#13#10
There was actually a clue to this in the way that the message was being displayed, with the closing quotes on a separate line as a result of that EOL.
The correct way to work with the selected filename depends on whether you are supporting multiple selection or single.
In the case of single selection (your case here) the simplest approach is to use the Filename property of the dialog:
if dlgOpen1.Execute then
synm1.Lines.LoadFromFile(dlgOpen1.Filename);
For multiple selection you would use the Files property, but access each filename by index in the list:
if dlgOpen1.Execute then
for i := 0 to Pred(dlgOpen1.Files.Count) do
begin
// Do something with each dlgOpen1.Files[i] ...
end;

Resources