C# OpenFileDialog Thread start but dialog not shown
Asked Answered
H

1

5

I am trying to finish my static Prompt class to be able to call it from anywhere. But the problem is couldn't make the dialog show. I am already using [STAThread] and here is my code.

public static string ShowFileDialog()
{
    string selectedPath = "";
    var t = new Thread((ThreadStart)(() =>
    {
        FolderBrowserDialog fbd = new FolderBrowserDialog();
        fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
        fbd.ShowNewFolderButton = true;
        if (fbd.ShowDialog() == DialogResult.OK)
        {
            selectedPath = fbd.SelectedPath;
        }
    }));
    t.SetApartmentState(ApartmentState.STA);
    t.Start();

    t.Join();
    return selectedPath;
}

public static class Prompt is my Prompt Class. I am calling it from public partial class Dashboard : Form class

Thank you for your helps.

Havener answered 7/9, 2015 at 9:11 Comment(6)
Could you please describe your use case of using the ShowFileDialog() when the dialog is not visible? Could it be that it is visible but not in focus?Thedrick
I just want to ask user a path to file when the system received a command from socket.Coincidentally
Where are you calling ShowFileDialog() from?Muckraker
public static class Prompt is my Prompt Class. I am calling it from public partial class Dashboard : Form classCoincidentally
@HansPassant Please write this as an answer. I just learned that Forms requires owner windows from you and I solved my problem.Coincidentally
@AhmetCanGüven not always a window require another window. there various cases to show windows, there is API that can make a window focused or bring it on TopMost level and so one. In case of windows service you won't be able to dispay any window at all. So when it goes in windows and modal dialogs there should be clear from where you start a window.Thedrick
F
8

It surely works just fine when you don't get an exception. But yes, pretty decent odds that you don't see the dialog. Pretty ugly problem, you don't have a taskbar button either. Only way to find it back is by minimizing the other windows on the desktop.

A dialog, any dialog, must have an owner window. You are supposed to pass that owner to the ShowDialog(owner) method overload. If you don't specify one that it goes looking for an owner by itself. Underlying call is GetActiveWindow(). To come up with nothing, the desktop window now becomes the owner. That isn't good enough to ensure that the dialog window is in front.

At a minimum you must create that owner window, you'll now at least have the taskbar button. Like this:

    using (var owner = new Form() { Width = 0, Height = 0,
        StartPosition = FormStartPosition.CenterScreen,
        Text = "Browse for Folder"}) {
        owner.Show();
        owner.BringToFront();
        FolderBrowserDialog fbd = new FolderBrowserDialog();
        fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
        fbd.ShowNewFolderButton = true;
        if (fbd.ShowDialog(owner) == DialogResult.OK) {
            selectedPath = fbd.SelectedPath;
        }
    }

Still doesn't guarantee that the dialog is visible, you cannot push a window into the user's face when he's interacting with another window. But at least there's a taskbar button.

I'll very hesitantly show the hack around that, don't use it:

    owner.Show();
    var pid = System.Diagnostics.Process.GetCurrentProcess().Id;
    Microsoft.VisualBasic.Interaction.AppActivate(pid);

The proper way to draw the user's attention and get him to interact with your UI is NotifyIcon.ShowBalloonTip().

Flavopurpurin answered 7/9, 2015 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.