[comp.windows.ms] Why does SetFocus fail?

matt@nbires.nbi.com (Matthew Meighan) (02/14/89)

I have an app that has a parent window with three child windows.  Each
of the children's message handling procedures detects when the tab key
is pressed and sets the focus to the next of the three.

This works fine except when the app loses the focus and then regains
it (e.g., if I alt-tab to the dos executive and back).  In response to
the WM_ACTIVATEAPP message, I call SetFocus with one of the child's
handles.  However, the child does not get the focus; WM_KEYDOWN messages
go to the parent's window, not the child window, despite the SetFocus call.  
I tried calling SetFocus twice, and looking at its return; it is zero
BOTH times -- which would imply that the first SetFocus did not set
the focus at all.

Anyone know why SetFocus would fail like this?  Thanks in advance.

-- 

Matt Meighan            "The eighties are the fifties in color."  - Cowtown  
matt@nbires.nbi.com (nbires\!matt)

cig@genrad.UUCP (Charles I. Ganimian Jr.) (02/14/89)

In article <224@nbires.nbi.com> matt@nbires.nbi.com (Matthew Meighan) writes:
>I have an app that has a parent window with three child windows.  Each
>of the children's message handling procedures detects when the tab key
>is pressed and sets the focus to the next of the three.
>

What I have found to work is to process WM_ACTIVATEAPP in the parent and 
check if wParam != 0 (then you are are receiving the focus) and PostMessage
WM_ACTIVATE to child window, which processes WM_ACTIVATE and sets focus to
a child window control (button) or its self in your case.


					good luck and I hope this helped
					
					charlie g.

beckman@dev386.UUCP (Zacharias Beckman) (02/16/89)

In article <224@nbires.nbi.com>, matt@nbires.nbi.com (Matthew Meighan) writes:
> handles.  However, the child does not get the focus; WM_KEYDOWN messages
> go to the parent's window, not the child window, despite the SetFocus call.  

One possible cause is that the child windows are not yet ready to receive the
focus (for instance, they have not been created or brought to the top; I do
not believe you can give the focus to a window that is covered).  Perhaps you
could try using PostMessage() to send a message which you define to the child
window; when it receives the message, it should then do a SetFocus() on itself.
Hope this helps (your problems are reminiscent of a dialog box problem we had
some time ago).

Zacharias J. Beckman   ...   gatech!mdt!pgthor!dev386!beckman
                       ...   uunet!mcrware!pgthor!dev386!beckman
(319) 354-5116               (319) 351-1993

If God had intended Man to Walk, He would have given him Feet.

bturner@hpcvlx.HP.COM (Bill Turner) (02/16/89)

> This works fine except when the app loses the focus and then regains
> it (e.g., if I alt-tab to the dos executive and back).  In response to
> the WM_ACTIVATEAPP message, I call SetFocus with one of the child's
> handles.  However, the child does not get the focus;....

How about doing the SetFocus when the parent receives the WM_ACTIVATE
message?  I can't remember exactly what order ACTIVATEAPP and ACTIVATE
come in, and I think that DefWindowProc calls SetFocus on WM_ACTIVATE.

--Bill Turner

matt@nbires.nbi.com (Matthew Meighan) (02/22/89)

A while back, in <224@nbires.nbi.com>, I posted:

>I have an app that has a parent window with three child windows.  Each
>of the children's message handling procedures detects when the tab key
>is pressed and sets the focus to the next of the three.
>
>This works fine except when the app loses the focus and then regains
>it (e.g., if I alt-tab to the dos executive and back).  In response to
>the WM_ACTIVATEAPP message, I call SetFocus with one of the child's
>handles.  However, the child does not get the focus; WM_KEYDOWN messages
>go to the parent's window, not the child window, despite the SetFocus call.  
>I tried calling SetFocus twice, and looking at its return; it is zero
>BOTH times -- which would imply that the first SetFocus did not set
>the focus at all.

Here is a summary of what I've learned since then:

The problem seems to be that _after_ the WM_ACTIVATEAPP message, the
main window gets a WM_ACTIVATE message.  DefWindowProc calls SetFocus
when it gets this message.  So if you set the focus in response to
WM_ACTIVATEAPP, windows sets it back on the WM_ACTIVATE message.

The simplest solution I've found is to handle the WM_ACTIVATE message in 
the parent window. I check wParam to see if the window is being activated, and
HIWORD(lParam) to make sure it's not an icon.   If so, I call SetFocus; 
otherwise, I call DefWindowProc:


case WM_ACTIVATE:
	if (wParam && (! HIWORD(lParam) ) )
		SetFocus (whichever) ;
	else
		return DefWindowProc (win, message, wParam, lParam) ;
	break ;

This seems to work fine for me. 

Another suggestion was:

>From: cig@genrad.UUCP (Charles I. Ganimian Jr.)
>
>What I have found to work is to process WM_ACTIVATEAPP in the parent and 
>check if wParam != 0 (then you are are receiving the focus) and PostMessage
>WM_ACTIVATE to child window, which processes WM_ACTIVATE and sets focus to
>a child window control (button) or its self in your case.

This also worked for me, but I found I also had to PostMessage when my
app was returning from being an icon (on the WM_COMMAND message); I also got a 
WM_ACTIVATEAPP message then but it came while the app was still an icon and 
that was too early for the child to handle things properly.   Finally, I had to 
do an explicit SetFocus to the child after each DialogBox() call.  With the
first method (setting focus on WM_ACTIVATE), all of these cases were handled. 

-- 

Matt Meighan          
matt@nbires.nbi.com (nbires\!matt)

-- 

Matt Meighan          
matt@nbires.nbi.com (nbires\!matt)