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 - 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
,NULL
,WM_PAINT
,WM_PAINT
, PM_REMOVE
))
36 ::TranslateMessage(&message1
);
37 ::DispatchMessage(&message1
);
41 /**********************************************************************/
43 CACListWnd::CACListWnd()
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
;
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);
256 /*********************************************************************/
258 void CACListWnd::OnSize(UINT nType
, int cx
, int cy
)
260 CWnd::OnSize(nType
, cx
, cy
);
264 if(!m_LastSize
.IsRectEmpty())
265 GetWindowRect(m_LastSize
);
268 /*********************************************************************/
270 long CACListWnd::ScrollBarWidth()
272 if(m_VertBar
.IsWindowVisible())
273 return GetSystemMetrics(SM_CYVSCROLL
);
278 /*********************************************************************/
280 void CACListWnd::SetProp()
287 CWnd::GetWindowRect(rcWnd
);
288 ScreenToClient(rcWnd
);
291 si
.cbSize
= sizeof(SCROLLINFO
);
292 si
.fMask
= SIF_PAGE
|SIF_RANGE
;
294 si
.nMax
= m_lCount
-1;
295 m_VisibleItems
= si
.nPage
= rcWnd
.Height()/m_ItemHeight
;
297 m_VertBar
.SetScrollRange(0,m_lCount
-1);
298 m_VertBar
.SetScrollInfo(&si
);
300 if(m_VisibleItems
> m_lCount
-1)
301 m_VertBar
.ShowWindow(false);
303 m_VertBar
.ShowWindow(true);
305 if(m_lTopIndex
+m_VisibleItems
> m_lCount
)
307 m_lTopIndex
= m_lCount
-m_VisibleItems
;
310 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
314 /*********************************************************************/
316 BOOL
CACListWnd::OnEraseBkgnd(CDC
* /*pDC*/)
321 /*********************************************************************/
323 void CACListWnd::OnNcPaint()
326 CRect rectClient
, rectWindow
,rcWnd
;
328 GetClientRect(rectClient
);
329 GetWindowRect(rectWindow
);
330 ScreenToClient(rectWindow
);
332 rectClient
.OffsetRect(-(rectWindow
.left
), -(rectWindow
.top
));
333 dc
.ExcludeClipRect(rectClient
);
335 rectWindow
.OffsetRect(-rectWindow
.left
, -rectWindow
.top
);
337 dc
.FillSolidRect(rectWindow
,::GetSysColor(COLOR_WINDOWTEXT
));
340 /*********************************************************************/
342 void CACListWnd::OnKeyDown(UINT nChar
, UINT nRepCnt
, UINT nFlags
)
344 CWnd::OnKeyDown(nChar
, nRepCnt
, nFlags
);
346 if (nChar
== VK_ESCAPE
)
350 /*********************************************************************/
352 void CACListWnd::OnNcCalcSize(BOOL
/*bCalcValidRects*/, NCCALCSIZE_PARAMS FAR
* lpncsp
)
354 ::InflateRect(lpncsp
->rgrc
,
355 -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
358 /*********************************************************************/
360 int CACListWnd::HitTest(CPoint point
)
365 GetClientRect(rcWnd
);
366 long width
= rcWnd
.Width() - ScrollBarWidth();
368 for(int i
= m_lTopIndex
; i
< m_lCount
; i
++)
370 long y
= i
- m_lTopIndex
;
371 rcItem
.SetRect(2,y
*m_ItemHeight
,width
,(y
+1)*m_ItemHeight
);
373 if(PtInRect(&rcItem
, point
))
374 return (m_lSelItem
= (y
+m_lTopIndex
));
380 /*********************************************************************/
382 LRESULT
CACListWnd::OnNcHitTest(CPoint point
)
385 GetWindowRect(rectClient
);
387 rectClient
.left
= rectClient
.right
- GetSystemMetrics(SM_CYVSCROLL
);
388 rectClient
.top
= rectClient
.bottom
- GetSystemMetrics(SM_CXVSCROLL
);
390 if(rectClient
.PtInRect(point
))
391 return HTBOTTOMRIGHT
;
396 /*********************************************************************/
398 void CACListWnd::OnLButtonDown(UINT nFlags
, CPoint point
)
400 CWnd::OnLButtonDown(nFlags
, point
);
401 int sel
= HitTest(point
);
405 if(!EnsureVisible(sel
,true))
408 m_pEditParent
->SendMessage(ENAC_UPDATE
, WM_KEYDOWN
, GetDlgCtrlID());
409 DoPaintMessageLoop();
417 if(!rc
.PtInRect(point
))
422 /*********************************************************************/
424 void CACListWnd::OnRButtonDown(UINT nFlags
, CPoint point
)
426 CWnd::OnRButtonDown(nFlags
, point
);
430 /*********************************************************************/
432 BOOL
CACListWnd::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
437 GetWindowRect(rectClient
);
438 ScreenToClient(&rectClient
);
440 rectClient
.left
= rectClient
.right
- GetSystemMetrics(SM_CYVSCROLL
);
441 rectClient
.top
= rectClient
.bottom
- GetSystemMetrics(SM_CXVSCROLL
);
444 GetCursorPos(&ptCursor
);
445 ScreenToClient(&ptCursor
);
447 if(rectClient
.PtInRect(ptCursor
)) // Vergrößerungs-Cursor
449 return CWnd::OnSetCursor(pWnd
, nHitTest
, message
);
452 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW
));
456 /*********************************************************************/
458 void CACListWnd::InvalidateAndScroll()
460 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
462 DoPaintMessageLoop();
465 /*********************************************************************/
467 bool CACListWnd::EnsureVisible(int item
, bool m_bWait
)
469 if(item
> m_lTopIndex
&& item
< m_lTopIndex
+ m_VisibleItems
)
470 return false; // ist visible
472 if(item
> m_lTopIndex
) // scroll down
475 for(int i
= m_lTopIndex
; i
< m_len
; i
++)
477 if(i
>= m_lCount
-m_VisibleItems
)
479 if(i
>= m_lCount
-m_VisibleItems
|| i
+ m_VisibleItems
> item
)
488 InvalidateAndScroll();
490 DoPaintMessageLoop();
493 InvalidateAndScroll();
497 if(item
< m_lTopIndex
) // scroll up
499 while(item
< m_lTopIndex
)
510 InvalidateAndScroll();
512 DoPaintMessageLoop();
516 InvalidateAndScroll();
523 /*********************************************************************/
525 bool CACListWnd::SelectItem(int item
)
532 EnsureVisible(m_lSelItem
,false);
539 if(!EnsureVisible(item
,true))
545 /*********************************************************************/
547 int CACListWnd::FindStringExact( int nStartAfter
, LPCTSTR lpszString
)
549 if(nStartAfter
> m_SearchList
.GetSize())
552 for(int i
= nStartAfter
+1; i
< m_SearchList
.GetSize(); i
++)
553 if(m_SearchList
.GetAt(i
).Compare(lpszString
) == 0)
558 /*********************************************************************/
561 * NEW: m_bDisplayOnly
563 int CACListWnd::FindString(int nStartAfter
, LPCTSTR lpszString
, bool m_bDisplayOnly
)
565 long m_AktCount
= (long)m_DisplayList
.GetSize();
569 CString m_Str1
,m_Str2
= lpszString
;
576 if(nStartAfter
> m_SearchList
.GetSize())
588 m_DisplayList
.RemoveAll();
592 for(int i
= nStartAfter
+1; i
< m_SearchList
.GetSize(); i
++)
595 m_Str1
= m_PrefixChar
;
599 m_Str1
+= m_SearchList
.GetAt(i
);
603 if(m_lMode
& _MODE_FIND_ALL_
)
605 if(m_Str1
.Find(m_Str2
) >= 0)
607 m_DisplayList
.Add(m_SearchList
.GetAt(i
));
610 else // _MODE_FIND_EXACT_
612 if(m_Str1
.Find(m_Str2
) == 0)
614 m_DisplayList
.Add(m_SearchList
.GetAt(i
));
619 m_lCount
= (long)m_DisplayList
.GetSize();
626 m_pEditParent
->GetWindowRect(rcWnd
);
634 iHeight
= m_lCount
*m_ItemHeight
+(GetSystemMetrics(SM_CYBORDER
)*2);
636 if(m_lCount
> _MAX_ENTRYS_
)
637 iHeight
= _MAX_ENTRYS_
*m_ItemHeight
+(GetSystemMetrics(SM_CYBORDER
)*2);
639 if(!m_LastSize
.IsRectEmpty())
641 iWight
= m_LastSize
.Width();
642 iHeight
= m_LastSize
.Height();
643 rcWnd
.top
+= rcWnd
.Height();
644 rcWnd
.right
= rcWnd
.left
+iWight
;
645 rcWnd
.bottom
= rcWnd
.top
+iHeight
;
647 SetWindowPos(&CWnd::wndTopMost
, rcWnd
.left
,
654 SetWindowPos(&CWnd::wndTopMost
, rcWnd
.left
,
655 rcWnd
.top
+ rcWnd
.Height(),
660 if(m_AktCount
!= m_DisplayList
.GetSize())
663 SortList(m_DisplayList
);
673 /*********************************************************************/
675 int CACListWnd::SelectString(LPCTSTR lpszString
)
677 int item
= FindString(-1, lpszString
);
682 /*********************************************************************/
684 bool CACListWnd::GetText(int item
, CString
& m_Text
)
686 if(item
< 0 || item
> m_SearchList
.GetSize())
688 m_Text
= m_SearchList
.GetAt(item
);
692 /*********************************************************************/
694 void CACListWnd::OnShowWindow(BOOL bShow
, UINT nStatus
)
698 m_nIDTimer
= (long)SetTimer( IDTimerInstall
, 200, NULL
);
699 m_pEditParent
->GetParent()->GetWindowRect(m_ParentRect
);
704 KillTimer(IDTimerInstall
);
710 CWnd::OnShowWindow(bShow
, nStatus
);
711 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW
));
714 /*********************************************************************/
716 void CACListWnd::OnNcLButtonDown(UINT nHitTest
, CPoint point
)
719 if(OnNcHitTest(point
) == HTBOTTOMRIGHT
)
720 GetWindowRect(m_LastSize
);
721 CWnd::OnNcLButtonDown(nHitTest
, point
);
724 /*********************************************************************/
726 CString
CACListWnd::GetString()
728 int i
= (int)m_DisplayList
.GetSize();
732 if(i
<= m_lSelItem
|| m_lSelItem
== -1)
737 return m_DisplayList
.GetAt(i
);
740 /*********************************************************************/
742 void CACListWnd::OnVScroll(UINT nSBCode
, UINT nPos
, CScrollBar
* pScrollBar
)
744 CWnd::OnVScroll(nSBCode
, nPos
, pScrollBar
);
745 long m_oldlTopIndex
= m_lTopIndex
;
753 m_lTopIndex
-= m_VisibleItems
;
759 m_lTopIndex
+= m_VisibleItems
;
760 if(m_lTopIndex
>= m_lCount
-m_VisibleItems
)
761 m_lTopIndex
= m_lCount
-m_VisibleItems
;
772 if(m_lTopIndex
>= m_lCount
-m_VisibleItems
)
773 m_lTopIndex
= m_lCount
-m_VisibleItems
;
781 m_VertBar
.SetScrollPos(m_lTopIndex
,true);
783 if(m_oldlTopIndex
!= m_lTopIndex
)
787 /*********************************************************************/
789 CString
CACListWnd::GetNextString(int nChar
)
802 m_lSelItem
-= m_VisibleItems
;
808 m_lSelItem
+= m_VisibleItems
;
809 if(m_lSelItem
>= m_lCount
-1)
810 m_lSelItem
= m_lCount
-1;
818 m_lSelItem
= m_lCount
-1;
823 m_lSelItem
= m_lCount
-1;
825 if(m_lSelItem
>= m_lCount
)
828 if(EnsureVisible(m_lSelItem
,(m_lCount
> 50) ? false : true))
829 InvalidateAndScroll();
834 /*********************************************************************/
836 void CACListWnd::OnMouseMove(UINT nFlags
, CPoint point
)
838 CWnd::OnMouseMove(nFlags
, point
);
839 int sel
= HitTest(point
);
846 /*********************************************************************/
848 void CACListWnd::OnTimer(UINT_PTR nIDEvent
)
850 CWnd::OnTimer(nIDEvent
);
853 m_pEditParent
->GetParent()->GetWindowRect(m_ParentRect1
);
854 if(!m_ParentRect1
.EqualRect(m_ParentRect
))
858 /*********************************************************************/
860 void CACListWnd::OnGetMinMaxInfo(MINMAXINFO FAR
* lpMMI
)
865 long m_lMinY1
= GetSystemMetrics(SM_CYHSCROLL
)*2 + GetSystemMetrics(SM_CYSIZEFRAME
) + GetSystemMetrics(SM_CXHTHUMB
),
866 m_lMinY2
= m_lCount
* m_ItemHeight
+ (GetSystemMetrics(SM_CYBORDER
)*2);
868 if(m_VisibleItems
> m_lCount
-1 && m_lMinY2
< m_lMinY1
)
869 lpMMI
->ptMinTrackSize
.y
= m_lMinY2
;
871 lpMMI
->ptMinTrackSize
.y
= m_lMinY1
;
874 lpMMI
->ptMinTrackSize
.x
= GetSystemMetrics(SM_CXHSCROLL
)*4;
878 if(m_pEditParent
!= NULL
)
881 m_pEditParent
->GetWindowRect (&rc
);
882 lpMMI
->ptMinTrackSize
.x
= rc
.right
- rc
.left
;
886 CWnd::OnGetMinMaxInfo(lpMMI
);
889 /*********************************************************************/
891 int CACListWnd::CompareString(const void* p1
, const void* p2
)
893 return _stricmp( * ( char** ) p1
, * ( char** ) p2
);
896 /*********************************************************************/
898 void CACListWnd::SortList(CStringArray
& m_List
)
900 int m_Count
= (int)m_List
.GetSize();
905 CStringArray m_Liste1
;
906 m_Liste1
.Copy(m_List
);
908 LPCTSTR
* ppSortArray
= new LPCTSTR
[m_Count
+1];
911 for(i
=0; i
< m_Count
; i
++)
913 ppSortArray
[i
] = (LPCTSTR
)m_Liste1
.GetAt(i
);
918 qsort(ppSortArray
, m_Count
, sizeof(LPCTSTR
), CompareString
);
920 for(i
=0; i
< m_Count
; i
++)
922 m_List
.Add((LPCTSTR
) ppSortArray
[i
]);
924 m_Liste1
.RemoveAll();
925 delete [] ppSortArray
;
929 /*********************************************************************/
934 void CACListWnd::CopyList()
936 m_DisplayList
.Copy(m_SearchList
);
937 m_lCount
= (long)m_DisplayList
.GetSize();
939 FindString(0,_T(""),true);
942 /*********************************************************************/