2009-06-01 51 views
1

私は、winformsアプリケーション内のMFCライブラリクラスからウィンドウメッセージを受け取るためのメッセージ専用ウィンドウを作成しようとしています。Windowsフォームからメッセージ専用ウィンドウを作成するにはどうすればよいですか?

私はNativeWindowをサブクラス化し、コンストラクタで、次のようにウィンドウハンドルを要求しようとしました:

CreateParams cp = new CreateParams(); 
cp.Parent = (IntPtr)HWND_MESSAGE; 
this.CreateHandle(cp); 

が、私はメッセージ「エラー作成ウィンドウハンドル」と投げWin32Exceptionを取得します。 Windowsフォームからメッセージ専用ウィンドウを作成するにはどうすればよいですか? NativeWindowを正しい方法で使用していますか?

+0

答えをマークできますか? –

+1

答えは私には当てはまりませんでした。結局、私はC++/CLIを使い、Windows APIを掘り下げなければなりませんでした。私は使用したコードを投稿したいが、これは元の雇用者に属する。 – Simon

答えて

0

私はあなたもウィンドウクラスを指定する必要があると考えています。

+0

私は何に設定する必要がありますか?私は "メッセージ"とクラスの名前を試しましたが、どちらもうまくいきませんでした。 "Message"は私に同じエラーを与え、クラス名は私に "Window class name is not valid"を与えます。 – Simon

0

それを試してみてください。

[DllImport("user32.dll")] 
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 

static IntPtr HWND_MESSAGE = new IntPtr(-3); 

protected override void OnHandleCreated(EventArgs e) 
{ 
    base.OnHandleCreated(e); 
    SetParent(this.Handle, HWND_MESSAGE); 
} 
+0

注意:ShowInTaskbar = falseを設定する必要があります。 注意:FindWindowExを使用してメッセージ専用ウィンドウを検出する必要があるとMSDNに通知しているにもかかわらず、別のプロセスからメッセージを送信する場合は、メッセージ専用ウィンドウは役に立ちません。 – Elmue

+0

@Elmue、ブロードキャストされたメッセージを受信したい場合にはまだ便利です。 –

+0

MSDNを読む必要があります。メッセージのみのウィンドウでは、メッセージを送受信できます。表示されず、zオーダーがなく、列挙できず、ブロードキャストメッセージを受信しません。 – Elmue

0

私はあなたがFormから派生し、不可視のウィンドウを強制しなければならないことを恐れています。

別のアプローチは、(場合にクラスライブラリが変更可能である)(Application.RunApplication.AddMessageFilterを参照するか、またはあなたがPeekMessage &共同を使用してpinvokesを好む場合)窓なしでメッセージポンプを実行することです。

PostThreadMessageを使用してメッセージを送信するには、Application.Runを実行するスレッドIDを使用しますが、実際にはメッセージ確認応答を待機しないため、アプリケーションメッセージポンプスレッドと同期できません。

1

私はこれが7.5歳であることを知っていますが、誰かがこれを見つけた場合に備えて、私は応答すると考えました。私はMicrosoftのTimerNativeWindow codeを使用し、タイマー機能を削除しました。私はこのアプローチを使用して終了しました:

public class MyNativeWindow : NativeWindow 
    { 
     private readonly string _caption; 
     private const int WmClose = 0x0010; 

     [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 
     private static readonly HandleRef HwndMessage = new HandleRef(null, new IntPtr(-3)); 

     [DllImport("user32.dll", CharSet = CharSet.Auto)] 
     [ResourceExposure(ResourceScope.None)] 
     private static extern IntPtr PostMessage(HandleRef hwnd, int msg, int wparam, int lparam); 

     [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] 
     [ResourceExposure(ResourceScope.Process)] 
     private static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId); 

     [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] 
     [ResourceExposure(ResourceScope.Process)] 
     private static extern int GetCurrentThreadId(); 

     public MyNativeWindow(string caption) 
     { 
      _caption = caption; 
     } 

     public bool CreateWindow() 
     { 
      if (Handle == IntPtr.Zero) 
      { 
       CreateHandle(new CreateParams 
       { 
        Style = 0, 
        ExStyle = 0, 
        ClassStyle = 0, 
        Caption = _caption, 
        Parent = (IntPtr)HwndMessage 
       }); 
      } 
      return Handle != IntPtr.Zero; 
     } 


     public void DestroyWindow() 
     { 
      DestroyWindow(true, IntPtr.Zero); 
     } 

     private bool GetInvokeRequired(IntPtr hWnd) 
     { 
      if (hWnd == IntPtr.Zero) return false; 
      int pid; 
      var hwndThread = GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid); 
      var currentThread = GetCurrentThreadId(); 
      return (hwndThread != currentThread); 
     } 

     private void DestroyWindow(bool destroyHwnd, IntPtr hWnd) 
     { 
      if (hWnd == IntPtr.Zero) 
      { 
       hWnd = Handle; 
      } 

      if (GetInvokeRequired(hWnd)) 
      { 
       PostMessage(new HandleRef(this, hWnd), WmClose, 0, 0); 
       return; 
      } 

      lock (this) 
      { 
       if (destroyHwnd) 
       { 
        base.DestroyHandle(); 
       } 
      } 
     } 

     public override void DestroyHandle() 
     { 
      DestroyWindow(false, IntPtr.Zero); 
      base.DestroyHandle(); 
     } 
    } 
関連する問題