TNB Library
TnbMfcSubEditListCtrl.h
[詳解]
1#pragma once
12
13
14
15//TNB Library
16namespace TNB {
17namespace MFC {
18
19
20
36{
38 virtual ~ISelcEditFp(void) {}
44 virtual void SetStartRect(const RECT& rect, int clientWidth) = 0;
49 virtual CEdit* GetEdit(void) = 0;
53 virtual void OnEditEnd(void) = 0;
54};
55
70template<typename TYP>
71class CSelcEditFpT : public TYP, public ISelcEditFp
72{
73 DEFSUPER(TYP);
74public:
76 CSelcEditFpT(void) : m_rect(0)
77 {
78 }
84 void SetStartRect(const RECT& rect, int clientWidth)
85 {
86 m_rect = rect;
87 m_clientWidth = clientWidth;
88 }
94 {
95 return this;
96 }
100 virtual void OnEditEnd(void) {}
101protected:
112 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
113 {
114 if ( message == WM_WINDOWPOSCHANGING )
115 {
116 WINDOWPOS* P = reinterpret_cast<WINDOWPOS*>(lParam);
117 P->y = m_rect.top;
118 P->cy = m_rect.Height();
119 if ( (P->flags & (SWP_NOSIZE | SWP_NOMOVE)) == 0 )
120 {
121 P->x = m_rect.left;
122 if ( P->cx < m_rect.Width() )
123 {
124 P->cx = m_rect.Width();
125 }
126 if ( (P->x) + (P->cx) > m_clientWidth )
127 {
128 // はみ出る
129 int d = m_clientWidth - (P->cx);
130 if ( d >= 0 )
131 {
132 P->x = d;
133 }
134 else
135 {
136 P->x = 0;
137 P->cx = m_clientWidth;
138 }
139 }
140 }
141 }
142 return _super::WindowProc(message, wParam, lParam);
143 }
144private:
145 CRect m_rect;
146 int m_clientWidth;
147};
148
149
150
221{
222 DEFSUPER(CDrawingListCtrl);
223public:
224
226 CSubEditListCtrl(void) : m_currentSubItem(-1), m_pSubclassEdit(NULL), m_isAutoEdit(false), m_editingSubItem(-1)
227 {
228 }
229
235 void SetAutoEditMode(bool isEnable)
236 {
237 m_isAutoEdit = isEnable;
238 }
239
247 bool EditSubItemLabel(int iItem, int iSubItem)
248 {
249 m_currentSubItem = iSubItem;
250 return _super::EditLabel(iItem) != NULL;
251 }
252
258 bool EditLabel(void)
259 {
260 int iItem = _super::GetSelectedItem();
261 int iSubItem = m_currentSubItem;
262 if ( iItem >= 0 && iSubItem >=0 )
263 {
264 return _super::EditLabel(iItem) != NULL;
265 }
266 return false;
267 }
268
274 bool IsEditingLabel(void) const
275 {
276 return m_editingSubItem >= 0;
277 }
278
285 int GetSelectedItem(void) const
286 {
287 return _super::GetSelectedItem();
288 }
289
294 int GetSelectedSubItem(void) const
295 {
296 return m_currentSubItem;
297 }
298
305 void SetSelectedItem(int item, int subItem)
306 {
307 m_currentSubItem = subItem;
308 _super::SetSelectedItem(item);
309 }
310
319 BOOL EnsureVisibleEx(int item, int subItem)
320 {
321 BOOL r = _super::EnsureVisible(item, FALSE);
322 m_ViewSubItem(subItem);
323 return r;
324 }
325
331 void SetDefaultMarkDrawer(COLORREF base = ::GetSysColor(COLOR_WINDOW))
332 {
333 _super::SetDefaultMarkDrawer(base);
334 _super::SetSelectMarkDrawer(
335 CMySelectDrawer(this, ::GetSysColor(COLOR_HIGHLIGHT), base, true),
336 CMySelectDrawer(this, ::GetSysColor(COLOR_BTNFACE), base, false)
337 );
338 _super::SetFocusMarkDrawer(CMyFoucsDrawer(this));
339 CTextDrawer tx(*GetFont(), RGB(0, 0, 0), _T(""), DT_END_ELLIPSIS);
340 _super::SetTextDrawer(tx);
341 }
342
351 {
352 return false;
353 }
354
363 bool SetSelectMarkDrawer(const IDrawable& draw1, const IDrawable& draw2, ESelectMarkType type = OVERLAP)
364 {
365 return false;
366 }
367
375 {
376 return false;
377 }
378
385 {
386 if ( m_pSubclassEdit != NULL )
387 {
388 return m_pSubclassEdit->GetEdit();
389 }
390 return NULL;
391 }
392
393protected:
394
402 virtual ISelcEditFp* GetSubItemEditControl(int item, int subItem)
403 {
404 return &m_myEdit;
405 }
406
415 virtual LRESULT OnItemPainting(TDrawParam* P)
416 {
417 m_drawingSubItem = P->subItemNo;
418 return _super::OnItemPainting(P);
419 }
420
433 virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* _pResult)
434 {
435 if ( message == WM_NOTIFY )
436 {
437 LPNMHDR lpNmHdr = reinterpret_cast<LPNMHDR>(lParam);
438 if ( lpNmHdr->hwndFrom == m_hWnd)
439 {
440 NMLVDISPINFO* lpLv = reinterpret_cast<NMLVDISPINFO*>(lParam);
441 if ( lpLv->hdr.code == LVN_BEGINLABELEDIT )
442 {
443 LVITEM& item = lpLv->item;
444 if ( m_currentSubItem >= 0 )
445 {
446 item.iSubItem = m_currentSubItem;
447 m_editingSubItem = m_currentSubItem;
448 if ( _super::GetItemDrawer(item.iItem, item.iSubItem) != NULL )
449 {
450 // 描画情報がある枠
451 *_pResult = TRUE;
452 return TRUE;
453 }
454 ISelcEditFp* pIEdit = GetSubItemEditControl(item.iItem, item.iSubItem);
455 if ( pIEdit == NULL )
456 {
457 *_pResult = TRUE;
458 return TRUE;
459 }
460 CEdit* pEdit = pIEdit->GetEdit();
461 m_ViewSubItem(m_currentSubItem);
462 CRect rect;
463 _super::GetSubItemRect(item.iItem, m_currentSubItem, LVIR_LABEL, rect);
464 CSize sz(max(rect.Width() + 2, 50), rect.Height() + 3);
465 CRect clRc;
466 GetClientRect(clRc);
467 CPoint pos = rect.TopLeft();
468 pos.x -= 2;
469 pos.y -= 2;
470 if ( pos.x + sz.cx > clRc.right )
471 {
472 pos.x = clRc.right - sz.cx;
473 }
474 if ( pos.x < 0 )
475 {
476 pos.x = 0;
477 }
478 CEdit* pNowEdit = _super::GetEditControl();
479 pNowEdit->SetWindowText(GetItemText(item.iItem, m_currentSubItem));
480 pIEdit->SetStartRect(CRect(pos, sz), clRc.Width());
481 pEdit->SubclassWindow(pNowEdit->m_hWnd);
482 m_pSubclassEdit = pIEdit;
483 }
484 return FALSE;
485 }
486 else if ( lpLv->hdr.code == LVN_ENDLABELEDIT )
487 {
488 if ( m_pSubclassEdit != NULL )
489 {
490 CEdit* pEd = m_pSubclassEdit->GetEdit();
491 LVITEM& item = lpLv->item;
492 if ( m_editingSubItem >= 0 && pEd->GetSafeHwnd() != NULL )
493 {
494 item.iSubItem = m_editingSubItem;
495 m_editingSubItem = -1;
496 if ( m_isAutoEdit && (item.mask & LVIF_TEXT) != 0 )
497 {
498 m_pSubclassEdit->OnEditEnd();
499 CString s;
500 pEd->GetWindowText(s);
501 _super::SetItemText(item.iItem, item.iSubItem, s);
502 }
503 pEd->UnsubclassWindow();
504 m_pSubclassEdit = NULL;
505 }
506 }
507 return FALSE;
508 }
509 }
510 }
511 return _super::OnChildNotify(message, wParam, lParam, _pResult);
512 }
513
524 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
525 {
526 switch ( message )
527 {
528 case CMySelectDrawer::WM_SELC_DRAWINGSUBITEM:
529 return m_drawingSubItem;
530 break;
531 case WM_KEYDOWN:
532 if ( wParam == VK_F2 )
533 {
534 if ( m_currentSubItem >= 0 )
535 {
536 _super::EditLabel(_super::GetSelectedItem());
537 }
538 }
539 else if ( wParam == VK_RIGHT || wParam == VK_LEFT )
540 {
541 CWnd* P = _super::GetParent();
542 if ( P != NULL )
543 {
544 // 親に通知
545 NMLVKEYDOWN nm;
546 nm.hdr.code = LVN_KEYDOWN;
547 nm.hdr.hwndFrom = _super::GetSafeHwnd();
548 nm.hdr.idFrom = _super::GetDlgCtrlID();
549 nm.wVKey = static_cast<WORD>(wParam);
550 nm.flags = 0;
551 P->SendMessage(WM_NOTIFY, nm.hdr.idFrom, reinterpret_cast<LPARAM>(&nm));
552 }
553 CHeaderCtrl* H = _super::GetHeaderCtrl();
554 int m = H->GetItemCount();
555 int c = m_currentSubItem;
556 if ( wParam == VK_RIGHT )
557 {
558 if ( m_currentSubItem < 0 )
559 {
560 m_currentSubItem = 0;
561 }
562 else if ( m_currentSubItem < m - 1 )
563 {
564 m_currentSubItem++;
565 }
566 }
567 else //if ( wParam == VK_LEFT )
568 {
569 if ( m_currentSubItem < 0 )
570 {
571 m_currentSubItem = m - 1;
572 }
573 else if ( m_currentSubItem > 0 )
574 {
575 m_currentSubItem--;
576 }
577 }
578 if ( c != m_currentSubItem )
579 {
580 m_ViewSubItem(m_currentSubItem);
581 CRect rc;
582 _super::GetItemRect(GetSelectedItem(), rc, LVIR_BOUNDS);
583 _super::InvalidateRect(rc, FALSE);
584 }
585 return 0;
586 }
587 break;
588 case WM_LBUTTONDOWN:
589 case WM_RBUTTONDOWN:
590 {
591 LVHITTESTINFO ht;
592 ht.pt = CPoint(lParam);
593 if ( _super::SubItemHitTest(&ht) >= 0 )
594 {
595 if ( m_currentSubItem != ht.iSubItem )
596 {
597 m_currentSubItem = ht.iSubItem;
598 DWORD ff = (_super::GetStyle() & LVS_EDITLABELS); //編集スタイル状態取得
599 _super::ModifyStyle(ff, 0); //編集スタイルOFF。
600 LRESULT r = _super::WindowProc(message, wParam, lParam);
601 _super::ModifyStyle(0, ff); //編集スタイル元へ。
602 CRect rc;
603 _super::GetItemRect(ht.iItem, rc, LVIR_BOUNDS);
604 _super::InvalidateRect(rc, FALSE);
605 return r;
606 }
607 }
608 }
609 break;
610 }
611 return _super::WindowProc(message, wParam, lParam);
612 }
613
619 virtual void PreSubclassWindow(void)
620 {
621 _super::PreSubclassWindow();
622 _super::ModifyStyle(0, LVS_SINGLESEL);
623 _super::SetExtendedStyle(LVS_EX_FULLROWSELECT | _super::GetExtendedStyle());
624 _super::SetAdjustWidthMode(false);
626 }
627
628private:
630 // @note 使用禁止
631 CEdit* EditLabel(int item);
632
634 void m_ViewSubItem(int subItem)
635 {
636 CRect rc;
637 //見えている範囲
638 GetClientRect(rc);
639 int cx1 = rc.Width();
640 int x1 = GetScrollPos(SB_HORZ);
641 //見せたいアイテムの範囲
642 CHeaderCtrl* H = _super::GetHeaderCtrl();
643 H->GetItemRect(subItem, rc);
644 int cx2 = rc.Width();
645 int x2 = rc.left;
646 //調整
647 int xx = x1;
648 if ( (x1 + cx1) < (x2 + cx2) )
649 {
650 xx = (x2 + cx2) - cx1;
651 }
652 if ( x1 > x2 )
653 {
654 xx = x2;
655 }
656 Scroll(CSize(xx - x1, 0));
657 }
659 class CMySelectDrawer : public CSelectedBeltDrawer
660 {
661 DEFSUPER(CSelectedBeltDrawer);
662 public:
663 enum
664 {
665 WM_SELC_DRAWINGSUBITEM = WM_APP,
666 };
667 CMySelectDrawer(CSubEditListCtrl* H, COLORREF beltColor, COLORREF backColor, bool isTextInvert = true)
668 : m_pCtrl(H), _super(beltColor, backColor, isTextInvert)
669 {
670 }
671 // [作成] クローン作成.
672 virtual IDrawable* Clone(void) const
673 {
674 CMySelectDrawer* P = new CMySelectDrawer(m_pCtrl, 0, 0, false);
675 *P = *this;
676 return P;
677 }
678 // [描画] 描画.
679 virtual void Draw(HDC dc, int x = 0, int y = 0) const
680 {
681 if ( m_pCtrl->SendMessage(WM_SELC_DRAWINGSUBITEM) == m_pCtrl->GetSelectedSubItem() )
682 {
683 _super::Draw(dc, x , y);
684 }
685 }
686 private:
687 CSubEditListCtrl* m_pCtrl;
688 };
689
691 class CMyFoucsDrawer : public CNullDrawer
692 {
693 public:
694 CMyFoucsDrawer(CSubEditListCtrl* H) : m_pCtrl(H)
695 {
696 }
697 // [作成] クローン作成.
698 virtual IDrawable* Clone(void) const
699 {
700 return new CMyFoucsDrawer(m_pCtrl);
701 }
702 // [描画] 描画.
703 virtual void Draw(HDC dc, int x = 0, int y = 0) const
704 {
705 CHeaderCtrl* H = m_pCtrl->GetHeaderCtrl();
706 if ( H != NULL )
707 {
708 CRect rc;
709 H->GetItemRect(m_pCtrl->GetSelectedSubItem(), rc);
710 rc.OffsetRect(x, y);
711 rc.bottom = rc.top + m_size.cy;
712 ::DrawFocusRect(dc, rc);
713 }
714 }
715 private:
716 CSubEditListCtrl* m_pCtrl;
717 };
718
719 class CMyEdit : public CSelcEditFpT<CEdit>
720 {
721 };
722
723 CMyEdit m_myEdit;
724 ISelcEditFp* m_pSubclassEdit;
725 bool m_isAutoEdit;
726 int m_currentSubItem;
727 int m_drawingSubItem;
728 int m_editingSubItem;
729};
730
731
732
733}; // MFC
734}; // TNB
描画情報ListCtrl関係のヘッダ
Editコントロール.
ウィンドウ管理.
HWND GetSafeHwnd(void) const
[取得] ウィンドウハンドル取得.
NULL描画クラス
Definition: TnbDrawable.h:106
SIZE m_size
サイズ
Definition: TnbDrawable.h:109
選択帯描画クラス
テキスト描画クラス
Definition: TnbTextDrawer.h:52
ESelectMarkType
セレクトマークタイプ
@ OVERLAP
アイテム描画上に描画
描画情報ListCtrlコントロール
サブアイテム編集リスト専用エディットコントロールテンプレート.
void SetStartRect(const RECT &rect, int clientWidth)
[設定] 開始表示位置指定.
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
CEdit * GetEdit(void)
[取得] CEdit取得.
virtual void OnEditEnd(void)
[通知] 編集終了通知.
CSelcEditFpT(void)
コンストラクタ
サブアイテム編集リストコントロール.
int GetSelectedSubItem(void) const
[取得] 選択サブアイテムNo取得.
virtual ISelcEditFp * GetSubItemEditControl(int item, int subItem)
[参照] サブアイテム編集コントロール取得.
void SetDefaultMarkDrawer(COLORREF base=::GetSysColor(COLOR_WINDOW))
[設定] デフォルトのマーク描画指定.
void SetAutoEditMode(bool isEnable)
[設定] 自動テキスト編集モード.
bool SetSelectMarkDrawer(const IDrawable &draw1, const IDrawable &draw2, ESelectMarkType type=OVERLAP)
[設定] 選択マーク描画指定.
bool SetSelectMarkDrawer(const IDrawable &draw, ESelectMarkType type=OVERLAP)
[設定] 選択マーク描画指定.
virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *_pResult)
[通知] for notifications from parent
bool EditLabel(void)
[設定] アイテムラベル編集開始.
CSubEditListCtrl(void)
コンストラクタ
virtual void PreSubclassWindow(void)
[通知] subclassing/unsubclassing functions.
bool SetFocusMarkDrawer(const IDrawable &draw)
[設定] フォーカスマーク描画指定.
BOOL EnsureVisibleEx(int item, int subItem)
[設定] アイテム表示.
CEdit * GetEditControl(void) const
[取得] Editコントロール取得.
bool IsEditingLabel(void) const
[確認] 編集中確認.
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
int GetSelectedItem(void) const
[取得] 選択アイテム取得.
void SetSelectedItem(int item, int subItem)
[設定] 選択アイテム設定.
bool EditSubItemLabel(int iItem, int iSubItem)
[設定] サブアイテムラベル編集開始.
virtual LRESULT OnItemPainting(TDrawParam *P)
[通知] アイテム描画.
TNB Library
Definition: TnbDoxyTitle.txt:2
描画情報インターフェース
Definition: TnbDrawable.h:37
サブアイテム編集リスト専用エディットインターフェース.
virtual void SetStartRect(const RECT &rect, int clientWidth)=0
[設定] 開始表示位置指定.
virtual CEdit * GetEdit(void)=0
[取得] CEdit取得.
virtual ~ISelcEditFp(void)
デストラクタ
virtual void OnEditEnd(void)=0
[通知] 編集終了通知.