The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Jimg on August 04, 2005, 03:52:31 PM

Title: Getting Focus
Post by: Jimg on August 04, 2005, 03:52:31 PM
I have another Newbie type question :(

I have a dialog as main program.  While the program is running, the user can click on some other program or the desktop or whatever, and my program loses focus.  What is the best message in the dlgproc to trap to know when the focus is returned to my dialog or anything in it?  I need to update my information in case the user made changes to the desktop, specifically moving icons around, while he was gone.  By best message, I suppose I mean the last general one where all the painting and whatever is done, and things have settled down.  I'm really hazy on the order of events in a situation like this or what I should be looking for.
Title: Re: Getting Focus
Post by: PBrennick on August 04, 2005, 09:12:47 PM
Jimq,
GetFocus will return the handle of the current open window, dialogbox or control.  Since you already know what your handles are, just call the API and do a compare.
Paul
Title: Re: Getting Focus
Post by: Mark Jones on August 04, 2005, 10:14:25 PM
You could toggle on the WM_ACTIVATE message.
Title: Re: Getting Focus
Post by: Jimg on August 05, 2005, 02:18:11 AM
Thanks Paul.

Mark-
  Yeah, WM_ACTIVATE would have been my guess.  The problem is it is only a guess and I would prefer some definitive statement from someone who knows the actual answer or at least what Microsoft recommends.  I also get a WM_USER message after the activate.  Anyone know if this is always the case or just some quirk of my program?  If it's reliable, it's a little cleaner to use than WM_ACTIVATE.
Title: Re: Getting Focus
Post by: hutch-- on August 05, 2005, 03:22:02 AM
Jim,

If you actually want an app to stay on top you can set the zorder property for its main window with SetWindowPos() and will not disappear when something else gets the focus.
Title: Re: Getting Focus
Post by: Jimg on August 05, 2005, 05:21:12 AM
Thanks Hutch.  No, in this app I would encourge the user to move the desktop icons around, I just wanted to know when he was done and came back to the app.  I think I'll do a postmessage when I get the activate, and let all the other stuff run it's course before doing anything.
Title: Re: Getting Focus
Post by: tenkey on August 05, 2005, 05:25:58 AM
Well, I went to MSDN and when I looked at the SetFocus API, they mentioned two messages WM_KILLFOCUS and WM_SETFOCUS.
Title: Re: Getting Focus
Post by: Tedd on August 05, 2005, 10:18:32 AM
When your app loses focus, it will receive a WM_KILLFOCUS message (with wParam set to the 'new' window's handle.)
When it gains focus, it receives a WM_SETFOCUS message (with wParam set to the 'old' window's handle.)

You will receive a WM_SETFOCUS message just after creation (when your window becomes the foreground), and then any other time you regain focus.

Repainting is actually done lazily. Whenever you receive a WM_PAINT message, it's actually because there are no other relevant messages in your queue (and there is a region that needs updating.)


Tracking access to the desktop through wm_killfocus probably isn't very reliable though - a user could easily move to another window, and then onto the desktop, yet you would have no indication of this.

Random thoughts:
- some kind of mouse hooking; or
- if you only need to know which icons have changed then you only need to know when your app regains focus, and then just compare the positions of the icons with their previously known positions.
Title: Re: Getting Focus
Post by: Jimg on August 05, 2005, 01:59:19 PM
Quote- if you only need to know which icons have changed then you only need to know when your app regains focus, and then just compare the positions of the icons with their previously known positions.
Thanks Tedd, that's exactly what I intended to do :wink

Interesting.   After much testing, these are the messages I always get when my app gets focus  (using alt-tab to return the focus to the app)-

In this order:

WM_WINDOWPOSCHANGING = 00000046h
WM_WINDOWPOSCHANGED = 00000047h
WM_ACTIVATEAPP = 0000001Ch
WM_NCACTIVATE = 00000086h
WM_GETTEXT = 0000000Dh
WM_ACTIVATE = 00000006h
WM_USER = 00000400h

I get a whole lot of other messages (mouse movement, etc.)  but these are the only consistant messages

I never see the wm_setfocus message at all????  I don't know if any of these are the result of calling PrintHex from the debug library to print out the values.

I find that last WM_USER strangely attractive.  I'm not sending it, and it's supposed to be for my use.  Is this something used by the debug library?
Title: Re: Getting Focus
Post by: PBrennick on August 05, 2005, 03:23:20 PM
Jimg,
wm_setfocus is a message you send, not receive.  The earlier mention of this was probably a typo.  Using GetFocus is all you need to do as all you are interested in is if your message queue has reawakened.  When it reawakens, you can check the icon positions.  Until they return to your window, it does not matter if they give focus to another window as you do not need to update until the user is active in your window.

Paul
Title: Re: Getting Focus
Post by: Jimg on August 05, 2005, 04:15:29 PM
Hi Paul-

I must be misunderstanding the GetFocus function.  As I read it, I have to execute the GetFocus function to find out which window currently has the (keyboard) focus.  So I would have to continually execute GetFocus to find out when I lose focus, and when it returns.  This would be like setting up a timer that ticks every few milliseconds and executes the GetFocus?  I really don't like that kind of situation, it's bad enough the windows wastes all that time polling, it should just tell me.  Again, maybe I'm just misunderstanding the function.
Title: Re: Getting Focus
Post by: Mark Jones on August 05, 2005, 07:13:39 PM
I thought WM_ACTIVATE was simple enough solution. Whenever your window becomes active, BANG, you get a WM_ACTIVATE message. Unless I missed something? Try this in your main loop:


        .elseif uMsg==WM_ACTIVATE
            invoke Beep,500,500
Title: Re: Getting Focus
Post by: Jimg on August 05, 2005, 07:17:15 PM
Hi Mark-

Yes, I think so too (although it's a little more complicated than that, I seem to get activates at odd-ball times not just when the focus returns to me).  I was just trying to respond to Paul and not doing a very good job of it.
Title: Re: Getting Focus
Post by: PBrennick on August 06, 2005, 12:50:09 AM
Jimg,
I don't mind whose method you use and Mark is a good coder.  But remember one thing, according to what you want to do you will be running some kind of loop no matter what method you use and it 'does' tell you.  You just are not understanding what I am saying.  You do not add another loop.  The message loop you are already using is good enough.  All I am saying is you can be doing anything you want and then if your message loop tells you there is a message, see if your window has focus.  The reason this is better than WM_ACTIVATE is because for 'this particular test' you do not carewhat uMsg contains.  All you care is if it contains something.  Then and only then, you issue a GetFocus and compare it to the handle of your message.  The normal loop processor will handle the contents of uMsg.  If you decide to use Marks method, there are problems with it.  If your window has focus and the screensaver fires, it will lose focus.  When the screensaver shuts down, your window will regain focus as it was the last window to have focus before the event.  When this happens WM_ACTIVATE will trigger a message and you will respond to an improper event.  Read every thing you can and then try the methods that make sense to you.  We just want to help.

Paul
Title: Re: Getting Focus
Post by: Mark Jones on August 06, 2005, 01:07:12 AM
Quote from: PBrennick on August 06, 2005, 12:50:09 AM
Jimg,
I don't mind whose method you use and Mark is a good coder.

Ha! Thanks Paul, but I think you should reserve "good" for someone with some actual skillz. :bg

Quote...When this happens WM_ACTIVATE will trigger a message and you will respond to an improper event.  Read every thing you can and then try the methods that make sense to you.  We just want to help.

Indeed. WM_ACTIVATE just seemed simple to use, but it's bound to have its share of issues. Still, in the land of endless oodles and oodles of code, simple is good. :)
Title: Re: Getting Focus
Post by: Jimg on August 06, 2005, 01:32:00 AM
Ok, let's see if I got this right-

Marks method:  ( this is currently working)

DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    .if uMsg == WM_COMMAND
        mov eax,wParam  ; identifier of the control, or accelerator
        .if eax==WM_USER+3
            PrintText "Time to doit"
        .endif
    .elseif uMsg==WM_ACTIVATE
        mov eax,wParam
        .if ax==WA_ACTIVE || ax==WA_CLICKACTIVE
            inv PostMessage,hWnd,WM_COMMAND,WM_USER+3,0 ; send me a message when everything else is settled
        .endif
    .else


Pauls Method:

DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    ; I'm here because there is a uMsg so before I check what it is, do this every time, for the thousands of messages I get
.data
InFocusFlag dd 0
.code
     invoke GetFocus
     .if eax==hWnd   ; then it's me
        .if InFocusFlag==1 then   ; I didn't have focus for a while
            inv PostMessage,hWnd,WM_COMMAND,WM_USER+3,0 ; send me a message to take care of business when all else is settled
            mov InFocusFlag,0    ; reset the flag
        .endif
    .else    ; it's not me
        mov InFocusFlag,1    ; flag that I lost focus
    .endif
    ; now do normal message processing           
    .if uMsg == WM_COMMAND
Title: Re: Getting Focus
Post by: PBrennick on August 06, 2005, 02:31:35 PM
Jimg,
If Mark's method is working, I say 'If it is not broke, don't fix it.'  And be sure to say thanks to Mark.  :U

BTW, I see you got the point I was trying to make...
Paul