Развернуть окно из основной функции?

#c# #.net #windows #winapi #maximize

#c# #.net #Windows #winapi #развернуть

Вопрос:

Я использовал мьютекс для запуска программы с одним экземпляром, и теперь я хочу, чтобы окно стало максимальным, если оно в данный момент свернуто, когда пользователь повторно открывает приложение.

Вот код, который у меня сейчас есть в файле Program.cs:

 static class Program
{
    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        bool Ok = true;
        string ProductName = Application.ProductName;
        Mutex m = new Mutex(true, ProductName, out Ok);
        if (!Ok)
        {
            System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName(ProductName);
            SetForegroundWindow(p[0].MainWindowHandle);

    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());

    }
}
  

Комментарии:

1. Могу ли я предположить, что восстановление окна (то есть не-минимизация) имеет больше смысла, чем его максимизация .

2. @romkyns: Согласен, определенно. SW_SHOW это способ сделать это, как я упоминал в нижней части моего ответа. Это вернет окно в его предыдущее состояние перед сворачиванием, независимо от того, было ли это стандартное окно или развернутое окно.

Ответ №1:

Вы ищете ShowWindow функцию и SW_MAXIMIZE флаг.

В C # объявление P / Invoke выглядело бы следующим образом:

 [DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

private const int SW_MAXIMIZE = 3;
  

Добавьте это в свой код здесь:

 if (!Ok)
{
   Process[] p = Process.GetProcessesByName(ProductName);
   SetForegroundWindow(p[0].MainWindowHandle);
   ShowWindow(p[0].MainWindowHandle, SW_MAXIMIZE);
}
  

Если вы действительно хотите сначала проверить, свернуто ли окно, прежде чем его развернуть, вы можете использовать IsIconic функцию старой школы:

 [DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsIconic(IntPtr hWnd);

// [...]

if (!Ok)
{
   Process[] p = Process.GetProcessesByName(ProductName);
   IntPtr hwndMain= p[0].MainWindowHandle;
   SetForegroundWindow(hwndMain);

   if (IsIconic(hwndMain))
   {
      ShowWindow(hwndMain, SW_MAXIMIZE);
   }
}
  

Если вы просто хотите активировать окно (а не разворачивать его), используйте SW_SHOW значение ( 5 ) вместо SW_MAXIMIZE . Это вернет его в предыдущее состояние, до того, как оно было свернуто.

Комментарии:

1. отлично, это работает. просто исправьте это в своем ответе [DllImport («user32.dll «, кодировка = CharSet.Auto)]

2. @moslem: Хорошо, готово. Все время от времени забывают закрывающую фигурную скобку. Можете ли вы сказать, что я привык писать код в IDE?

3. У меня не работаетSW_SHOW или value (5) — с свернутым окном ничего не происходит (протестировано на Win XP SP3 и Win 7 SP1 ). SW_RESTORE или value (9) сработали для меня, и, на мой взгляд, это правильный выбор в соответствии с описанием MSDN

4. @bairog Это правильно. Вы должны выбрать правильный флаг для того, что вы хотите сделать. SW_SHOW не восстановит или не развернет свернутое окно. Для этого вам нужен SW_RESTORE or SW_MAXIMIZE . Документация — хорошее место для просмотра, этот ответ только поможет вам начать. Это было составлено специально для первоначального задаваемого вопроса.

Ответ №2:

Я хотел бы предложить решение, которое является чисто .NET (т. Е. без зависимости от операционной системы).

Program.cs

 static class Program
{
    private static volatile bool _exitProcess;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        bool createdNew;
        var showMeEventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, "MyApp.ShowMe", out createdNew);

        if (createdNew)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form1();
            new Thread(() =>
            {
                while (!_exitProcess)
                {
                    showMeEventHandle.WaitOne(-1);
                    if (!_exitProcess)
                    {
                        if (form.InvokeRequired)
                        {
                            form.BeginInvoke((MethodInvoker)form.BringFormToFront);
                        }
                        else
                        {
                            form.BringFormToFront();
                        }
                    }
                }
            }).Start();

            Application.Run(form);
        }

        _exitProcess = true;
        showMeEventHandle.Set();

        showMeEventHandle.Close();
    }
}
  

ExtMethods.cs

 public static class ExtMethods
{
    public static void BringFormToFront(this Form form)
    {
        form.WindowState = FormWindowState.Normal;
        form.ShowInTaskbar = true;
        form.Show();
        form.Activate();
    }
}
  

Form1.cs

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.BringFormToFront();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            ShowInTaskbar = false;
            Hide();
        }
    }
  

Комментарии:

1. Абсолютно блестяще и намного лучше, чем решение с DLL.