Redmineダウンローダ開発メモ(8) 簡易ビューワーの開発-ひとくぎり - ドナドナされるプログラマのメモの続き。
個別Issueしか開けなかった簡易ビューワーをもとに、複数のIssueを開いたりRedmineプロジェクト全体に対する検索ができる正規ビューワーを作る。
CMFCTabCtrlでのタブコントロール表示方法
複数のIssueを開く機能はタブコントロールで実現する。自分が今まで使ってきたCTabCtrlはドキュメントごとのタブ生成・削除には不向き(タブに「閉じる」アイコンを付けられないなど)なので、今回はCMFCTabCtrl(とベースクラス: CMFCBaseTabCtrl)を使うことにした。
しかし、CMFCTabCtrlはリソースエディタでサポートされていない。そのうえ、CMFCTabCtrlとCTabCtrlは継承関係にないため、普通のタブコントロールを配置したうえでクラスをCMFCTabCtrlにしてもうまくいかない。
以下、変数追加時のクラスをCMFCTabCtrlにした場合の挙動。OnInitDialog内にてタブコントロール変数のm_hWndからCreate()時に登録されたウィンドウクラス名を調べたところ、本来ならAfx:TabWnd:83e70000:8:10003:10みたいになっているはずなのにSysTabControl32となっていた。これはCTabCtrlのCreate()実行時に登録されるウィンドウクラスなので、どうやら変数追加時のクラスをCMFCTabCtrlにしてもDDX_ControlではCTabCtrlのCreate()を呼び出すようだ。だめじゃん。
ということは、DDX_Controlは使わずに手動でOnInitDialog内でCreateすれば解決のはず・・・なのだが、まだ表示されない。少し悩んだあと、描画は非標準コントロールが実施していることに気づき、リソースエディタ上のタブコントロールを「非表示」にしてみた。ビンゴ!無事、CMFCTabCtrlが表示されるようになった。無事解決。
// CMFCTabCtrlの生成 CRect rect; GetDlgItem(IDC_TAB_VIEWER)->GetWindowRect(&rect); ScreenToClient(&rect); if (!m_CtrlTabViewer.Create(CMFCTabCtrl::STYLE_3D, rect, this, IDC_TAB_VIEWER, CMFCTabCtrl::LOCATION_TOP, WS_VISIBLE | WS_CHILD)) { TRACE(_T("Failed to create tab control\n")); return FALSE; }

CMFCTabCtrlのサイズ変更方法
CMFCTabCtrlはOnSize()を受け取ると各タブに登録したCWnd*に対しWM_SIZEを送出し適切な大きさにしてくれる。すばらしい。だがしかし、1点だけ注意事項がある。リソースエディタ上でサイズ調整の種類を「両方」に設定しても、ダイアログサイズ変更時にCMFCTabCtrlへWM_SIZEが飛ばないため、CMFCTabCtrlのOnSize()が呼び出されないのだ。マイクロソフトがCTabViewと無関係に設計したツケがここにも・・・。しょうがないので、ダイアログ側のOnSize()から手動でCMFCTabCtrlの大きさを変更する。すなわち、ダイアログのサイズ変更により自動でサイズ変更されたIDC_TAB_VIEWERからサイズを取得し、CMFTabCtrlへ変更後のサイズを与える。
void CRedmineViewerDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (m_hWnd == NULL || m_CtrlTabViewer.m_hWnd == NULL) return; CRect rect; GetDlgItem(IDC_TAB_VIEWER)->GetWindowRect(&rect); ScreenToClient(&rect); m_CtrlTabViewer.MoveWindow(&rect); }
なお、WebView2と連携させるときは、CMFCTabCtrlに登録したCWnd子クラスより手動でWebView2のput_Bounds()を呼び出す。この時に使うCRect領域情報は、CMFcTabCtrl::GetWndArea()で一発取得できる。楽。
CRect rect; m_pParent->m_CtrlTabViewer.GetWndArea(rect); m_WebViewController->put_Bounds(rect);
次: