2010-07-13 3 views
1

아래 시나리오를 가지고 있습니다. 이 앱의 인스턴스 하나만 실행되도록 허용하는 WinForms 앱입니다. 여기서는 뮤텍스를 사용하여 확인합니다. 일부 매개 변수로 시작하는 앱은 실행되지만 숨겨집니다. 누군가가 앱을 다시 클릭하면 뮤텍스는 앱이 이미 실행 중임을 감지하고 기본 메소드 호출을 통해 기본 폼을 '숨기기'합니다 (아래 BringWindowToFront 참조).PInvoke로 양식보기

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); 
    } 
} 

모든 것이 괜찮습니다하지만 나는 아직 한 기능이 필요 : 여기

찾아 쇼 형태 창하는 코드입니다. 주 양식이 처음 표시 될 때 다른 추가 양식을 보여 드리고자합니다. 일반적으로 양식으로 처리합니다. _ 표시 이벤트. 그러나 PInvoke 메서드를 사용하여 창을 표시하면이 이벤트가 발생하지 않습니다. 기본 폼이

이 가능 (이 ShowWindow의 PInvoke 방법을 사용) 표시 될 때

그래서 기본적으로 내가 추가 폼을 표시 하시겠습니까? 그것을 달성하는 다른 아이디어?

미리 감사드립니다.

+0

P/Invoke mec 이 일을하는 것에 대한 허니 스틱? C# 코드 내에서 단일 인스턴스 응용 프로그램을 생성하는 다른 방법이 있습니다. – ChrisF

+0

뮤 텍스 (Mutex)가 단일 인스턴스를 달성했습니다. 이제 public static extern int로 MainWindow를 보여준 후에 추가 Form을 보여 주려고합니다. ShowWindow (int hwnd, int cmdShow); – binball

답변

2

단일 인스턴스 응용 프로그램을 작성하는 것은 까다 롭습니다. .NET Framework에서 이미이를 지원하고 있습니다 .PP + 참조 추가, 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); 
      //} 
     } 
    } 
} 
+0

Scott Hanselman이 게시했습니다. - http://www.hanselman.com/blog/CommentView.aspx?guid=d2f676ea-025b-4fd6-ae79-80b04a34f24c – ChrisF

+0

한스,이 예제를 이용해 주셔서 감사합니다. .내 특별한 경우에는 단일 인스턴스 응용 프로그램에 대한이 방법은 Mutex보다 훨씬 좋습니다. 그래서 frmAnother frm = new frmAnother();를 추가하십시오. main.BringToFront(); 그리고 그것은 내가 원하는만큼 정확히 나를 위해 일합니다. Thx! – binball

2

Form.Shown 이벤트는 양식이 처음 표시 될 때 (예 :로드 된 후)에만 실행되고 나중에 다른 동작을 수행하면 (예 : 숨기기 및 다시 표시) 이벤트를 트리거하지 않습니다. 자세한 내용은 다음을 참조하십시오 http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx

귀하의 경우에 유용 할 수있는 다른 이벤트의 몇 가지가 있습니다

은 이들 중 어느 것도 작동하지 않는다면, P/Invoke를 사용해야한다면 SetActiveWindow과 함께 WM_ACTIVATE 메시지를 보내고, 이는 Form.Activated이되어야합니다.

SetActiveWindow이 낮은 순서 비트 1을 사용하여 WM_ACTIVATE을 전송하여 마우스로 활성화되지 않았 음을 나타내므로 다음 주소로 직접 메시지를 보내이 문제를 해결할 수 있습니다. WM_ACTIVATE 메시지가있는 창

+0

thx에 대한 설명이 – binball