1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (c) 2003 by Andreas Kapust <info@akinstaller.de>; <http://www.codeproject.com/Articles/2607/AutoComplete-without-IAutoComplete>
4 // Copyright (C) 2009, 2012-2013, 2015-2016 - TortoiseGit
6 // Licensed under: The Code Project Open License (CPOL); <http://www.codeproject.com/info/cpol10.aspx>
8 // ACWnd.cpp: Implementierungsdatei
12 #include "ACListWnd.h"
17 static char THIS_FILE
[] = __FILE__
;
20 static UINT auIDStatusBar
[] =
25 #define _MAX_ENTRYS_ 8
26 #define _MODE_FIND_ALL_ (1L << 5)
28 /////////////////////////////////////////////////////////////////////////////
31 void DoPaintMessageLoop()
34 while (::PeekMessage(&message1
, nullptr, WM_PAINT
, WM_PAINT
, PM_REMOVE
))
36 ::TranslateMessage(&message1
);
37 ::DispatchMessage(&message1
);
41 /**********************************************************************/
43 CACListWnd::CACListWnd()
50 m_pEditParent
= nullptr;
51 m_LastSize
.SetRectEmpty();
56 SecureZeroMemory(&logfont
, sizeof(LOGFONT
));
59 /**********************************************************************/
61 CACListWnd::~CACListWnd()
63 m_SearchList
.RemoveAll();
64 m_DisplayList
.RemoveAll();
68 /*********************************************************************/
70 void CACListWnd::OnActivateApp(BOOL bActive
, DWORD dwThreadID
)
72 #if (_MSC_VER >= 1300)
73 CWnd::OnActivateApp(bActive
, dwThreadID
); //vc7 FIX 1.2
75 CWnd::OnActivateApp(bActive
, (HTASK
)dwThreadID
); //vc6 FIX 1.2
82 BEGIN_MESSAGE_MAP(CACListWnd
, CWnd
)
83 //{{AFX_MSG_MAP(CACListWnd)
100 ON_WM_GETMINMAXINFO()
105 /////////////////////////////////////////////////////////////////////////////
106 // Behandlungsroutinen für Nachrichten CACListWnd
108 void CACListWnd::DrawItem(CDC
* pDC
,long m_lItem
,long width
)
110 long y
= m_lItem
- m_lTopIndex
;
111 CRect
rcLabel(2,y
*m_ItemHeight
,width
,(y
+1)*m_ItemHeight
);
113 pDC
->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT
));
115 if(m_lItem
== m_lSelItem
)
118 pDC
->FillSolidRect(rcLabel
,::GetSysColor(COLOR_HIGHLIGHT
));
119 pDC
->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT
));
124 m_DisplayStr
= m_PrefixChar
+ m_DisplayList
.GetAt(m_lItem
);
126 m_DisplayStr
= m_DisplayList
.GetAt(m_lItem
);
128 pDC
->DrawText(m_DisplayStr
, -1, rcLabel
, DT_LEFT
| DT_SINGLELINE
|
129 DT_NOPREFIX
| DT_VCENTER
| DT_END_ELLIPSIS
);
132 /*********************************************************************/
134 void CACListWnd::OnPaint()
137 CRect rcWnd
,m_rect
, rc
;
138 CDC MemDC
, *pDC
= nullptr;
139 CBitmap m_bitmap
, *m_pOldBitmap
;
145 rc
.left
= rc
.right
-GetSystemMetrics(SM_CXHSCROLL
);
146 rc
.top
= rc
.bottom
-GetSystemMetrics(SM_CYVSCROLL
);
148 m_rect
.right
-= ScrollBarWidth();
150 MemDC
.CreateCompatibleDC(&dc
);
152 m_bitmap
.CreateCompatibleBitmap(&dc
, m_rect
.Width(), m_rect
.Height());
153 m_pOldBitmap
= MemDC
.SelectObject(&m_bitmap
);
155 MemDC
.SetWindowOrg(m_rect
.left
, m_rect
.top
);
157 long width
= rcWnd
.Width() - ScrollBarWidth();
159 MemDC
.FillSolidRect(rcWnd
,::GetSysColor(COLOR_WINDOW
));
160 MemDC
.SelectObject(GetStockObject(DEFAULT_GUI_FONT
));
161 MemDC
.SetBkMode(TRANSPARENT
);
163 for(i
= m_lTopIndex
; i
< m_lCount
;i
++)
165 DrawItem(&MemDC
,i
,width
);
169 CPen
m_Pen1(PS_SOLID
, 1, ::GetSysColor(COLOR_WINDOW
));
170 CPen
m_Pen2(PS_SOLID
, 1, ::GetSysColor(COLOR_BTNFACE
));
171 CPen
m_Pen3(PS_SOLID
, 1, ::GetSysColor(COLOR_3DSHADOW
));
175 if(m_VertBar
.IsWindowVisible())
176 dc
.FillSolidRect(rc
, ::GetSysColor(COLOR_BTNFACE
) );
180 CPen
*pOldPen
= (CPen
*)pDC
->SelectObject(&m_Pen1
);
183 width
= GetSystemMetrics(SM_CXHSCROLL
);
184 bottom
= (rcWnd
.bottom
-GetSystemMetrics(SM_CXHSCROLL
))-1;
187 for( i
= 0; i
< 20 ;i
++,a
++)
190 pDC
->SelectObject(&m_Pen1
);
192 pDC
->SelectObject(&m_Pen2
);
194 pDC
->SelectObject(&m_Pen3
);
198 pDC
->MoveTo(rc
.left
+ i
- 1, rcWnd
.bottom
);
199 pDC
->LineTo(rc
.left
+ i
+ width
, bottom
);
202 dc
.BitBlt(m_rect
.left
, m_rect
.top
, m_rect
.Width(), m_rect
.Height(),
203 &MemDC
, m_rect
.left
, m_rect
.top
, SRCCOPY
);
205 pDC
->SelectObject( pOldPen
);
206 MemDC
.SelectObject(m_pOldBitmap
);
209 /*********************************************************************/
211 void CACListWnd::Init(CWnd
*pWnd
)
213 VERIFY(m_VertBar
.Create(WS_VISIBLE
|SBS_VERT
|SBS_LEFTALIGN
,
214 CRect(0,0,GetSystemMetrics(SM_CYVSCROLL
),100),this,0));
217 m_pEditParent
= (CEdit
*)pWnd
;
219 m_lCount
= (long)m_DisplayList
.GetSize();
220 m_VertBar
.SetScrollPos(0,false);
227 m_pDC
->SelectObject(GetStockObject(DEFAULT_GUI_FONT
));
228 CSize m_Size
= m_pDC
->GetOutputTextExtent(_T("Hg"));
229 m_ItemHeight
= m_Size
.cy
;
234 /*********************************************************************/
236 void CACListWnd::SetScroller()
239 GetClientRect(rcWnd
);
241 if(m_VertBar
.GetSafeHwnd())
245 rcBar
.left
= (rcWnd
.Width()-GetSystemMetrics(SM_CYVSCROLL
));
246 rcBar
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
247 m_VertBar
.MoveWindow(rcBar
);
248 rcBar
.top
= rcWnd
.bottom
-20;
249 rcBar
.bottom
= rcWnd
.bottom
;
251 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
255 /*********************************************************************/
257 void CACListWnd::OnSize(UINT nType
, int cx
, int cy
)
259 CWnd::OnSize(nType
, cx
, cy
);
263 if(!m_LastSize
.IsRectEmpty())
264 GetWindowRect(m_LastSize
);
267 /*********************************************************************/
269 long CACListWnd::ScrollBarWidth()
271 if(m_VertBar
.IsWindowVisible())
272 return GetSystemMetrics(SM_CYVSCROLL
);
277 /*********************************************************************/
279 void CACListWnd::SetProp()
286 CWnd::GetWindowRect(rcWnd
);
287 ScreenToClient(rcWnd
);
290 si
.cbSize
= sizeof(SCROLLINFO
);
291 si
.fMask
= SIF_PAGE
|SIF_RANGE
;
293 si
.nMax
= m_lCount
-1;
294 m_VisibleItems
= si
.nPage
= rcWnd
.Height()/m_ItemHeight
;
296 m_VertBar
.SetScrollRange(0,m_lCount
-1);
297 m_VertBar
.SetScrollInfo(&si
);
299 if(m_VisibleItems
> m_lCount
-1)
300 m_VertBar
.ShowWindow(false);
302 m_VertBar
.ShowWindow(true);
304 if(m_lTopIndex
+m_VisibleItems
> m_lCount
)
306 m_lTopIndex
= m_lCount
-m_VisibleItems
;
309 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
313 /*********************************************************************/
315 BOOL
CACListWnd::OnEraseBkgnd(CDC
* /*pDC*/)
320 /*********************************************************************/
322 void CACListWnd::OnNcPaint()
325 CRect rectClient
, rectWindow
,rcWnd
;
327 GetClientRect(rectClient
);
328 GetWindowRect(rectWindow
);
329 ScreenToClient(rectWindow
);
331 rectClient
.OffsetRect(-(rectWindow
.left
), -(rectWindow
.top
));
332 dc
.ExcludeClipRect(rectClient
);
334 rectWindow
.OffsetRect(-rectWindow
.left
, -rectWindow
.top
);
336 dc
.FillSolidRect(rectWindow
,::GetSysColor(COLOR_WINDOWTEXT
));
339 /*********************************************************************/
341 void CACListWnd::OnKeyDown(UINT nChar
, UINT nRepCnt
, UINT nFlags
)
343 CWnd::OnKeyDown(nChar
, nRepCnt
, nFlags
);
345 if (nChar
== VK_ESCAPE
)
349 /*********************************************************************/
351 void CACListWnd::OnNcCalcSize(BOOL
/*bCalcValidRects*/, NCCALCSIZE_PARAMS FAR
* lpncsp
)
353 ::InflateRect(lpncsp
->rgrc
,
354 -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
357 /*********************************************************************/
359 int CACListWnd::HitTest(CPoint point
)
364 GetClientRect(rcWnd
);
365 long width
= rcWnd
.Width() - ScrollBarWidth();
367 for(int i
= m_lTopIndex
; i
< m_lCount
; i
++)
369 long y
= i
- m_lTopIndex
;
370 rcItem
.SetRect(2,y
*m_ItemHeight
,width
,(y
+1)*m_ItemHeight
);
372 if(PtInRect(&rcItem
, point
))
373 return (m_lSelItem
= (y
+m_lTopIndex
));
379 /*********************************************************************/
381 LRESULT
CACListWnd::OnNcHitTest(CPoint point
)
384 GetWindowRect(rectClient
);
386 rectClient
.left
= rectClient
.right
- GetSystemMetrics(SM_CYVSCROLL
);
387 rectClient
.top
= rectClient
.bottom
- GetSystemMetrics(SM_CXVSCROLL
);
389 if(rectClient
.PtInRect(point
))
390 return HTBOTTOMRIGHT
;
395 /*********************************************************************/
397 void CACListWnd::OnLButtonDown(UINT nFlags
, CPoint point
)
399 CWnd::OnLButtonDown(nFlags
, point
);
400 int sel
= HitTest(point
);
404 if(!EnsureVisible(sel
,true))
407 m_pEditParent
->SendMessage(ENAC_UPDATE
, WM_KEYDOWN
, GetDlgCtrlID());
408 DoPaintMessageLoop();
416 if(!rc
.PtInRect(point
))
421 /*********************************************************************/
423 void CACListWnd::OnRButtonDown(UINT nFlags
, CPoint point
)
425 CWnd::OnRButtonDown(nFlags
, point
);
429 /*********************************************************************/
431 BOOL
CACListWnd::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
436 GetWindowRect(rectClient
);
437 ScreenToClient(&rectClient
);
439 rectClient
.left
= rectClient
.right
- GetSystemMetrics(SM_CYVSCROLL
);
440 rectClient
.top
= rectClient
.bottom
- GetSystemMetrics(SM_CXVSCROLL
);
443 GetCursorPos(&ptCursor
);
444 ScreenToClient(&ptCursor
);
446 if(rectClient
.PtInRect(ptCursor
)) // Vergrößerungs-Cursor
448 return CWnd::OnSetCursor(pWnd
, nHitTest
, message
);
451 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW
));
455 /*********************************************************************/
457 void CACListWnd::InvalidateAndScroll()
459 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
461 DoPaintMessageLoop();
464 /*********************************************************************/
466 bool CACListWnd::EnsureVisible(int item
, bool m_bWait
)
468 if(item
> m_lTopIndex
&& item
< m_lTopIndex
+ m_VisibleItems
)
469 return false; // ist visible
471 if(item
> m_lTopIndex
) // scroll down
474 for(int i
= m_lTopIndex
; i
< m_len
; i
++)
476 if(i
>= m_lCount
-m_VisibleItems
)
478 if(i
>= m_lCount
-m_VisibleItems
|| i
+ m_VisibleItems
> item
)
487 InvalidateAndScroll();
489 DoPaintMessageLoop();
492 InvalidateAndScroll();
496 if(item
< m_lTopIndex
) // scroll up
498 while(item
< m_lTopIndex
)
509 InvalidateAndScroll();
511 DoPaintMessageLoop();
515 InvalidateAndScroll();
522 /*********************************************************************/
524 bool CACListWnd::SelectItem(int item
)
531 EnsureVisible(m_lSelItem
,false);
538 if(!EnsureVisible(item
,true))
544 /*********************************************************************/
546 int CACListWnd::FindStringExact( int nStartAfter
, LPCTSTR lpszString
)
548 if(nStartAfter
> m_SearchList
.GetSize())
551 for(int i
= nStartAfter
+1; i
< m_SearchList
.GetSize(); i
++)
552 if(m_SearchList
.GetAt(i
).Compare(lpszString
) == 0)
557 /*********************************************************************/
560 * NEW: m_bDisplayOnly
562 int CACListWnd::FindString(int nStartAfter
, LPCTSTR lpszString
, bool m_bDisplayOnly
)
564 long m_AktCount
= (long)m_DisplayList
.GetSize();
568 CString m_Str1
,m_Str2
= lpszString
;
575 if(nStartAfter
> m_SearchList
.GetSize())
587 m_DisplayList
.RemoveAll();
591 for(int i
= nStartAfter
+1; i
< m_SearchList
.GetSize(); i
++)
594 m_Str1
= m_PrefixChar
;
598 m_Str1
+= m_SearchList
.GetAt(i
);
602 if(m_lMode
& _MODE_FIND_ALL_
)
604 if(m_Str1
.Find(m_Str2
) >= 0)
606 m_DisplayList
.Add(m_SearchList
.GetAt(i
));
609 else // _MODE_FIND_EXACT_
611 if(m_Str1
.Find(m_Str2
) == 0)
613 m_DisplayList
.Add(m_SearchList
.GetAt(i
));
618 m_lCount
= (long)m_DisplayList
.GetSize();
625 m_pEditParent
->GetWindowRect(rcWnd
);
633 iHeight
= m_lCount
*m_ItemHeight
+(GetSystemMetrics(SM_CYBORDER
)*2);
635 if(m_lCount
> _MAX_ENTRYS_
)
636 iHeight
= _MAX_ENTRYS_
*m_ItemHeight
+(GetSystemMetrics(SM_CYBORDER
)*2);
638 if(!m_LastSize
.IsRectEmpty())
640 iWight
= m_LastSize
.Width();
641 iHeight
= m_LastSize
.Height();
642 rcWnd
.top
+= rcWnd
.Height();
643 rcWnd
.right
= rcWnd
.left
+iWight
;
644 rcWnd
.bottom
= rcWnd
.top
+iHeight
;
646 SetWindowPos(&CWnd::wndTopMost
, rcWnd
.left
,
653 SetWindowPos(&CWnd::wndTopMost
, rcWnd
.left
,
654 rcWnd
.top
+ rcWnd
.Height(),
659 if(m_AktCount
!= m_DisplayList
.GetSize())
662 SortList(m_DisplayList
);
672 /*********************************************************************/
674 int CACListWnd::SelectString(LPCTSTR lpszString
)
676 int item
= FindString(-1, lpszString
);
681 /*********************************************************************/
683 bool CACListWnd::GetText(int item
, CString
& m_Text
)
685 if(item
< 0 || item
> m_SearchList
.GetSize())
687 m_Text
= m_SearchList
.GetAt(item
);
691 /*********************************************************************/
693 void CACListWnd::OnShowWindow(BOOL bShow
, UINT nStatus
)
697 m_nIDTimer
= (long)SetTimer(IDTimerInstall
, 200, nullptr);
698 m_pEditParent
->GetParent()->GetWindowRect(m_ParentRect
);
703 KillTimer(IDTimerInstall
);
709 CWnd::OnShowWindow(bShow
, nStatus
);
710 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW
));
713 /*********************************************************************/
715 void CACListWnd::OnNcLButtonDown(UINT nHitTest
, CPoint point
)
717 if(OnNcHitTest(point
) == HTBOTTOMRIGHT
)
718 GetWindowRect(m_LastSize
);
719 CWnd::OnNcLButtonDown(nHitTest
, point
);
722 /*********************************************************************/
724 CString
CACListWnd::GetString()
726 int i
= (int)m_DisplayList
.GetSize();
730 if(i
<= m_lSelItem
|| m_lSelItem
== -1)
735 return m_DisplayList
.GetAt(i
);
738 /*********************************************************************/
740 void CACListWnd::OnVScroll(UINT nSBCode
, UINT nPos
, CScrollBar
* pScrollBar
)
742 CWnd::OnVScroll(nSBCode
, nPos
, pScrollBar
);
743 long m_oldlTopIndex
= m_lTopIndex
;
751 m_lTopIndex
-= m_VisibleItems
;
757 m_lTopIndex
+= m_VisibleItems
;
758 if(m_lTopIndex
>= m_lCount
-m_VisibleItems
)
759 m_lTopIndex
= m_lCount
-m_VisibleItems
;
770 if(m_lTopIndex
>= m_lCount
-m_VisibleItems
)
771 m_lTopIndex
= m_lCount
-m_VisibleItems
;
779 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
781 if(m_oldlTopIndex
!= m_lTopIndex
)
785 /*********************************************************************/
787 CString
CACListWnd::GetNextString(int nChar
)
800 m_lSelItem
-= m_VisibleItems
;
806 m_lSelItem
+= m_VisibleItems
;
807 if(m_lSelItem
>= m_lCount
-1)
808 m_lSelItem
= m_lCount
-1;
816 m_lSelItem
= m_lCount
-1;
821 m_lSelItem
= m_lCount
-1;
823 if(m_lSelItem
>= m_lCount
)
826 if(EnsureVisible(m_lSelItem
,(m_lCount
> 50) ? false : true))
827 InvalidateAndScroll();
832 /*********************************************************************/
834 void CACListWnd::OnMouseMove(UINT nFlags
, CPoint point
)
836 CWnd::OnMouseMove(nFlags
, point
);
837 int sel
= HitTest(point
);
844 /*********************************************************************/
846 void CACListWnd::OnTimer(UINT_PTR nIDEvent
)
848 CWnd::OnTimer(nIDEvent
);
851 m_pEditParent
->GetParent()->GetWindowRect(m_ParentRect1
);
852 if(!m_ParentRect1
.EqualRect(m_ParentRect
))
856 /*********************************************************************/
858 void CACListWnd::OnGetMinMaxInfo(MINMAXINFO FAR
* lpMMI
)
863 long m_lMinY1
= GetSystemMetrics(SM_CYHSCROLL
)*2 + GetSystemMetrics(SM_CYSIZEFRAME
) + GetSystemMetrics(SM_CXHTHUMB
),
864 m_lMinY2
= m_lCount
* m_ItemHeight
+ (GetSystemMetrics(SM_CYBORDER
)*2);
866 if(m_VisibleItems
> m_lCount
-1 && m_lMinY2
< m_lMinY1
)
867 lpMMI
->ptMinTrackSize
.y
= m_lMinY2
;
869 lpMMI
->ptMinTrackSize
.y
= m_lMinY1
;
872 lpMMI
->ptMinTrackSize
.x
= GetSystemMetrics(SM_CXHSCROLL
)*4;
879 m_pEditParent
->GetWindowRect (&rc
);
880 lpMMI
->ptMinTrackSize
.x
= rc
.right
- rc
.left
;
884 CWnd::OnGetMinMaxInfo(lpMMI
);
887 /*********************************************************************/
889 int CACListWnd::CompareString(const void* p1
, const void* p2
)
891 return _stricmp( * ( char** ) p1
, * ( char** ) p2
);
894 /*********************************************************************/
896 void CACListWnd::SortList(CStringArray
& list
)
898 int m_Count
= (int)list
.GetSize();
903 CStringArray m_Liste1
;
906 LPCTSTR
* ppSortArray
= new LPCTSTR
[m_Count
+1];
909 for(i
=0; i
< m_Count
; i
++)
911 ppSortArray
[i
] = (LPCTSTR
)m_Liste1
.GetAt(i
);
916 qsort(ppSortArray
, m_Count
, sizeof(LPCTSTR
), CompareString
);
918 for(i
=0; i
< m_Count
; i
++)
920 list
.Add((LPCTSTR
) ppSortArray
[i
]);
922 m_Liste1
.RemoveAll();
923 delete [] ppSortArray
;
927 /*********************************************************************/
932 void CACListWnd::CopyList()
934 m_DisplayList
.Copy(m_SearchList
);
935 m_lCount
= (long)m_DisplayList
.GetSize();
937 FindString(0,_T(""),true);
940 /*********************************************************************/