Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# OpenFileDialog Thread start but dialog not shown

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.

like image 231
Ahmet Can Güven Avatar asked Mar 14 '23 20:03

Ahmet Can Güven


1 Answers

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().

like image 69
Hans Passant Avatar answered Mar 31 '23 12:03

Hans Passant