2012-07-09 4 views
2

window1이라는 창이있는 app1이라는 WPF 응용 프로그램이 있습니다. 사용자가 window1의 닫기 버튼을 클릭하면 앱이 닫히지 않고 창 1이 숨겨집니다 (this.hide()).C#의 다른 응용 프로그램에서 WPF 창 표시

응용 프로그램의 다른 인스턴스가 시작될 때 이미 실행되고 있는지 확인하고 싶습니다. 그렇다면 이미 실행중인 인스턴스를 표시하고 새 인스턴스를 종료하고 싶습니다.

어떻게하면됩니까? 내 응용 프로그램 시작 이벤트에서 나는 과정을 확인하는 방법과 현재 응용 프로그램을 닫습니다하지만 실행하는 다른 WPF 과정에서 창을 표시하는 방법을 몰라하는 방법을 알고

...

내가 할 이 :

private void Application_Startup(object sender, StartupEventArgs e) 
{ 
    if(Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1) 
    { 
     Application.Current.Shutdown(0); 
    } 
} 

답변

1

작업 방법을 찾았습니다.

"Reed Copsey"도움말 및 Windows SendMessage API로 문제가 해결되었습니다. 내 window1.xaml.cs에서이 코드를 쓴이 일을위한 파일 :

 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Reflection; 
using System.Runtime.InteropServices; 
using System.Windows.Interop; 


namespace app1 
{ 
    public partial class window1: Window 
    { 
     public window1() 
     { 
      InitializeComponent();    
     } 
     private void window1_Loaded(object sender, RoutedEventArgs e) 
     { 
      HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); 
      source.AddHook(new HwndSourceHook(WndProc)); 
     } 
     private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
     { 
      System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hwnd, msg, wParam, lParam); 
      if (m.Msg == WM_COPYDATA) 
      { 
       // Get the COPYDATASTRUCT struct from lParam. 
       COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT)); 

       // If the size matches 
       if (cds.cbData == Marshal.SizeOf(typeof(MyStruct))) 
       { 
        // Marshal the data from the unmanaged memory block to a 
        // MyStruct managed struct. 
        MyStruct myStruct = (MyStruct)Marshal.PtrToStructure(cds.lpData, 
         typeof(MyStruct)); 

        // Display the MyStruct data members. 
        if (myStruct.Message == "Show Up") 
        { 
         this.Show(); 
        } 
       } 
      } 
      return IntPtr.Zero; 
     } 

     internal const int WM_COPYDATA = 0x004A; 

     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
     internal struct MyStruct 
     { 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
      public string Message; 
     } 
     [StructLayout(LayoutKind.Sequential)] 
     internal struct COPYDATASTRUCT 
     { 
      public IntPtr dwData;  // Specifies data to be passed 
      public int cbData;   // Specifies the data size in bytes 
      public IntPtr lpData;  // Pointer to data to be passed 
     } 


    } 
} 

 

그리고 나는이 내 App.xaml.cs를에서 코드 작성 :

 

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Data; 
using System.Linq; 
using System.Windows; 
using System.Windows.Threading; 
using System.Runtime.InteropServices; 
using System.Security; 

namespace app1 
{  
    public partial class App : Application 
    {  
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
     internal struct MyStruct 
     { 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
      public string Message; 
     } 



     internal const int WM_COPYDATA = 0x004A; 
     [StructLayout(LayoutKind.Sequential)] 
     internal struct COPYDATASTRUCT 
     { 
      public IntPtr dwData;  // Specifies data to be passed 
      public int cbData;   // Specifies the data size in bytes 
      public IntPtr lpData;  // Pointer to data to be passed 
     } 
     [SuppressUnmanagedCodeSecurity] 
     internal class NativeMethod 
     {    
      [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
      public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, 
       IntPtr wParam, ref COPYDATASTRUCT lParam); 


      [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
      public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
     } 

     private void Application_Startup(object sender, StartupEventArgs e) 
     {    
      if (System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1) 
      { 
       IntPtr hTargetWnd = NativeMethod.FindWindow(null, "window1"); 
       if (hTargetWnd == IntPtr.Zero) 
       {      
        return; 
       } 
       MyStruct myStruct; 
       myStruct.Message = "Show Up"; 
       int myStructSize = Marshal.SizeOf(myStruct); 
       IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize); 
       try 
       { 
        Marshal.StructureToPtr(myStruct, pMyStruct, true); 

        COPYDATASTRUCT cds = new COPYDATASTRUCT(); 
        cds.cbData = myStructSize; 
        cds.lpData = pMyStruct; 
        NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, new IntPtr() , ref cds); 

        int result = Marshal.GetLastWin32Error(); 
        if (result != 0) 
        {      
        } 
       } 
       finally 
       { 
        Marshal.FreeHGlobal(pMyStruct); 
       } 
       Application.Current.Shutdown(0); 
      }    
     } 

    } 
} 
 

그리고 그것 뿐이다을 . : D

6

이에 대한 일반적인 접근 방식은 뮤텍스를 사용하는 것입니다. 이렇게하면 두 번째 인스턴스가 시작되는 것을 방지 할 수 있습니다 (또는 은 응용 프로그램의 두 번째 인스턴스 내에서이를 감지 함).

그 시점에서 원래 응용 프로그램 인스턴스에 "표시"되도록 알릴 수 있습니다. 여기에 a good article describing the entire process in detail입니다 (Windows Forms 사용).

WPF 응용 프로그램의 경우이 논리를 응용 프로그램의 시작 논리에 넣고 WPF 창에 표시 할 add an HwndSourceHook to process the windows message을 표시해야합니다.

관련 문제