|
1
|
1 #include "stdafx.h"
|
|
|
2 #include "CListControl.h"
|
|
|
3 #include "PaintUtils.h"
|
|
|
4 #include "DarkMode.h"
|
|
|
5
|
|
|
6 LRESULT CListControlTruncationTooltipImpl::OnTTShow(int,LPNMHDR,BOOL&) {
|
|
|
7 SetTimer(KTooltipTimer,KTooltipTimerDelay);
|
|
|
8 return 0;
|
|
|
9 }
|
|
|
10 LRESULT CListControlTruncationTooltipImpl::OnTTPop(int,LPNMHDR,BOOL&) {
|
|
|
11 KillTimer(KTooltipTimer);
|
|
|
12 return 0;
|
|
|
13 }
|
|
|
14 LRESULT CListControlTruncationTooltipImpl::OnTTGetDispInfo(int,LPNMHDR p_hdr,BOOL&) {
|
|
|
15 LPNMTTDISPINFO info = (LPNMTTDISPINFO)p_hdr;
|
|
|
16
|
|
|
17 info->lpszText = const_cast<TCHAR*>(this->m_tooltipText.get_ptr());
|
|
|
18 info->hinst = 0;
|
|
|
19 info->uFlags = 0;
|
|
|
20
|
|
|
21 return 0;
|
|
|
22 }
|
|
|
23
|
|
|
24 LRESULT CListControlTruncationTooltipImpl::OnDestroyPassThru(UINT,WPARAM,LPARAM,BOOL& bHandled) {
|
|
|
25 if (m_tooltip.m_hWnd != NULL) m_tooltip.DestroyWindow();
|
|
|
26 KillTimer(KTooltipTimer);
|
|
|
27 bHandled = FALSE; return 0;
|
|
|
28 }
|
|
|
29
|
|
|
30 CListControlTruncationTooltipImpl::CListControlTruncationTooltipImpl()
|
|
|
31 : m_toolinfo()
|
|
|
32 , m_tooltipRect(0,0,0,0)
|
|
|
33 {
|
|
|
34 }
|
|
|
35
|
|
|
36
|
|
|
37
|
|
|
38 void CListControlTruncationTooltipImpl::TooltipRemove() {
|
|
|
39 m_tooltipRect = CRect(0,0,0,0);
|
|
|
40 if (m_tooltip.m_hWnd != NULL) {
|
|
|
41 m_tooltip.TrackActivate(&m_toolinfo,FALSE);
|
|
|
42 }
|
|
|
43 }
|
|
|
44
|
|
|
45 void CListControlTruncationTooltipImpl::TooltipRemoveCheck() {
|
|
|
46 CPoint pt; ;
|
|
|
47 if (GetCursorPos(&pt) && ScreenToClient(&pt)) {
|
|
|
48 TooltipRemoveCheck( MAKELPARAM( pt.x, pt.y ) );
|
|
|
49 }
|
|
|
50 }
|
|
|
51 void CListControlTruncationTooltipImpl::TooltipRemoveCheck(LPARAM pos) {
|
|
|
52 if (!m_tooltipRect.IsRectEmpty()) {
|
|
|
53 CPoint pt(pos);
|
|
|
54 if (!GetClientRectHook().PtInRect(pt)) {
|
|
|
55 TooltipRemove();
|
|
|
56 } else {
|
|
|
57 ClientToScreen(&pt);
|
|
|
58 if (!m_tooltipRect.PtInRect(pt)) {
|
|
|
59 TooltipRemove();
|
|
|
60 }
|
|
|
61 }
|
|
|
62 }
|
|
|
63 }
|
|
|
64
|
|
|
65 LRESULT CListControlTruncationTooltipImpl::OnTimer(UINT,WPARAM wp,LPARAM,BOOL& bHandled) {
|
|
|
66 switch(wp) {
|
|
|
67 case KTooltipTimer:
|
|
|
68 TooltipRemoveCheck();
|
|
|
69 return 0;
|
|
|
70 default:
|
|
|
71 bHandled = FALSE;
|
|
|
72 return 0;
|
|
|
73 }
|
|
|
74 }
|
|
|
75
|
|
|
76 LRESULT CListControlTruncationTooltipImpl::OnMouseMovePassThru(UINT,WPARAM,LPARAM lp,BOOL& bHandled) {
|
|
|
77 TooltipRemoveCheck(lp);
|
|
|
78 {
|
|
|
79 TRACKMOUSEEVENT ev = {sizeof(ev)};
|
|
|
80 ev.dwFlags = TME_HOVER;
|
|
|
81 ev.hwndTrack = *this;
|
|
|
82 ev.dwHoverTime = HOVER_DEFAULT;
|
|
|
83 TrackMouseEvent(&ev);
|
|
|
84 }
|
|
|
85 bHandled = FALSE;
|
|
|
86 return 0;
|
|
|
87 }
|
|
|
88
|
|
|
89
|
|
|
90 bool CListControlTruncationTooltipImpl::IsRectPartiallyObscuredAbs(CRect const & r) const {
|
|
|
91 const CRect cl = GetVisibleRectAbs();
|
|
|
92 return r.right > cl.right || r.top < cl.top || r.bottom > cl.bottom;
|
|
|
93 }
|
|
|
94
|
|
|
95 bool CListControlTruncationTooltipImpl::IsRectFullyVisibleAbs(CRect const & r) {
|
|
|
96 const CRect cl = GetVisibleRectAbs();
|
|
|
97 return r.left >= cl.left && r.right <= cl.right && r.top >= cl.top && r.bottom <= cl.bottom;
|
|
|
98 }
|
|
|
99
|
|
|
100 bool CListControlTruncationTooltipImpl::GetTooltipData(CPoint pt, pfc::string_base & outText, CRect & outRC, CFontHandle & outFont) const {
|
|
|
101 t_size item;
|
|
|
102 if (ItemFromPointAbs(pt, item)) {
|
|
|
103 PFC_ASSERT(item < GetItemCount());
|
|
|
104 const CRect itemRectAbs = this->GetItemRectAbs(item);
|
|
|
105 /*if (this->IsHeaderEnabled()) */{
|
|
|
106 t_uint32 cbase = 0;
|
|
|
107 auto orderArray = this->GetColumnOrderArray();
|
|
|
108 for (t_size _cwalk = 0; _cwalk < orderArray.size(); ++_cwalk) {
|
|
|
109 const t_size cwalk = orderArray[_cwalk];
|
|
|
110 //const TColumnRuntime & col = m_columns[cwalk];
|
|
|
111
|
|
|
112 const t_uint32 width = GetSubItemWidth(cwalk);
|
|
|
113 if ((t_uint32)pt.x < cbase + width) {
|
|
|
114 t_uint32 estWidth = GetOptimalSubItemWidthSimple(item, cwalk);
|
|
|
115 CRect rc = itemRectAbs; rc.left = cbase; rc.right = cbase + estWidth;
|
|
|
116 if (estWidth > width || (IsRectPartiallyObscuredAbs(rc) && rc.PtInRect(pt))) {
|
|
|
117 pfc::string_formatter label, ccTemp;
|
|
|
118 if (GetSubItemText(item, cwalk, label)) {
|
|
|
119 PaintUtils::TextOutColors_StripCodes(ccTemp, label);
|
|
|
120 outFont = GetFont(); outRC = rc; outText = ccTemp;
|
|
|
121 return true;
|
|
|
122 }
|
|
|
123 }
|
|
|
124 break;
|
|
|
125 }
|
|
|
126 cbase += width;
|
|
|
127 }
|
|
|
128 }
|
|
|
129 } else if (GroupHeaderFromPointAbs2(pt, item)) {
|
|
|
130 CRect rc;
|
|
|
131 if (GetGroupHeaderRectAbs2(item, rc) && rc.PtInRect(pt)) {
|
|
|
132 const t_uint32 estWidth = GetOptimalGroupHeaderWidth2( item );
|
|
|
133 CRect rcText = rc; rcText.right = rcText.left + estWidth;
|
|
|
134 if (estWidth > (t_uint32)rc.Width() || (IsRectPartiallyObscuredAbs(rcText) && rcText.PtInRect(pt))) {
|
|
|
135 pfc::string_formatter label;
|
|
|
136 if (GetGroupHeaderText2(item, label)) {
|
|
|
137 outFont = GetGroupHeaderFont(); outRC = rc; outText = label;
|
|
|
138 return true;
|
|
|
139 }
|
|
|
140 }
|
|
|
141 }
|
|
|
142 }
|
|
|
143 return false;
|
|
|
144 }
|
|
|
145 LRESULT CListControlTruncationTooltipImpl::OnHover(UINT,WPARAM wp,LPARAM lp,BOOL&) {
|
|
|
146 if (!m_tooltipRect.IsRectEmpty()) {
|
|
|
147 return 0;
|
|
|
148 }
|
|
|
149 if (wp & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) return 0;
|
|
|
150
|
|
|
151 const CPoint pt = PointClientToAbs(CPoint(lp));
|
|
|
152
|
|
|
153 CFontHandle font;
|
|
|
154 CRect rc;
|
|
|
155 pfc::string8 text;
|
|
|
156 if ( this->GetTooltipData(pt, text, rc, font) ) {
|
|
|
157 this->m_tooltipFont = font;
|
|
|
158 // Gets stuck if the text is very long!
|
|
|
159 if (text.length() < 4096) {
|
|
|
160 TooltipActivateAbs(text, rc);
|
|
|
161 }
|
|
|
162 }
|
|
|
163 return 0;
|
|
|
164 }
|
|
|
165
|
|
|
166 void CListControlTruncationTooltipImpl::TooltipActivateAbs(const char * label, const CRect & rect) {
|
|
|
167 CRect temp = RectAbsToClient(rect);
|
|
|
168 ClientToScreen(temp);
|
|
|
169 TooltipActivate(label,temp);
|
|
|
170 }
|
|
|
171 void CListControlTruncationTooltipImpl::TooltipActivate(const char * label, const CRect & rect) {
|
|
|
172 if (rect.IsRectEmpty()) return;
|
|
|
173 if (m_tooltip.m_hWnd == NULL) {
|
|
|
174 try {
|
|
|
175 InitTooltip();
|
|
|
176 } catch(std::exception const & e) {
|
|
|
177 (void) e;
|
|
|
178 // console::complain("Tooltip initialization failure", e);
|
|
|
179 return;
|
|
|
180 }
|
|
|
181 }
|
|
|
182
|
|
|
183 m_tooltipText.convert( EscapeTooltipText( label ) );
|
|
|
184
|
|
|
185 m_tooltipRect = rect;
|
|
|
186
|
|
|
187 TooltipUpdateFont();
|
|
|
188 m_tooltip.TrackPosition(rect.left,rect.top);
|
|
|
189 m_tooltip.TrackActivate(&m_toolinfo,TRUE);
|
|
|
190 }
|
|
|
191
|
|
|
192 void CListControlTruncationTooltipImpl::TooltipUpdateFont() {
|
|
|
193 if (m_tooltip.m_hWnd != NULL) {
|
|
|
194 if (m_tooltipFont) {
|
|
|
195 m_tooltip.SetFont(m_tooltipFont);
|
|
|
196 }
|
|
|
197 }
|
|
|
198 }
|
|
|
199
|
|
|
200 void CListControlTruncationTooltipImpl::InitTooltip() {
|
|
|
201 m_tooltipRect = CRect(0,0,0,0);
|
|
|
202 WIN32_OP( m_tooltip.Create(NULL,NULL,NULL,WS_POPUP,WS_EX_TRANSPARENT) );
|
|
|
203 m_toolinfo.cbSize = sizeof(m_toolinfo);
|
|
|
204 m_toolinfo.uFlags = TTF_TRACK | TTF_IDISHWND | TTF_ABSOLUTE | TTF_TRANSPARENT;
|
|
|
205 m_toolinfo.hwnd = *this;
|
|
|
206 m_toolinfo.uId = 0;
|
|
|
207 m_toolinfo.lpszText = LPSTR_TEXTCALLBACK;
|
|
|
208 m_toolinfo.hinst = GetThisModuleHandle();
|
|
|
209 WIN32_OP_D( m_tooltip.AddTool(&m_toolinfo) );
|
|
|
210
|
|
|
211 if ( GetDarkMode() ) DarkMode::ApplyDarkThemeCtrl(m_tooltip, true );
|
|
|
212 }
|
|
|
213
|
|
|
214 void CListControlTruncationTooltipImpl::RefreshDarkMode() {
|
|
|
215 __super::RefreshDarkMode();
|
|
|
216 if (m_tooltip) {
|
|
|
217 DarkMode::ApplyDarkThemeCtrl(m_tooltip, GetDarkMode() );
|
|
|
218 }
|
|
|
219 }
|