Показать форму с PInvoke - PullRequest
1 голос
/ 14 июля 2010

У меня есть сценарий ниже: приложение WinForms, которое позволяет запускать только один экземпляр этого приложения (Mutex используется здесь для проверки).Приложение на старте с каким-то параматером работает, но скрыто.Когда кто-нибудь снова щелкнет приложение, Mutex обнаружит, что приложение уже запущено, и "раскроет" основную форму с помощью вызова собственного метода (см. Метод BringWindowToFront ниже).код для поиска и отображения окна формы:

    public static class NativeMethods
{
    public enum ShowWindowOptions
    {
        FORCEMINIMIZE = 11,
        HIDE = 0,
        MAXIMIZE = 3,
        MINIMIZE = 6,
        RESTORE = 9,
        SHOW = 5,
        SHOWDEFAULT = 10,
        SHOWMAXIMIZED = 3,
        SHOWMINIMIZED = 2,
        SHOWMINNOACTIVE = 7,
        SHOWNA = 8,
        SHOWNOACTIVATE = 4,
        SHOWNORMAL = 1
    }

    [DllImport("user32.dll")]
    public static extern int ShowWindow(int hwnd, int cmdShow);

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);

    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    public static void BringWindowToFront(string windowTitle)
    {
        // Get a handle to the application.
        IntPtr handle = FindWindow(null, windowTitle);

        // Verify that app is a running process.
        if (handle == IntPtr.Zero)
        {
            return;
        }

        // With this line you have changed window status from example, minimized to normal
        ShowWindow((int)handle, (int)ShowWindowOptions.SHOWDEFAULT);

        // Make app the foreground application
        SetForegroundWindow(handle);
    }
}

Все хорошо, НО мне пока нужна одна функциональность.Я хотел бы показать еще одну дополнительную форму, когда основная форма отобразится в первый раз.Обычно я делаю это с помощью события _Shown .Но когда я использую методы PInvoke для отображения окна, это событие не запускается.

Поэтому в основном я хотел бы показать дополнительную форму, когда отображается основная форма (с использованием метода ShowWindow PInvoke)это возможно?Есть еще идеи, как этого добиться?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 14 июля 2010

Писать приложения для одного экземпляра сложно.Вам не нужно, .NET Framework уже поддерживает их очень хорошо.Проект + Добавить ссылку, выберите Microsoft.VisualBasic.Откройте файл Program.cs вашего проекта и сделайте его похожим на это:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic.ApplicationServices;

namespace WindowsFormsApplication1 {
    class Program : WindowsFormsApplicationBase {
        [STAThread]
        static void Main(string[] args) {
            var prg = new Program();
            prg.EnableVisualStyles = true;
            prg.IsSingleInstance = true;
            prg.MainForm = new Form1();
            prg.Run(args);
        }

        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs e) {
            var main = this.MainForm as Form1;
            main.WindowState = FormWindowState.Normal;
            main.BringToFront();
            // You could do something interesting with the command line arguments:
            //foreach (var arg in e.CommandLine) {
            //    main.OpenFile(arg);
            //}
        }
    }
}
2 голосов
/ 14 июля 2010

Событие Form.Shown вызывается только при первом показе формы (т. Е. После загрузки), дальнейшее выполнение каких-либо других действий (например, скрытие и повторное отображение) не вызовет событие. Для получения дополнительной информации см .: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx

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

Если ничего из этого не работает, и вы должны использовать P / Invoke, то я бы пошел с SetActiveWindow , который отправит сообщение WM_ACTIVATE , которое должно вызвать форму . Активированный .

Обратите внимание, что если это не сработает (поскольку SetActiveWindow отправляет WM_ACTIVATE с младшим битом 1, указывающим, что окно не было активировано мышью, вы можете обойти это, отправив сообщение прямо в окно с вашим собственным сообщением WM_ACTIVATE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...