TNB Library
TnbMfcRowHeaderCtrl.h
[詳解]
1#pragma once
12#include "TnbBitmapImage.h"
13#include "TnbDrawable.h"
14#include "TnbMfcBitmapDC.h"
15
16
17
18//TNB Library
19namespace TNB {
20namespace MFC {
21
22
23
42class CRowHeaderCtrl : public CWnd
43{
44 DEFSUPER(CWnd);
45public:
46
48 CRowHeaderCtrl(void) : m_pBuddyCtrl(NULL), m_headerWidth(0), m_offset(2, 0)
49 , m_textColor(::GetSysColor(COLOR_WINDOWTEXT)), m_backColor(::GetSysColor(COLOR_BTNFACE))
50 , m_hCursor(NULL), m_isWidthVariable(true), m_textStyle(DT_LEFT | DT_VCENTER), m_hasCapture(false)
51 , m_isPartialOk(false)
52 {
53 }
54
60 void SetTextStyle(DWORD ts)
61 {
62 m_textStyle = ts;
63 }
64
70 void SetPartialView(bool isPartialOk = false)
71 {
72 m_isPartialOk = isPartialOk;
73 }
74
81 void SetTextColor(COLORREF color)
82 {
83 m_textColor = color;
84 }
85
90 void SetHeaderDrawer(const IDrawable* pDrawer = NULL)
91 {
92 m_phHeaderDrawer.Null();
93 if ( pDrawer != NULL )
94 {
95 m_phHeaderDrawer = pDrawer->Clone();
96 }
97 Invalidate(FALSE);
98 }
99
107 void SetBackground(COLORREF color, const IDrawable* pBkDrawer = NULL, int offsetX = 2, int offsetY = 0)
108 {
109 m_backColor = color;
110 m_phBkDrawer.Null();
111 m_offset.x = offsetX;
112 m_offset.y = offsetY;
113 if ( pBkDrawer != NULL )
114 {
115 m_phBkDrawer = pBkDrawer->Clone();
116 }
117 if ( ::IsWindow(_super::GetSafeHwnd()) )
118 {
119 _super::Invalidate(FALSE);
120 }
121 }
122
131 bool SetBuddy(CListCtrl* pCtrl, size_t headerWidth, bool isWidthVariable = false)
132 {
133 if ( m_pBuddyCtrl == NULL )
134 {
135 if ( pCtrl != NULL && ::IsWindow(pCtrl->GetSafeHwnd()) )
136 {
137 m_myHooker.m_hParent = GetSafeHwnd();
138 m_myHooker.Attach(pCtrl->GetSafeHwnd());
139 pCtrl->ModifyStyle(WS_BORDER, 0);
140 pCtrl->ModifyStyleEx(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, 0);
141 SetWindowPos(pCtrl, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
142 bool isVisible = (GetStyle() & WS_VISIBLE) != 0;
143 ShowWindow(isVisible ? SW_SHOW : SW_HIDE);
144 SetFont(pCtrl->GetFont());
145 //
146 m_headerWidth = down_cast<int>(headerWidth);
147 m_isWidthVariable = isWidthVariable;
148 m_pBuddyCtrl = pCtrl;
149 m_params.SetSize(pCtrl->GetItemCount());
150 m_RewidthHeader();
151 return true;
152 }
153 }
154 return false;
155 }
156
162 void SetHeaderWidth(size_t headerWidth, bool isWidthVariable = false)
163 {
164 m_headerWidth = down_cast<int>(headerWidth);
165 m_isWidthVariable = isWidthVariable;
166 m_RewidthHeader();
167 }
168
173 size_t GetHeaderWidth(void) const
174 {
175 return m_headerWidth;
176 }
177
183 size_t GetItemCount(void) const
184 {
185 if ( m_pBuddyCtrl != NULL )
186 {
187 ASSERT( ToInt(m_params.GetSize()) == m_pBuddyCtrl->GetItemCount() );
188 }
189 return m_params.GetSize();
190 }
191
199 bool SetItemDrawer(int item, const IDrawable& draw)
200 {
201 if ( m_params.IsInRange(item) )
202 {
203 m_params[item].phDraw = draw.Clone();
204 Invalidate(FALSE);
205 return true;
206 }
207 return false;
208 }
209
217 bool SetItemText(int item, LPCTSTR lpszText)
218 {
219 if ( m_params.IsInRange(item) )
220 {
221 m_params[item].phDraw.Null();
222 m_params[item].text = lpszText;
223 Invalidate(FALSE);
224 return true;
225 }
226 return false;
227 }
228
237 int InsertItem(int item, LPCTSTR lpszItem)
238 {
239 if ( m_pBuddyCtrl != NULL )
240 {
241 int r = m_pBuddyCtrl->InsertItem(item, _T(""));
242 if ( r >= 0 )
243 {
244 SetItemText(r, lpszItem);
245 }
246 return r;
247 }
248 return -1;
249 }
250
259 int InsertItem(int item, const IDrawable& draw)
260 {
261 int r = InsertItem(item, _T(""));
262 if ( r >= 0 )
263 {
264 SetItemDrawer(r, draw);
265 }
266 return r;
267 }
268
277 int HitTest(const CPoint& pt) const
278 {
279 int r = -1;
280 if ( m_pBuddyCtrl != NULL )
281 {
282 CRect rc;
283 GetClientRect(rc);
284 if ( rc.PtInRect(pt) )
285 {
286 CHeaderCtrl* pHead = m_pBuddyCtrl->GetHeaderCtrl();
287 if ( pHead != NULL )
288 {
289 pHead->GetWindowRect(rc);
290 if ( pt.y >= rc.Height() )
291 {
292 r = m_pBuddyCtrl->HitTest(CPoint(0, pt.y));
293 }
294 else
295 {
296 r = -99; // ヘッダ部
297 }
298 }
299 }
300 }
301 return r;
302 }
303
304protected:
305
316 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
317 {
318 switch ( message )
319 {
320 case CMyHooker::WM_RHC_HOOKMESSAGE:
321 {
322 CMyHooker::TMsg* P = reinterpret_cast<CMyHooker::TMsg*>(lParam);
323 if ( P != NULL )
324 {
325 m_BuddyWindowProc(P->message, P->wParam, P->lParam, P->lResult);
326 }
327 }
328 break;
329 case WM_SIZE:
330 m_RewidthHeader();
331 break;
332 case WM_MOVE:
333 m_RewidthHeader();
334 break;
335 case WM_ERASEBKGND:
336 return 0;
337 case WM_PAINT:
338 m_Draw(CPaintDC(this));
339 return 0;
340 case WM_LBUTTONDOWN:
341 if ( m_isWidthVariable )
342 {
343 CPoint pos(lParam);
344 if ( m_IsDragSpace(pos) )
345 {
346 ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
347 ::SetCapture(GetSafeHwnd());
348 m_hasCapture = true;
349 m_captureStartPos = CPoint(lParam);
350 m_captureStartHeaderWidth = m_headerWidth;
351 }
352 }
353 break;
354 case WM_LBUTTONUP:
355 if ( m_hasCapture )
356 {
357 ::ReleaseCapture();
358 m_hasCapture = false;
359 }
360 break;
361 case WM_RBUTTONDOWN:
362 if ( m_hasCapture )
363 {
364 ::ReleaseCapture();
365 m_hasCapture = false;
366 m_headerWidth = m_captureStartHeaderWidth;
367 m_RewidthHeader();
368 }
369 break;
370 case WM_MOUSEMOVE:
371 if ( m_isWidthVariable )
372 {
373 if ( m_hCursor == NULL )
374 {
375 m_hCursor = ::GetCursor();
376 }
377 CPoint pos(lParam);
378 if ( m_hasCapture )
379 {
380 ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
381 int x = m_captureStartHeaderWidth + pos.x - m_captureStartPos.x;
382 CRect rc;
383 GetClientRect(rc);
384 int l = rc.Width() - 5;
385 if ( x > l )
386 {
387 x = l;
388 }
389 if ( x < 5 )
390 {
391 x = 5;
392 }
393 m_headerWidth = x;
394 m_RewidthHeader();
395 if ( m_pBuddyCtrl != NULL )
396 {
397 m_pBuddyCtrl->GetHeaderCtrl()->RedrawWindow(); //カラムの再描画により再カラム幅調整をする
398 }
399 }
400 else if ( m_IsDragSpace(pos) )
401 {
402 ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
403 }
404 else
405 {
406 ::SetCursor(m_hCursor);
407 }
408 }
409 break;
410 }
411 return _super::WindowProc(message, wParam, lParam);
412 }
413
419 virtual void PreSubclassWindow(void)
420 {
421 m_pBuddyCtrl = NULL;
422 m_hCursor = NULL;
423 _super::ModifyStyle(0, SS_NOTIFY);
424 _super::PreSubclassWindow();
425 }
426
427private:
428 // ヘッダの幅変更
429 void m_RewidthHeader(void)
430 {
431 if ( m_pBuddyCtrl != NULL )
432 {
433 CRect rc;
434 GetClientRect(rc);
435 ClientToScreen(rc);
436 GetParent()->ScreenToClient(rc);
437 rc.left += m_headerWidth;
438 m_pBuddyCtrl->SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER);
439 }
440 }
441 // ドラック空間?
442 bool m_IsDragSpace(const POINT& pos) const
443 {
444 if ( m_pBuddyCtrl != NULL )
445 {
446 CRect headerRect;
447 CHeaderCtrl* pHead = m_pBuddyCtrl->GetHeaderCtrl();
448 pHead->GetClientRect(headerRect);
449 if ( pos.x >= m_headerWidth - 5 && pos.x <= m_headerWidth )
450 {
451 if ( pos.y < headerRect.Height() )
452 {
453 return true;
454 }
455 }
456 }
457 return false;
458 }
459
460 // 背景描画
461 void m_BkDraw(HDC hdc, const CRect& rect)
462 {
463 if ( m_phBkDrawer != NULL )
464 {
465 m_phBkDrawer->Resize(rect.Size());
466 m_phBkDrawer->Draw(hdc, rect.left, rect.top);
467 }
468 else
469 {
470 CRect r = rect;
471 r.top = r.bottom - 1;
472 ::InvertRect(hdc, r);
473 r = rect;
474 r.left = r.right - 1;
475 ::InvertRect(hdc, r);
476 }
477 }
478 // 全体描画
479 void m_Draw(HDC hdc)
480 {
481 CRect clientRect;
482 GetClientRect(clientRect);
483 CBitmapImage bi;
484 bi.Set(m_headerWidth, clientRect.Height(), m_backColor);
485 if ( m_pBuddyCtrl != NULL )
486 {
487 CBitmapDC dc(&bi);
488 CDcSelectAssistant dsa(dc);
489 dsa.SetBkMode(TRANSPARENT);
490 dsa.SelectFont(GetFont());
491 dsa.SetTextColor(m_textColor);
492 {
493 // ヘッダ部
494 CRect headerRect;
495 CHeaderCtrl* pHead = m_pBuddyCtrl->GetHeaderCtrl();
496 pHead->GetClientRect(headerRect);
497 CRect r = headerRect;
498 r.left = 0;
499 r.right = m_headerWidth;
500 m_BkDraw(dc, r);
501 if ( ! m_phHeaderDrawer.IsNull() )
502 {
503 m_phHeaderDrawer->Resize(r.Size());
504 m_phHeaderDrawer->Draw(dc, r.left, r.top);
505 }
506 }
507 int count = m_pBuddyCtrl->GetItemCount();
508 int cpp = m_pBuddyCtrl->GetCountPerPage();
509 int si = m_pBuddyCtrl->GetTopIndex();
510 loop ( i, cpp + (m_isPartialOk ? 1 : 0) )
511 {
512 if ( si >= count )
513 {
514 break;
515 }
516 CRect rc;
517 m_pBuddyCtrl->GetItemRect(si, rc, LVIR_BOUNDS);
518 rc.left = 0;
519 rc.right = m_headerWidth;
520 m_BkDraw(dc, rc);
521 rc.left += m_offset.x;
522 rc.top += m_offset.y;
523 HRGN hRgn = ::CreateRectRgnIndirect(&rc);
524 ::SelectClipRgn(dc, hRgn);
525 if ( m_params.IsInRange(si) )
526 {
527 TParam& prm = m_params[si];
528 if ( prm.phDraw.IsNull() )
529 {
530 ::DrawText(dc, prm.text, -1, rc, m_textStyle);
531 }
532 else
533 {
534 prm.phDraw->Resize(rc.Size());
535 prm.phDraw->Draw(dc, rc.left, rc.top);
536 }
537 }
538 ::SelectClipRgn(dc, NULL);
539 _DeleteObject(hRgn);
540 si++;
541 }
542 }
543 bi.Draw(hdc);
544 }
545 // 相棒のプロシージャ
546 void m_BuddyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, LRESULT lResult)
547 {
548 switch ( message )
549 {
550 case WM_KEYDOWN:
551 case WM_VSCROLL:
552 case WM_MOUSEWHEEL:
553 case WM_SIZE:
554 {
555 CRect rc;
556 GetClientRect(rc);
557 rc.right = m_headerWidth;
558 InvalidateRect(rc, FALSE);
559 }
560 break;
561 case WM_SHOWWINDOW:
562 _super::ShowWindow((wParam != FALSE) ? SW_SHOW : SW_HIDE);
563 break;
564 case LVM_INSERTITEM:
565 if ( lResult >= 0 )
566 {
567 m_params.Insert(lResult, TParam());
568 }
569 break;
570 case LVM_DELETEITEM:
571 if ( lResult != 0 )
572 {
573 m_params.Remove(wParam);
574 }
575 break;
576 case LVM_DELETEALLITEMS:
577 if ( lResult != 0 )
578 {
579 m_params.RemoveAll();
580 }
581 break;
582 }
583 }
584
588 class CMyHooker : public CWindowProcedureHooker
589 {
590 DEFSUPER(CWindowProcedureHooker);
591 public:
592 enum
593 {
594 WM_RHC_HOOKMESSAGE = WM_APP,
595 };
597 struct TMsg
598 {
599 LRESULT lResult;
600 UINT message;
601 WPARAM wParam;
602 LPARAM lParam;
603 };
604 HWND m_hParent;
605 protected:
616 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
617 {
618 switch ( message )
619 {
620 case WM_SHOWWINDOW:
621 case WM_KEYDOWN:
622 case WM_VSCROLL:
623 case WM_MOUSEWHEEL:
624 case WM_SIZE:
625 case LVM_INSERTITEM:
626 case LVM_DELETEITEM:
627 case LVM_DELETEALLITEMS:
628 {
629 LRESULT r = _super::WindowProc(message, wParam, lParam);
630 TMsg msg = { 0 };
631 msg.message = message;
632 msg.wParam = wParam;
633 msg.lParam = lParam;
634 msg.lResult = r;
635 ::SendMessage(m_hParent, WM_RHC_HOOKMESSAGE, NULL, reinterpret_cast<LPARAM>(&msg));
636 return r;
637 }
638 break;
639 default:
640 break;
641 }
642 return _super::WindowProc(message, wParam, lParam);
643 }
644 };
645
647 struct TParam
648 {
649 CStr text;
650 IDrawable::Ptr phDraw;
651 };
652
653 TParam m_headParam;
654 CVectorT<TParam> m_params;
655 COLORREF m_textColor;
656 IDrawable::Ptr m_phHeaderDrawer;
657 IDrawable::Ptr m_phBkDrawer;
658 COLORREF m_backColor;
659 CMyHooker m_myHooker;
660 CListCtrl* m_pBuddyCtrl;
661 int m_headerWidth;
662 CPoint m_offset;
663 DWORD m_textStyle;
664 bool m_isWidthVariable;
665 HCURSOR m_hCursor;
666 bool m_hasCapture;
667 CPoint m_captureStartPos;
668 int m_captureStartHeaderWidth;
669 bool m_isPartialOk;
670};
671
672
673
674}; // MFC
675}; // TNB
ビットマップイメージ管理関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
描画情報関係のヘッダ
ビットマップDC関係のヘッダ
ウィンドウプロシージャフック関係のヘッダ
リストコントロール.
int GetItemCount(void) const
[取得] アイテム数取得.
int InsertItem(int nItem, LPCTSTR lpszItem)
[設定] アイテム挿入.
ウィンドウ管理.
DWORD GetStyle(void) const
[取得] ウィンドウスタイル取得.
BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags=0)
[設定] ウィンドウスタイル変更.
BOOL SetWindowPos(const CWnd *pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
[設定] ウィンドウサイズポジション設定.
BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags=0)
[設定] ウィンドウ拡張スタイル変更.
BOOL ShowWindow(int nCmdShow)
[設定] ウィンドウ表示状態.
HWND GetSafeHwnd(void) const
[取得] ウィンドウハンドル取得.
ビットマップイメージ管理クラス
bool Set(int cx, int cy, COLORREF color=CLR_INVALID)
[設定] イメージ設定.
bool Draw(HDC hdc, int x=0, int y=0) const
[処理] イメージ描画.
デバイステキストセレクトアシスタント
bool IsNull(void) const
[確認] NULLチェック
void Null(void)
[設定] 開放.
virtual size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbVector.h:368
virtual bool Insert(INDEX index, const TYP &t)
[追加] 要素一つ挿入
Definition: TnbVector.h:579
virtual bool Remove(INDEX index)
[削除] 要素一つ削除.
Definition: TnbVector.h:397
virtual bool SetSize(size_t size)
[操作] サイズ指定
Definition: TnbVector.h:618
virtual bool RemoveAll(void)
[削除] 空化
Definition: TnbVector.h:565
ウィンドウプロシージャフッククラス
ビットマップデバイスコンテキストクラス
ROWヘッダコントロール
bool SetBuddy(CListCtrl *pCtrl, size_t headerWidth, bool isWidthVariable=false)
[設定] 相棒リストコントロール設定.
int HitTest(const CPoint &pt) const
[取得] ヒットテスト.
CRowHeaderCtrl(void)
コンストラクタ
size_t GetItemCount(void) const
[取得] アイテム数取得
int InsertItem(int item, LPCTSTR lpszItem)
[設定] アイテム挿入.
void SetTextStyle(DWORD ts)
[設定] テキスト表示スタイル設定.
virtual void PreSubclassWindow(void)
[通知] subclassing/unsubclassing functions.
size_t GetHeaderWidth(void) const
[取得] ヘッダ幅取得.
bool SetItemText(int item, LPCTSTR lpszText)
[設定] アイテム文字情報設定.
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
void SetHeaderWidth(size_t headerWidth, bool isWidthVariable=false)
[設定] ヘッダ幅設定.
bool SetItemDrawer(int item, const IDrawable &draw)
[設定] アイテム描画情報設定.
void SetTextColor(COLORREF color)
[設定] テキストカラー設定.
void SetPartialView(bool isPartialOk=false)
[設定] 半端表示設定.
void SetBackground(COLORREF color, const IDrawable *pBkDrawer=NULL, int offsetX=2, int offsetY=0)
[設定] 背景設定
void SetHeaderDrawer(const IDrawable *pDrawer=NULL)
[設定] ヘッダ設定
int InsertItem(int item, const IDrawable &draw)
[設定] アイテム挿入.
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
TNB Library
Definition: TnbDoxyTitle.txt:2
bool IsInRange(INDEX index) const
[確認] INDEXの有効確認.
描画情報インターフェース
Definition: TnbDrawable.h:37
virtual bool Resize(const SIZE &size)=0
[設定] サイズ設定.
virtual IDrawable * Clone(void) const =0
[作成] クローン作成.
virtual void Draw(HDC dc, int x=0, int y=0) const =0
[描画] 描画.