2013-07-05 42 views
6

Bir uygulamada, bir tablette çalıştığı sırada bir ekran klavyesi (OSK) kullanıyorum. Bir gösteri ve gizleme yöntemine sahip OSK adında bir sınıf oluşturduk.Ekran Klavyesi close button olayı nedir?

Kullanıcı, ekran klavyesinde 'enter' düğmesine bastığında, osk gizler. Sorun, kullanıcı OSK'yi close (x) düğmesiyle kapattığı zamandır. OSK gizleniyor, ancak bazı durumlarda UI'de değişiklik olması gerekiyor.

Kullanıcının OSK'daki kapat düğmesini ne zaman zorladığını bilmek için bir yol var mı (bir olay ya da benzeri bir şey var)?

ben "gösteren ve OSK gizleme kullandı. gösterilen kod Oxygene içindedir (ama bence C# çok benziyor) Elimizdeki ettik

Birinci ettik kod bazı göstereceğiz bazı dllImports: bir sonraki kod OSK gizlemek için kullanılır gizle yönteminde

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; 

: Bu kod var

gösteri yöntemde
[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; 

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

Güncelleme: Bulunan Windows 7 için bir çalışma çözüm .... (i gerekenler)

Bu şimdiye pencerelerde 7'de sorunu çözmek için ne yaptığını pencereler 8 için çalışmıyor: ana fikir, OSK sınıfında, osk gösterildiğinde bir Dispatchertimer başlattığımdır. Şimdi, eğer osk penceresi görünürse her saniye kontrol edilir. Eğer öyleyse, birkaç yerde ele alınabilecek bir olay kovulur. osk görünmesi için bazen biraz zaman alıyor çünkü (Ben de zamanlayıcı bir _firstshown boole kontrol

İşte

Nasıl yaptığımı var. ilk ben IsWindowVisible yöntemin bir Dllımport yapılan

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

yılında OSK.Show zamanlayıcıyı başlatın ve _firstShown'u false olarak ayarlayın (osk'un görünmesi biraz zaman alabilir) Bundan önce 1 saniye içinde zamanlayıcı aralığını ayarladım ve zamanlayıcıya bir eventhandlerf ekledim.Tick:

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

Bu _timer_tick içinde kodudur:

bu etmedi i tabletin üzerinde test (windows 8) çünkü (windows 7), sevinç kısa sürmüş benim geliştirme makinede çalışırken zevk oldu
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; 

iş. zamanlayıcı vb iyi çalışıyor, sadece windows 8 iswindowVisible yöntemi ele almıyor gibi görünüyor. Programınız OSK kendisi başlatır yana

Neyse bütün Yardım çok dürüst olmak gerekirse

cevap

1

Son olarak kayıt kullanarak soruna bir çözüm bulduk. osk, UserClosed adlı bir kayıt defteri anahtarını kullanır. Kullanıcı osk'yi kapatırsa, kullanıcı tarafından kapatılan kayıt defteri anahtarı bir olur.

Yani yapmanız gereken ilk şey (App.Xaml.cs içinde OnStartup geçersiz)

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

Şimdi kayıt defteri anahtarı 0 uygulama başladığında olarak ayarlanır 0 olarak bu kayıt defteri anahtarını ayarlamaktır.

Şimdi osk çağrıldığında, zamanlayıcı başlar ve her kene üzerinde kayıt anahtarının 1 olup olmadığını (kullanıcı OSK'yi kapattı) görmemiz gerekir, eğer olayı tetiklerse, zamanlayıcıyı durdurup kayıt defteri anahtarını ayarla süreç OSK başlattığınızda

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

Tüm bu korsanları kullanmanız gerekmemelidir çünkü osk, hem Windows 7 hem de 8 için yerleşik bir işlevselliktir. Bunun için Microsoft Ink API'sini kullanmalısınız. –

+0

Bunu nasıl anladın? Çok benzer bir işlevsellik arıyorum ama maalesef bu işe yaramadı. – YasharBahman

+0

, bu çözümün çok sayıda sorunu olduğunu, burada çalıştığını, ancak eyaletlerde ve daha birçok problemde işe yaramadığını öğrendi. Henüz uygun bir çözüm bulamadık. Bu sorun çok acil bir durum değil çünkü dokunmatik işlev şu an için düşük öncelikli. –

2

takdir, ben OXYGENE bilmiyorum ama .NET :)

için Pascal benziyor yapabilirsiniz Sadece kullanıcı OSK'yi kapattığında çağrılacak olan Process.Exited etkinliğine abone olun.

Yani, yerine p.MainWindowHandle kullanamaz, sen FindWindow neden ihtiyaç Ayrıca, ben görmüyorum p küresel değişkeni yapmak ve 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; 

abone?

Update2

Önceki güncelleme işe yaramadı, ama birden düşündüm: neden hack yerine Microsoft'un Mürekkep API kullanılmasın?

varsayılan olarak listede yok çünkü ( Program Files altında microsoft.ink.dll aramak), dosyaya gidin gerekir, projenize Microsoft.Ink derlemesine ekleyin.

Sonra OSK gereken her giriş için TextInputPanel nesnesi oluşturmak: textBox1 odaklanmak ve odağı kaybettiğinde gizlemek aldığında
tip = new TextInputPanel(textBox1); 
tip.InPlaceVisibleOnFocus = true; 
tip.DefaultInPlaceState = InPlaceState.Expanded; 

Şimdi, metin giriş paneli görünecektir. Hatta kullanıcı panelini gizler zaman ilgileniyorsanız InPlaceVisibilityChanged olaya bir işleyici ekleyebilirsiniz:

tip.InPlaceVisibilityChanged += tip_InPlaceVisibilityChanged; 

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

Eğer TextBox ait HWND almak için bu yöntemi kullanabilirsiniz WPF kullanıyorsanız:

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

Ben ettik (Am hala çıkıldı Olay deneme) (türlerinde örnek üyeleri arayamaz) –

+0

bu istisna olsun p.MainWindowHandle kullanamazsınız ... :-) bir DOMOTECH sistemini dont own p.enableRaisingevents öğesini true olarak ayarlayın ve p: = new Process ile ilgili kullanım ifadesinden kurtuldu. Şimdi _osk_exited show yönteminden hemen sonra tetiklenir (kullanıcı OSK üzerindeki (x) kapama düğmesine bastığında değil –

+0

Daha kesin olması için, _osk_exited p.Start() –

0

bir zamanlayıcı başlatabilirsiniz: geri 0.

Bu benim yeni timer_tick yöntemidir. Bu zamanlayıcıda

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

oskprocess.Length =

0 Sonra hiçbir osk koşu olduğunda. Sonra

0

ara tekrar ben artık Windows 10 içinde alışkanlık çalışması osk.exe sonuna kadar NotTaskkill kullanılan kod yazdım sayacı durdurabilirsiniz ama bunu yazarken bu işlem yapıldığını ben Windows8 kullanıyordum düşünüyorum (java) ama bu yardımcı olabilir ???

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

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