Link to home
Start Free TrialLog in
Avatar of chris rrr
chris rrrFlag for United States of America

asked on

set dialog focus for next mouse event

I have an dialog that when I click on a static control (bitmap) it starts a timer that calculate the position of the mouse pointer (even when it is not over my dialog). Then I have a test in my timer func thats checks if mouse up has occured. When this occures I am killing the timer and getting the mouse coords.

The problem is, that in order for me to click in the staticControl again to start my timer, I first have to click somwhere in the dialog to set the focus to the window. I have tried to uses mouse_event() to simulate the click in the window, and I have tried to use SetFocus(). None of this seems to help.

Any Ideas?
Avatar of KurtVon
KurtVon

Err, so you mean that you are trying to find the place the person clicked, but not blocking the click?  That would mean the place they clicked had focus, and so you have to refocus the dialog with the timer by clicking on it.  Right?

If this is what you mean, the problem is that the set focus to the new dialog takes place after your handling of the button up.  What you need to do is give your timer dialog a handler for the WM_USER message, and have the handler call SetFocus.  Then just use PostMessage to post the WM_USER message to the dialog.

This way the whole post-mouse-click stuff happens before you return focus to your dialog.

Hope this helps.
Avatar of chris rrr

ASKER

KurtVon,

Sorry this is very confusing.
I wish I could explain it easier. I think you understand except there is one thing that you said which makes me wonder.

>>If this is what you mean, the problem is that the set focus to the new dialog takes place
>>after your handling of the button up.

There is no new dialog.

Basically my program works just like spy++ (find window) . when I click and drag from my dialog I actually get the window handle of the dialog from my mouse position. When I MouseUP , I stop the timer and use that window handle that the mouse is on.
OnTimer()
{...
     if(!GetKeyState(VK_LBUTTON ) )
     {      
      ::SetFocus(m_hWnd);
      KillTimer(111);
     }
...
}
The problem is that once I release the MouseButton(L) & I am over another window, My first click in my dialog appears to just set the dialogs focus. Then On the second click I can start the drag action over again.....hmmmm wait......
If I don't click on the dialog first, the drag action still works, but somehow my GetKeyState() function in the timer doesn't pick up my mouse button action.....

OK does this shed more light on the problem....?
Hope so.
If your Idea above still sounds good to you, can you help make it sound good to me....maybe some simple code snips or somethng...I am just a bit confused.

Thanks
...
Increase points from 125 - 200

reason(Confusion Factor)
So when does your dialog lose focus?  When the drag starts, or when the mouse goes up?  Or is it only when the timer expires?

From what you describe, it might be better to add a bool variable to the dialog, and set that when the drag starts, clear it when the mouse up happens.  This is probably safer anyway since the mouse up can get missed and then the timer is never killed if you rely just on the current button state.
Oh, and don't forget to kill the timer in the mouse up, since if you don't, the next timer action may be overridden if the timer hadn't expired yet (since it is still "live").  In that case you don't need the bool since if the timer expires the mouse up must not have happened or it would already have been killed.

Sorry if this is confusing.
I already have 2 different bools that handle this.
m_Drag;
m_MsUp;

But the timer has to set them so they actually reside in the if(!GetKeyState(VK_LBUTTON ) ) statements. (shown above)

As far as the dialog losing focus. I don't see it loose focus it just seems to. Actually it visually looks like it has focus.
 I also do this:
//m_Window is the new CWnd *handle that I get when the mouse is released

m_Window->SetWindowPos(&wndNoTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(&wndNoTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

this brings the window selected to the front and then brings the dialog back to the front also. So in theory it should have the focus.

Is it possible for the mouse to need to be reset or something...I am pretty new to C++?
Well, if you did a SetCapture, and didn't do a ReleaseCapture the mouse will be in a goofy state.  Iseem to remember button-ups getting absorbed in certain circumstances, and you have to click the mouse just to clear the button state.

I'm not clear on Something, though.

The user clicks down and starts the drag.
    You capture mouse movement and start a timer.
The user Moves the mouse over a new window
The User releases the mouse button
    (1) You do your window swap and (I assume) record some information for whatever the dialog really does.
The timer expires.
    (2) If the mouse is released do nothing
    (3) If the mouse is not released, clear some bools and kill the timer.

Now, here are the things you might be doing, and if not that may be what to look for:

  At (1) you shoul release the mouse capture
  At (1) you should reset the flags and kill the timer
  If you do the above, (2) is unnecesary since any timer event must mean the mouse never went button up.
  At (3), instead of checking if the button is not up, check if the drag flag was never cleared -- actually you can just assert this since it should not have been cleared if the timer actually timed out.
I revised your list to try and clear things up

OK - The user clicks down and starts the drag.
NO - Start a timer to capture mouse movement. and tests if mouse is down. (you had it backwards, just want to be clear)
OK - The user Moves the mouse over a new window.
OK - The User releases the mouse button (when the mouse is not down than timer test kills the timer )

The timer expires.
OK -  (1) You do your window swap and (I assume) record some information for whatever the dialog really does.

--------------  main action is done. --------------------
 if you try to go through the drag sequence again : 2 possibilities
       (a) click and drag - this resets my bools & starts the timer again and you can see it capturing the mouse movement.
              but when you release this time. It doesn't get the mouse release and capture the window. It instead keeps  captureing the mouse position. (if I actually click on the window it works fine)

       (b) if you click on the dialog, then click and drag it works perfectly.

how do I release capture the mouse?

FYI-
All I am doing in the timer is getting the mouse coords and testing to see if the mouse is down. If it is not down, then I know that the user has released it and I kill the timer and do my stuff.
I am using a virtual key function since it seemed the only way, does this need released? If so How?:
...in timer func....
if(!GetKeyState(VK_LBUTTON ) )
     {    
           KillTimer(111);
     }
ASKER CERTIFIED SOLUTION
Avatar of KurtVon
KurtVon

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I didn't know about set capture or Release Capture.

Let me try this in my app and make sure there are no problems....
Seems to work in my tests.

Thanks.
Excellent !!!

I didn't know how to keep captureing the mouse position once my mouse left the dialog....that is why I was using the timer.

I was never totally happy with this Idea, but it was all I could think of.

SetCapture and ReleaseCapture    are exactly what I needed.

Thanks for your patients.

Chris
It didn't actually solve the problem I was having, but it did lead to a better solution.
Ah, I thought you were using SetCapture and just using the timer to expire capturing the mouse if the user took too long to pick a window.

Glad to help.