Why is a dialog box being displayed behind the main form?
Earlier today I went to open a file in a Delphi app I wrote. For some reason the connection to the file's network was down--reasons unimportant--and Windows created a dialog box alerting me to the problem. My app's main form, however, was on top of the newly created dialog (i.e., there was a form for my app, for the File Open dialog, and for the warning dialog box). The warning dialog was modal, and hidden behind the main form. Obviously, I had a problem.
Any ide开发者_开发问答a what's going on, or how I can remedy the issue? The main form's position property is set to poDesigned, and I save/load the form's position on close/startup, I'm too much of a newbie to even know what info would help you diagnose the problem. To be clear, though, the issue was not the File Open dialog--that was displayed where it was supposed to be displayed--the issue was the warning dialog.
Thanks, as always --
I don't understand why is Windows creating a dialog in your app. Which API call resulted in that happening? Normal file operations don't show UI.
Most likely you were using an API function that can show UI, perhaps from the shell API. Any function that can show a modal dialog will request an owner HWND
.
For example consider MessageBox()
, a function that you know will show a modal dialog in your app. Its first parameter is called hWnd
and is documented
A handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.
Raymond Chen has a whole series of articles on modality which explain why setting this is important.
I have a hunch that you are calling some Win32 API function that shows modal UI, and are not setting the owner HWND
correctly. Of course, I could be completely wrong, but there's not more information to go on.
You can stop this by using SetErrorMode before trying to open the file on the network share:
var
OldErrorMode: Integer;
begin
OldErrorMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
try
if OpenDialog1.Execute then
begin
// ....
end;
finally
SetErrorMode(OldErrorMode);
end;
end;
Later versions of Delphi (IIRC, D2007 and higher) added an overloaded version of TOpenDialog.Execute that accepts a window handle as a parameter; this sets the TOpenDialog's parent and prevents the OpenDialog (and any error window it generates) from appearing behind the main window.
NOTE: You can get to the background dialog (from Windows) using Alt+Tab to cycle through until your application comes back up; this usually brings the hidden dialog forwaard on top of your form.
精彩评论