第9回 「タブ」の右クリックメニューを実装する (タブブラウザーを作る)

tabbrowser33.gif
今回はタブブラウザーの「タブ」部分で右クリックをしたときのメニュー表示機能を実装する。

まずはメニューリソースを作る。前回までに作成した作成したプロジェクトで「リソース」ウインドウを開き、Visual Studioの「プロジェクト」メニューから「リソースの追加」を選択する。

tabbrowser34.gif
「リソースの追加」ダイアログが開いたら「Menu」を選択して「新規作成」ボタンを押す。

tabbrowser35.gif
そして右クリック用のメニューリソースを作る。「タブの右クリック」というダミー項目を作り、その下に実際に右クリックメニューとして利用する「タブを閉じる」と「最新の状態に更新」の2つのメニューを作る。

tabbrowser36.gif
デフォルトのままだとメニューリソースのIDが「IDC_MENU1」のようになっているので、これを「プロパティ」ウインドウで「IDM_TAB」に変更する。

tabbrowser37.gif
さらに「タブを閉じる」は「ID_WINDOW_CLOSE」に、「最新の状態に更新」は「ID_IE_REFRESH」にそれぞれ変更する。

これでメニューリソースの準備が整った。

tabbrowser38.gif 次にソリューションウインドウで「MainFrm.h」をダブルクリックして開き、タブで右クリックされたときに届く「TBVN_CONTEXTMENU」用のメッセージハンドラと処理を追加する。 右クリックメニューを実際に表示するTrackPopupMenuを呼ぶときは、フラグでTPM_RETURNCMDを指定して関数内で選択されたメニューの処理している。これを指定せずにこのウインドウのメッセージハンドラに処理させると、アクティブでないタブの上の右クリックで「タブを閉じる」を選択したときであっても、アクティブなタブが閉じてしまうなどの不具合が生じるためだ。
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_DNP_CHANGEFOCUS, OnDnpChangeFocus)
		NOTIFY_CODE_HANDLER(CBEN_ENDEDIT, OnAddressbarEnter)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
		COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
		COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
		COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
		COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
		COMMAND_ID_HANDLER(ID_IE_BACK, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_NEXT, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_STOP, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_REFRESH, OnIECommand)
		NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnTabContextMenu)		//■追加
		CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()


	//■追加
	//タブ右クリックメニューの表示
	LRESULT OnTabContextMenu(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
	{
		if(pnmh == NULL)
			return	0;

		int		nPage = pnmh->idFrom;		//メニューが表示されたタブ
		UINT	nCmd;
		BOOL	ret;
		CMenu	cMenu;
		CMenu	cSubMenu;
		POINT	pt;
		CTabBrowser100View*	pView;

		pView = (CTabBrowser100View*)m_view.GetPageData(nPage);
		if(pView == NULL)
			return	0;		//ビューが取得できなかった

		ret = cMenu.LoadMenu(IDM_TAB);		//メニューリソースからメニューを読み込む
		if(ret == FALSE)
			return	0;						//メニュー取得失敗

		::GetCursorPos(&pt);				//マウスカーソル位置取得

		nCmd = 0;
		cSubMenu = cMenu.GetSubMenu(0);
		if(cSubMenu.m_hMenu)
			nCmd = (UINT)cSubMenu.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN,pt.x,pt.y,m_hWnd);	//メニュー表示
		if(nCmd == 0)
			return	0;		//メニューが選択されなかった

		//選択されたメニューコマンドの処理
		switch(nCmd)
		{
		case	ID_WINDOW_CLOSE:	//タブを閉じる
			m_view.RemovePage(nPage);
			break;

		case	ID_IE_REFRESH:		//更新
			pView->Refresh();
			break;

		default:
			ATLASSERT(0);		//サポートされていないコマンド
			break;
		}

		return	0;
	}

tabbrowser39.gif
これでタブ上で右クリックするとメニューが表示され、「タブを閉じる」などの処理ができるようになった。

次回はInternet Exploreのお気に入りをこのタブブラウザから使えるようにする。

プロジェクトファイルをダウンロード


カテゴリー「タブブラウザーを作る」 のエントリー