1

以下のシナリオがあります:このアプリの1つのインスタンスのみを実行できる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);
    }
}

すべて問題ありませんが、まだ1つの機能が必要です。メインフォームが最初に再表示されるときに、別の追加フォームを表示したいと思います。通常、私はフォーム_Shownイベントによってそれを行います。しかし、PInvokeメソッドを使用してウィンドウを表示すると、このイベントは発生しません。

したがって、基本的に、メインフォームが表示されたときに追加のフォームを表示したいと思います(ShowWindow PInvokeメソッドを使用)

これは可能ですか?それを達成する方法の他のアイデアはありますか?

4

2 に答える 2

2

イベントは、Form.Shownフォームが最初に表示されたとき(つまり、ロード後)にのみ発生し、後で他のアクション(たとえば、非表示にしてから再表示)を実行してもイベントはトリガーされません。詳細については、http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspxを参照してください。

あなたのケースで役立つかもしれない他のいくつかのイベントがあります:

これらのいずれも機能せず、P / Invokeを使用する必要がある場合は、 SetActiveWindowを使用して、 WM_ACTIVATEメッセージを送信します。これにより、 Form.Activatedが強制されます。

それが機能しない場合(ウィンドウがマウスによってアクティブ化されなかったことを示す1の下位ビットでをSetActiveWindow送信WM_ACTIVATEするため)、独自のWM_ACTIVATEを使用してウィンドウに直接メッセージを送信することでこれを回避できることに注意してください。メッセージ。

于 2010-07-13T23:35:56.953 に答える
2

シングルインスタンスアプリの作成には注意が必要です。必ずしもそうする必要はありません。.NETFrameworkはすでにそれらを非常にうまくサポートしています。プロジェクト+参照の追加、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);
            //}
        }
    }
}
于 2010-07-14T00:01:01.290 に答える