How to fix getting Arabic characters display in TListView? - delphi

The address book sample displays Arabic characters messed up, like that س ا ش ص. I tried to change the font of the text item to "Arial" or "Courier New", but the result is the same. Is there a way to display non-English characters correctly in TListView?
Loading contacts code:
procedure TForm1.FillContactList(Source: TAddressBookSource);
var
I: Integer;
Contacts: TAddressBookContacts;
begin
Contacts := TAddressBookContacts.Create;
try
AddressBook1.AllContacts(Source, Contacts);
ListViewContacts.BeginUpdate;
try
ListViewContacts.Items.Clear;
for I := 0 to Contacts.Count - 1 do
AddListViewItem(Contacts.Items[I]);
finally
ListViewContacts.EndUpdate;
end;
finally
Contacts.Free;
end;
end;
procedure TForm1.AddListViewItem(Contact: TAddressBookContact);
var
ListViewItem: TListViewItem;
begin
ListViewItem := ListViewContacts.Items.Add;
ListViewItem.Text := Contact.DisplayName;
ListViewItem.Tag := Contact.ID;
end;

Skia indeed solved the problem. More Details:
https://github.com/skia4delphi/skia4delphi#right-to-left
Right-to-Left
Using Skia's Canvas, your application will now support Right-To-Left text rendering. But for that you will need to make 3 changes to your project:
Open the source of your Delphi Application Project (.dpr), include the line Application.BiDiMode := TBiDiMode.bdRightToLeft;, like below:
program Project1;
uses
System.StartUpCopy,
FMX.Forms,
System.Classes,
Skia.FMX,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.BiDiMode := TBiDiMode.bdRightToLeft;
GlobalUseSkia := True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Set the property BiDiMode of your forms to bdRightToLeft;
Keyboard input controls like TEdit and TMemo, need to be fixed by Embarcadero, meanwhile, as a workaround, set the ControlType property of these controls to Platform.

Related

Override regional settings at the application start up

I want to force my application to always use the Spanish regional settings, using the FormatSettings global variable, but the application ignores those settings. Do you know what I have missed ?.
program TestProject;
uses
Vcl.Forms,
SysUtils,
Rutinas in 'Rutinas.pas',
Conexion in 'Conexion.pas' {dmConexion: TDataModule},
MainForm in 'MainForm.pas' {frmMainForm};
{$R *.res}
begin
Application.Initialize;
FormatSettings := TFormatSettings.Create('es-ES');
Application.MainFormOnTaskbar := True;
Application.Title := Application_Name;
Application.CreateForm(TdmConexion, dmConexion);
Application.CreateForm(TfrmMainForm, frmMainForm);
Application.Run;
end.
Thank you.
PS: I know that FormatSettings is not recommended because it's not thread safe, but it shouldn't be a problem here because I only change it once at the application start up, any other time that I need a customized conversion I use a local TFormatSettings variable.
I apologize, the problem wasn't in Delphi but on the DevExpress controls that I use to present the data.
DevExpress uses their own format settings: https://www.devexpress.com/Support/Center/Question/Details/A517/how-to-use-custom-formats-for-editors
Now this works correctly :
program TestProject;
uses
Vcl.Forms,
SysUtils,
cxFormats,
Rutinas in 'Rutinas.pas',
Conexion in 'Conexion.pas' {dmConexion: TDataModule},
MainForm in 'MainForm.pas' {frmMainForm};
{$R *.res}
begin
Application.Initialize;
FormatSettings := TFormatSettings.Create('es-ES');
Application.UpdateFormatSettings := False;
cxFormatController.BeginUpdate;
cxFormatController.UseDelphiDateTimeFormats := True;
cxFormatController.EndUpdate;
cxFormatController.GetFormats;
cxFormatController.NotifyListeners;
Application.MainFormOnTaskbar := True;
Application.Title := Application_Name;
Application.CreateForm(TdmConexion, dmConexion);
Application.CreateForm(TfrmMainForm, frmMainForm);
Application.Run;
end.

How to change the object inspector font?

