How to set FireMonkey form icon runtime in Delphi 10.2 - delphi

I'm creating an application for Windows and OS X using Firemonkey Framework with Delphi 10.2 Tokyo and can't set application or form icon dynamically.
In VCL project I've used following code:
Form1.Icon.LoadFromFile()
or
Application.Icon.LoadFromFile()
But there are no such properties or methods in FMX. Is there any way to set project icon otherwise than in Project -> Options menu?

Add to your uses list {$IFDEF WIN32}WinApi.Windows,FMX.Platform.Win,{$ENDIF}
procedure setFormIcon(Form: TForm; FileName: String);
var Icon : NativeUInt;
begin
{$IFDEF WIN32}
ICON := LoadImage(0,PWideChar(Filename),IMAGE_ICON,0,0,LR_LOADFROMFILE OR LR_DEFAULTSIZE OR LR_SHARED);
SetClassLong(FmxHandleToHWND(Form.Handle), GCL_HICON, icon);
{$ENDIF}
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
setFormIcon(Form1,'my icon path.ico');
end;

In the 10.2 Rio sources, I see that the function TPlatformWin.CreateWindow, which is used to create a window in the Windows, have only this line to provide a window's icon:
WindowClass.hIcon := LoadIconW(MainInstance, PChar('MAINICON'));
And function TPlatformWin.CreateAppHandle have an absolutely same code! So, we have not a direct way to set app or form icon through FireMonkey components.
At Windows You still can use WinAPI message WM_SETICON (SendMessage(Handle, WM_SETICON, ICON_BIG, MyIconHandle);), but I have not tried that and do not know any troubles in this way.
Also in Windows we may use TTaskbarBase and TPreviewClipRegion classes to the more precise and functional way of TaskBar interactions.
P.S. I do not know, what we have for same requirements at OS X.

Related

File Open Dialog with Preview in Delphi 10.3

