TNB Library
TnbMfcColorfulListBox.h
[詳解]
1#pragma once
11#include "TnbPointerVector.h"
12#include "TnbMfcListBoxCp.h"
13#include "TnbMfcBitmapDC.h"
15
16
17
18//TNB Library
19namespace TNB {
20namespace MFC {
21
22
23
81{
82 DEFSUPER(CListBoxCp);
83public:
84
91 class CColor
92 {
93 public:
95 struct TParam
96 {
97 size_t len;
98 COLORREF textColor;
99 COLORREF backColor;
100 };
105 CColor(void) : m_textColor(::GetSysColor(COLOR_WINDOWTEXT)), m_backColor(::GetSysColor(COLOR_WINDOW))
106 {
107 }
113 CColor(COLORREF textColor, COLORREF backColor) : m_textColor(textColor), m_backColor(backColor)
114 {
115 }
121 bool IsEmpty(void) const
122 {
123 return m_infos.IsEmpty();
124 }
128 void RemoveAll(void)
129 {
130 m_infos.RemoveAll();
131 m_params.RemoveAll();
132 }
140 void Add(INDEX pos, size_t len, COLORREF textColor = CLR_INVALID, COLORREF backColor = CLR_INVALID)
141 {
142 if ( ! IS_RGBVALUE(textColor) )
143 {
144 textColor = m_textColor;
145 }
146 if ( ! IS_RGBVALUE(backColor) )
147 {
148 backColor = m_backColor;
149 }
150 if ( pos + len >= m_infos.GetSize() )
151 {
152 TInfo pa(m_textColor, m_backColor);
153 loop ( i, (pos + len) - m_infos.GetSize() )
154 {
155 m_infos.Add(pa);
156 }
157 }
158 TInfo pa(textColor, backColor);
159 loop ( i, len )
160 {
161 m_infos.Set(pos + i, pa);
162 }
163 m_params.RemoveAll();
164 }
172 const CVectorT<TParam>& GetParam(void) const
173 {
174 if ( m_params.IsEmpty() )
175 {
176 if ( m_infos.IsEmpty() )
177 {
178 TParam pa = { 100000, m_textColor, m_backColor };
179 m_params.Add(pa);
180 }
181 else
182 {
183 size_t ll = 0;
184 loop ( i, m_infos.GetSize() - 1 )
185 {
186 ll++;
187 if ( m_infos[i].textColor != m_infos[i + 1].textColor || m_infos[i].backColor != m_infos[i + 1].backColor )
188 {
189 //違う
190 TParam pa = { ll, m_infos[i].textColor, m_infos[i].backColor };
191 m_params.Add(pa);
192 ll = 0;
193 }
194 }
195 ll++;
196 INDEX i = m_infos.GetSize() - 1;
197 TParam pa = { ll, m_infos[i].textColor, m_infos[i].backColor };
198 m_params.Add(pa);
199 TParam pa2 = { 100000, m_textColor, m_backColor };
200 m_params.Add(pa2);
201 }
202 }
203 return m_params;
204 }
205
206 private:
208 struct TInfo
209 {
210 COLORREF textColor;
211 COLORREF backColor;
213 TInfo(COLORREF text = 0, COLORREF back = 0)
214 : textColor(text), backColor(back)
215 {
216 }
217 };
218 CVectorT<TInfo> m_infos;
219 mutable CVectorT<TParam> m_params;
220 COLORREF m_textColor;
221 COLORREF m_backColor;
222 };
223
226 : _super(), m_iItemHeight(-1), m_iItemWidth(-1), m_margin(0), m_isView(true), m_postCount(-1), m_oneCharWidth(-1)
227 {
228 }
229
232 {
233 m_ColorsRemoveAll();
234 }
235
242 {
243 m_currentColor = color;
244 }
245
252 void SetColor(INDEX nIndex, const CColorfulListBox::CColor& color)
253 {
254 if ( m_colors.GetSize() > nIndex )
255 {
256 m_colors[nIndex]->color = color;
257 RedrawWindow();
258 }
259 }
260
265 void SetMargin(DWORD m)
266 {
267 m_margin = m;
268 m_iItemHeight = -1;
269 }
270
277 void SetPostViewMode(bool isView, bool isDelayMode = false)
278 {
279 m_isView = isView;
280 m_postCount = isDelayMode ? 0 : -1;
281 }
282
291 void PostString(int nIndex, LPCTSTR lpszItem)
292 {
293 CColor c;
294 PostString(nIndex, lpszItem, c);
295 }
296
307 void PostString(int nIndex, LPCTSTR lpszItem, const CColorfulListBox::CColor& color)
308 {
309 if ( ! ::IsWindow(m_hWnd) )
310 {
311 return;
312 }
313 TParam* P = new TParam;
314 P->item = lpszItem;
315 P->color = color;
316 if ( ! _super::PostMessage(WM_CLB_POSTSTRING, nIndex, reinterpret_cast<LPARAM>(P)) )
317 {
318 delete P;
319 }
320 }
321
332 int InsertString(int nIndex, LPCTSTR lpszItem)
333 {
334 return _super::InsertString(nIndex, lpszItem);
335 }
336
345 int AddString(LPCTSTR lpszItem)
346 {
347 return _super::AddString(lpszItem);
348 }
349
350protected:
351
356 virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
357 {
358 if ( lpDrawItemStruct->CtlType != ODT_LISTBOX || lpDrawItemStruct->hwndItem != _super::GetSafeHwnd() )
359 {
360 return;
361 }
362 UINT nIndex = lpDrawItemStruct->itemID;
363// if ( static_cast<UINT>(m_linesString.GetSize()) <= nIndex )
364 if ( static_cast<UINT>(m_colors.GetSize()) <= nIndex )
365 {
366 return;
367 }
368 CString strText = m_colors[nIndex]->item;
369 CRect rcItem = lpDrawItemStruct->rcItem;
370 const CColor& colors = m_colors[nIndex]->color;
371 const CVectorT<CColor::TParam> vp = colors.GetParam();
372 //
373 CBitmapImage bi;
374 bi.Set(rcItem.Width(), rcItem.Height());
375 {
376 CRect rect = rcItem;
377 rect.OffsetRect(-rect.left, -rect.top);
378 CRect rc2 = rect;
379 //
380 CBitmapDC dc(&bi);
381 CDcSelectAssistant dca(dc);
382 dca.SelectFont(_super::GetFont());
383 dca.SetBkMode(TRANSPARENT);
384 rect.top += m_margin;
385 COLORREF colorText = 0;
386 COLORREF colorBack = 0;
387 loop ( i, vp.GetSize() )
388 {
389 const CColor::TParam& v = vp[i];
390 CString s = strText.Left(ToInt(v.len));
391 colorText = v.textColor;
392 colorBack = v.backColor;
393 if ( (lpDrawItemStruct->itemState & ODS_SELECTED) != 0 )
394 {
395 colorText = v.backColor;
396 colorBack = v.textColor;
397 }
398 if ( s.IsEmpty() )
399 {
400 rect.right = rect.left;
401 }
402 else
403 {
404 dc.DrawText(s, &rect, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT);
405 dc.FillSolidRect(&rect, colorBack);
406 dca.SetTextColor(colorText);
407 dc.DrawText(s, &rect, DT_SINGLELINE | DT_NOPREFIX);
408 rect.left = rect.right;
409 }
410 rect.right = lpDrawItemStruct->rcItem.right;
411 if ( strText.GetLength() > ToInt(v.len) )
412 {
413 strText = strText.Mid(ToInt(v.len));
414 }
415 else
416 {
417 strText.Empty();
418 }
419 }
420 dc.FillSolidRect(&rect, colorBack);
421 if ( ! strText.IsEmpty() )
422 {
423 dca.SetTextColor(colorText);
424 dc.DrawText(strText, &rect, DT_SINGLELINE | DT_NOPREFIX);
425 }
426 //
427 if ( (lpDrawItemStruct->itemState & ODS_FOCUS) != 0 )
428 {
429 dca.SetTextColor(RGB(255, 255, 255));
430 dc.DrawFocusRect(&rc2); //破線
431 }
432 }
433 bi.Draw(lpDrawItemStruct->hDC, rcItem.left, rcItem.top);
434 }
435
440 virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
441 {
442 if ( lpMeasureItemStruct->CtlType != ODT_LISTBOX || ToInt(lpMeasureItemStruct->CtlID) != _super::GetDlgCtrlID() )
443 {
444 return;
445 }
446 if ( m_iItemHeight < 0 )
447 {
448 LOGFONT lf;
449 GetFont()->GetLogFont(&lf);
450 m_iItemHeight = lf.lfHeight;
451 if ( m_iItemHeight < 0 )
452 {
453 m_iItemHeight = -m_iItemHeight;
454 }
455 m_iItemHeight += m_margin * 2;
456 }
457 lpMeasureItemStruct->itemHeight = m_iItemHeight;
458 }
459
460protected:
461
472 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
473 {
474 int iIndex = ToInt(wParam);
475 switch ( message )
476 {
477 case WM_ERASEBKGND: //背景
478 {
479 CDC dc;
480 dc.Attach(reinterpret_cast<HDC>(wParam));
481 CRect rect;
482 GetClientRect(rect);
483 int y = (GetCount() - GetTopIndex()) * m_iItemHeight;
484 int h = rect.Height();
485 if( h > y )
486 {
487 if ( y < 0 )
488 {
489 y = 0;
490 }
491 CBrush* B = dc.GetCurrentBrush();
492 dc.FillRect(CRect(0, y, rect.Width(), h), B);
493 }
494 dc.Detach();
495 }
496 return 0;
497 case WM_SETFONT:
498 m_oneCharWidth = -1;
499 break;
500 case WM_SETFOCUS:
501 case WM_KILLFOCUS:
502 RedrawWindow();
503 break;
504 case LB_GETTEXTLEN: //文字列長取得
505 // @param iIndex INDEX
506 // @return 長さ
507 if ( IsInRange(iIndex, m_colors.GetSize()) )
508 {
509 return m_colors[iIndex]->item.GetLength();
510 }
511 return 0;
512 case LB_GETTEXT: //文字列取得
513 // @param[in] iIndex INDEX
514 // @param[out] lParam 格納先
515 if ( IsInRange(iIndex, m_colors.GetSize()) )
516 {
517 STRLIB::Copy(reinterpret_cast<TCHAR*>(lParam), m_colors[iIndex]->item);
518 }
519 return 0;
520 case LB_DELETESTRING: //削除
521 // @param iIndex INDEX
522 if ( IsInRange(iIndex, m_colors.GetSize()) )
523 {
524// m_linesString.RemoveAt(iIndex);
525 delete m_colors[iIndex];
526 m_colors.Remove(iIndex);
527 }
528 break;
529 case LB_ADDSTRING: //追加
530 // @param lParam 文字列アドレス
531 // @note 実際コントロールに設定するのは ""
532 {
533 ASSERTLIB( ToInt(m_colors.GetSize()) == _super::GetCount() );
534// INT_PTR i = m_linesString.Add(reinterpret_cast<LPCTSTR>(lParam));
535 TParam* P = new TParam;
536 P->item = reinterpret_cast<LPCTSTR>(lParam);
537 P->color = m_currentColor;
538 m_colors.Add(P);
539 m_CheckWidth(P->item);
540 }
541 lParam = reinterpret_cast<LPARAM>(_T(""));
542 break;
543 case LB_INSERTSTRING: //挿入
544 // @param iIndex INDEX
545 // @param lParam 文字列アドレス
546 // @note 実際コントロールに設定するのは ""
547 if ( iIndex < 0 )
548 {
549 ASSERTLIB( ToInt(m_colors.GetSize()) == _super::GetCount() );
550 TParam* P = new TParam;
551 P->item = reinterpret_cast<LPCTSTR>(lParam);
552 P->color = m_currentColor;
553 m_colors.Add(P);
554 m_CheckWidth(P->item);
555 }
556 else if ( IsInRange(iIndex, m_colors.GetSize() + 1) )
557 {
558 // m_linesString.InsertAt(iIndex, reinterpret_cast<LPCTSTR>(lParam));
559 TParam* P = new TParam;
560 P->item = reinterpret_cast<LPCTSTR>(lParam);
561 P->color = m_currentColor;
562 m_colors.Insert(iIndex, P);
563 m_CheckWidth(P->item);
564 }
565 lParam = reinterpret_cast<LPARAM>(_T(""));
566 break;
567 case LB_RESETCONTENT: //全消し
568// m_linesString.RemoveAll();
569// m_colors.RemoveAll();
570 m_ColorsRemoveAll();
571 m_iItemWidth = -1;
572 _super::SetHorizontalExtent(m_iItemWidth);
573 break;
574 case WM_TIMER:
575 if ( wParam == TIMERID_SETTOPINDEX )
576 {
577 KillTimer(TIMERID_SETTOPINDEX);
578 m_postCount = 0;
579 _super::SetTopIndex(m_lastPostIndex);
580 }
581 break;
582 case WM_CLB_POSTSTRING:
583 {
584 TParam* P = reinterpret_cast<TParam*>(lParam);
585 if ( ! P->color.IsEmpty() )
586 {
587 m_currentColor = P->color;
588 }
589 if ( ::IsWindow(m_hWnd) )
590 {
591// CStr s;
592// s.Format("%s -(%d)", P->item, GetCount());
593// LRESULT r = _super::InsertString(iIndex, s);
594 LRESULT r = _super::InsertString(iIndex, P->item);
595 KillTimer(TIMERID_SETTOPINDEX);
596 if ( m_isView )
597 {
598 if ( m_postCount < 0 )
599 {
600 _super::SetTopIndex(ToInt(r));
601 }
602 else if ( ++m_postCount > 4 )
603 {
604 m_postCount = 0;
605 _super::SetTopIndex(ToInt(r));
606 }
607 else
608 {
609 m_lastPostIndex = ToInt(r);
610 SetTimer(TIMERID_SETTOPINDEX, 100, NULL);
611 }
612 }
613 }
614 delete P;
615 return 0;
616 }
617 break;
618 case WM_DESTROY:
619 {
620 MSG msg;
621 while ( ::PeekMessage(&msg, m_hWnd, WM_CLB_POSTSTRING, WM_CLB_POSTSTRING, PM_REMOVE) )
622 {
623 if ( msg.message == WM_CLB_POSTSTRING )
624 {
625 TParam* P = reinterpret_cast<TParam*>(msg.lParam);
626 delete P;
627 }
628 }
629 }
630 break;
631 }
632 return _super::WindowProc(message, wParam, lParam);
633 }
639 virtual void PreSubclassWindow(void)
640 {
641 #ifdef _DEBUG
642 DWORD dwStyle = _super::GetStyle();
643 ASSERT( dwStyle & LBS_OWNERDRAWVARIABLE );
644 ASSERT( dwStyle & LBS_EXTENDEDSEL );
645 ASSERT( dwStyle & LBS_HASSTRINGS );
646 ASSERT( m_colors.GetSize() == 0 );
647 #endif
648 _super::PreSubclassWindow();
649 }
653 virtual void PostNcDestroy(void)
654 {
655// m_linesString.RemoveAll();
656// m_colors.RemoveAll();
657 m_ColorsRemoveAll();
658 _super::PostNcDestroy();
659 }
660
661private:
662 enum { TIMERID_SETTOPINDEX = 1 };
664 struct TParam
665 {
666 CString item;
667 CColor color;
668 };
669 int m_iItemHeight;
670 int m_iItemWidth;
671 CColor m_currentColor;
672 CVectorT<TParam*> m_colors;
673// CPointerVectorT<TParam> m_colors; ///< 表示文字のカラー
674// CPointerVectorT<CColor> m_colors; ///< 表示文字のカラー
675// CStringArray m_linesString; ///< 表示文字の内容
676 DWORD m_margin;
677 bool m_isView;
678 int m_oneCharWidth;
679 //
680 DWORD m_lastPostIndex;
681 int m_postCount;
682
683 void m_ColorsRemoveAll(void)
684 {
685 loop ( i, m_colors )
686 {
687 delete m_colors[i];
688 }
689 m_colors.RemoveAll();
690 }
691
695 void m_CheckWidth(const CString& strItem)
696 {
697 if ( m_oneCharWidth < 0 )
698 {
699 CDC* pDC = GetDC();
700 CFont* pFont = _super::GetFont();
701 CFont* pFontOld = pDC->SelectObject(pFont);
702 m_oneCharWidth = pDC->GetTextExtent("W").cx;
703 pDC->SelectObject(pFontOld);
704 ReleaseDC(pDC);
705 }
706 int l = strItem.GetLength() * m_oneCharWidth;
707 if ( m_iItemWidth < l )
708 {
709 m_iItemWidth = l;
710 _super::SetHorizontalExtent(m_iItemWidth);
711 }
712 }
713};
714
715
716
717}; // MFC
718}; // TNB
デバイステキストセレクトアシスタント関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
ビットマップDC関係のヘッダ
コピー機能付ListBox関係のヘッダ
ポインタ配列管理関係のヘッダ
ビットマップイメージ管理クラス
bool Set(int cx, int cy, COLORREF color=CLR_INVALID)
[設定] イメージ設定.
bool Draw(HDC hdc, int x=0, int y=0) const
[処理] イメージ描画.
デバイステキストセレクトアシスタント
void SetTextColor(COLORREF c)
[設定] 文字色設定.
void SetBkMode(int mode)
[設定] 背景モード設定.
void SelectFont(HFONT font)
[選択] フォント選択.
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 RemoveAll(void)
[削除] 空化
Definition: TnbVector.h:565
virtual INDEX Add(const TYP &t)
[追加] 要素一つ追加.
Definition: TnbVector.h:383
virtual bool Set(INDEX index, const TYP &t)
[設定] 要素の設定.
Definition: TnbVector.h:265
ビットマップデバイスコンテキストクラス
カラフルListBoxコントロールのカラー情報.
void Add(INDEX pos, size_t len, COLORREF textColor=CLR_INVALID, COLORREF backColor=CLR_INVALID)
[追加] 色情報追加.
bool IsEmpty(void) const
[確認] 空っぽ?
void RemoveAll(void)
[消去] 全消去.
CColor(COLORREF textColor, COLORREF backColor)
コンストラクタ
const CVectorT< TParam > & GetParam(void) const
[取得] 情報一覧取得.
カラフルListBoxコントロール
CColorfulListBox(void)
コンストラクタ
void PostString(int nIndex, LPCTSTR lpszItem)
[追加] 文字列追加.
void SetColor(INDEX nIndex, const CColorfulListBox::CColor &color)
[設定] 文字色設定.
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
[通知] オーナードロー通知.
void PostString(int nIndex, LPCTSTR lpszItem, const CColorfulListBox::CColor &color)
[追加] 文字列追加.
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
[通知] オーナードロー計算通知.
virtual void PostNcDestroy(void)
破棄
void SetMargin(DWORD m)
[設定] マージン設定
virtual void PreSubclassWindow(void)
[通知] subclassing/unsubclassing functions.
int InsertString(int nIndex, LPCTSTR lpszItem)
[追加] 文字列追加.
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
void SetPostViewMode(bool isView, bool isDelayMode=false)
[設定] PostString表示モード設定.
void SetCurrentColor(const CColorfulListBox::CColor &color)
[設定] 文字色設定.
~CColorfulListBox(void)
デストラクタ
int AddString(LPCTSTR lpszItem)
[追加] 文字列追加.
文字列コピー機能付ListBoxコントロール
void Copy(LPSTR _dst, LPCSTR src)
[複製] 文字列コピー(ASCII/SJIS用)
Definition: TnbStrLib.h:89
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
bool IsInRange(INDEX value, size_t size)
[確認] 範囲チェック.
Definition: TnbDef.h:421
TNB Library
Definition: TnbDoxyTitle.txt:2
bool IsEmpty(void) const
[確認] 要素の有無確認.