The default font of the object inspector is ridiculously small, esp on a high resolution screen.
Is there a way to make it bigger?
Yes there is and it's really easy.
You can alter any window in the IDE by creating a package and installing this in the IDE.
Because the bpl gets loaded into the main process of the Delphi IDE you can alter any IDE window's properties from there.
Code by Mike Fletcher
Create a new package and add the following unit:
unit AdjustOIFont;
interface
uses Vcl.Forms, Vcl.Controls, Vcl.Dialogs, Vcl.StdCtrls;
procedure Register;
implementation
function GetOIForm: TForm;
var
i: Integer;
begin
Result:= nil;
for i:= 0 to Screen.FormCount - 1 do begin
if Screen.Forms[i].Name = 'PropertyInspector' then begin
Result:= Screen.Forms[I];
Exit;
end;
end;
end;
function GetChildControl(AParent: TWinControl; AName: string): TWinControl;
var
i: Integer;
begin
Result:= nil;
for i:= 0 to AParent.ControlCount - 1 do begin
if AParent.Controls[i].Name = AName then begin
Result:= TWinControl(AParent.Controls[i]);
Exit;
end;
end;
end;
function GetOIControl: TCustomListBox;
var
OIForm: TForm;
begin
OIForm:= GetOIForm;
Result:= TCustomListBox(GetChildControl(GetChildControl(OIForm, 'Panel3'), 'PropList'));
end;
procedure Register;
var
OI: TListBox;
OIForm: TForm;
begin
OIForm:= GetOIForm;
OIForm.Font.Size:= 10;
OI:= TListBox(GetOIControl);
OI.Font.Size:= 10;
OI.ItemHeight:= 20;
end;
end.
Build the package and install.
The change will take effect immediately.
Knowing this trick it's also be easy to collect all the enumerated names in a stringlist and copy them to the clipboard.
These names can than be used to expand the code and fix the fonts of other IDE elements as well (e.g. the Structure pane).
Much better.
Works on Seattle and XE7.
One way to achieving this is by modifying registry like it is described in Malcolm Groves article here: http://www.malcolmgroves.com/blog/?p=1804
Another option is to use Delphi IDE Colorizer which is a third party application designed to greatly change appearance of Delphi IDE by changing fonts, colors, etc. You can find it here: https://github.com/RRUZ/Delphi-IDE-Colorizer
And if you perhaps also want to change syntax fonts and syntax highlighting you can also check Delphi IDE Theme Editor which is designed to change the appearance of code highlighting based on your desires. You can find it here: https://github.com/RRUZ/delphi-ide-theme-editor

Delphi: TOpenDialog + VCL Styles corrupts filenames with large amount of files

Using Delphi Seattle in W7 x64. When using a custom VCL style and you select a large amount of files (like 2-3k+), the filenames are corrupted. Without a custom style this doesn't happen.
program Project1;
uses
Vcl.Forms,
Unit1 in 'Unit1.pas' {Form1},
Vcl.Themes,
Vcl.Styles;
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
TStyleManager.TrySetStyle('Onyx Blue');
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
procedure TForm1.FormCreate(Sender: TObject);
Var s: string;
ts: TStringList;
begin
if OpenDialog1.Execute then begin
ts := TStringList.Create;
for s in OpenDialog1.Files do
ts.Add(s);
end else Exit;
ts.SaveToFile('z:\files.txt');
ts.Free;
end;
object OpenDialog1: TOpenDialog
Filter = 'Pictures (jpg,png,bmp,gif)|*.jpg;*.png;*.bmp;*.gif|All Files|*.*'
Options = [ofReadOnly, ofAllowMultiSelect, ofEnableSizing, ofForceShowHidden]
Title = 'Select files to upload'
Left = 201
Top = 64
end
On my end, this code results in only 769 files written to the log out of ~5000, and their initial path "z:" gets corrupted with other characters "?"
Any way to fix this?
Note: the new TFileOpenDialog does not seem to have this issue, however it does bring others as shown here: (besides being Vista+)
You are experimenting this behavior because the size of the buffer passed to the Classic Open Dialog Box to retrieve the results of the selected file(s), the buffer is represented by the lpstrFile element which is part of the OPENFILENAME structure. The VCL internally set the size of this buffer to High(Word) - 16 (65519) bytes when the multi-select option is enabled and a MAX_PATH buffer size when the single file selection is enabled.
This is part of the VCL code (Vcl.Dialogs) which show this
function TOpenDialog.DoExecute(Func: Pointer; ParentWnd: HWND): Bool;
const
MultiSelectBufferSize = High(Word) - 16;
...
...
if ofAllowMultiSelect in FOptions then
nMaxFile := MultiSelectBufferSize else
nMaxFile := MAX_PATH;
SetLength(TempFilename, nMaxFile + 2);
lpstrFile := PChar(TempFilename);
...
...
Starting with Windows Vista and the introduction of the New Dialogs (IFileOpenDialog), the selected files are returned by the IFileOpenDialog::GetResults method in a IShellItemArray, So the buffer limitation doesn't apply.
In summary this behavior is not caused by the VCL Styles.
Finally if you want use the modern dialogs with a custom style try the VCL Styles Utils project.
That is not about Delphi it seems.
Just five seconds in Google and we have this:
" File Open dialog cannot return more than 1000 files "
http://answers.microsoft.com/en-us/windows/forum/windows_7-files/shameful-limitation-file-open-dialog-cannot-return/bfff43fc-0da5-48d6-8703-dc0eac3c7581?auth=1

