Activate window from taskbar [duplicate] - delphi

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.

Related

Delphi 11 Alexandria PaintBox flicker in RDP

I've just upgraded to Delphi 11 Alexandria from Delphi 10.4.2. I use RDP a lot so I noticed flicker when a TPaintBox is invalidated. The weird thing is that it doesn't flicker if the form with the TPaintBox is the first one created. Also it doesn't flicker if run on local machine. Only in RDP. If I compile same project in Delphi 10.4.2 it doesn't flicker in RDP.
Can anyone figure this one out? Is it "simply" a bug in Delphi 11?
Edit: Demoproject http://procurisupdate.se/downloads/Temp/PaintBoxFlicker.zip
Simple project with two forms. One has an TImage so it is quite large.
If run as is, when you click the picture and move the mouse it flickers. If you change so that Form23 is created first (or even if it is created before Application.run) it doesn't flicker. Note it onlyt flickers in RDP.
Edit2: After some looking I find the following in TApplication.Run:
procedure TApplication.Run;
begin
FRunning := True;
try
{$IF NOT DEFINED(CLR)}
AddExitProc(DoneApplication);
{$ENDIF}
RemoteSessionCheck; // This has been added since Delphi 10.4.2
if FMainForm <> nil then
...
If I comment out RemoteSessionCheck; and recompile (you have to add Your Source\vcl dir to Library path) it works with no flicker.
Per a private communication with Embarcadero:
fyi: This issue seems related to:
TRemoteSessionChangedEvent = procedure (Sender: TObject; var InRemoteSession) of object;
which should have been:
TRemoteSessionChangedEvent = procedure (Sender: TObject; var InRemoteSession: Boolean) of object;
Our Support team tracked down the issue; explained why it does not affect auto-created forms, and how this will mess up C++ (where the untyped parameter will be exposed as Variant).
A bug ticket was filed, but it is private to their internal system only.
You can check the TApplication.SingleBufferingInRemoteSessions property and set it to False.

How to set FireMonkey form icon runtime in Delphi 10.2

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.

Form is hidden behind other forms when ShowModal is called

