8

I am working on a virtual keyboard the problem is when i press a key on the virtual keyboard the window witch the data needs to be sent loses focus. How can i avoid that ?

opc0de
  • 11,557
  • 14
  • 94
  • 187
  • What you mean by `virtual keyboard`? are you using something like the `TTouchKeyboard` component? – RRUZ Nov 14 '11 at 17:42

4 Answers4

6

When your keyboard form receives focus, part of the message it receives is the handle of the window that lost focus (wParam). Do what you need to do and set the focus back to the window that lost focus.

EDIT: See the documentation on WM_SETFOCUS

EDIT 2:

Also, you could use the following when creating your custom form:

procedure TMainForm.CreateParams(var Params: TCreateParams) ;
 //const WS_EX_NOACTIVATE = $8000000;
 begin
   inherited;
   Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;
 end;

To prevent your form from activating (taking focus from the other form). Like I alluded to in my comment, you should probably be using non-windowed controls for keys.

Jerry Gagnon
  • 1,131
  • 8
  • 16
  • Keep in mind that if you are using windowed controls for keyboard buttons then they will also receive WM_SETFOCUS messages. I wrote "form" in my answer but I meant "window", which could be any windowed control that can receive keyboard focus. – Jerry Gagnon Nov 14 '11 at 18:27
  • The last method works great.One more question i know how to intercept a message belonging to a form but how can i intercept a message belonging to a control? Any example would be great.thanks – opc0de Nov 14 '11 at 18:52
  • Use `SetWindowsHookEx()` like rodrigo suggested. Some info here: http://delphi.about.com/od/kbwinshell/a/delphi_hook.htm though I'm not sure about how old it is. – Jerry Gagnon Nov 14 '11 at 19:24
5

The only method I've seen to do what you want is to disable the window with the virtual keyboard EnableWindow(hWnd, FALSE).

Now, if the window is disabled you will not get mouse messages, right? You have to options:

  • The easy one: Use WM_SETCURSOR. It is sent even to disabled windows, and in the high-order word of lParam you have the identifier of the original message (WM_LBUTTONDOWN, etc.). The coordinates of the cursor can be read using GetMessagePos().
  • The cool one: Use a windows hook: SetWindowsHookEx(WH_MOUSE, ...). You'll have full control of your mouse messages.
rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • I was looking for a way of detecting button down in a disabled window, and your hack with WM_SETCURSOR is pure genius. – Mark Ransom Nov 16 '18 at 20:58
1

Does this help?

procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE;

procedure TMyForm.WMMouseActivate(var Message: TWMMouseActivate);
begin
  Message.Result := MA_NOACTIVATE;
end;
Tim Post
  • 33,371
  • 15
  • 110
  • 174
Brian Frost
  • 13,334
  • 11
  • 80
  • 154
1

Use a class that does not have the ability to gain keyboard focus, but only responds to mouse input.

Solution: Derive your virtual keyboard from TControl or TGraphicControl, and not from TWinControl or TCustomControl.

NGLN
  • 43,011
  • 8
  • 105
  • 200