Create own Splashscreen Delphi 10 seattle

Instead of using the png images through the project options for a splashscreen I want to use my own Form for a splashscreen.
I've found a solution for XE2 in the following link, but it doesn't work for Delphi 10 Seattle: https://stackoverflow.com/a/9080804/2728408
Below I have some examples I've tried in my project .dpr:
Example 1:
program Project2;
uses
FMX.Forms,
System.SysUtils,
Unit1 in 'Unit1.pas' {MainForm},
Unit2 in 'Unit2.pas' {SplashForm};
{$R *.res}
begin
Application.Initialize;
SplashForm := TSplashForm.Create(nil);
SplashForm.Show;
Application.ProcessMessages;
Sleep(1000); // Whatever to control display time of splash screen
Application.CreateForm(TMainForm, MainForm);
SplashForm.Close;
SplashForm.Free;
Application.Run;
end.
Example 2:
program Project2;
uses
FMX.Forms,
System.SysUtils,
Unit1 in 'Unit1.pas' {MainForm},
Unit2 in 'Unit2.pas' {SplashForm};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TSplashForm, SplashForm);
Application.Run;
Sleep(1000);
Application.Terminate;// Also tried Application.Destroy
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
Example 3:
program Project2;
uses
FMX.Forms,
System.SysUtils,
Unit1 in 'Unit1.pas' {MainForm},
Unit2 in 'Unit2.pas' {SplashForm};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TSplashForm, SplashForm);
Application.Run;
Sleep(1000);
Application.CreateForm(TMainForm, MainForm);
SplashForm.Close;
Application.ProcessMessages;
Application.Run;
end.
Anyone has a solution to my problem?
you should not interfere with Application.Terminare/Inititalse the way you do it in the code.
In Firemonkey, you can change the main form of the application in runtime. So, you should show your splash form first, do all the job you want and then switch to your main form.
See this for an example: http://www.uweraabe.de/Blog/2016/01/22/a-splash-form-in-firemonkey/
procedure TFormSplash.FormCreate(Sender: TObject);
begin
StartupTimer.Enabled := false;
StartupTimer.Interval := 500; // can be changed to improve startup speed in later releases
end;
procedure TFormSplash.SplashImagePaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
StartupTimer.Enabled := not FInitialized;
end;
procedure TFormSplash.StartupTimerTimer(Sender: TObject);
begin
StartupTimer.Enabled := false;
if not FInitialized then begin
FInitialized := true;
LoadMainForm;
end;
end;
procedure TFormSplash.LoadMainForm;
var
form: TForm;
begin
form := TMainForm.Create(Application);
form.Show;
Application.MainForm := form;
Close;
end;
Here is what I have been doing for the past 3 days or so.
First: Create the form of the splash screen. Like normal loading of Delphi/C++ IDE, it has an indicator that "xxxx dll is loading..". So the basic steps are to include the splash screen as part of the usual loading of the main application.
Second: Remember that your DPR file takes a vital role in loading and/or creating all the forms. Although I agree with the VCL function (Application.ProcessMessages) to show to the user that it is creating the form.
Third: Never run a procedure in your Main Form OnCreate Event except for Skinning or to instantiate the skin. But call it again in the DPR once the Main Form is created.
Fourth: Disable first your Main Form once it is created, so that the user will not click on buttons or whatever then re-enable it when the Splash Screen is hidden.
Here is the DPR:
program xxxx;
uses
Forms, MidasLib,.....
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.Title := 'xxxxx';
SplashFrm := TSplashFrm.Create(Application);
try
Application.CreateForm(TMain_Form, Main_Form);
Main_Form.Skinning;
Application.ProcessMessages;
SplashFrm.FormStyle := TFormStyle.fsStayOnTop;
Main_Form.Enabled := False;
Main_Form.WindowState := TWindowState.wsMaximized;
Application.ProcessMessages;
SplashFrm.Show; //Never use showModal coz splash form needs to be closed first and create all the rest of the forms.
SplashFrm.Label5.Caption := 'Loading... Database handlers..';
Application.CreateForm(TDM, DM);
Application.ProcessMessages;
SplashFrm.Label5.Caption := 'Loading... Login Libraries..';
Application.CreateForm(TLogin_Frm, Login_Frm);
Application.ProcessMessages;
.....// All the rest of the Forms.
Main_Form.DSiTrimWorkingSet; //[StockOverflow/questions/2031577][1]
finally
SplashFrm.Free;
Main_Form.Check_Registration;
Main_Form.Checking_Internet_Proc;
Main_Form.Enabled := True;
Main_Form.sStatusBar1.Panels[0].Text := 'Ready...';
Application.ProcessMessages;
Main_Form.DSiTrimWorkingSet;
end;
Application.Run;
end.