My application is based on modal forms. Main form opens one form with ShowModal, this form opens another with ShowModal, so we have stacked modal forms. There is sometimes a problem that when we call ShowModal in new form, it hides behind previous forms, instead of showing on top. After pressing alt+tab, form comes back to the top, but this is not good solution. Did You meet this problem and how did you handle it?
EDIT:
I use Delphi 7.
You didn't mention which version of Delphi...
Newer Delphi versions have added two new properties to TCustomForm: PopupMode and PopupParent. Setting PopupParent of your modal dialog to the form that's creating that dialog makes sure that the child form stays on top of it's parent. It usually fixes the problem you're describing.
I think this pair of properties were added in Delphi 2006, but it may have been 2005. They're definitely there in Delphi 2007 and up.
EDIT: After seeing you're using Delphi 7, the only suggestion I have is that, in the code that displays your modal form, you disable the form creating it, and re-enable on return. That should prevent the creating window from receiving input, which may help keep the Z-order correct.
Something like this may work (untested, as I'm no longer using D7):
procedure TForm1.ShowForm2;
begin
Self.Enabled := False;
try
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOk then
// Returned OK. Do something;
finally
Free;
end;
end;
finally
Self.Enabled := True;
end;
end;
If Form2 creates a modal window (as you've mentioned), just repeat the process - disable Form2, create Form3 and show it modally, and re-enable Form2 when it returns. Make sure to use try..finally as I've shown, so that if something goes wrong in the modal form the creating form is always re-enabled.
Sorry for adding a separate answer, but I have done a bit more research, and some of it indicates that my previous answer (DisableProcessWindowsGhosting) doesn't help. Since I can't always reproduce this issue, I cannot say for sure.
I found a solution that appears to appropriate. I referenced the code in Delphi 2007 for the CreateParams method and it matches pretty close (without having all of the other code that handles PopupMode).
I created the unit below which subclasses TForm.
unit uModalForms;
interface
uses Forms, Controls, Windows;
type
TModalForm = class(TForm)
protected
procedure CreateParams(var params: TCreateParams); override;
end;
implementation
procedure TModalForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := Screen.ActiveForm.Handle;
if (params.WndParent <> 0) and (IsIconic(params.WndParent)
or not IsWindowVisible(params.WndParent)
or not IsWindowEnabled(params.WndParent)) then
params.WndParent := 0;
if params.WndParent = 0 then
params.WndParent := Application.Handle;
end;
What I do then is include this unit in with a form unit, and then change the form's class (in the .pas code file) from class(TForm) to class(TModalForm)
It works for me, appears to be close to CodeGear's solution.
From this link it appears that the problem is with the "Ghosting window" that was introduced in 2000/XP. You can disable the ghosting feature by calling the following code at startup.
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'),
'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
The only issue that I can see is that it will cause problems with the feature that allows for the user to minimize, move, or close the main window of an application that is not responding. But in this way you do not have to cover each call with the Self.Enabled := False code.
Just set the Visible property of the form, that you want to open modal, to False. Then you can open it with .ShowModal(); and it will work.
I have found that using the "Always On Top" flag on more than one form causes problems with the Z order. And you may also find the need for the BringWindowToTop function.
When launching a message box using the built-in WinAPI (MessageBox), I have found that passing the calling window's handle is necessary in order to make sure that the the prompt appears on top all the time.
try it
OnShowForm:
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);

Delphi - How Control Z Order Of TOpenDialog

I have a modal dialog that is created with the following:
procedure TFormCompose.createParams(var Params: TCreateParams);
begin
inherited createParams(Params);
with Params do begin
exStyle:=exStyle or WS_EX_APPWINDOW;
wndParent:=getDesktopWindow;
end;
end;
In this form, I create an instance of TOpenDialog. When it opens, it sends my first modal dialog behind the main application window.
Is there a way to get the TOpenDialog to open without affecting the Z order of the modal dialog?
Thanks!
What version of Delphi are you using? Delphi 2007 and up add an overloaded TOpenDialog.Execute(ParentWnd: HWND); passing the handle of your modal dialog as the ParentWnd when calling Execute() may help.
For future reference, make sure you specify which version of Delphi. Answers appropriate to Delphi 2009, for example, wouldn't be of much use to you if you were using Delphi 5, and would be a waste of time for the person providing the answer.

Delphi MDI Application and the titlebar of the MDI Children

I've got an MDI application written in Delphi 2006 which runs XP with the default theme.
Is there a way of controlling the appearance of the MDI Children to avoid the large XP-style title bar on each window?
I've tried setting the BorderStyle of the MDIChildren to bsSizeToolWin but they are still rendered as normal Forms.
All your need - overload procedure CreateWindowHandle, like this:
unit CHILDWIN;
interface
uses Windows, Classes, Graphics, Forms, Controls, StdCtrls;
type
TMDIChild = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
procedure CreateWindowHandle(const Params: TCreateParams); override;
end;
implementation
{$R *.dfm}
procedure TMDIChild.CreateWindowHandle(const Params: TCreateParams);
begin
inherited CreateWindowHandle(Params);
SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
end;
end.
The way MDI works doesn't gel with what you're trying to do.
If you need the "MDI" format, you should consider using either the built-in or a commercial docking package, and use the docking setup to mimic the MDI feel.
In my Delphi apps, I frequently use TFrames and parent them to the main form, and maximizing them so they take up the client area. This gives you something similar to how Outlook looks. It goes a little something like this:
TMyForm = class(TForm)
private
FCurrentModule : TFrame;
public
property CurrentModule : TFrame read FModule write SetCurrentModule;
end;
procedure TMyForm.SetCurrentModule(ACurrentModule : TFrame);
begin
if assigned(FCurrentModule) then
FreeAndNil(FCurrentModule); // You could cache this if you wanted
FCurrentModule := ACurrentModule;
if assigned(FCurrentModule) then
begin
FCurrentModule.Parent := Self;
FCurrentModule.Align := alClient;
end;
end;
To use it, you can simply do this:
MyForm.CurrentModule := TSomeFrame.Create(nil);
There is a good argument that you should use interfaces (creating an IModule interface or something) that you use. I often do that, but it's more complex than needed to explain the concept here.
HTH
I don't think there is; in my experience, MDI in Delphi is very strictly limited and controlled by its implementation in the VCL (and perhaps also by the Windows API?). For example, don't try hiding an MDI child (you'll get an exception if you try, and you'll have to jump through a couple of API hoops to work around that), or changing the way an MDI child's main menu is merged with the host form's.
Given these limitations, perhaps you should reconsider why you'd like to have special title bars in the first place? I guess there are also good reasons why this MDI stuff is standardized --- your users might appreciate it :)
(PS: nice to see a Delphi question around here!)
Thanks onnodb
Unfortunately the client insists on MDI and the smaller title bar.
I have worked out one way of doing it which is to hide the title bar by overriding the windows CreateParams and then create my own title bar (simple panel with some Mouse handling for moving). Works well enough so I think I might run it by the client and see if it will do...

Resources