Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

PRB: Windowless ATL Control Does Not Receive Focus Messages in Internet Explorer


View products that this article applies to.

This article was previously published under Q318034

↑ Back to the top


Symptoms

When you run Active Template Library (ATL) windowless ActiveX controls in Internet Explorer, you receive the WM_SETFOCUS message, but you do not receive the WM_KILLFOCUS message when you press the TAB key to move out of the control or out of the application.

↑ Back to the top


Cause

By design, Internet Explorer forwards the WM_SETFOCUS message to the windowless ActiveX control, but it does not forward the WM_KILLFOCUS message. The specifications for windowless ActiveX controls (in the IOleInPlaceObjectWindowless::OnWindowMessage method documentation) state that windowless ActiveX control containers do not have to forward either of these messages.

↑ Back to the top


Resolution

You can handle the state changes if you implement the following methods:

  • IOleInPlaceObject::UIDeactivate
  • IOleObject::DoVerb
  • IOleInPlaceActiveObject::OnFrameWindowActivate

↑ Back to the top


More information

This section includes a code sample that you can add to an ATL windowless control. Notice the following features in the code sample:

  • IOleInPlaceObject::UIDeactivate is called if you press TAB or click another control in Internet Explorer. This is where you can handle the equivalent of a WM_KILLFOCUS event.
  • IOleObject::DoVerb is called with OLEIVERB_UIACTIVATE if you press TAB or click your control. You must not call IOleInPlaceSiteWindowless::SetFocus(TRUE) from here because that function calls the DoVerb method and causes a stack overflow.
  • IOleInPlaceActiveObject::OnFrameWindowActivate is called on the user interface (UI) active control whenever the hosting application switches in and out of focus. If you want to receive keyboard messages, you must call IOleInPlaceSiteWindowless::SetFocus(TRUE) when your control is being activated.
  • The OnKeyDown function is added to demonstrate when the keyboard messages are received.
  • The OnLButtonDown function is added to show that you must call the SetFocus method when you click the control. If you do not call SetFocus, you do not receive keyboard messages.
class ATL_NO_VTABLE CAtlFocusTest : 
...
{
public:
...
	STDMETHOD(UIDeactivate)(void)
	{
		ATLTRACE("CAtlFocusTest::UIDeactivate() - handle kill focus event\n");
		return IOleInPlaceObjectWindowlessImpl<CAtlFocusTest>::UIDeactivate();
	}

	STDMETHOD(DoVerb)(LONG iVerb, LPMSG pMsg, IOleClientSite* pActiveSite, LONG lindex,
									 HWND hwndParent, LPCRECT lprcPosRect)
	{
		if (iVerb == OLEIVERB_UIACTIVATE)
		{
			ATLTRACE("CAtlFocusTest::DoVerb(iVerb=%d) - handle set focus event\n", iVerb);
			// Do not call IOleInPlaceSiteWindowless::SetFocus(TRUE) here because
			// it will call DoVerb again!
		}
		else
			ATLTRACE("CAtlFocusTest::DoVerb(iVerb=%d) - handle some other event\n", iVerb);
		return IOleObjectImpl<CAtlFocusTest>::DoVerb(iVerb, pMsg, pActiveSite, lindex, hwndParent, lprcPosRect);
	}

	STDMETHOD(OnFrameWindowActivate)(BOOL fActivate)
	{
		if (fActivate)
		{
			ATLTRACE("CAtlFocusTest::OnFrameWindowActivate(fActivate=%d) - handle set focus event (switching app)\n", fActivate);
			if (m_spInPlaceSite)
				m_spInPlaceSite->SetFocus(TRUE);
		}
		else
		{
			ATLTRACE("CAtlFocusTest::OnFrameWindowActivate(fActivate=%d) - handle kill focus event (switching app)\n", fActivate);
			if (m_spInPlaceSite)
				m_spInPlaceSite->SetFocus(FALSE);
		}
		return IOleInPlaceActiveObjectImpl<CAtlFocusTest>::OnFrameWindowActivate(fActivate);
	}
	LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		ATLTRACE("CAtlFocusTest::OnKeyDown(%d, %d, %d, %d)\n",
			uMsg, wParam, lParam, bHandled);
		return 0;
	}
	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (m_spInPlaceSite)
			m_spInPlaceSite->SetFocus(TRUE);
		return 0;
	}
...
};
				
This code can be added to both the ATL full control and the ATL lite control.

↑ Back to the top


References

For additional information, visit the following MSDN Web site:

↑ Back to the top


Keywords: KB318034, kbprb, kbctrlcreate, kbctrl

↑ Back to the top

Article Info
Article ID : 318034
Revision : 2
Created on : 5/12/2003
Published on : 5/12/2003
Exists online : False
Views : 532