How to make Edit1.Font.Charset work with themes (visual styles)

If you have a non-themed, non-Unicode VCL application with an TEdit "TestEdit" and set TestEdit.Font.Charset to RUSSIAN_CHARSET TestEdit displays cyrillic characters. If however you switch the app to use theming this doesn't work anymore. Try the following to see this:
Create a new VCL app.
Close the default Unit1 without saving.
Replace the project source code (Project1.pas) with the code at the bottom of this posting and save as CharsetTest.pas.
Uncheck runtime theming in the project options.
Run the program, click the radio buttons, watch the edit box' font.
Now check runtime theming in the project options or add XPMan to the uses clause.
Repeat step 5.
My question is: Is there a way to make the app honor the charset even when themed? (Without switching to Unicode.)
program CharsetTest;
uses
Windows,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
StdCtrls,
ExtCtrls;
{$R *.res}
type
TForm1 = class(TForm)
private
CharsetRadioGroup: TRadioGroup;
TestEdit: TEdit;
procedure CharsetRadioGroupClick(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
end;
constructor TForm1.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
BorderWidth := 8;
Caption := 'Charset Test';
ClientHeight := 180;
ClientWidth := 250;
CharsetRadioGroup := TRadioGroup.Create(Self);
CharsetRadioGroup.Name := 'CharsetRadioGroup';
CharsetRadioGroup.Height := 105;
CharsetRadioGroup.Align := alTop;
CharsetRadioGroup.Caption := 'Charset';
CharsetRadioGroup.Parent := Self;
CharsetRadioGroup.Items.Add('Default');
CharsetRadioGroup.Items.Add('Russian');
CharsetRadioGroup.Items.Add('Greek');
CharsetRadioGroup.OnClick := CharsetRadioGroupClick;
TestEdit := TEdit.Create(Self);
TestEdit.Name := 'TestEdit';
TestEdit.Align := alBottom;
TestEdit.Font.Size := 20;
TestEdit.Font.Name := 'Courier New';
TestEdit.Text := 'äöüÄÖÜß';
TestEdit.Parent := Self;
CharsetRadioGroup.ItemIndex := 1;
end;
procedure TForm1.CharsetRadioGroupClick(Sender: TObject);
begin
case CharsetRadioGroup.ItemIndex of
0:
TestEdit.Font.Charset := DEFAULT_CHARSET;
1:
TestEdit.Font.Charset := RUSSIAN_CHARSET;
2:
TestEdit.Font.Charset := GREEK_CHARSET;
end;
end;
var
Form1: TForm1;
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Not a direct answer, but you can use the TMS Unicode Controls to add Unicode support for just the edits, and leave the rest of your application as-is. We did that a few years back to get support in a single combobox, and the overhead wasn't bad.
The original TNT Unicode library that the TMS pack was based on is available here, but TMS isn't expensive, and they've made a bunch of improvements since they bought it.
This seems to be an issue with the windows edit control:
Edit Controls and Charset and XP
XPMan charset problem (try 2)
Until we upgrade to a recent (read "Unicode enabled") Delphi some of our customers will have to live without themes.

Resources