I changed for Delphi 10.3 and its default TOpenDialog contains a preview pane. I made some searches and found the IFileDialogCustomize interface provided by Microsoft to customize standard WinAPI dialogs. I know I have to use the OnSelectionChange event handler to modify the picture of the pane. The big question for me is : how can I access the preview pane image by IFileDialogCustomize? What is the ItemID for this? I couldn't find any answer to this question on the net. Somebody know the answer? Then please share with me and the community! :)
I replaced some code fragments by ... for the sake of brevity, because these are trivial or app dependent sections.
procedure TMainWindow.OnSelectionChange( Sender : TObject );
var
dc : HDC;
aBMP : TBitmap;
function isSelectedFilePreviewAble : boolean;
begin
result := ...;
end;
functon getPreviewPictureDC : HDC;
var
iCustomize : IFileDialogCustomize;
h : THandle;
begin
if OpenDialog1.QueryInterface( IFileDialogCustomize, iCustomize ) = S_OK then
begin
h := iCustomize.??? this is the missing code fragment
result := GetDC( h );
end else
result := 0;
end;
procedure generatePreviewPicture;
begin
...
end;
begin
dc := getPreviewPictureDC;
if ( dc <> 0 ) then
begin
aBMP := TBitmap.Create;
try
if ( isSelectedFilePreviewAble ) then
generatePreviewPicture;
StretchBlt( aBMP.Handle, ...);
finally
aBMP.Free;
ReleaseDC( dc );
end;
end;
end;
I made some searches and found the IFileDialogCustomize interface provided by Microsoft to customize standard WinAPI dialogs.
First, IFileDialogCustomize does not "customize standard WinAPI dialogs". It customizes only IFileOpenDialog and IFileSaveDialog dialogs, no others.
Second, TOpenDialog primarily uses the legacy Win32 API GetOpenFileName() function. On Windows Vista+, GetOpenFileName() uses IFileOpenDialog internally with basic options enabled, so that legacy apps can still have a modern look.
Although, under the following conditions, TOpenDialog will instead use IFileOpenDialog directly rather than using GetOpenFileName():
Win32MajorVersion is >= 6 (Vista+)
UseLatestCommonDialogs is True
StyleServices.Enabled is True
TOpenDialog.Template is nil
TOpenDialog.OnIncludeItem, TOpenDialog.OnClose, and TOpenDialog.OnShow are unassigned.
But even so, TOpenDialog still does not give you access to its internal IFileOpenDialog interface, when it is used.
If you really want to access the dialog's IFileOpenDialog and thus its IFileDialogCustomize, you need to use TFileOpenDialog instead of TOpenDialog (just know that dialog won't work on XP and earlier systems, if you still need to support them).
The big question for me is : how can I access the preview pane image by IFileDialogCustomize?
You don't. The preview pane is not a dialog customization, so it can't be accessed via IFileDialogCustomize. Even if you could get a control ID for the preview pane (which you can't), there is no function of IFileDialogCustomize that would allow you to access the preview pane's HWND or HDC, or otherwise alter the content of the preview pane in any way. The preview pane is an integral and private component of IFileDialog for any file type that supports previews. It is not something that you can access and draw on directly. IFileOpenDialog itself will update the preview pane as needed when the user selects a file that has (or lacks) a preview to display.
My boss want to show previews for our own file formats.
The correct way to handle that on Vista+ is to create a Preview Handler for your custom file types. Then, any Shell component that wants to display previews of your files, including IFileOpenDialog, can use your handler.

Why SendToBack is not working with Delphi XE4

I'm using Delphi XE4 and trying to create 2nd form and set it as a background while the first form is transparent (AlphaBlend = true; AlphaBlendValue = 220)
uses Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
Form2.SendToBack;
end;
The codes above are working with Delphi 7, but not with Delphi XE4 (Form2 still over on the Form1). Can anyone tell me why the codes are not working with XE4? And how to make it working?
Thanks in advance.
Check the setting of Form2's PopupMode property. It is likely set in a way that cause's Form1's window to become the parent of Form2's window, which would prevent Form2 from moving behind Form1. The PopupMode (and PopupParent) property did not exist in D7, it was introduced in a later version to address z-order bugs that the VCL suffered from in earlier versions.
Read the following blob article for more details:
PopupMode and PopupParent

How to use Delphi standard confirmation dialog but with checkbox "Don't ask me again"?

In many confirmation dialogs it is usefull to have such option (quick wayt to disable confirmation).
But i can't find how to do that. I don't want to design it myself because i need this dialog to be standard-like and don't wont to redesign with every update of Delphi. Is there simple way to use Delphi standard confirmation dialog with such checkbox ?
UPDATE2. Suggested SynTaskDialog library from Synopse project does great job (all i need and even more), i will use it in my projects. Thanks!
UPDATE. So, thank you guys for ideas. System function MessageBoxCheck is nice solution but seem to be not so stable as it should be. In general i agree that it is good idea to use latest API functions to provide users with best UI experience of modern os and use old-fashioned design for older systems. At moment i stay on simple solution (code is following), but if someone share the code with support of UI for modern OS, it will be nice.
function MsgDlgWithCB(const Msg,Title,CBMsg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: TCheckBox): TForm;
var
i: integer;
b: TButton;
y: integer;
begin
Result := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton) ;
Result.Position := poScreenCenter;
cbDontAskAnymore := TCheckBox.Create(Result);
cbDontAskAnymore.Caption := CBMsg;
cbDontAskAnymore.Width := 130;
y := -1;
for i := 0 to result.ComponentCount-1 do
if result.Components[i] is TButton then
begin
b := TButton(result.Components[i]);
b.Left := b.Left + cbDontAskAnymore.Width + 16;
Result.ClientWidth := Max(Result.ClientWidth, b.Left+b.Width+16);
y := b.Top+b.Height-cbDontAskAnymore.Height;
end;
if y<0 then
y := Result.ClientHeight - cbDontAskAnymore.height - 16;
Result.Caption := Title;
cbDontAskAnymore.Parent := Result;
cbDontAskAnymore.Top := y;
cbDontAskAnymore.Left := 8;
end;
function MessageDlgCheckbox(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: Boolean;
const Title: string ='Confirmation';
const CBMsg: string = 'Don''t ask anymore'): integer;
var
f: TForm;
c: TCheckbox;
begin
f := MsgDlgWithCB(Msg,Title,CBMsg,DlgType,Buttons,DefaultButton,c);
try
result := f.ShowModal;
cbDontAskAnymore := c.Checked;
finally
f.free;
end;
end;
You can use our Open Source SynTaskDialog unit.
Windows provides a generic task dialog available since Vista/Seven. But there is none available with previous versions of Windows, i.e. Windows XP or 2K.
This unit (licensed under a MPL/GPL/LGPL tri-license) will use the new TaskDialog API under Vista/Seven, and emulate it with pure Delphi code and standard themed VCL components under XP or 2K. It supports Delphi 6 up to XE4, and is Win32/Win64 Unicode ready.
Here is the result under a Windows Seven 64 bit computer:
And here is the same dialog created from our emulated pure Delphi code:
Since this screenshot was made on a Win 7 machine, the styling is native for that OS. When the emulated version of the dialog runs on XP it displays in a style native to that OS.
You have your "Do not ask for this setting next time" checkbox... and potentially much more!
The system native functionality that offers such facilities is the task dialog API introduced in Vista. This provides means for you to show much more capable dialogs than the older MessageBox API.
Should you need to support XP then you will have to create your own dialog. For example by deriving from TForm and calling ShowModal. If you do this, make the form capable of building itself dynamically. Don't make one form per message that you show!
In my codebase, I have my own wrapper of the task dialog API. This detects at runtime versions of Windows that do not support task dialog and falls back on a custom built Delphi dialog.
Regarding SHMessageBoxCheck I'd be a little wary of taking a dependency on that. According to its documentation it's not supported beyond XP, and you have to import it by ordinal. I'd personally be worried that it might be dropped from a future version of Windows. That said, MS has a strong track record of doing whatever it takes to keep legacy apps working with new OS releases.

