2012-07-09 161 views
2

我有一個叫做app1的WPF應用程序,它有一個名爲window1的窗口。當用戶點擊關閉按鈕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

一個典型的方法是使用Mutex。這樣可以防止啓動第二個實例(或者,在應用程序的第二個實例內檢測到它)。

此時,您可以通知原始應用程序實例自行「顯示」。這裏是a good article describing the entire process in detail(儘管使用Windows窗體)。

對於WPF應用程序,您需要將此邏輯放入應用程序的啓動邏輯中,並在您想要顯示的WPF窗口中輸入add an HwndSourceHook to process the windows message

相關問題