Solution46
CWndDocumentTab.cpp
[詳解]
1 //=============================================================================
2 /// @file
3 /// ドキュメントタブウィンドウクラス実装ファイル
4 ///
5 /// ドキュメントタブウィンドウクラス実装ファイルです。
6 ///
7 /// $Id: CWndDocumentTab.cpp 245 2019-03-20 15:03:41Z admin $
8 /// $Date: 2019-03-21 00:03:41 +0900 (2019/03/21 (木)) $
9 /// $Author: admin $
10 ///
11 /// @attention なし
12 
13 #pragma managed( push, off )
14 
15 //=============================================================================
16 // インクルードファイル
17 #include <CWndDocumentTab.h>
18 #include <LibWindowUtility.h>
19 #include <commctrl.h>
20 #include <algorithm>
21 
22 //=============================================================================
23 // インクルード実装ファイル
24 #include <CArray.hpp>
25 
26 //=============================================================================
27 // ウィンドウライブラリ名前空間
28 namespace LibWindow {
29  //=========================================================================
30  // ドキュメントタブウィンドウクラス
31  //=========================================================================
32  // 構築子と解体子
33  //-------------------------------------------------------------------------
34  // コンストラクタ
35  CWndDocumentTab::CWndDocumentTab( CWndElement* ( *pfnCreateElement )(), wchar_t const* pszElementName ) noexcept
36  // 基底クラスコンストラクタ
37  : CWndContainer( *pfnCreateElement, pszElementName )
38  // メンバ変数初期化
39  , m_cTitleBar()
40  , m_hTabControl( nullptr )
41  {}
42 
43  //-------------------------------------------------------------------------
44  // ムーブコンストラクタ
46  // 基底クラスコンストラクタ
47  : CWndContainer( std::move( rcInstance ) )
48  // メンバ変数初期化
49  , m_cTitleBar()
50  , m_hTabControl( nullptr )
51  {}
52 
53  //=========================================================================
54  // 公開関数
55  //-------------------------------------------------------------------------
56  // ウィンドウ作成関数
57  bool CWndDocumentTab::Create( HWND hParent, HMENU hMenu ) noexcept {
58  // 処理ブロック
59  bool result = false;
60  do {
61  // 基底クラスの関数を実行する
62  if ( !CWndContainer::Create( hParent, hMenu ) ) {
63  // 失敗!
64  break;
65  }
66  // タイトルバーを作成する
67  else if ( !m_cTitleBar.Create( m_hWnd ) ) {
68  // 失敗!
69  break;
70  }
71  // タブコントロールを作成する
72  else if ( !CreateTabControl() ) {
73  // 失敗!
74  break;
75  }
76 
77  // 成功!
78  result = true;
79  } while ( false );
80 
81  // 実行結果を返す
82  return result;
83  }
84 
85  //-------------------------------------------------------------------------
86  // WM_SIZEメッセージ処理関数
87  LRESULT CWndDocumentTab::WmSize() noexcept {
88  // 処理ブロック
89  LRESULT result = 0;
90  do {
91  // ウィンドウ表示状態を調べる
92  if ( 0 == ::IsWindowVisible( m_hWnd ) ) {
93  // 終了!
94  break;
95  }
96 
97  // タブコントロールを更新する
99 
100  // クライアント領域を取得する
101  RECT sClientRect = {};
102  ::GetClientRect( m_hWnd, &sClientRect );
103 
104  // タブ下端表示状態を調べる
105  if ( IsTabBottom() ) {
106  // タイトルバー表示領域を初期化する
107  int nLeft = sClientRect.left;
108  int nTop = sClientRect.top;
109  int nWidth = ( sClientRect.right - nLeft );
110  int nHeight = TITLE_BAR_HEIGHT;
111 
112  // タイトルバーを表示する
113  ::SetWindowPos( m_cTitleBar.GetHandle(), HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
114  ::UpdateWindow( m_cTitleBar.GetHandle() );
115 
116  // クライアント描画領域から減算する
117  SubtractChildRect( m_cTitleBar.GetHandle(), sClientRect );
118  }
119  else {
120  // タイトルバーを隠す
121  ::ShowWindow( m_cTitleBar.GetHandle(), SW_HIDE );
122  }
123 
124  // 表示状態カレントインデックスを取得する
125  int nCurrent = m_cElementList.GetShowCurrentIndex();
126 
127  // タブ項目数を調べる
128  int nTabCount = static_cast< int >( ::SendMessageW( m_hTabControl, TCM_GETITEMCOUNT, 0, 0 ) );
129  if ( 0 < nTabCount ) {
130  // タブコントロール矩形領域を取得する
131  RECT sTabRect = sClientRect;
132  ::SendMessageW( m_hTabControl, TCM_ADJUSTRECT, 0, reinterpret_cast< LPARAM >( &sTabRect ) );
133 
134  // タブ下端表示状態を調べる
135  if ( !IsTabBottom() ) {
136  // タブコントロールを上端に表示する
137  int nLeft = sClientRect.left;
138  int nTop = sClientRect.top;
139  int nWidth = ( sClientRect.right - nLeft );
140  int nHeight = ( sTabRect.top - nTop );
141  ::SetWindowPos( m_hTabControl, HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
142  ::UpdateWindow( m_hTabControl );
143 
144  // クライアント描画領域から減算する
145  SubtractChildRect( m_hTabControl, sClientRect );
146  }
147  // タブ項目数を調べる
148  else if ( 1 < nTabCount ) {
149  // タブコントロールを下端に表示する
150  int nHeight = ( ( sClientRect.bottom - sClientRect.top ) - ( sTabRect.bottom - sTabRect.top ) );
151  int nLeft = sClientRect.left;
152  int nTop = ( sClientRect.bottom - nHeight );
153  int nWidth = ( sClientRect.right - nLeft );
154  ::SetWindowPos( m_hTabControl, HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
155  ::UpdateWindow( m_hTabControl );
156 
157  // クライアント描画領域から減算する
158  SubtractChildRect( m_hTabControl, sClientRect );
159  }
160  else {
161  // タブコントロールを隠す
162  ::ShowWindow( m_hTabControl, SW_HIDE );
163  }
164 
165  // カレントエレメントウィンドウを取得する
166  CWndElement* pcElement = m_cElementList[ nCurrent ];
167  if ( nullptr != pcElement ) {
168  // エレメントウィンドウを表示する
169  int nLeft = sClientRect.left;
170  int nTop = sClientRect.top;
171  int nWidth = ( sClientRect.right - nLeft );
172  int nHeight = ( sClientRect.bottom - nTop );
173  ::SetWindowPos( pcElement->GetHandle(), HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
174  ::UpdateWindow( pcElement->GetHandle() );
175  }
176  }
177  else {
178  // タブコントロールを隠す
179  ::ShowWindow( m_hTabControl, SW_HIDE );
180 
181  // カレントインデックスを無効化する
182  nCurrent = -1;
183  }
184 
185  // 巡回する
186  for ( int nIndex = 0, nCount = m_cElementList.GetCount(); nCount > nIndex; ++nIndex ) {
187  // エレメントウィンドウを取得する
188  CWndElement* pcElement = m_cElementList[ nIndex ];
189  if ( nullptr != pcElement ) {
190  // カレントインデックスを調べる
191  if ( nCurrent != nIndex ) {
192  // エレメントウィンドウを隠す
193  ::ShowWindow( pcElement->GetHandle(), SW_HIDE );
194  }
195  }
196  }
197  } while ( false );
198 
199  // 実行結果を返す
200  return result;
201  }
202 
203  //-------------------------------------------------------------------------
204  // WM_DRAWITEMメッセージ処理関数
205  LRESULT CWndDocumentTab::WmDrawItem() noexcept {
206  // 処理ブロック
207  LRESULT result = 0;
208  do {
209  // コントロールハンドルを取得する
210  LPDRAWITEMSTRUCT lpDraw = reinterpret_cast< LPDRAWITEMSTRUCT >( m_lParam );
211 
212  // コントロールハンドルを調べる
213  if ( m_cTitleBar.GetHandle() == lpDraw->hwndItem ) {
214  // タイトルバーを描画する
215  DrawTitleBar( lpDraw );
216 
217  // 終了!
218  break;
219  }
220  // コントロールハンドルを調べる
221  else if ( m_hTabControl == lpDraw->hwndItem ) {
222  // タブコントロールを描画する
223  DrawTabControl( lpDraw );
224 
225  // 終了!
226  break;
227  }
228 
229  // 基底クラスの関数を実行する
230  result = CWndContainer::WmDrawItem();
231  } while ( false );
232 
233  // 実行結果を返す
234  return result;
235  }
236 
237  //-------------------------------------------------------------------------
238  // TCN_SELCHANGEメッセージ関数
239  LRESULT CWndDocumentTab::TcnSelChange() noexcept {
240  // 処理ブロック
241  LRESULT result = 0;
242  do {
243  // 通知メッセージヘッダ構造体を取得する
244  NMHDR* psNmHdr = reinterpret_cast< LPNMHDR >( m_lParam );
245 
246  // コントロールハンドルを調べる
247  if ( m_hTabControl == psNmHdr->hwndFrom ) {
248  // 選択タブ項目インデックスを取得する
249  int nIndex = static_cast< int >( ::SendMessageW( m_hTabControl, TCM_GETCURSEL, 0, 0 ) );
250  if ( 0 <= nIndex ) {
251  // タブ項目情報を取得する
252  TCITEMW sTcItem = {};
253  sTcItem.mask = TCIF_PARAM;
254  if ( TRUE == ::SendMessageW( m_hTabControl, TCM_GETITEM, nIndex, reinterpret_cast< LPARAM >( &sTcItem ) ) ) {
255  // エレメントウィンドウを取得する
256  HWND hElement = reinterpret_cast< HWND >( sTcItem.lParam );
257  CWndElement* pcElement = m_cElementList.GetElementWindow( hElement );
258  if ( nullptr != pcElement ) {
259  // カレントエレメントウィンドウを設定する
260  if ( m_cElementList.SetCurrentElement( pcElement ) ) {
261  // WM_SIZEメッセージを送信する
262  ::SendMessageW( m_hWnd, WM_SIZE, 0, 0 );
263  ::UpdateWindow( m_hWnd );
264 
265  // フォーカスウィンドウを設定する
266  ::SetFocus( pcElement->GetHandle() );
267 
268  // 終了!
269  break;
270  }
271  }
272  }
273  }
274 
275  // 終了!
276  break;
277  }
278 
279  // 基底クラスの関数を実行する
280  result = CWndContainer::TcnSelChange();
281  } while ( false );
282 
283  // 実行結果を返す
284  return result;
285  }
286 
287  //-------------------------------------------------------------------------
288  // NM_CLICKメッセージ処理関数
289  LRESULT CWndDocumentTab::NmClick() noexcept {
290  // 処理ブロック
291  LRESULT result = 0;
292  do {
293  // 通知メッセージヘッダ構造体を取得する
294  NMHDR* psNmHdr = reinterpret_cast< LPNMHDR >( m_lParam );
295 
296  // コントロールハンドルを調べる
297  if ( m_hTabControl == psNmHdr->hwndFrom ) {
298  // フォーカスウィンドウを設定する
299  ::SetFocus( m_hWnd );
300 
301  // 終了!
302  break;
303  }
304 
305  // 基底クラスの関数を実行する
306  result = CWndContainer::NmClick();
307  } while ( false );
308 
309  // 実行結果を返す
310  return result;
311  }
312 
313  //-------------------------------------------------------------------------
314  // STN_CLICKEDメッセージ処理関数
315  LRESULT CWndDocumentTab::StnClicked() noexcept {
316  // 処理ブロック
317  LRESULT result = 0;
318  do {
319  // コントロールハンドルを調べる
320  HWND hCtrl = reinterpret_cast< HWND >( m_lParam );
321  if ( m_cTitleBar.GetHandle() == hCtrl ) {
322  // フォーカスウィンドウを設定する
323  ::SetFocus( m_hWnd );
324 
325  // 終了!
326  break;
327  }
328 
329  // 基底クラスの関数を実行する
330  result = CWndContainer::StnClicked();
331  } while ( false );
332 
333  // 実行結果を返す
334  return result;
335  }
336 
337  //-------------------------------------------------------------------------
338  // WM_CONTEXTMENUメッセージ処理関数
339  LRESULT CWndDocumentTab::WmContextMenu() noexcept {
340  // 処理ブロック
341  LRESULT result = 0;
342  do {
343  // カーソル位置を取得する
344  POINT sPoint = { LOWORD( m_lParam ), HIWORD( m_lParam ) };
345 
346  // タブコントロールのクライアント座標系に変換する
347  ::ScreenToClient( m_hTabControl, &sPoint );
348 
349  // タブ項目数を取得する
350  int nTabCount = static_cast< int >( ::SendMessageW( m_hTabControl, TCM_GETITEMCOUNT, 0, 0 ) );
351 
352  // 巡回する
353  for ( int nIndex = 0;; ++nIndex ) {
354  // インデックスを調べる
355  if ( nTabCount <= nIndex ) {
356  // 基底クラスの関数を実行する
357  result = CWndContainer::WmContextMenu();
358  break;
359  }
360 
361  // タブ項目矩形領域を取得する
362  RECT sRect;
363  if ( TRUE == ::SendMessageW( m_hTabControl, TCM_GETITEMRECT, nIndex, reinterpret_cast< LPARAM >( &sRect ) ) ) {
364  // カーソル座標を調べる
365  if ( 0 != ::PtInRect( &sRect, sPoint ) ) {
366  // タブ項目情報を取得する
367  TCITEMW sTcItem = {};
368  sTcItem.mask = TCIF_PARAM;
369  if ( TRUE == ::SendMessageW( m_hTabControl, TCM_GETITEM, nIndex, reinterpret_cast< LPARAM >( &sTcItem ) ) ) {
370  // エレメントウィンドウを取得する
371  HWND hElement = reinterpret_cast< HWND >( sTcItem.lParam );
372  CWndElement* pcElement = m_cElementList.GetElementWindow( hElement );
373  if ( nullptr != pcElement ) {
374  // WM_CONTEXTMENUメッセージを送信する
375  ::SendMessageW( pcElement->GetHandle(), WM_CONTEXTMENU, reinterpret_cast< WPARAM >( hElement ), m_lParam );
376  }
377  }
378 
379  // 終了!
380  break;
381  }
382  }
383  }
384  } while ( false );
385 
386  // 実行結果を返す
387  return result;
388  }
389 
390  //-------------------------------------------------------------------------
391  // クライアント領域更新関数
393  // 処理ブロック
394  bool result = false;
395  do {
396  // タイトルバーを無効化する
397  ::InvalidateRect( m_cTitleBar.GetHandle(), nullptr, false );
398 
399  // ウィンドウを更新する
400  ::UpdateWindow( m_cTitleBar.GetHandle() );
401 
402  // タブコントロールを無効化する
403  ::InvalidateRect( m_hTabControl, nullptr, false );
404 
405  // ウィンドウを更新する
406  ::UpdateWindow( m_hTabControl );
407 
408  // 基底クラスの関数を実行する
410  } while ( false );
411 
412  // 実行結果を返す
413  return result;
414  }
415 
416  //-------------------------------------------------------------------------
417  // クライアント描画領域取得関数
418  bool CWndDocumentTab::GetPaintRect( RECT& rsRect ) noexcept {
419  // 処理ブロック
420  bool result = false;
421  do {
422  // クライアント領域を取得する
423  if ( 0 == ::GetClientRect( m_hWnd, &rsRect ) ) {
424  // 失敗!
425  break;
426  }
427 
428  // タイトルバー表示状態を調べる
429  if ( 0 != ::IsWindowVisible( m_cTitleBar.GetHandle() ) ) {
430  // クライアント領域から減算する
431  if ( !SubtractChildRect( m_cTitleBar.GetHandle(), rsRect ) ) {
432  // 失敗!
433  break;
434  }
435  }
436 
437  // タブコントロール表示状態を調べる
438  if ( 0 != ::IsWindowVisible( m_hTabControl ) ) {
439  // クライアント領域から減算する
440  if ( !SubtractChildRect( m_hTabControl, rsRect ) ) {
441  // 失敗!
442  break;
443  }
444  }
445 
446  // 表示状態カレントインデックスを取得する
447  int nIndex = m_cElementList.GetShowCurrentIndex();
448  if ( 0 <= nIndex ) {
449  // エレメントウィンドウを取得する
450  CWndElement* pcElement = m_cElementList[ nIndex ];
451  if ( nullptr != pcElement ) {
452  // クライアント領域から減算する
453  if ( !SubtractChildRect( pcElement->GetHandle(), rsRect ) ) {
454  // 失敗!
455  break;
456  }
457  }
458  }
459 
460  // 成功!
461  result = true;
462  } while ( false );
463 
464  // 実行結果を返す
465  return result;
466  }
467 
468  //-------------------------------------------------------------------------
469  // 最小水平サイズ取得関数
471  // 処理ブロック
472  int result = 0;
473  do {
474  // 基底クラスの関数を実行する
475  result = CWndContainer::GetMinWidth();
476 
477  // 表示状態カレントインデックスを取得する
478  int nIndex = m_cElementList.GetShowCurrentIndex();
479  if ( 0 <= nIndex ) {
480  // エレメントウィンドウを取得する
481  CWndElement* pcElement = m_cElementList[ nIndex ];
482  if ( nullptr != pcElement ) {
483  // ウィンドウ表示フラグを調べる
484  if ( !pcElement->IsShow() ) {
485  // 最小水平サイズを取得する
486  int nMinWidth = pcElement->GetMinWidth();
487 
488  // 最小水平サイズを更新する
489  result = max( result, nMinWidth );
490  }
491  }
492  }
493  } while ( false );
494 
495  // 実行結果を返す
496  return result;
497  }
498 
499  //-------------------------------------------------------------------------
500  // 最小垂直サイズ取得関数
502  // 処理ブロック
503  int result = 0;
504  do {
505  // 基底クラスの関数を実行する
506  result = CWndContainer::GetMinHeight();
507 
508  // 表示状態カレントインデックスを取得する
509  int nIndex = m_cElementList.GetShowCurrentIndex();
510  if ( 0 <= nIndex ) {
511  // エレメントウィンドウを取得する
512  CWndElement* pcElement = m_cElementList[ nIndex ];
513  if ( nullptr != pcElement ) {
514  // ウィンドウ表示フラグを調べる
515  if ( !pcElement->IsShow() ) {
516  // 最小垂直サイズを取得する
517  int nMinHeight = pcElement->GetMinHeight();
518 
519  // 最小垂直サイズを更新する
520  result = max( result, nMinHeight );
521  }
522  }
523  }
524 
525  // タイトルバー表示状態を調べる
526  if ( 0 != ::IsWindowVisible( m_cTitleBar.GetHandle() ) ) {
527  // タイトルバー表示領域を取得する
528  RECT sRect;
529  ::GetWindowRect( m_cTitleBar.GetHandle(), &sRect );
530 
531  // 最小垂直サイズを更新する
532  result += ( sRect.bottom - sRect.top );
533  }
534 
535  // タブコントロール表示状態を調べる
536  if ( 0 != ::IsWindowVisible( m_hTabControl ) ) {
537  // タブコントロール表示領域を取得する
538  RECT sRect;
539  ::GetWindowRect( m_hTabControl, &sRect );
540 
541  // 最小垂直サイズを更新する
542  result += ( sRect.bottom - sRect.top );
543  }
544  } while ( false );
545 
546  // 実行結果を返す
547  return result;
548  }
549 
550  //-------------------------------------------------------------------------
551  // タイトルバー描画関数
552  bool CWndDocumentTab::DrawTitleBar( LPDRAWITEMSTRUCT lpDraw ) noexcept {
553  // 処理ブロック
554  bool result = false;
555  do {
556  // 表示状態カレントインデックスを取得する
557  wchar_t szBuffer[ MAX_PATH ];
558  int nCurrent = m_cElementList.GetShowCurrentIndex();
559  if ( 0 <= nCurrent ) {
560  // エレメントウィンドウを取得する
561  CWndElement* pcElement = m_cElementList[ nCurrent ];
562  if ( nullptr != pcElement ) {
563  // ウィンドウタイトルを取得する
564  ::GetWindowTextW( pcElement->GetHandle(), szBuffer, MAX_PATH );
565 
566  // ウィンドウタイトルを設定する
567  ::SetWindowTextW( m_hWnd, szBuffer );
568  }
569  }
570 
571  // フォーカスウィンドウを調べる
572  UINT uFlags = DC_SMALLCAP | DC_TEXT | DC_GRADIENT;
573  if ( IsOwnOrChild( m_hWnd, ::GetFocus() ) ) {
574  // アクティブフラグをセットする
575  uFlags |= DC_ACTIVE;
576  }
577 
578  // キャプションバーを描画する
579  ::DrawCaption( lpDraw->hwndItem, lpDraw->hDC, &lpDraw->rcItem, uFlags );
580 
581  // ペンを作成する
582  HPEN hPen = ::CreatePen( PS_SOLID, 1, COLOR_TITLE_SEPARATOR );
583  ::SelectObject( lpDraw->hDC, hPen );
584 
585  // 境界を描画する
586  int nLeft = lpDraw->rcItem.left;
587  int nTop = ( lpDraw->rcItem.bottom - 1 );
588  int nWidth = ( lpDraw->rcItem.right - nLeft );
589  ::MoveToEx( lpDraw->hDC, nLeft, nTop, nullptr );
590  ::LineTo( lpDraw->hDC, ( nLeft + nWidth ), nTop );
591 
592  // ペンを削除する
593  ::DeleteObject( hPen );
594 
595  // 成功!
596  result = true;
597  } while ( false );
598 
599  // 実行結果を返す
600  return result;
601  }
602 
603  //-------------------------------------------------------------------------
604  // タブコントロール作成関数
606  // 処理ブロック
607  bool result = false;
608  do {
609  // タブ下端表示状態を調べる
610  DWORD dwStyle = ( WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_OWNERDRAWFIXED );
611 
612  // タブコントロールを作成する
613  m_hTabControl = ::CreateWindowExW( 0, WC_TABCONTROLW, nullptr, dwStyle, 0, 0, 0, 0, m_hWnd, nullptr, ::GetModuleHandleW( nullptr ), nullptr );
614  if ( nullptr == m_hTabControl ) {
615  // 失敗!
616  break;
617  }
618 
619  // フォントを設定する
620  ::SendMessageW( m_hTabControl, WM_SETFONT, reinterpret_cast< WPARAM >( ::GetStockObject( DEFAULT_GUI_FONT ) ), 0 );
621 
622  // 成功!
623  result = true;
624  } while ( false );
625 
626  // 実行結果を返す
627  return result;
628  }
629 
630  //-------------------------------------------------------------------------
631  // タブコントロール更新関数
633  // 処理ブロック
634  bool result = false;
635  do {
636  // ウィンドウスタイルを取得する
637  LONG_PTR nStyle = ::GetWindowLongPtrW( m_hTabControl, GWL_STYLE );
638 
639  // タブ下端表示状態を調べる
640  if ( IsTabBottom() ) {
641  // タブコントロールスタイルを設定する
642  nStyle |= TCS_BOTTOM;
643  }
644  else {
645  // タブコントロールスタイルを設定する
646  nStyle &= ~TCS_BOTTOM;
647  }
648 
649  // ウィンドウスタイルを設定する
650  ::SetWindowLongPtrW( m_hTabControl, GWL_STYLE, nStyle );
651 
652  // タイトルバー文字列を初期化する
653  wchar_t szTitle[ MAX_PATH ];
654  ::wcscpy_s( szTitle, GetSectionName() );
655 
656  // エレメントウィンドウ数を取得する
657  int nCount = m_cElementList.GetCount();
658 
659  // 表示状態カレントインデックスを取得する
660  int nCurrent = m_cElementList.GetShowCurrentIndex();
661 
662  // タブ項目数を取得する
663  int nTabCount = static_cast< int >( ::SendMessageW( m_hTabControl, TCM_GETITEMCOUNT, 0, 0 ) );
664 
665  // 表示状態エレメントウィンドウ数をクリアする
666  int nShowCount = 0;
667 
668  // 巡回する
669  for ( int nIndex = 0; nCount > nIndex; ++nIndex ) {
670  // エレメントウィンドウを取得する
671  CWndElement* pcElement = m_cElementList[ nIndex ];
672  if ( nullptr != pcElement ) {
673  // ウィンドウ表示フラグを調べる
674  if ( pcElement->IsShow() ) {
675  // ウィンドウタイトルを取得する
676  wchar_t szBuffer[ MAX_PATH ];
677  ::GetWindowTextW( pcElement->GetHandle(), szBuffer, MAX_PATH );
678 
679  // タブ項目情報を作成する
680  TCITEMW sTcItem = {};
681  sTcItem.mask = ( TCIF_TEXT | TCIF_PARAM );
682  sTcItem.pszText = szBuffer;
683  sTcItem.lParam = reinterpret_cast< LPARAM >( pcElement->GetHandle() );
684 
685  // インデックスを調べる
686  if ( nTabCount > nShowCount ) {
687  // タブ項目情報を設定する
688  ::SendMessageW( m_hTabControl, TCM_SETITEM, nShowCount, reinterpret_cast< LPARAM >( &sTcItem ) );
689  }
690  else {
691  // タブ項目を追加する
692  ::SendMessageW( m_hTabControl, TCM_INSERTITEMW, nShowCount, reinterpret_cast< LPARAM >( &sTcItem ) );
693 
694  // タブ項目数をインクリメントする
695  ++nTabCount;
696  }
697 
698  // カレントインデックスを調べる
699  if ( nCurrent == nIndex ) {
700  // エレメントウィンドウタイトルを取得する
701  ::wcscpy_s( szTitle, szBuffer );
702 
703  // タブ項目を選択する
704  ::SendMessageW( m_hTabControl, TCM_SETCURSEL, nShowCount, 0 );
705  }
706 
707  // 表示状態エレメントウィンドウ数をインクリメントする
708  ++nShowCount;
709  }
710  }
711  }
712 
713  // 巡回する
714  for ( ; nShowCount < nTabCount; --nTabCount ) {
715  // タブ項目を削除する
716  ::SendMessageW( m_hTabControl, TCM_DELETEITEM, ( nTabCount - 1 ), 0 );
717  }
718 
719  // タイトルバー文字列を設定する
720  ::SetWindowTextW( m_cTitleBar.GetHandle(), szTitle );
721 
722  // 成功!
723  result = true;
724  } while ( false );
725 
726  // 実行結果を返す
727  return result;
728  }
729 
730  //-------------------------------------------------------------------------
731  // タブコントロール描画関数
732  bool CWndDocumentTab::DrawTabControl( LPDRAWITEMSTRUCT lpDraw ) noexcept {
733  // 処理ブロック
734  bool result = false;
735  do {
736  // タブ項目情報を取得する
737  TCITEMW sTcItem = {};
738  wchar_t szBuffer[ MAX_PATH ];
739  sTcItem.mask = ( TCIF_TEXT | TCIF_PARAM );
740  sTcItem.pszText = szBuffer;
741  sTcItem.cchTextMax = MAX_PATH;
742  if ( TRUE != ::SendMessageW( lpDraw->hwndItem, TCM_GETITEM, lpDraw->itemID, reinterpret_cast< LPARAM >( &sTcItem ) ) ) {
743  // 失敗!
744  break;
745  }
746 
747  // エレメントウィンドウハンドルを取得する
748  HWND hElement = reinterpret_cast< HWND >( sTcItem.lParam );
749 
750  // フォーカスウィンドウ保存ハンドルを調べる
751  COLORREF dwColor = COLOR_TAB_NORMAL;
752  if ( IsOwnOrChild( hElement, s_hFocus ) ) {
753  // 背景色を取得する
754  dwColor = COLOR_TAB_FOCUS;
755  }
756 
757  // ブラシを作成する
758  HBRUSH hBrush = ::CreateSolidBrush( dwColor );
759 
760  // 塗りつぶす
761  ::FillRect( lpDraw->hDC, &lpDraw->rcItem, hBrush );
762 
763  // ブラシを削除する
764  ::DeleteObject( hBrush );
765 
766  // タブ項目タイトルを表示する
767  lpDraw->rcItem.left += 4;
768  ::SetTextColor( lpDraw->hDC, ::GetSysColor( COLOR_WINDOWTEXT ) );
769  ::SetBkMode( lpDraw->hDC, TRANSPARENT );
770  ::DrawTextW( lpDraw->hDC, szBuffer, -1, &lpDraw->rcItem, ( DT_LEFT | DT_SINGLELINE | DT_VCENTER ) );
771 
772  // 成功!
773  result = true;
774  } while ( false );
775 
776  // 実行結果を返す
777  return result;
778  }
779 }
780 
781 #pragma managed( pop )
virtual int GetMinWidth() noexcept override
最小水平サイズ取得関数
virtual HWND & GetHandle() noexcept
ウィンドウハンドル取得関数
Definition: CWndBase.h:69
ウィンドウユーティリティライブラリヘッダファイル
virtual LRESULT TcnSelChange() noexcept override
virtual int GetShowCurrentIndex() const noexcept
表示状態カレントインデックス取得関数
Definition: CWndList.cpp:159
virtual bool IsShow() noexcept
表示フラグ取得関数
Definition: CWndPane.h:191
virtual bool UpdateClientRect() noexcept override
クライアント領域更新関数
virtual CWndElement * GetElementWindow(HWND hWnd) const noexcept
エレメントウィンドウ取得関数
Definition: CWndList.cpp:234
コンテナウィンドウクラス
Definition: CWndContainer.h:31
virtual int GetMinHeight() noexcept
最小垂直サイズ取得関数
Definition: CWndPane.h:631
virtual LRESULT StnClicked() noexcept override
virtual LRESULT NmClick() noexcept
Definition: CWndBase.h:1268
virtual bool CreateTabControl() noexcept
タブコントロール作成関数
virtual LRESULT WmDrawItem() noexcept
Definition: CWndBase.h:601
virtual bool IsTabBottom() const noexcept
タブ下端表示状態取得関数
virtual bool Create(HWND hParent, HMENU hMenu=nullptr) noexcept override
ウィンドウ作成関数
CWndTitleBar m_cTitleBar
タイトルバー
配列クラス実装ヘッダファイル
virtual bool SubtractChildRect(HWND hChild, RECT &rsRect) noexcept
子ウィンドウ表示領域減算関数
Definition: CWndBase.cpp:1425
virtual bool DrawTitleBar(LPDRAWITEMSTRUCT lpDraw) noexcept
タイトルバー描画関数
virtual LRESULT StnClicked() noexcept
Definition: CWndBase.h:1322
HWND m_hWnd
ウィンドウハンドル
Definition: CWndBase.h:1539
static int const TITLE_BAR_HEIGHT
タイトルバー垂直サイズ
virtual int GetMinWidth() noexcept
最小水平サイズ取得関数
Definition: CWndPane.h:620
virtual LRESULT WmContextMenu() noexcept override
static HWND s_hFocus
フォーカスウィンドウ保存ハンドル
Definition: CWndPane.h:697
ウィンドウライブラリ名前空間
Definition: CommandIdDef.h:22
CWndList m_cElementList
エレメントウィンドウリスト
virtual LRESULT WmContextMenu() noexcept override
Definition: CWndPane.cpp:230
HWND m_hTabControl
タブコントロールハンドル
virtual bool DrawTabControl(LPDRAWITEMSTRUCT lpDraw) noexcept
タブコントロール描画関数
CWndDocumentTab(CWndElement *(*pfnCreateElement)()=&CreateDocumentWindow, wchar_t const *pszElementName=L"ドキュメントウィンドウ") noexcept
コンストラクタ
virtual bool UpdateTabControl() noexcept
タブコントロール更新関数
virtual bool UpdateClientRect() noexcept
クライアント領域更新関数
Definition: CWndPane.cpp:730
LPARAM m_lParam
メッセージ第2引数
Definition: CWndBase.h:1542
ドキュメントタブウィンドウクラス
virtual LRESULT WmDrawItem() noexcept override
virtual LRESULT TcnSelChange() noexcept
Definition: CWndBase.h:1208
static COLORREF const COLOR_TAB_FOCUS
フォーカス所有タブ項目背景色
virtual bool Create(HWND hParent, HMENU hMenu=nullptr) noexcept override
ウィンドウ作成関数
ペインウィンドウクラス
Definition: CWndPane.h:74
virtual int GetMinHeight() noexcept override
最小垂直サイズ取得関数
virtual bool SetCurrentElement(CWndElement *pcElement) noexcept
カレントエレメントウィンドウ設定関数
Definition: CWndList.h:172
virtual bool Create(HWND hParent=nullptr, HMENU hMenu=nullptr) noexcept override
ウィンドウ作成関数
ドキュメントタブウィンドウクラスヘッダファイル
virtual wchar_t const * GetSectionName() const noexcept override
セクション名取得関数
static COLORREF const COLOR_TITLE_SEPARATOR
タイトルバー境界色
virtual bool GetPaintRect(RECT &rsRect) noexcept override
クライアント描画領域取得関数
virtual LRESULT WmSize() noexcept override
各種メッセージ処理関数
static COLORREF const COLOR_TAB_NORMAL
通常タブ項目背景色
virtual int GetCount() const noexcept
配列要素数取得関数
Definition: CArray.h:149
virtual LRESULT NmClick() noexcept override
LIB_WINDOW_API bool IsOwnOrChild(HWND hWnd, HWND hChild) noexcept
自分または子ウィンドウ判定関数