title: On Screen Keyboard close button event?
body: <p>In an application I am using an onscreen keyboard(OSK) for when it is running on a tablet.
  We've made a class called OSK which has a show and hide method.</p>
  
  <p>When the user presses 'enter' on the onscreen keyboard, the osk hides. The problem is when the user closes the OSK with the close (x) button. The OSK hides, but some things need to change in the UI when this happens.</p>
  
  <p>Is there a way (an event or something like that) to know when the user pushes the close button on the OSK? </p>
  
  <p>I'll show some of the code I"ve used for showing and hiding the OSK.
  The code shown is in Oxygene (but it looks a lot like C# I think)</p>
  
  <p>First we've have some dllImports:</p>
  
  <pre><code>[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; 
  </code></pre>
  
  <p>In the show method there is this code:</p>
  
  <pre><code>  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; 
  </code></pre>
  
  <p>In the Hide method the next code is used to hide the OSK:</p>
  
  <pre><code>      var oskWindow := FindWindow("IPTip_Main_Window", nil);
        var WM_SYSCOMMAND  := 274;
        var SC_CLOSE := 61536;
        PostMessage(oskWindow, WM_SYSCOMMAND, SC_CLOSE, 0);
  </code></pre>
  
  <p>Update:
  Found a working solution for windows 7....not working for windows 8 (What i need)</p>
  
  <p>This is what i did to solve the problem in windows 7:
  The main idea is that in the OSK class i start a Dispatchertimer when the osk is shown. Now every second is checked if the osk window is visible. If so an event is fired which can be handled in several places. (I also check a _firstshown boolean in the timer because it sometimes takes a while for the osk to appear.</p>
  
  <p>Here's how I did that:
  first i made a dllImport of the IsWindowVisible method</p>
  
  <pre><code>[DllImport("user32.dll", CharSet:=CharSet.Auto)]
  class method IsWindowVisible(hWnd:IntPtr):Boolean; external;
  </code></pre>
  
  <p>In OSK.Show i start the timer and set _firstShown to false (because it can take a while for the osk to appear)
  Before this i've set the timer interval on 1 second and added an eventhandlerf to timer.Tick:</p>
  
  <pre><code>  _timer.Interval := new TimeSpan(0,0,1);
    _timer.Tick += new EventHandler(_timer_Tick);
  </code></pre>
  
  <p>This is the code in _timer_tick:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>There was pleasure when this worked on my development machine (windows 7), the joy was shortlived because when i tested it on the tablet (windows 8) it didn't work. the timer etc works fine, it just looks like windows 8 doesn't handle the iswindowVisible method.</p>
  
  <p>Anyway all help is very much appreciated   </p>