Windows Forms 및 WPF 상호 운용성 입력 아키텍처

WPF와 Windows Forms 간의 상호 운용을 위해서는 두 기술 모두 적절한 키보드 입력 처리가 필요합니다. 이 항목에서는 이러한 기술이 하이브리드 애플리케이션에서 원활한 상호 운용을 가능하게 하는 키보드 및 메시지 처리를 구현하는 방법에 대해 설명합니다.

이 항목에는 다음과 같은 하위 단원이 포함되어 있습니다.

  • 모덜리스 양식 및 대화 상자

  • WindowsFormsHost 키보드 및 메시지 처리

  • ElementHost 키보드 및 메시지 처리

모덜리스 양식 및 대화 상자

WindowsFormsHost 요소에서 EnableWindowsFormsInterop 메서드를 호출하여 WPF 기반 애플리케이션에서 모덜리스 양식 또는 대화 상자를 엽니다.

ElementHost 컨트롤에서 EnableModelessKeyboardInterop 메서드를 호출하여 Windows Forms 기반 애플리케이션에서 모덜리스 WPF 페이지를 엽니다.

WindowsFormsHost 키보드 및 메시지 처리

WPF 기반 애플리케이션에서 호스트되는 경우 Windows Forms 키보드 및 메시지 처리는 다음으로 구성됩니다.

  • WindowsFormsHost 클래스는 ComponentDispatcher 클래스에 의해 구현되는 WPF 메시지 루프에서 메시지를 가져옵니다.

  • WindowsFormsHost 클래스는 서로게이트 Windows Forms 키보드 처리가 발생하도록 대리 Windows Forms 메시지 루프를 만듭니다.

  • WindowsFormsHost 클래스는 WPF를 사용하여 포커스 관리를 조정하는 IKeyboardInputSink 인터페이스를 구현합니다.

  • WindowsFormsHost 컨트롤은 자신을 등록하고 메시지 루프를 시작합니다.

다음 섹션에서는 프로세스의 이러한 부분에 대해 자세히 설명합니다.

WPF 메시지 Loop에서 메시지 가져오기

ComponentDispatcher 클래스는 WPF에 대한 메시지 루프 관리자를 구현합니다. ComponentDispatcher 클래스는 WPF에서 메시지를 처리하기 전에 외부 클라이언트가 메시지를 필터링할 수 있도록 하는 후크를 제공합니다.

상호 운용 구현은 Windows Forms 컨트롤이 WPF 컨트롤보다 먼저 메시지를 처리할 수 있도록 하는 ComponentDispatcher.ThreadFilterMessage 이벤트를 처리합니다.

서로게이트 Windows Forms 메시지 Loop

기본적으로 System.Windows.Forms.Application 클래스에는 Windows Forms 애플리케이션에 대한 기본 메시지 루프가 포함되어 있습니다. 상호 운용하는 동안 Windows Forms 메시지 루프는 메시지를 처리하지 않습니다. 따라서 이 논리를 재현해야 합니다. ComponentDispatcher.ThreadFilterMessage 이벤트에 대한 처리기는 다음 단계를 수행합니다.

  1. IMessageFilter 인터페이스를 사용하여 메시지를 필터링합니다.

  2. Control.PreProcessMessage 메서드를 호출합니다.

  3. 필요한 경우 메시지를 번역하고 디스패치합니다.

  4. 다른 컨트롤이 메시지를 처리하지 않는 경우 메시지를 호스팅 컨트롤에 전달합니다.

IKeyboardInputSink 구현

서로게이트 메시지 루프는 키보드 관리를 처리합니다. 따라서 IKeyboardInputSink.TabInto 메서드는 WindowsFormsHost 클래스에서 구현해야 하는 유일한 IKeyboardInputSink 멤버입니다.

기본적으로 HwndHost 클래스는 IKeyboardInputSink.TabInto 구현에 대해 false를 반환합니다. 이렇게 하면 WPF 컨트롤에서 Windows Forms 컨트롤로 탭할 수 없습니다.

IKeyboardInputSink.TabInto 메서드의 WindowsFormsHost 구현은 다음 단계를 수행합니다.

  1. WindowsFormsHost 컨트롤에 포함되고 포커스를 받을 수 있는 첫 번째 또는 마지막 Windows Forms 컨트롤을 찾습니다. 컨트롤 선택은 순회 정보에 따라 달라집니다.

  2. 컨트롤에 포커스를 설정하고 true를 반환합니다.

  3. 컨트롤이 포커스를 받을 수 없는 경우 false를 반환합니다.

WindowsFormsHost 등록

