HOWTO: Remove Focus from a Control When Mouse Released Outside

ID: Q66947


The information in this article applies to:


SUMMARY

Under normal circumstances, when you move the mouse cursor into the client area of a child-window control, click it, and then release the mouse button, the child window sends a WM_COMMAND message to its parent and retains the focus.

If you move the mouse into the client area of the child-window control, press the mouse button, move the mouse cursor out of the client area of the control, and then release the mouse button, the control does not send a WM_COMMAND message. However, the control retains the focus.

If you do not want the control to retain the focus, you can remove it by performing the following steps:

  1. Define a static Boolean flag in the parent window function.


  2. When a WM_PARENTNOTIFY message is received, set the flag to TRUE. This indicates that the mouse button has been pressed while the mouse cursor is in the client area of the control.


  3. If a WM_COMMAND message is received, reset the flag to FALSE and perform normal processing.


  4. Otherwise, if a WM_MOUSEMOVE message is received, the mouse button was released after the mouse cursor was moved outside the control. Reset the flag to FALSE, and use SetFocus() to move the focus to the desired window.



MORE INFORMATION

When the mouse cursor is in the client area of a control and you press the mouse button, the parent window will receive a WM_PARENTNOTIFY message and a WM_MOUSEACTIVATE message. A Boolean (BOOL) flag should be set when the message is processed to indicate that this occurred.

The parent window will receive other messages, including a number of WM_CTLCOLOR messages, when the mouse is moved around with the mouse button down. When the mouse button is released, the parent window receives only one of two messages:

  1. WM_COMMAND: The mouse button was released over the control.


  2. WM_MOUSEMOVE: The mouse button was released outside the control.


Note that these are not the only messages received when the button is released, but these two are mutually exclusive.

In response to either message, the following steps must take place:
  1. Reset the flag indicating a mouse press.


  2. Call SetFocus() or send a WM_KILLFOCUS to the control in question to move the focus as desired.


If WM_KILLFOCUS is used, the ID of the control or its handle must be known. SetFocus(NULL) or SetFocus(hWndParent) removes the focus from the control but does not set the focus to any other control in the window.

In a dialog box, SetFocus(NULL) MUST be used. SetFocus(hDlg) does not remove the focus from the button.

The following code sample is taken from the dialog box procedure of a dialog that has a single OK button. If the mouse button is pressed while the mouse cursor is over the button, the mouse is moved outside the button, and then the mouse button is released, the focus is removed from the OK button.

   BOOL FAR PASCAL AboutProc(HWND hDlg, unsigned iMessage,
                             WORD wParam, LONG lParam)
    {
    static BOOL fMousePress;

    switch (iMessage)
        {
        case WM_INITDIALOG:
            fMousePress = FALSE;
            return TRUE;

        case WM_PARENTNOTIFY:  // or WM_MOUSEACTIVATE
            fMousePress = TRUE;
            break;

        case WM_MOUSEMOVE:
            if (fMousePress)
                SetFocus(NULL);
            fMousePress = FALSE;
            break;

        // Only command is the OK button.
        case WM_COMMAND:
            if (wParam == IDOK)
                EndDialog(hDlg, TRUE);
            break;
        }
    return FALSE;
    } 

Additional query words: win16sdk


Keywords          : kbcode kbCtrl kbNTOS kbGrpUser kbWinOS 
Version           : 
Platform          : 
Issue type        : kbhowto 

Last Reviewed: March 6, 1999