0

我有一个没有参数或标志的 WPF 应用程序。在App.xaml.cs我添加了一个OnStartUp处理程序,该处理程序尝试对应用程序的另一个实例执行一些 IPC,如果它使用参数执行。例如,我的主应用程序可以通过简单地执行来启动mainApp,这将加载主窗口。然后我可能会稍后执行mainApp msg bob some_message它将传递条件OnStartUp并将“msg bob some_message”发送到启动并运行的应用程序以处理其WndProc覆盖。

App.xaml.cs 中的代码:

private void OnStartUp(object sedner, StartupEventArgs e)
{
   Process localProcess = Process.GetCurrentProcess();

   foreach (Process process in Process.GetProcessesByName(localProcess.ProcessName))
   {
      if (process.Id != localProcess.Id)
      {
         NativeMethods.SendMessage(process.MainWindowHandle, NativeMethods.HWND_IPC, IntPtr.Zero, IntPtr.Zero);
         Environment.Exit(0);
      }
   }
}

主窗口代码隐藏中的代码:

public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr iParam, ref bool handled)
{
   if (msg == NativeMethods.HWND_IPC)
   {
      MessageBox.Show("Message Received!");
   }

   return IntPtr.Zero;
}

internal class NativeMethods
{
   public const int HWND_BROADCAST = 0xffff;
   public const int HWND_IPC = 0xfffe;
   public static readonly int WM_IPC = RegisterWindowMessage("WM_IPC");
   public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
   [DllImport("user32")]
   public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
   [DllImport("user32.dll")]//, CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
   [DllImport("user32")]
   public static extern int RegisterWindowMessage(string message);
}

我已经尝试过使用 PostMessage、SendMessage 的多种排列方式,仅使用静态 int 消息,实际上调用了 RegisterWindowMessage。似乎没有任何效果。

此外,我不仅希望能够指定特定消息,还希望能够指定其他动态详细信息,例如用户名和一些消息文本。

4

2 回答 2

3

您正在发送消息 HWND_IPC(窗口句柄?)而不是 WM_IPC。HWND_IPC 的值为 0xFFFE,不在用户消息 WM_USER+x 的范围内。

您不能以这种方式传输数据。有一个 WM_COPYDATA 将给定的缓冲区从一个进程的私有地址空间复制到另一个进程的私有地址空间......

我认为您应该使用命名管道来传输数据。SendMessage 是如此 Win31 ;-)

于 2013-11-13T20:44:15.837 回答
1

我认为您将需要覆盖,尽管我不确定它是否存在于 WPF 视图中:

尝试这个:

protected override void WndProc( etc...

[更新] 您不能以这种方式覆盖 WPF 的 Window 类中的 WndProc。

如何在 WPF 中处理 WndProc 消息?

将解释你需要一个钩子:

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }

把它放在一起:

在您的 App.xml.cs 中,您将初始化您的 App 启动参数。创建一些静态属性是最简单的。保持它们简单,没有集合以避免以后多线程崩溃:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    public static string SomeValue { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        SomeValue = e.Args[0];
    }
}

现在,您只需调用即可访问SomeValue整个代码App.SomeValue

然后; 必须将 WndProc 实现到窗口中。一个窗口有一个消息泵。没有消息泵,您将无法发送消息(您可以创建自己的消息,但这太多了)

所以在一个窗口中,例如 MainWindow,实现覆盖:

public partial class MainWindow : Window
{
    public MainWindow()
    {  
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }

    public IntPtr WndProc(IntPtr hwnd, int msg, 
                          IntPtr wParam, IntPtr iParam, ref bool handled)
    {
        if (msg == NativeMethods.HWND_IPC)
            MessageBox.Show("Message Received!");

        return IntPtr.Zero;
    }
}

internal class NativeMethods
{

etc. etc.

唯一需要实现的是触发消息的时刻,但由于它是 IPC,因此您基本上可以从任何地方发送它,只要您有目标窗口的句柄即可。

将此信息与 Franks 关于 WM_COPYDATA 的评论结合起来,就可以开始使用了。有关 WM_COPYDATA 的信息:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms649011%28v=vs.85%29.aspx

希望能帮助到你。

于 2013-11-13T20:32:19.743 回答