3

In Delphi, I have two edit boxes and a button.

Edit1 is selected by default. I want to change focus using messages. But if I do as below, it all gets messed up with selection ranges in both edits, caret in the wrong box etc.

The reason I'm using messages is so that I can control focus in an external application. This seems to work, up to a point but clearly, the windows internal state is a bit scrambled. I don't have the source for the external program.

procedure TForm1.Button1Click(Sender: TObject);
begin
  PostMessage(edit1.handle,WM_KILLFOCUS,0,0);
  PostMessage(edit2.handle,WM_SETFOCUS,0,0);
end;

... So can it be done? Am I missing a message?

Adam Richardson
  • 2,518
  • 1
  • 27
  • 31
Terry
  • 274
  • 1
  • 4
  • 16

1 Answers1

11

WM_SETFOCUS and WM_KILLFOCUS are both notification messages that Windows sends to window handles when they receive and lose input focus, respectively, and you should not post those yourself. Instead, simply call SetFocus(edit2.handle) or edit2.SetFocus() to set the focus.

If for some reason you can't do that synchronously from your button click handler, you can post a custom message to a local message handler in your own form and make the SetFocus call from that message handler.

  • I have the handle to a control I want to focus in a 3rd party application, so I need to send it messages if possible - I have no way to access the source for that application. – Terry Mar 18 '13 at 08:56
  • I'd read the documentation for SetFocus and it says it just sends those messages and selects the window. But I also see the comment ... "By using the AttachThreadInput function, a thread can attach its input processing to another thread. This allows a thread to call SetFocus to set the keyboard focus to a window attached to another thread's message queue." So I'm doing that now and it's working fine. Thanks for your reply. – Terry Mar 18 '13 at 22:38
  • 1
    `focusedThreadID := GetWindowThreadProcessID(wh, nil) ; if AttachThreadInput(GetCurrentThreadID, focusedThreadID, true) then try Windows.SetFocus(h); finally AttachThreadInput(GetCurrentThreadID, focusedThreadID, false) ; end;` – Terry Mar 18 '13 at 22:41