How to make OpenDialog show modal in Firemonkey? - delphi

When I'm calling an OpenDialog from my form on ButtonClick event. The dialog does not shows as modal and is also displays in taskbar (in WindowsXP). I can return to main form and click Open again and again - popping up several dialogs at once..
How do I make an OpenDialog to be modal in Firemonkey?
Is it specifically made so that no modal dialogs are allowed due to multi-platform anture of FM?
EDIT: The bug is fixed in Update 3.

I think it's a bug. There are a lot of modal type bugs with FireMonkey, and hopefully they will be fixing them soon. Currently, even modal forms aren't modal.
For your problem, I have a workaround for Windows, but you might not like it.
You need to fix the following line in the TPlatformWin.DialogOpenFiles() method in FMX.Platform.Win.
Under with OpenFile do change:
hwndOwner := 0;
To this:
hWndOwner := FmxHandleToHWND(Application.MainForm.Handle);
The function utilizes the Windows GetOpenFileName API call, even though it's deprecated on Vista and above. If a owner handle is passed in, the dialog is modal, otherwise it's not.
You might want to submit this as a bug to qc.embarcadero.com along with the workaround.

Related

Form moving to the back and staying active

I have a largish Delphi 6 app that I have ported to Delphi XE3. At one point the main form launches another non-modal form. Sometimes (say 50%) after a second or two the newly created form moves behind the main form. Even thought it is now at the back, the newly created form still has focus so there are no activate/deactivate events. There are a few Timer controls and I have disabled them. It still happens.
I can accept my code is doing this -- but how can I find out what is happening? Is there a way to intercept when then new form moves to the back?
Just to be clear: I want both forms to be used separately. Any of them can appear behind the other. What is happening at the moment is that the z-order seems to be changing.
I have found the answer to this. I discovered I had added a CreateParams override that did this:
// make a taskbar window
inherited CreateParams( params );
params.ExStyle := params.ExStyle or WS_EX_APPWINDOW;
params.WndParent := GetDesktopwindow; // this line caused the problem
Commenting the WndParent solved it. The effect is bizarre though. It is as if there is a timer that goes off about a second after any key or mouse event that forces the window behind others. Thanks to David Heffernan whose comments about stepping CreateParam made me notice it.

How to force user to click a button in only one active window and not be able to click things in other windows?

I have a small question.
I think there must be a easy way to do it but I just can't find the keyword, so please teach me.
Here is the question:
For example, default ShowMessage pops a window with 'OK' button, then program stops temporarily before you click 'OK'.
This makes sense, but the problem is, you can still interact with other objects before you click 'OK'.
It certainly causes some problems like this:
var
Count: Integer; //initial it to 1
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(Count));
Inc(Count);
end;
By not closing the message box, program always stops at same place and the variable remains the same.
How do I lock the popping window so you can't interact with other objects?(System forces you to turn your focus back to the popping window if you do so)
Is it possible to achieve this with ShowMessage?
It would be helpful if I can get some tips.
Thanks a lot.
Edit:
Using the unit QDialogs.ShowMessage version causes a non-modal problem. Beware of those units you are not familiar lol.
ShowMessage shows a modal dialog. In other words, it disables its owning window while the dialog shows. And so you cannot interact with the other windows in your app. ShowMessage already does what you want.
If you find that you can interact with other windows in your application whilst the dialog is showing, then you must have got the window ownership wrong.

How to prevent Delphi MainForm to show when a file dialog is showing?

My application has many forms, there is also one more important form, that is the main form, the behaviour is in general ok but in same cases (for example when I open a file dialog from a subform) the beahviour is: subform is hidden and mainform is shown.
How to avoid this?
Make sure you either implicitly or explicitly set the PopupParent of both the sub-form and the dialog. If you open both the sub-form and the dialog from some random bit of code somewhere and don't tell Windows about the correct Z-order, stacking issues can happen.

Delphi "Tray" icon (NotifyIcon) context-menu does not disappear when clicking outside it