WindowsFormsHost 컨트롤에 대한 창 핸들을 만들 때 WindowsFormsHost 컨트롤은 메시지 루프에 대한 현재 상태를 등록하는 내부 정적 메서드를 호출합니다.

등록하는 동안 WindowsFormsHost 컨트롤은 메시지 루프를 검사합니다. 메시지 루프가 시작되지 않은 경우 ComponentDispatcher.ThreadFilterMessage 이벤트 처리기가 만들어집니다. 메시지 루프는 ComponentDispatcher.ThreadFilterMessage 이벤트 처리기가 연결될 때 실행되는 것으로 간주됩니다.

창 핸들이 제거되면 WindowsFormsHost 컨트롤은 등록에서 자신을 제거합니다.

ElementHost 키보드 및 메시지 처리

Windows Forms 애플리케이션에서 호스트되는 경우 WPF 키보드 및 메시지 처리는 다음으로 구성됩니다.

다음 섹션에서는 이러한 부분에 대해 상세히 설명합니다.

인터페이스 구현

Windows Forms에서 키보드 메시지는 포커스가 있는 컨트롤의 창 핸들로 라우팅됩니다. ElementHost 컨트롤에서 이러한 메시지는 호스트된 요소로 라우팅됩니다. 이를 위해 ElementHost 컨트롤은 HwndSource 인스턴스를 제공합니다. ElementHost 컨트롤에 포커스가 있는 경우 HwndSource 인스턴스는 WPF InputManager 클래스에서 처리할 수 있도록 대부분의 키보드 입력을 라우팅합니다.

HwndSource 클래스는 IKeyboardInputSinkIKeyboardInputSite 인터페이스를 구현합니다.

키보드 상호 운용은 포커스를 호스트된 요소 밖으로 이동하는 TAB 키 및 화살표 키 입력을 처리하는 OnNoMoreTabStops 메서드 구현에 의존합니다.

탭 및 화살표 키

Windows Forms 선택 논리는 IKeyboardInputSink.TabIntoOnNoMoreTabStops 메서드에 매핑되어 TAB 및 화살표 키 탐색을 구현합니다. Select 메서드를 재정의하면 이 매핑이 수행됩니다.

명령 키 및 대화 상자 키

WPF에서 명령 키와 대화 키를 처리할 수 있는 첫 번째 기회를 제공하기 위해 Windows Forms 명령 전처리가 TranslateAccelerator 메서드에 연결됩니다. Control.ProcessCmdKey 메서드를 재정의하면 두 기술이 연결됩니다.

TranslateAccelerator 메서드를 사용하면 호스트된 요소는 TAB, ENTER, ESC 및 화살표 키와 같은 명령 키를 포함하여 WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN 또는 WM_SYSKEYUP와 같은 모든 키 메시지를 처리할 수 있습니다. 키 메시지가 처리되지 않으면 처리를 위해 Windows Forms 상위 계층 구조로 전송됩니다.

가속기 처리

가속기를 올바르게 처리하려면 Windows Forms 가속기 처리를 WPF AccessKeyManager 클래스에 연결해야 합니다. 또한 모든 WM_CHAR 메시지는 호스트된 요소로 올바르게 라우팅되어야 합니다.

TranslateChar 메서드의 기본 HwndSource 구현이 false를 반환하므로 WM_CHAR 메시지는 다음 논리를 사용하여 처리됩니다.

  • Control.IsInputChar 메서드는 모든 WM_CHAR 메시지가 호스트된 요소로 전달되도록 재정의됩니다.

  • ALT 키를 누르면 메시지는 WM_SYSCHAR입니다. Windows Forms는 IsInputChar 메서드를 통해 이 메시지를 전처리하지 않습니다. 따라서 ProcessMnemonic 메서드는 등록된 가속기에 대해 WPF AccessKeyManager를 쿼리하도록 재정의됩니다. 등록된 액셀러레이터가 찾으면 AccessKeyManager에서 처리합니다.

  • ALT 키를 누르지 않으면 WPF InputManager 클래스가 처리되지 않은 입력을 처리합니다. 입력이 액셀러레이터인 경우 AccessKeyManager에서 처리합니다. PostProcessInput 이벤트에서 처리되지 않은 WM_CHAR 메시지에 대해 처리됩니다.

사용자가 ALT 키를 누르면 전체 폼에 가속기 시각적 신호가 표시됩니다. 이 동작을 지원하기 위해 활성 폼의 모든 ElementHost 컨트롤은 포커스가 있는 컨트롤에 관계없이 WM_SYSKEYDOWN 메시지를 받습니다.

메시지는 활성 형식의 ElementHost 컨트롤에만 전송됩니다.

참고 항목