2009-06-01 4 views
1

winforms 응용 프로그램 내에서 MFC 라이브러리 클래스의 창 메시지를 받기 위해 메시지 전용 창을 만들려고합니다.Windows 양식에서 메시지 전용 창을 만드는 방법은 무엇입니까?

나는 NativeWindow를 서브 클래스, 생성자에서이 같은 창 핸들을 요청하는 시도했습니다

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

그러나 나는 메시지 "오류 생성 창 핸들"을 던져 Win32Exception를 얻을. Windows Forms에서 메시지 전용 창을 만드는 방법은 무엇입니까? 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로 설정해야합니다. 주의 : MSDN에서 FindWindowEx를 사용하여 메시지 전용 창을 찾았음에도 불구하고 다른 프로세스에서 메시지를 보내려는 경우 메시지 전용 창이 유용하지 않습니다. – Elmue

+0

@Elmue, 브로드 캐스트 메시지를 수신하려면 여전히 유용합니다. –

+0

MSDN : 메시지 전용 창을 사용하면 메시지를 보내고받을 수 있습니다. 표시되지 않으며 z 순서가없고 열거 될 수 없으며 브로드 캐스트 메시지를 수신하지 않습니다. – Elmue

0

나는 당신이 Form에서 파생, 보이지 않는 창을 강제해야한다는 것을 우려하고있다.

또 다른 방법은 (경우에 클래스 라이브러리가 수정할 수) 창없는 메시지 펌프를 실행하는 것입니다 (Application.RunApplication.AddMessageFilter를 참조하거나 PeekMessage & 공동 사용 pinvokes을 선호하는 경우).

이 경우 Application.Run을 실행하는 스레드 ID를 사용하여 PostThreadMessage을 사용하여 메시지를 보낼 수 있지만 실제로는 메시지 확인을 기다리지 않으므로 응용 프로그램 메시지 펌프 스레드와 동기화 할 수 없습니다.

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(); 
     } 
    } 
관련 문제