I'm trying to show a popup menu when right clicking my Notification Icon, which works fine; But I want the menu to disappear when the user clicks outside of that menu.
It's supposedly by design as per KB135788 - PRB: Menus for Notification Icons Do Not Work Correctly (archive).
But no decent app I know of behaves like this. I've tried calling SetForegroundWindow using the popup menu's handle to no avail. I'm sure it's possible to work around this, as I've done it years ago but don't remember how.
Anyone know how to achieve the expected behaviour?
I've found a solution!
I was calling
SetForegroundWindow(PopupMenu1.Handle);
Which doesn't work, but changing this in the OnPopup event handler to
procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
// Hack to fix the "by design" behaviour of popups from notification area icons.
// See: http://support.microsoft.com/kb/135788
BringToFront();
end;
Works!
Obviously, if the form is visible when this is called, your app will jump foremost, but if it's hidden (as mine is), then it'll work.
I'd be interested to know if there's a way to make the menu work right without the window jumping foremost, though.

Multiple form Delphi applications and dialogs

I have a Delphi 7 application that has two views of a document (e.g. a WYSIWYG HTML edit might have a WYSIWYG view and a source view - not my real application). They can be opened in separate windows, or docked into tabs in the main window.
If I open a modal dialog from one of the separate forms, the main form is brought to the front, and is shown as the selected window in the windows taskbar. Say the main form is the WYSIWYG view, and the source view is poped out. You go to a particular point in the source view and insert an image tag. A dialog appears to allow you to select and enter the properties you want for the image. If the WYSIWYG view and the source view overlap, the WYSIWYG view will be brought to the front and the source view is hidden. Once the dialog is dismissed, the source view comes back into sight.
I've tried setting the owner and the ParentWindow properties to the form it is related to:
dialog := TDialogForm.Create( parentForm );
dialog.ParentWindow := parentForm.Handle;
How can I fix this problem? What else should I be trying?
Given that people seem to be stumbling on my example, perhaps I can try with a better example: a text editor that allows you to have more than one file open at the same time. The files you have open are either in tabs (like in the Delphi IDE) or in its own window. Suppose the user brings up the spell check dialog or the find dialog. What happens, is that if the file is being editing in its own window, that window is sent to below the main form in the z-order when the modal dialog is shown; once the dialog is closed, it is returned to its original z-order.
Note: If you are using Delphi 7 and looking for a solution to this problem, see my answer lower down on the page to see what I ended up doing.
I'd use this code... (Basically what Lars said)
dialog := TDialogForm.Create( parentForm );
dialog.PopupParent := parentForm;
dialog.PopupMode := pmExplicit;
dialog.ShowModal();
I ultimately ended up finding the answer using Google Groups. In a nutshell, all the modal dialogs need to have the following added to them:
procedure TDialogForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style or WS_POPUP;
Params.WndParent := (Owner as TWinControl).Handle;
end;
I'm guessing this does the equivalent of Lars' and Marius' answers in Delphi 7.
Is the dialog shown using ShowModal or just Show? You should probably set the PopupMode property correct of the your dialog. pmAuto would probably your best choice. Also see if you need to set the PopupParent property.
First of all, I am not completely sure I follow, you might need to provide some additional details to help us understand what is happening and what the problem is. I guess I am not sure I understand exactly what you're trying to accomplish and what the problem is.
Second, you shouldn't need to set the dialog's parent since that is essentially what is happening with the call to Create (passing the parent). The dialogs you're describing sound like they could use some "re-thinking" a bit to be honest. Is this dialog to enter the properties of the image a child of the source window, or the WYSIWYG window?
I'm not sure I quite understand what you are getting at, but here's a few things I can suggest you can try...
This behaviour changes between different versions of Delphi. I'd suggest that this is due to the hoops they jumped through to support Windows Vista in Delphi 2007.
If you are using Delphi 2007, try removing the line from the project source file that sets the Application.MainFormOnTaskBar boolean variable.
With this removed, you should be able to use the various Form's BringToFront / SendToBack methods to achieve the Z-ordering that you are after.
I suspect that what you've discovered has been discussed on this link
Of course, I may have just missed your point entirely, so apologies in advance!

Resources