Delphi IDE custom menu items, how to Add them?

I am working on a project using Delphi 7 and Delphi 2006, i am developing a component that will get certain system information.
Now the requirement is that after the component is installed on the system, there should be a menu item on the IDE , like this
and for delphi 7 like this
i have searched on the net about adding a menu item but i have not got anything to add an item to the IDE like the one EurekaLog has.
can any body tell me how to add the item like EurekaLog or mysql ?
is it some where in the registry?
To add a menu to the Delphi IDE you must use the Delphi Open Tools API. from here you can access the Main menu of the delphi IDE using a code like this.
LMainMenu:=(BorlandIDEServices as INTAServices).MainMenu;
or
LMainMenu:=(BorlandIDEServices as INTAServices).GetMainMenu;
And then add the menu items which you want.
Check these links for additional samples
Open Tools API Chapter 15: IDE Main Menus
Introduction to the Delphi Open Tools API
How can I add a menu item to the IDE’s main menu?
If you want to specifically add a menu item to the HELP menu, and also make it get removed when your package unloads, and handle enable/disable of the items, then this wizard code might be helpful. I took the sample wizard code that GExperts documentation shows as a starter project, and posted it up here as a slightly nicer start project. You can get started very quickly if you grab this code and just extend it:
https://bitbucket.org/wpostma/helloworldwizard/
What they mean by "Wizard" is a "simple IDE Expert", that is, something with a menu added to the IDE, that implements IOTAWizard and IOTAMenuWizard. This approach has many benefits and is the way that the GExperts wizards are written.
The core of the code is this starter wizard, which needs to be put into a package (DPK) and installed, and registered with the IDE:
// "Hello World!" for the OpenTools API (IDE versions 4 or greater)
// By Erik Berry: http://www.gexperts.org/, eberry#gexperts.org
unit HelloWizardUnit;
interface
uses ToolsAPI;
type
// TNotifierObject has stub implementations for the necessary but
// unused IOTANotifer methods
THelloWizard = class(TNotifierObject, IOTAMenuWizard, IOTAWizard)
public
// IOTAWizard interface methods(required for all wizards/experts)
function GetIDString: string;
function GetName: string;
function GetState: TWizardState;
procedure Execute;
// IOTAMenuWizard (creates a simple menu item on the help menu)
function GetMenuText: string;
end;
implementation
uses Dialogs;
procedure THelloWizard.Execute;
begin
ShowMessage('Hello World!');
end;
function THelloWizard.GetIDString: string;
begin
Result := 'EB.HelloWizard';
end;
function THelloWizard.GetMenuText: string;
begin
Result := '&Hello Wizard';
end;
function THelloWizard.GetName: string;
begin
Result := 'Hello Wizard';
end;
function THelloWizard.GetState: TWizardState;
begin
Result := [wsEnabled];
end;
end.
The registration code is not shown above, but is included in its own "Reg" (registration) unit if you download this from the link above. A tutorial link is on EDN here.

Activate window from taskbar [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can you make a Borderless Application Main Window in Windows, without WS_POPUP style?
I have a form with BorderStyle:=bsNone;
How can I activate the minimized form by clicking on a it in task bar?
I'm guessing you're using an older version of Delphi (I've just done my testing on Delphi 2010, and I'm guessing you're using something older because in my version I don't need to do anything, restoring the window just works).
Problem 1: How do you MINIMIZE a border-less form? A border-less form doesn't have an "minimize" button! Are you sure it's minimized and it's not actually hidden? I've just attempted this, and I was only able to minimize the form by placing a button on it and running this code from the button:
ShowWindow(Handle, SW_MINIMIZE);
If I clicked on the application's button in my Windows 7 taskbar it came right up without problem. This brings us to the second problem.
Problem 2: What version of Delphi are you using? What version of Windows? Unfortunately it matters. There were changes in what Windows did with the taskbar button, and those changes prompted more changes in what Delphi does to support the taskbar button.
If you're on some old version of Delphi and on some new version of Windows you might try dropping a TApplicationEvents on your form, and from it's OnRestore event do this:
ShowWindow(Handle, SW_SHOW or SW_RESTORE);
The solution is to do
type
TForm1 = class(TForm)
private
protected
procedure CreateParams(var Params: TCreateParams); override;
{ Private declarations }
public
{ Public declarations }
end;
where
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style or WS_MINIMIZEBOX;
end;
exactly as David did in the old question about this topic.

Resources