Steps to Reproduce the Behavior
NOTE: These steps are written for Microsoft Visual C++ 6.0.
- Use the following code to create the frameset page, and then name the page frameset.htm:
<HTML>
<FRAMESET rows="100%" cols="33%,33%,34%">
<FRAME src="framesetChild.htm" frameborder="0" scrolling="0">
</FRAME>
<FRAME src="framesetChild.htm" frameborder="0" scrolling="0">
</FRAME>
<FRAME src="framesetChild.htm" frameborder="0" scrolling="0">
</FRAME>
</FRAMESET>
</HTML>
- Copy frameset.htm to the Web server.
- Use the following code to create a frame page, and then name the page framesetChild.htm:
<HTML>
<body>
This is a frame<br>
</body>
</HTML>
- Copy framesetChild.htm to the Web server.
- Create a default Microsoft Foundation Classes (MFC) dialog-based application.
- Right-click the dialog, and then click Insert ActiveX Control. Click Microsoft Web Browser Control.
- To add a control data member for the WebBrowser control, follow these steps:
- Open the Class Wizard, and then click the Member Variables tab.
- Make sure that the dialog class is selected in the Class name list.
- Click IDC_EXPLORER1 (which is the default ID of the WebBrowser control), and then click Add Variable.
- You receive a message that states that the control has not been inserted into the project. Click OK to add the control to the project. Click OK again to accept the defaults for the CWebBrowser2 class in the Confirm Class dialog box.
- Name your member variable m_webBrowser, and then click OK.
- Close the Class Wizard.
- To add the BeforeNavigate2 event handler, follow these steps:
- Open the Class Wizard, and then click the Message Maps tab.
- Make sure that the dialog class is selected in the Class name list.
- Click IDC_EXPLORER1 in the Object IDs list, and then click BeforeNavigate2 in the Messages list.
- Click Add Function to add the handler.
- Add the following code:
void CMFCReproDlg::OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
{
static int nCount = 0;
nCount++;
if (nCount == 2) // this should be the navigate for the first frame in frameset
{
IWebBrowser* pWB = NULL;
HRESULT hr = pDisp->QueryInterface(IID_IWebBrowser, (void**)&pWB);
COleVariant ve((long)0);
pWB->Navigate(::SysAllocString(L"http://myserver/mydirectory/framesetChild.htm"), &ve, &ve, &ve, &ve);
*Cancel = VARIANT_TRUE;
}
}
- Add the following code to navigate to the frame page in the end of the OnInitDialog function.
BOOL CMFCReproDlg::OnInitDialog()
{
...
m_webBrowser.Navigate("http://myserver/mydirectory/frameset.htm", NULL, NULL, NULL, NULL);
- Build the application, and then run it. Notice that the first frame has a scroll bar and a border on the right side.
Remove the Scroll Bar
To remove the scroll bar, use one of following methods:
- Add scroll attribute value of "auto" or "no" to the framesetChild.htm page as follows:
<HTML>
<body scroll="auto">
This is a frame<br>
</body>
</HTML>
- Dynamically add the scroll attribute value of "auto" or "no" in your code through DHTML as follows:
#include <mshtml.h>
// For brevity, this code adds the attribute to all documents.
void CMFCReproDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL)
{
HRESULT hr = S_OK;
IWebBrowser2* pWB = NULL;
hr = pDisp->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&pWB));
IDispatch* pDocDisp = NULL;
hr = pWB->get_Document(&pDocDisp);
if (pDocDisp)
{
VARIANT v;
VariantInit(&v);
IHTMLDocument2* pDoc = NULL;
hr = pDocDisp->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void **>(&pDoc));
IHTMLElement* pElement = NULL;
hr = pDoc->get_body(&pElement);
IHTMLBodyElement* pBodyElement = NULL;
hr = pElement->QueryInterface(IID_IHTMLBodyElement, (void**)&pBodyElement);
if (pBodyElement)
{
pBodyElement->put_scroll(::SysAllocString(L"auto"));
pBodyElement->Release();
}
pElement->Release();
pDoc->Release();
pDocDisp->Release();
}
pWB->Release();
}
NOTE: These first two options only remove the scroll bar. The border may still persist. - Post a user-defined message, and then perform the navigation in the user-defined message handler to delay the navigation.
Add the following code to the header file:
class CMFCReproDlg : public CDialog
{
...
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
};
Add the following code to the implementation file:
#define WM_MYMESSAGE (WM_USER + 1)
BEGIN_MESSAGE_MAP(CMFCReproDlg, CDialog)
//{{AFX_MSG_MAP(CMFCReproDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()
struct CMyData
{
IWebBrowser2* m_pWB;
BSTR m_pUrl;
};
void CMFCReproDlg::OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
{
static int nCount = 0;
nCount++;
if (nCount == 2) // this should be the navigate for the first frame in frameset
{
*Cancel = VARIANT_TRUE;
CMyData *data = new CMyData;
HRESULT hr = pDisp->QueryInterface(IID_IWebBrowser2, (void**)(&data->m_pWB));
data->m_pUrl = ::SysAllocString(L"http://myserver/mydirectory/framesetChild.htm");
PostMessage(WM_MYMESSAGE, (WPARAM)data, 0);
}
}
LRESULT CMFCReproDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
CMyData *data = (CMyData*)wParam;
COleVariant ve((long)0);
data->m_pWB->Navigate(data->m_pUrl, &ve, &ve, &ve, &ve);
delete data;
return 1;
}
Remove the Border
To remove the borders, use one of following methods:
- Post a user-defined message, and then perform the navigation in the user-defined message handler.
- Follow the steps in Microsoft Knowledge Base article Q196835 to provide the custom control site in which you can add the IDocHostUIHandler interface.
For additional information, click the article number below
to view the article in the Microsoft Knowledge Base:
196835 HOWTO: Override the MFC Default Control Containment
After you implement all the functions, you must add DOCHOSTUIFLAG_NO3DBORDER to the DOCHOSTUIINFO stucture in the dwFlags field for the GetHostInfo method. It is beyond the scope of this article to provide the steps to implement IDocHostUIHandler.
NOTE: The border problem does not appear in an Active Template Library (ATL) container because the ATL class,
CAxHostWindow, already implements the
IDocHostUIHandler interface. By default,
CAxHostWindow enables this flag.