WPF 텍스트 상자는 창 양식의 ElementHost에서 입력을 수락하지 않습니다.
-
08-07-2019 - |
문제
기존 Windows Forms / MFC Application Engine (Rhino 3D) 내에서 소비 할 WPF에서 UI 컨트롤을 개발하고 있습니다.
애플리케이션 엔진은 기능을 노출시켜 "도크 바"를 생성하는 능력을 노출시켜 엔진 인터페이스에 도킹 할 수있는 하위 창에 Windows 양식 컨트롤을 넣을 수 있습니다.
Dockbar에 추가되는 ElementHost 컨트롤 내에 간단한 WPF 텍스트 상자를 넣으려고합니다. 이것은 언뜻보기에 잘 작동하는 것으로 보입니다. 그러나 텍스트 상자에 입력하려고 시도한 후에는 특정 시퀀스 만 실제로 텍스트 상자에 나타납니다. 그만큼 삭제, 역행 키이, 복사, 반죽, 그리고 텍스트 선택 일하다. AZ, 1-9 등을 입력하면 해당 키가 나타나지 않습니다.
나는 그물을 수색했고 ElementHost.EnableModelessKeyboardInterop()
그러나 이것은 양식에서 생성되는 WPF Windows에만 적용됩니다. WPF USERCONTROLS 만 만들고 ElementHost 컨트롤에서 호스팅하고 있습니다.
나는 Dispatcher.run ()에 대해 이야기 한 게시물을 보았고 일종의 작품이지만 나머지 양식을 깨뜨 렸습니다.
System.Windows.Threading.Dispatcher.Run();
그만큼 미리 키키, 미리 키워 다운, 키 업, 그리고 키 다운 이벤트는 모든 텍스트 상자에 불이 붙지 만 텍스트 상자에는 텍스트가 표시되지 않습니다.
Windows 메시지에 대해 많이 알지 못하지만 WinSpector를 사용하여 텍스트 상자에서 WM_GETTEXT 메시지가 나오지 않는다는 것을 알았습니다 (심지어 알지 못하는 경우).
또한 새로운 Windows Forms 프로젝트를 만들고 그곳에서 동일한 작업을 수행했으며 잘 작동하므로 Rhino 3D 엔진 내에 Windows를 만드는 방법에 문제가 있어야합니다.
다음은 작동하지 않는 샘플 코드입니다.
ElementHost el = new ElementHost();
System.Windows.Controls.TextBox t = new System.Windows.Controls.TextBox();
t.Width = 100;
t.Text = "TEST";
el.Child = t;
panel1.Controls.Add(el);
해결책
나는 마침내 2 일간의 머리를 쫓아 낸 후 그것을 알아 냈습니다 ...
MFC 대화 창이 WM_CHAR
메시지 및 제어가 입력 처리를 방지합니다. 그래서 이것을 막기 위해 나는 hwndsource를 연결하고 내가받을 때마다 WM_GETDLGCODE
메시지는 수락 할 입력 유형으로 답장을 한 다음 이벤트를 처리 한대로 표시합니다.
모든 텍스트 상자를 수정하지 않기 위해 나만의 텍스트 상자를 만들었습니다 (아래 참조).
/// <summary>
/// Interop Enabled TextBox : This TextBox will properly handle WM_GETDLGCODE Messages allowing Key Input
/// </summary>
class IOTextBox : TextBox
{
private const UInt32 DLGC_WANTARROWS = 0x0001;
private const UInt32 DLGC_WANTTAB = 0x0002;
private const UInt32 DLGC_WANTALLKEYS = 0x0004;
private const UInt32 DLGC_HASSETSEL = 0x0008;
private const UInt32 DLGC_WANTCHARS = 0x0080;
private const UInt32 WM_GETDLGCODE = 0x0087;
public IOTextBox() : base()
{
Loaded += delegate
{
HwndSource s = HwndSource.FromVisual(this) as HwndSource;
if (s != null)
s.AddHook(new HwndSourceHook(ChildHwndSourceHook));
};
}
IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_GETDLGCODE)
{
handled = true;
return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
}
return IntPtr.Zero;
}
}
다른 팁
이것에 대한 내 자신의 질문을 확인하십시오. 결국, 당신이 필요한 것은 다음과 같습니다.
Window window1 = new Window();
ElementHost.EnableModelessKeyboardInterop(window1);
window1.Show();
WXWIDGETS 상위 창과 WPF 텍스트 상자 컨트롤과 비슷한 문제가 있습니다. childhwndsourcehook을 첨부하면 키보드 입력을받지 못하는 문제를 해결하지만 가끔 중복 공간 문자가 생겼음을 알았습니다. WM_Keydown 메시지는 공간 문자를 안정적으로 처리하는 것처럼 보이지만 일부 공간에 대해 중복 WM_CHAR 메시지도 수신됩니다. 이것을 해결하기 위해 나는 childhwndsourcehook 함수의 본문에 다음 절을 추가했는데, 이것은 단순히 WM_CHAR SPACE 문자를 무시합니다.
const UInt32 WM_CHAR = 0x0102;
if (msg == WM_CHAR)
{
// avoid duplicated spaces when parent window is a native window
if (wParam.ToInt32() == 32)
handled = true;
}
파생 된 텍스트 상자를 만들 필요는 없습니다. iotextbox의 코드는 UserControl 호스팅 텍스트 상자에서 사용할 수 있습니다. VS2010 패키지에 사용되는 사용자 정의 옵션 페이지에 사용 된 WPF 컨트롤로 성공적으로 테스트했습니다.