2013-07-05 3 views
6

응용 프로그램에서 태블릿에서 실행할 때 화면 키보드 (OSK)를 사용하고 있습니다. 우리는 show and hide 메서드가있는 OSK라는 클래스를 만들었습니다.화면 키보드 닫기 버튼 이벤트?

사용자가 화면상의 키보드에서 '엔터'를 누르면 osk가 숨겨집니다. 문제는 사용자가 close (x) 버튼을 사용하여 OSK를 닫을 때입니다. OSK가 숨겨 지지만 UI가 변경 될 때 일부 사항을 변경해야합니다.

사용자가 OSK에서 닫기 버튼을 눌렀을 때 알 수있는 방법 (이벤트 또는 이와 비슷한 방식)이 있습니까?

내가 "표시와 OSK를 숨기기 위해 사용. 을 표시 코드는 옥시 젼에 (하지만 내가 생각하는 C#을 같은 많은 모양) 우리가했습니다

먼저했습니다 코드의 일부를 보여 드리겠습니다 일부 dllImports : 다음 코드는 OSK를 숨기기 위해 사용되는 숨기기 방법에서

using p := new Process do 
    begin 
    p.StartInfo.UseShellExecute := true; 
    p.StartInfo.FileName := 'C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe'; 
    p.Start(); 
    end; 

:이 코드가

쇼 방법에
[DllImport("user32.dll", SetLastError := true)] 
class method PostMessage(hWnd: IntPtr; Msg: UInt32; wParam, lParam: IntPtr): Boolean; external; 
[DllImport("user32.dll", SetLastError := true)] 
class method FindWindow(lpClassName, lpWindowName: String): IntPtr; external; 

01 23,516,
 var oskWindow := FindWindow("IPTip_Main_Window", nil); 
     var WM_SYSCOMMAND := 274; 
     var SC_CLOSE := 61536; 
     PostMessage(oskWindow, WM_SYSCOMMAND, SC_CLOSE, 0); 

업데이트 : 찾을 수 윈도우 7에 대한 작업 솔루션 ... (내가 필요한 건)

