【问题标题】:Show WPF window from another application in C#在 C# 中显示来自另一个应用程序的 WPF 窗口
【发布时间】:2012-07-09 16:45:17
【问题描述】:

我有一个名为 app1 的 WPF 应用程序,它有一个名为 window1 的窗口。当用户点击window1的关闭按钮时,应用不会关闭,但window1会隐藏(this.hide())。

我想在启动时检查应用程序的另一个实例是否已经在运行;如果是这样,我想显示已经运行的实例并终止新的实例。

我该怎么做?

我知道如何检查进程以及如何关闭当前应用,但我不知道如何显示另一个正在运行的 WPF 进程的窗口...

在我的应用启动事件中,我这样做:

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

【问题讨论】:

    标签: c# wpf winapi process window


    【解决方案1】:

    一个典型的方法是使用互斥体。这允许您防止启动第二个实例(或者更确切地说,在应用程序的第二个实例中检测它)。

    此时,您可以通知原始应用程序实例“显示”自身。这里是a good article describing the entire process in detail(虽然使用的是 Windows 窗体)。

    对于 WPF 应用程序,您需要将此逻辑放入应用程序的启动逻辑中,并将 add an HwndSourceHook to process the windows message 放入您想要显示的 WPF 窗口中。

    【讨论】:

      【解决方案2】:

      我找到了工作的方法!

      “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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        • 1970-01-01
        • 2019-05-29
        • 1970-01-01
        相关资源
        最近更新 更多