// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////

#pragma once

#define WINDOW_MENU_POSITION	3


class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
		public CMessageFilter, public CIdleHandler
{
public:
	DECLARE_FRAME_WND_CLASS(_T("TabBrowser_MainFrame"), IDR_MAINFRAME)

// Data members
	CCommandBarCtrl m_CmdBar;
	CCustomTabView m_view;
	CAddressComboBox m_cb;

	CString m_strHomePage;

// CMessageFilter
	virtual BOOL PreTranslateMessage(MSG* pMsg)
	{
		if(ProcessComboReturnKey(pMsg) != FALSE)
			return TRUE;

		if(m_view.PreTranslateMessage(pMsg) != FALSE)
			return TRUE;

		return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
	}

	BOOL ProcessComboReturnKey(MSG* pMsg)
	{
		BOOL bRet = FALSE;

		if(IsPageActive() && (pMsg->hwnd == m_cb.m_hWnd || ::IsChild(m_cb.m_hWnd, pMsg->hwnd)))
		{
			if((pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) && pMsg->wParam == VK_RETURN)
			{
				CString str;
				int nLen = m_cb.GetWindowTextLength();
				m_cb.GetWindowText(str.GetBuffer(nLen), nLen + 1);
				str.ReleaseBuffer();
				str.TrimLeft();
				str.TrimRight();

				if(!str.IsEmpty())
				{
					if(pMsg->message == WM_SYSKEYDOWN)
					{
						OpenPage(str, true);
					}
					if(GetKeyState(VK_CONTROL) < 0)
					{
						CString strExp;
						strExp.Format(_T("http://www.%s.com"), (LPCTSTR)str);

						m_cb.SetWindowText(strExp);
						OpenPage(strExp, false);
					}
					else
					{
						OpenPage(str, false);
					}
				}

				bRet = TRUE;
			}
		}

		return bRet;
	}

// CIdleHandler
	virtual BOOL OnIdle()
	{
		bool bActive = IsPageActive();

		bool bCanGoBack = false;
		bool bCanGoForward = false;

		if(bActive)
		{
			CBrowserView* pView = (CBrowserView*)m_view.GetPageData(m_view.GetActivePage());
			bCanGoBack = pView->m_bCanGoBack;
			bCanGoForward = pView->m_bCanGoForward;
		}

		UIEnable(ID_BROWSER_BACK, bActive && bCanGoBack);
		UIEnable(ID_BROWSER_FORWARD, bActive && bCanGoForward);
		UIEnable(ID_BROWSER_STOP, bActive);
		UIEnable(ID_BROWSER_REFRESH, bActive);
		UIEnable(ID_BROWSER_HOME, bActive);
		UIEnable(ID_BROWSER_SEARCH, bActive);

		UIEnable(ID_WINDOW_CLOSE, bActive);
		UIEnable(ID_WINDOW_CLOSE_ALL, bActive);

		UIEnable(ID_WINDOW_SHOW_VIEWS, bActive);

		UIEnable(ID_GO, bActive);

		UIUpdateToolBar();

		m_cb.EnableWindow(bActive ? TRUE : FALSE);

		return FALSE;
	}

// Methods
	bool GetHomePage()
	{
		LPCTSTR lpstrHomePageRegKey = _T("Software\\Microsoft\\Internet Explorer\\Main");
		LPCTSTR lpstrHomePageRegValue = _T("Start Page");

		ATL::CRegKey rk;
		LONG lRet = rk.Open(HKEY_CURRENT_USER, lpstrHomePageRegKey);
		ATLASSERT(lRet == ERROR_SUCCESS);
		if(lRet != ERROR_SUCCESS)
			return false;

#if (_ATL_VER >= 0x0700)
		ULONG ulLength = 0;
		lRet = rk.QueryStringValue(lpstrHomePageRegValue, NULL, &ulLength);
		if(lRet == ERROR_SUCCESS)
			lRet = rk.QueryStringValue(lpstrHomePageRegValue, m_strHomePage.GetBuffer(ulLength), &ulLength);
#else
		DWORD dwLength = 0;
		lRet = rk.QueryValue(NULL, lpstrHomePageRegValue, &dwLength);
		if(lRet == ERROR_SUCCESS)
			lRet = rk.QueryValue(m_strHomePage.GetBuffer(dwLength / sizeof(TCHAR)), lpstrHomePageRegValue, &dwLength);
#endif
		ATLASSERT(lRet == ERROR_SUCCESS);
		m_strHomePage.ReleaseBuffer();

		return (lRet == ERROR_SUCCESS);
	}

	bool IsPageActive() const
	{
		return (m_view.GetActivePage() != -1);
	}

	IWebBrowser2* GetBrowser(int nPage) const
	{
		CAxWindow wnd = m_view.GetPageHWND(nPage);

		CComPtr<IWebBrowser2> spWebBrowser;
		HRESULT hRet = wnd.QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser);
		hRet;   // avoid level 4 warning
		ATLASSERT(SUCCEEDED(hRet));

		return spWebBrowser;
	}

	void OpenPage(LPCTSTR lpstrURL, bool bNewTab)
	{
		CString strLoading;
		strLoading.LoadString(IDS_LOADING);

		bool bSuccess = false;

		if(bNewTab)
		{
			CBrowserView* pView = new CBrowserView;
			pView->Create(m_view, rcDefault, lpstrURL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL);
			if(pView->IsWindow())
				bSuccess = m_view.AddPage(pView->m_hWnd, strLoading, 0, pView);
		}
		else
		{
			m_view.SetPageTitle(m_view.GetActivePage(), strLoading);

			CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(m_view.GetActivePage());
			if(spWebBrowser != NULL)
			{
				CComVariant vtURL(lpstrURL);
				CComVariant vt;
				HRESULT hRet = spWebBrowser->Navigate2(&vtURL, &vt, &vt, &vt, &vt);
				bSuccess = SUCCEEDED(hRet);
			}
		}

		if(!bSuccess)
		{
			CString strError;
			strError.LoadString(IDS_OPEN_ERROR);
			strError += lpstrURL;
			CString strTitle;
			strTitle.LoadString(IDR_MAINFRAME);
			MessageBox(strError, strTitle, MB_OK | MB_ICONERROR);
		}
	}

	void BuildLinksToolbar(HWND hWndToolBar)
	{
		CToolBarCtrl tb = hWndToolBar;

		tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS);

		// add links buttons
		CString strTitle;
		strTitle.LoadString(ID_LINKS_MICROSOFT);
		tb.AddButton(ID_LINKS_MICROSOFT, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
		strTitle.LoadString(ID_LINKS_MSDN);
		tb.AddButton(ID_LINKS_MSDN, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
		strTitle.LoadString(ID_LINKS_LIVE);
		tb.AddButton(ID_LINKS_LIVE, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
		strTitle.LoadString(ID_LINKS_UPDATE);
		tb.AddButton(ID_LINKS_UPDATE, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
		strTitle.LoadString(ID_LINKS_WTL);
		tb.AddButton(ID_LINKS_WTL, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);

		// delete initial button (not used)
		tb.DeleteButton(0);
	}

	void DeactivateHTMLPage()
	{
		if(IsPageActive())
		{
			CAxWindow wnd = m_view.GetPageHWND(m_view.GetActivePage());
			CComPtr<IOleInPlaceObject> spInPlaceObject;
			HRESULT hRet = wnd.QueryControl(IID_IOleInPlaceObject, (void**)&spInPlaceObject);
			ATLASSERT(SUCCEEDED(hRet));
			if(spInPlaceObject != NULL)
			{
				hRet = spInPlaceObject->UIDeactivate();
				ATLASSERT(SUCCEEDED(hRet));
			}
		}
	}

// Update UI map
	BEGIN_UPDATE_UI_MAP(CMainFrame)
		UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ADDRESS_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_LINKS_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_LOCK_TOOLBARS, UPDUI_MENUPOPUP)

		UPDATE_ELEMENT(ID_BROWSER_BACK, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_BROWSER_FORWARD, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_BROWSER_STOP, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_BROWSER_REFRESH, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_BROWSER_HOME, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_BROWSER_SEARCH, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)

		UPDATE_ELEMENT(ID_GO, UPDUI_TOOLBAR)

		UPDATE_ELEMENT(ID_WINDOW_CLOSE, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_WINDOW_CLOSE_ALL, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
	END_UPDATE_UI_MAP()

// Message map and handlers
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)

		MESSAGE_HANDLER(WM_BROWSERTITLECHANGE, OnBrowserTitleChange)
		MESSAGE_HANDLER(WM_BROWSERDOCUMENTCOMPLETE, OnBrowserDocumentComplete)
		MESSAGE_HANDLER(WM_BROWSERSTATUSTEXTCHANGE, OnBrowserStatusTextChange)

		MESSAGE_HANDLER(WM_COMBOMOUSEACTIVATE, OnComboMouseActivate)

		CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)

		COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
		COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
		COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen)

		COMMAND_ID_HANDLER(ID_BROWSER_BACK, OnBrowserNavigate)
		COMMAND_ID_HANDLER(ID_BROWSER_FORWARD, OnBrowserNavigate)
		COMMAND_ID_HANDLER(ID_BROWSER_STOP, OnBrowserNavigate)
		COMMAND_ID_HANDLER(ID_BROWSER_REFRESH, OnBrowserNavigate)
		COMMAND_ID_HANDLER(ID_BROWSER_HOME, OnBrowserNavigate)
		COMMAND_ID_HANDLER(ID_BROWSER_SEARCH, OnBrowserNavigate)

		COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
		COMMAND_ID_HANDLER(ID_VIEW_ADDRESS_BAR, OnViewAddressBar)
		COMMAND_ID_HANDLER(ID_VIEW_LINKS_BAR, OnViewLinksBar)
		COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
		COMMAND_ID_HANDLER(ID_VIEW_LOCK_TOOLBARS, OnViewLockToolbars)

		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
		COMMAND_ID_HANDLER(ID_NEXT_PANE, OnNextPrevPane)
		COMMAND_ID_HANDLER(ID_PREV_PANE, OnNextPrevPane)

		COMMAND_ID_HANDLER(ID_LINKS_MICROSOFT, OnLinks)
		COMMAND_ID_HANDLER(ID_LINKS_MSDN, OnLinks)
		COMMAND_ID_HANDLER(ID_LINKS_LIVE, OnLinks)
		COMMAND_ID_HANDLER(ID_LINKS_UPDATE, OnLinks)
		COMMAND_ID_HANDLER(ID_LINKS_WTL, OnLinks)

		COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
		COMMAND_ID_HANDLER(ID_WINDOW_SHOWTABLIST, OnShowWindows)

		NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabViewPageActivated)
		NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnTabViewContextMenu)

		NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnTBDropDown)
		COMMAND_ID_HANDLER(ID_GO, OnGo)

		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()

	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// create command bar window
		HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
		// attach menu
		m_CmdBar.AttachMenu(GetMenu());
		// load command bar images
		m_CmdBar.SetImageMaskColor(RGB(255, 0, 255));
		m_CmdBar.LoadImages(IDR_MAINFRAME);
		m_CmdBar.LoadImages(IDR_TABTOOLBAR);
		// remove old menu
		SetMenu(NULL);

		// create toolbar
		HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME_BIG, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

		// create rebar
		CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
		AddSimpleReBarBand(hWndCmdBar);
		AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

		// create address bar combo
		RECT rcCombo = { 0, 0, 1, 300 };
		m_cb.Create(m_hWnd, rcCombo, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBS_DROPDOWN | CBS_AUTOHSCROLL);
		m_cb.SetFont(AtlGetDefaultGuiFont());

		CString strAddress;
		strAddress.LoadString(IDS_ADDRESS);
		AddSimpleReBarBand(m_cb, strAddress, FALSE, 10000);
		SizeSimpleReBarBands();

		// create links bar
		HWND hWndToolBarLinks = CreateSimpleToolBarCtrl(m_hWnd, IDB_PAGEIMAGE, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST);
		BuildLinksToolbar(hWndToolBarLinks);
		CString strLinks;
		strLinks.LoadString(IDS_LINKS);
		AddSimpleReBarBand(hWndToolBarLinks, strLinks);

		CReBarCtrl rebar = m_hWndToolBar;
		rebar.LockBands(true);

		CreateSimpleStatusBar();

		// create tab view
		m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
		m_view.SetTitleBarWindow(m_hWnd);

		// Set up update UI stuff
		UIAddToolBar(hWndToolBar);
		UIAddToolBar(m_cb.m_tb);

		UISetCheck(ID_VIEW_TOOLBAR, 1);
		UISetCheck(ID_VIEW_STATUS_BAR, 1);
		UISetCheck(ID_VIEW_ADDRESS_BAR, 1);
		UISetCheck(ID_VIEW_LINKS_BAR, 1);
		UISetCheck(ID_VIEW_LOCK_TOOLBARS, 1);

		UISetBlockAccelerators(true);

		// register object for message filtering and idle updates
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		pLoop->AddIdleHandler(this);

		// set tab view image list
		CImageList il;
		il.CreateFromImage(IDB_PAGEIMAGE, 16, 1, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
		m_view.SetImageList(il);

		// srt up window menu
		m_view.m_bWindowsMenuItem = true;
		CMenuHandle menuMain = m_CmdBar.GetMenu();
		m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));

		// get home page address
		bool bRet = GetHomePage();
		if(!bRet)
		{
			ATLTRACE(_T("TabBrowser: Can't get home page from the registry - using blank page\n"));
			m_strHomePage.LoadString(IDS_BLANK_URL);
		}

		return 0;
	}

	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		// unregister object for message filtering and idle updates
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->RemoveMessageFilter(this);
		pLoop->RemoveIdleHandler(this);

		bHandled = FALSE;
		return 1;
	}

	LRESULT OnContextMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if((HWND)wParam == m_hWndToolBar || ::IsChild(m_hWndToolBar, (HWND)wParam))
		{
			POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
			CMenu menu;
			menu.LoadMenu(IDR_TOOLBAR_MENU);
			CMenuHandle menuPopup = menu.GetSubMenu(0);
			m_CmdBar.TrackPopupMenu(menuPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y);
		}
		else
		{
			bHandled = FALSE;
		}

		return 0;
	}

	LRESULT OnBrowserTitleChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		HWND hWnd = (HWND)wParam;
		LPCTSTR lpstrTitle = (LPCTSTR)lParam;

		CString strBlank;
		strBlank.LoadString(IDS_BLANK_URL);
		CString strBlankTitle;
		if(lstrcmp(lpstrTitle, strBlank) == 0)
		{
			strBlankTitle.LoadString(IDS_BLANK_TITLE);
			lpstrTitle = (LPCTSTR)strBlankTitle;
		}

		int nIndex = m_view.PageIndexFromHwnd(hWnd);
		m_view.SetPageTitle(nIndex, lpstrTitle);

		return 0;
	}

	LRESULT OnBrowserDocumentComplete(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		LPCTSTR lpstrAddress = (LPCTSTR)lParam;
		m_cb.SetWindowText(lpstrAddress);

		if(m_cb.FindStringExact(-1, lpstrAddress) == CB_ERR)
			m_cb.AddItem(lpstrAddress, -1, -1, 0);

		return 0;
	}

	LRESULT OnBrowserStatusTextChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		LPCTSTR lpstrText = (LPCTSTR)lParam;
		CStatusBarCtrl sb = m_hWndStatusBar;
		sb.SetText(ID_DEFAULT_PANE, lpstrText);

		return 0;
	}

	LRESULT OnComboMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		DeactivateHTMLPage();

		return 0;
	}

	LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		PostMessage(WM_CLOSE);
		return 0;
	}

	LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		OpenPage(m_strHomePage, true);

		return 0;
	}

	LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CString strURL;

		int nActivePage = m_view.GetActivePage();
		if(nActivePage != -1)
		{
			CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(nActivePage);
			ATLASSERT(spWebBrowser != NULL);
			BSTR bstrURL;
			spWebBrowser->get_LocationURL(&bstrURL);
			strURL = bstrURL;
		}

		COpenDlg dlg(strURL);
		if(dlg.DoModal() != IDOK)
			return 0;

		OpenPage(dlg.m_strURL, dlg.m_bNewTab);

		return 0;
	}

	LRESULT OnBrowserNavigate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nActivePage = m_view.GetActivePage();
		if(nActivePage != -1)
		{
			CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(nActivePage);
			ATLASSERT(spWebBrowser != NULL);
			HRESULT hRet = E_FAIL;
			switch(wID)
			{
			case ID_BROWSER_BACK:
				hRet = spWebBrowser->GoBack();
				break;
			case ID_BROWSER_FORWARD:
				hRet = spWebBrowser->GoForward();
				break;
			case ID_BROWSER_STOP:
				hRet = spWebBrowser->Stop();
				break;
			case ID_BROWSER_REFRESH:
				hRet = spWebBrowser->Refresh();
				break;
			case ID_BROWSER_HOME:
				hRet = spWebBrowser->GoHome();
				break;
			case ID_BROWSER_SEARCH:
				hRet = spWebBrowser->GoSearch();
				break;
			default:
				break;
			}
			ATLASSERT(SUCCEEDED(hRet));
		}
		else
		{
			::MessageBeep((UINT)-1);
		}

		return 0;
	}

	LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		static BOOL bVisible = TRUE;	// initially visible
		bVisible = !bVisible;
		CReBarCtrl rebar = m_hWndToolBar;
		int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);	// toolbar is 2nd added band
		rebar.ShowBand(nBandIndex, bVisible);
		UISetCheck(ID_VIEW_TOOLBAR, bVisible);
		UpdateLayout();

		return 0;
	}

	LRESULT OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		static BOOL bVisible = TRUE;	// initially visible
		bVisible = !bVisible;
		CReBarCtrl rebar = m_hWndToolBar;
		int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 2);	// address bar is 2nd added band
		rebar.ShowBand(nBandIndex, bVisible);
		UISetCheck(ID_VIEW_ADDRESS_BAR, bVisible);
		UpdateLayout();

		return 0;
	}

	LRESULT OnViewLinksBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		static BOOL bVisible = TRUE;	// initially visible
		bVisible = !bVisible;
		CReBarCtrl rebar = m_hWndToolBar;
		int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 3);	// links bar is 3rd added band
		rebar.ShowBand(nBandIndex, bVisible);
		UISetCheck(ID_VIEW_LINKS_BAR, bVisible);
		UpdateLayout();

		return 0;
	}

	LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
		::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
		UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
		UpdateLayout();

		return 0;
	}

	LRESULT OnViewLockToolbars(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		static bool bLock = true;	// initially locked
		bLock = !bLock;
		CReBarCtrl rebar = m_hWndToolBar;
		rebar.LockBands(bLock);
		UISetCheck(ID_VIEW_LOCK_TOOLBARS, bLock);

		return 0;
	}

	LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CAboutDlg dlg;
		dlg.DoModal();

		return 0;
	}

	LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nActivePage = m_view.GetActivePage();
		if(nActivePage != -1)
			m_view.RemovePage(nActivePage);
		else
			::MessageBeep((UINT)-1);

		return 0;
	}

	LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		m_view.RemoveAllPages();

		return 0;
	}

	LRESULT OnNextPrevPane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		// we have only two destinations, so there is no need to look at the direction
		HWND hWndFocus = ::GetFocus();
		if(IsPageActive() && (hWndFocus == m_cb.m_hWnd || ::IsChild(m_cb.m_hWnd, hWndFocus)))
		{
			m_view.SetFocus();
		}
		else
		{
			DeactivateHTMLPage();
			m_cb.SetFocus();
		}

		return 0;
	}

	LRESULT OnLinks(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		ATLASSERT(wID >= ID_LINKS_FIRST && wID <= ID_LINKS_LAST);

		UINT nStringID = wID + (ID_LINKS_URL_FIRST - ID_LINKS_FIRST);
		CString strURL;
		strURL.LoadString(nStringID);
		ATLASSERT(!strURL.IsEmpty());

		OpenPage(strURL, !IsPageActive());

		return 0;
	}

	LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nPage = wID - ID_WINDOW_TABFIRST;
		m_view.SetActivePage(nPage);

		return 0;
	}

	LRESULT OnShowWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CWindowsDlg dlg(&m_view);
		dlg.DoModal(m_hWnd);

		return 0;
	}

	LRESULT OnTabViewPageActivated(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		if(pnmh->idFrom != -1)
		{
			CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(pnmh->idFrom);
			ATLASSERT(spWebBrowser != NULL);
			BSTR bstrURL;
			HRESULT hRet = spWebBrowser->get_LocationURL(&bstrURL);
			hRet;   // avoid level 4 warning
			ATLASSERT(SUCCEEDED(hRet));

			USES_CONVERSION;
			m_cb.SetWindowText(OLE2T(bstrURL));
		}
		else
		{
			m_cb.SetWindowText(_T(""));
		}

		return 0;
	}

	LRESULT OnTabViewContextMenu(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		LPTBVCONTEXTMENUINFO lpcmi = (LPTBVCONTEXTMENUINFO)pnmh;
		CMenuHandle menuMain = m_CmdBar.GetMenu();
		CMenuHandle menuPopup = menuMain.GetSubMenu(WINDOW_MENU_POSITION);	// Window sub menu
		int nRet = (int)m_CmdBar.TrackPopupMenu(menuPopup, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_RIGHTBUTTON, lpcmi->pt.x, lpcmi->pt.y);
		if(nRet == ID_WINDOW_CLOSE)
			m_view.RemovePage(pnmh->idFrom);
		else
			SendMessage(WM_COMMAND, MAKEWPARAM(nRet, 0));

		return 0;
	}

	LRESULT OnTBDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		LPNMTOOLBAR lpTB = (LPNMTOOLBAR)pnmh;

		if(lpTB->iItem != ID_WINDOW_SHOW_VIEWS)	// something else
		{
			bHandled = FALSE;
			return 1;
		}

		CToolBarCtrl wndToolBar = pnmh->hwndFrom;
		int nIndex = wndToolBar.CommandToIndex(ID_WINDOW_SHOW_VIEWS);
		RECT rect;
		wndToolBar.GetItemRect(nIndex, &rect);
		wndToolBar.ClientToScreen(&rect);

		CMenu menu;
		menu.CreatePopupMenu();

		m_view.BuildWindowMenu(menu);

		m_CmdBar.TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, rect.left, rect.bottom);

		return TBDDRET_DEFAULT;
	}

	LRESULT OnGo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CString str;
		int nLen = m_cb.GetWindowTextLength();
		m_cb.GetWindowText(str.GetBuffer(nLen), nLen + 1);
		str.ReleaseBuffer();

		str.TrimLeft();
		str.TrimRight();

		if(!str.IsEmpty())
			OpenPage(str, false);

		return 0;
	}
};