이 내가 윈도우 7에서 문제를 해결하기 위해 무슨 짓을 윈도우 8에 대한 작동하지 : 주 아이디어는 osk가 표시 될 때 OSK 클래스에서 Dispatchertimer를 시작한다는 것입니다. osk 창이 보이면 1 초마다 검사합니다. 그렇다면 여러 장소에서 처리 할 수있는 이벤트가 발생합니다. OSK를 표시하는 것이 때로는 시간이 걸립니다 때문에 (나는 또한 타이머의 _firstshown 부울을 확인

다음

내가 그랬어 방법은 다음과 같습니다. 먼저 내가 IsWindowVisible 방법의 같이 DllImport를 만들어

[DllImport("user32.dll", CharSet:=CharSet.Auto)] 
class method IsWindowVisible(hWnd:IntPtr):Boolean; external; 

에서 OSK.Show 타이머를 시작하고 _firstShown을 false로 설정하십시오 (osk가 나타나기까지 시간이 걸릴 수 있기 때문에) 이 전에 타이머 간격을 1 초로 설정하고 timer.Tick에 eventhandlerf를 추가했습니다 :

_timer.Interval := new TimeSpan(0,0,1); 
    _timer.Tick += new EventHandler(_timer_Tick); 

이 _timer_tick의 코드입니다 :

이 그것을하지 않았다 내가 태블릿에 그것을 테스트 (윈도우 8) 때문에 (윈도우 7), 기쁨이 단명 한 내 개발 시스템에서 일할 때 기쁨이 있었다
class method OSK._timer_Tick(sender: Object; e: EventArgs); 
begin 
    var oskWindow := FindWindow("IPTip_Main_Window", nil); 
    var IsOSKOpen := IsWindowVisible(oskWindow); 

    if not _firstShown then begin 
     if IsOSKOpen then _firstShown := true; 

     exit; 
    end; 
    if not IsOSKOpen then begin   
     OSKClosed(nil,new EventArgs());  
     _timer.Stop(); 
     _firstShown := false; 
    end; 
end; 

작업. 타이머 등 괜찮아요, 그냥 창 8 iswindowVisible 메서드를 처리하지 않는 것 같습니다. 프로그램이 OSK 자체를 시작하기 때문에

가 어쨌든 모든 도움은 매우 정직하게

답변

1

마지막으로 레지스트리를 사용하여 내 문제에 대한 해결책을 발견했습니다. osk는 UserClosed라는 레지스트리 키를 사용합니다. 사용자가 osk를 닫으면 userclosed 레지스트리 키가 하나가됩니다.

그래서 할 수있는 첫 번째 일은 (App.xaml.cs를에 OnStartup 무시)

var regKeyUserClosed := Registry.CurrentUser.OpenSubKey("Software\Microsoft\TabletTip\1.7",true); 
    regKeyUserClosed.SetValue("UserClosed",0); 

가 이제 레지스트리 키가 0 응용 프로그램이 시작될 때로 설정이 레지스트리 키를 0으로 설정하는 것입니다.

이제 osk가 호출되면 타이머가 시작되고 모든 틱에서 레지스트리 키가 1 (사용자가 OSK를 닫음)인지 확인해야합니다. 그러면 이벤트를 트리거하고 타이머를 중지하고 레지스트리 키를 설정합니다 프로세스가 OSK를 시작할 때

class method OSK._timer_Tick(sender: Object; e: EventArgs); 
begin 

var regKeyUserClosed := Registry.CurrentUser.OpenSubKey("Software\Microsoft\TabletTip\1.7",true); 

    var UserClosed := Convert.ToInt32(regKeyUserClosed.GetValue("UserClosed")); 

    if UserClosed.Equals(1) then begin 

    OSKClosed(nil,new EventArgs()); 

    _timer.Stop(); 

    regKeyUserClosed.SetValue("UserClosed",0); 

    end; 

end; 
+0

osk는 Windows 7 & 8의 기본 제공 기능이므로 모든 해킹을 사용하지 않아도됩니다. Microsoft Ink API를 사용해야합니다. –

+0

당신은 어떻게 이것을 알아 냈습니까?! 매우 비슷한 기능을 찾고 있지만 불행히도이 기능은 작동하지 않습니다. – YasharBahman

+0

이 솔루션에는 많은 문제가 있지만이 문제는 주에서 발생했지만 더 많은 문제가 있다는 것을 알게되었습니다. 우리는 아직 적절한 해결책을 찾지 못했습니다. 터치 기능이 현재로서는 우선 순위가 낮기 때문에이 문제는 매우 긴급하지 않습니다. –

2

을 감사합니다, 나는 옥시 젼 모르지만, 그것은 .NET :

에 대한 파스칼과 같은 작업을 수행 할 수 있습니다 사용자가 OSK를 닫을 때 호출 될 Process.Exited 이벤트에 가입하십시오.

그래서, 대신 p.MainWindowHandle을 사용할 수 없습니다, 당신은 FindWindow 필요한 이유 또한, 나는 보지 않는다 p에게 전역 변수를 확인하고 Exited

p.Exited += new EventHandler(_osk_Exited); 

class method OSK._osk_Exited(sender: Object; e: EventArgs); 
begin 
    // will be called when OSK gets closed 
end; 

에 가입?

UPDATE2

이전 업데이트는 작동하지 않았지만, 갑자기 생각 : 왜 해킹 대신 마이크로 소프트의 잉크 API를 사용하지?

프로젝트에 Microsoft.Ink 어셈블리에 대한 참조를 추가하면 파일이 기본적으로 목록에 없으므로 파일을 찾아야합니다 (Program Files 아래에서 microsoft.ink.dll 검색).

그런 다음 OSK를 필요로 각 입력에 대한 TextInputPanel 객체를 생성 : textBox1가 집중하고 포커스를 잃을 때 숨길 얻을 때
tip = new TextInputPanel(textBox1); 
tip.InPlaceVisibleOnFocus = true; 
tip.DefaultInPlaceState = InPlaceState.Expanded; 

지금, 텍스트 입력 패널이 표시됩니다. 당신은 당신이 사용자가 패널을 숨 깁니다 때에 관심이 있다면 InPlaceVisibilityChanged 이벤트 핸들러를 첨부 할 수 있습니다

tip.InPlaceVisibilityChanged += tip_InPlaceVisibilityChanged; 

void tip_InPlaceVisibilityChanged(object sender, InPlaceVisibilityChangeEventArgs e) 
{ 
    // do something with e.Visible 
} 

당신이 TextBoxHWND를 얻기 위해이 방법을 사용할 수 있습니다 WPF를 사용하는 경우 :

HwndSource textHandle = (HwndSource)PresentationSource.FromVisual(wpfTextBox); 
tip = new TextInputPanel(); 
tip.AttachedEditWindow = textHandle.Handle; 
tip.InPlaceVisibleOnFocus = true; 
tip.DefaultInPlaceState = InPlaceState.Expanded; 
+0

나는 내가했습니다 (암 여전히 종료 이벤트 실험) (유형에 대한 인스턴스 멤버를 호출 할 수 없습니다) –

+0

을이 예외가 p.MainWindowHandle을 사용할 수 없습니다 ... :-) Domotech 시스템을 소유하지 말아 p.enableRaisingevents를 true로 설정하고 p : = new Process 주변의 using 문을 제거합니다. 이제 _osk_exited는 show 메서드 바로 다음에 트리거됩니다 (사용자가 OSK에서 (x) 닫기 버튼을 누를 때가 아님). –

+0

더 정확히 말하면 p.Start() 후 _osk_exited가 트리거 됨 –

0

당신은 타이머를 시작할 수 있습니다 : 다시 0

이 나의 새로운 timer_tick 방법입니다. 해당 타이머에서 확인할 수 있습니다.

var oskprocess = Process.GetProcessesByName ("osk");

oskprocess.Length는 =

0 그리고 더 OSK 실행이없는 경우. 는 그런 다음

0

언젠가 다시 난 더 이상 윈도우 10에서 실 거예요 작업 osk.exe 최종에서 taskkill 사용하는 코드를 작성 타이머를 중지 할 수 있습니다하지만 난 그것을 쓸 때 나는이이 처리에 이루어졌다 내가 windows8 을 사용했다 생각 (자바) 그러나 이것은 mighthelp ???

launch(new String[] {"c:/Windows/system32/osk.exe" }); // OSK open 

launch(new String[] {"taskkill /IM osk.exe"}); // OSK close