I have a program with several custom controls. One of these custom controls is a text input control. Since a window does not automatically receive keyboard focus when you click on it, i've created a mouse hook in my program that calls SetFocus() on a window when the user clicks in that window. However, there is a problem.

If another program has focus when you click on my program's window (or any of the controls in that window) SetFocus() fails. I then have to click again for it to succeed. Here's the code:

Your kbfProc callback method is assumingly called whenever the mouse moves? Show us the call to the WINAPI method. Also, I think it's preferable to set the focus via a form load event.
–
Chibueze OpataMar 10 '12 at 4:00

I'm confused about the need for the mouse hook. Are all the windows above your text input window marked with WS_EX_TRANSPARENT? If so, clicking the mouse in the text input window should set focus to the window.
–
Larry OstermanMar 10 '12 at 4:18

1

How "custom" is your custom control? If, for instance the text input field subclasses a text box, it should work fine. You can dramatically change the visuals while still keeping the core input functionality. In general, it's often better to find a window control that's close in function to the one you want to emulate and subclass it than to completely roll your own.
–
Larry OstermanMar 10 '12 at 4:27

1

Btw, the reason you're having difficulties with your SetFocus call is that Windows tries very hard to prevent apps from stealing focus. My guess is that the calls which are failing are failing because Windows thinks you're trying to steal focus from the current input window - opatachibueze's solution below will help there. But I'm STILL leery about the need for an input hook - I know they're needed in some circumstances, but this doesn't seem like one of them.
–
Larry OstermanMar 10 '12 at 4:29

2 Answers
2

I've found the solution. I ended up doing a lot of googling and trying a lot of different things, and i eventually came across this webpage. It's a bit of a lengthy read and it's a bit wordy and hard to understand, but it has a lot of information. I ended up adding some code to the WM_ACTIVATE handler of my main window that searches for the child window that was clicked when the window is activated. Here's all the code:

Whenever you're calling SetFocus, the window must be attached to the calling thread's message queue or SetFocus will return invalid if it's not. To workaround this, use SetForegroundWindow first when the mouse moves over your window before calling SetFocus.

I tried your suggestion, but i'm still getting the exact same result.
–
Gogeta70Mar 10 '12 at 4:31

Hmm, what is the return value of SetFocus when it succeeds in the two cases? It should return the window that had the previous focus. Also, have you tried SetActiveWindow ?
–
Chibueze OpataMar 10 '12 at 4:52

@Gogeta70 Try Jonathan Lingle's suggestion and tell us the result. NB: Perform that instead of SetForeGroundWindow before using SetFocus.
–
Chibueze OpataMar 11 '12 at 9:26

@JonathanLingle Properly attaching and detaching from threads of an external process would be a real mess, i imagine. I've just figured out the solution to my problem, i'll post an answer now. Still, thank you to everyone for all of your suggestions.
–
Gogeta70Mar 12 '12 at 6:14