2013-11-13 5 views
0

У меня есть приложение WPF, которое запускается без параметров или флагов. В App.xaml.cs я добавил обработчик OnStartUp, который пытается сделать несколько IPC для другого экземпляра приложения, если он выполняется с параметрами. Например, основное приложение можно запустить, просто выполнив mainApp, который загрузит основные окна. Затем я мог бы позже выполнить mainApp msg bob some_message, который передал бы условие в OnStartUp и отправил «msg bob some_message» в запущенное приложение для обработки в своем WndProc переопределении.Родной SendMessage с переопределением WndProc для IPC не работает

Код в 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. Ничто не работает.

Кроме того, я хотел бы не просто указать конкретное сообщение, но и дополнительные динамические данные, такие как имя пользователя и текст сообщения.

+0

Возможный дубликат [Как обрабатывать сообщения WndProc в WPF?] (Http://stackoverflow.com/questions/624367/how-to-handle-wndproc-messages-in-wpf) – Stefan

ответ

1

Я думал, что вам нужно переопределение, хотя я не уверен, что существует в представлении WPF:

попробовать это:

protected override void WndProc(etc... 

[UPDATE] Вы не можете переопределить WndProc в окне класс WPF таким образом.

How to handle WndProc messages in WPF?

Поясню, что вам нужно крюк:

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, вы в принципе можете отправить его из любого места, если у вас есть дескриптор целевого окна.

Комбинируйте эту информацию с примечаниями Фрэнкса о WM_COPYDATA и она готова к работе.Для получения информации о WM_COPYDATA:

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

Надеется, что это помогает.

+0

Спасибо за ответ. Разве это переопределение не имеет таких параметров, как «ref message message»? Я нацелен на фреймворк 4, поэтому не думаю, что могу использовать тип 'Message'. – kmarks2

+0

Спасибо, просто посмотрел обновление. Я пробовал что-то очень похожее на это ранее, но проблема заключалась в том, что WndProc был в моем классе MainWindow. Который когда бы я попытался получить доступ через App.xaml.cs, я бы получил исключения «Объект неиспользуемый». – kmarks2

+0

Я не могу его скомпилировать. Тем не менее, я все еще использую обработчик событий App.xaml StartUp. Я ничего не вижу для SourceInitialization. – kmarks2

3

Вы отправляете сообщение HWND_IPC (дескриптор окна?) Вместо WM_IPC. HWND_IPC со значением 0xFFFE не в диапазоне для сообщений пользователя WM_USER + x.

Вы не можете передавать данные таким образом. Существует WM_COPYDATA, который копирует , данный буфер от одного обрабатывает частное адресное пространство до другого ...

Я думаю, вы должны использовать именованный канал для передачи данных. SendMessage так Win31 ;-)

+0

Я надеюсь, что смогу обойти всю проблему написания трубного сервера. Я думаю, что мне удастся в два или около того очень коротких методах выполнить это с помощью родного окна сообщений. – kmarks2

+2

Я думаю, что решение Named pipes является наиболее удобным: вы настраиваете «серверный» поток и ждете подключения какого-либо «клиента». Затем вы передаете данные так же, как и через любой другой поток. Здесь NamedPipeServerStream: http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeserverstream.aspx И это NamedPipeClientStream: http://msdn.microsoft.com/en-us/ library/system.io.pipes.namedpipeclientstream.aspx Пример кода там в значительной степени покрывает его. –

+0

Проверка, когда мы говорим. Спасибо за ссылки! – kmarks2