yum-archive/TaSTT-Whisper

High-performance GPGPU inference of OpenAI's Whisper automatic speech recognition (ASR) model

git clone https://git.yummers.dev/yum-archive/TaSTT-Whisper

KonstantinSource codes8c4603c

master
258.8 KiB9764 linesraw
1// Windows Template Library - WTL version 10.0
2// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
3//
4// This file is a part of the Windows Template Library.
5// The use and distribution terms for this software are covered by the
6// Microsoft Public License (http://opensource.org/licenses/MS-PL)
7// which can be found in the file MS-PL.txt at the root folder.
8
9#ifndef __ATLCTRLS_H__
10#define __ATLCTRLS_H__
11
12#pragma once
13
14#ifndef __ATLAPP_H__
15	#error atlctrls.h requires atlapp.h to be included first
16#endif
17
18#ifndef __ATLWIN_H__
19	#error atlctrls.h requires atlwin.h to be included first
20#endif
21
22#include <richedit.h>
23#include <richole.h>
24
25#if (_RICHEDIT_VER < 0x0300)
26	#error WTL10 requires _RICHEDIT_VER >= 0x0300
27#endif
28
29// protect template members from windowsx.h macros
30#ifdef _INC_WINDOWSX
31  #undef GetNextSibling
32  #undef GetPrevSibling
33#endif // _INC_WINDOWSX
34
35
36///////////////////////////////////////////////////////////////////////////////
37// Classes in this file:
38//
39// CStaticT<TBase> - CStatic
40// CButtonT<TBase> - CButton
41// CListBoxT<TBase> - CListBox
42// CComboBoxT<TBase> - CComboBox
43// CEditT<TBase> - CEdit
44// CEditCommands<T>
45// CScrollBarT<TBase> - CScrollBar
46//
47// CImageListT<t_bManaged> - CImageList, CImageListManaged
48// CListViewCtrlT<TBase> - CListViewCtrl
49// CTreeViewCtrlT<TBase> - CTreeViewCtrl
50// CTreeItemT<TBase> - CTreeItem
51// CTreeViewCtrlExT<TBase> - CTreeViewCtrlEx
52// CHeaderCtrlT<TBase> - CHeaderCtrl
53// CToolBarCtrlT<TBase> - CToolBarCtrl
54// CStatusBarCtrlT<TBase> - CStatusBarCtrl
55// CTabCtrlT<TBase> - CTabCtrl
56// CToolInfo
57// CToolTipCtrlT<TBase> - CToolTipCtrl
58// CTrackBarCtrlT<TBase> - CTrackBarCtrl
59// CUpDownCtrlT<TBase> - CUpDownCtrl
60// CProgressBarCtrlT<TBase> - CProgressBarCtrl
61// CHotKeyCtrlT<TBase> - CHotKeyCtrl
62// CAnimateCtrlT<TBase> - CAnimateCtrl
63// CRichEditCtrlT<TBase> - CRichEditCtrl
64// CRichEditCommands<T>
65// CDragListBoxT<TBase> - CDragListBox
66// CDragListNotifyImpl<T>
67// CReBarCtrlT<TBase> - CReBarCtrl
68// CComboBoxExT<TBase> - CComboBoxEx
69// CDateTimePickerCtrlT<TBase> - CDateTimePickerCtrl
70// CMonthCalendarCtrlT<TBase> - CMonthCalendarCtrl
71// CFlatScrollBarImpl<T>
72// CFlatScrollBarT<TBase> - CFlatScrollBar
73// CIPAddressCtrlT<TBase> - CIPAddressCtrl
74// CPagerCtrlT<TBase> - CPagerCtrl
75// CLinkCtrlT<TBase> - CLinkCtrl
76//
77// CCustomDraw<T>
78
79
80namespace WTL
81{
82
83// These are wrapper classes for Windows standard and common controls.
84// To implement a window based on a control, use following:
85// Example: Implementing a window based on a list box
86//
87// class CMyListBox : CWindowImpl<CMyListBox, CListBox>
88// {
89// public:
90//      BEGIN_MSG_MAP(CMyListBox)
91//          // put your message handler entries here
92//      END_MSG_MAP()
93// };
94
95
96
97// --- Standard Windows controls ---
98
99///////////////////////////////////////////////////////////////////////////////
100// CStatic - client side for a Windows STATIC control
101
102template <class TBase>
103class CStaticT : public TBase
104{
105public:
106// Constructors
107	CStaticT(HWND hWnd = NULL) : TBase(hWnd)
108	{ }
109
110	CStaticT< TBase >& operator =(HWND hWnd)
111	{
112		this->m_hWnd = hWnd;
113		return *this;
114	}
115
116	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
117			DWORD dwStyle = 0, DWORD dwExStyle = 0,
118			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
119	{
120		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
121	}
122
123// Attributes
124	static LPCTSTR GetWndClassName()
125	{
126		return _T("STATIC");
127	}
128
129	HICON GetIcon() const
130	{
131		ATLASSERT(::IsWindow(this->m_hWnd));
132		return (HICON)::SendMessage(this->m_hWnd, STM_GETICON, 0, 0L);
133	}
134
135	HICON SetIcon(HICON hIcon)
136	{
137		ATLASSERT(::IsWindow(this->m_hWnd));
138		return (HICON)::SendMessage(this->m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L);
139	}
140
141	HENHMETAFILE GetEnhMetaFile() const
142	{
143		ATLASSERT(::IsWindow(this->m_hWnd));
144		return (HENHMETAFILE)::SendMessage(this->m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L);
145	}
146
147	HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile)
148	{
149		ATLASSERT(::IsWindow(this->m_hWnd));
150		return (HENHMETAFILE)::SendMessage(this->m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
151	}
152
153	CBitmapHandle GetBitmap() const
154	{
155		ATLASSERT(::IsWindow(this->m_hWnd));
156		return CBitmapHandle((HBITMAP)::SendMessage(this->m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L));
157	}
158
159	CBitmapHandle SetBitmap(HBITMAP hBitmap)
160	{
161		ATLASSERT(::IsWindow(this->m_hWnd));
162		return CBitmapHandle((HBITMAP)::SendMessage(this->m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
163	}
164
165	HCURSOR GetCursor() const
166	{
167		ATLASSERT(::IsWindow(this->m_hWnd));
168		return (HCURSOR)::SendMessage(this->m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L);
169	}
170
171	HCURSOR SetCursor(HCURSOR hCursor)
172	{
173		ATLASSERT(::IsWindow(this->m_hWnd));
174		return (HCURSOR)::SendMessage(this->m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
175	}
176};
177
178typedef CStaticT<ATL::CWindow>   CStatic;
179
180
181///////////////////////////////////////////////////////////////////////////////
182// CButton - client side for a Windows BUTTON control
183
184template <class TBase>
185class CButtonT : public TBase
186{
187public:
188// Constructors
189	CButtonT(HWND hWnd = NULL) : TBase(hWnd)
190	{ }
191
192	CButtonT< TBase >& operator =(HWND hWnd)
193	{
194		this->m_hWnd = hWnd;
195		return *this;
196	}
197
198	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
199			DWORD dwStyle = 0, DWORD dwExStyle = 0,
200			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
201	{
202		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
203	}
204
205// Attributes
206	static LPCTSTR GetWndClassName()
207	{
208		return _T("BUTTON");
209	}
210
211	UINT GetState() const
212	{
213		ATLASSERT(::IsWindow(this->m_hWnd));
214		return (UINT)::SendMessage(this->m_hWnd, BM_GETSTATE, 0, 0L);
215	}
216
217	void SetState(BOOL bHighlight)
218	{
219		ATLASSERT(::IsWindow(this->m_hWnd));
220		::SendMessage(this->m_hWnd, BM_SETSTATE, bHighlight, 0L);
221	}
222
223	int GetCheck() const
224	{
225		ATLASSERT(::IsWindow(this->m_hWnd));
226		return (int)::SendMessage(this->m_hWnd, BM_GETCHECK, 0, 0L);
227	}
228
229	void SetCheck(int nCheck)
230	{
231		ATLASSERT(::IsWindow(this->m_hWnd));
232		::SendMessage(this->m_hWnd, BM_SETCHECK, nCheck, 0L);
233	}
234
235	UINT GetButtonStyle() const
236	{
237		ATLASSERT(::IsWindow(this->m_hWnd));
238		return (UINT)::GetWindowLong(this->m_hWnd, GWL_STYLE) & 0xFFFF;
239	}
240
241	void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE)
242	{
243		ATLASSERT(::IsWindow(this->m_hWnd));
244		::SendMessage(this->m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw);
245	}
246
247	HICON GetIcon() const
248	{
249		ATLASSERT(::IsWindow(this->m_hWnd));
250		return (HICON)::SendMessage(this->m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L);
251	}
252
253	HICON SetIcon(HICON hIcon)
254	{
255		ATLASSERT(::IsWindow(this->m_hWnd));
256		return (HICON)::SendMessage(this->m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
257	}
258
259	CBitmapHandle GetBitmap() const
260	{
261		ATLASSERT(::IsWindow(this->m_hWnd));
262		return CBitmapHandle((HBITMAP)::SendMessage(this->m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L));
263	}
264
265	CBitmapHandle SetBitmap(HBITMAP hBitmap)
266	{
267		ATLASSERT(::IsWindow(this->m_hWnd));
268		return CBitmapHandle((HBITMAP)::SendMessage(this->m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
269	}
270
271	BOOL GetIdealSize(LPSIZE lpSize) const
272	{
273		ATLASSERT(::IsWindow(this->m_hWnd));
274		return (BOOL)::SendMessage(this->m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize);
275	}
276
277	BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const
278	{
279		ATLASSERT(::IsWindow(this->m_hWnd));
280		return (BOOL)::SendMessage(this->m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist);
281	}
282
283	BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist)
284	{
285		ATLASSERT(::IsWindow(this->m_hWnd));
286		return (BOOL)::SendMessage(this->m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist);
287	}
288
289	BOOL GetTextMargin(LPRECT lpRect) const
290	{
291		ATLASSERT(::IsWindow(this->m_hWnd));
292		return (BOOL)::SendMessage(this->m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect);
293	}
294
295	BOOL SetTextMargin(LPRECT lpRect)
296	{
297		ATLASSERT(::IsWindow(this->m_hWnd));
298		return (BOOL)::SendMessage(this->m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect);
299	}
300
301#if (WINVER >= 0x0600)
302	void SetDontClick(BOOL bDontClick)
303	{
304		ATLASSERT(::IsWindow(this->m_hWnd));
305		::SendMessage(this->m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L);
306	}
307#endif // (WINVER >= 0x0600)
308
309#if (_WIN32_WINNT >= 0x0600)
310	BOOL SetDropDownState(BOOL bDropDown)
311	{
312		ATLASSERT(::IsWindow(this->m_hWnd));
313		ATLASSERT((this->GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
314		return (BOOL)::SendMessage(this->m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L);
315	}
316
317	BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const
318	{
319		ATLASSERT(::IsWindow(this->m_hWnd));
320		ATLASSERT((this->GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
321		return (BOOL)::SendMessage(this->m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo);
322	}
323
324	BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo)
325	{
326		ATLASSERT(::IsWindow(this->m_hWnd));
327		ATLASSERT((this->GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
328		return (BOOL)::SendMessage(this->m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo);
329	}
330
331	int GetNoteLength() const
332	{
333		ATLASSERT(::IsWindow(this->m_hWnd));
334		ATLASSERT((this->GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
335		return (int)::SendMessage(this->m_hWnd, BCM_GETNOTELENGTH, 0, 0L);
336	}
337
338	BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const
339	{
340		ATLASSERT(::IsWindow(this->m_hWnd));
341		ATLASSERT((this->GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
342		return (BOOL)::SendMessage(this->m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText);
343	}
344
345	BOOL SetNote(LPCWSTR lpstrNoteText)
346	{
347		ATLASSERT(::IsWindow(this->m_hWnd));
348		ATLASSERT((this->GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
349		return (BOOL)::SendMessage(this->m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText);
350	}
351
352	LRESULT SetElevationRequiredState(BOOL bSet)
353	{
354		ATLASSERT(::IsWindow(this->m_hWnd));
355		return ::SendMessage(this->m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet);
356	}
357#endif // (_WIN32_WINNT >= 0x0600)
358
359// Operations
360	void Click()
361	{
362		ATLASSERT(::IsWindow(this->m_hWnd));
363		::SendMessage(this->m_hWnd, BM_CLICK, 0, 0L);
364	}
365};
366
367typedef CButtonT<ATL::CWindow>   CButton;
368
369
370///////////////////////////////////////////////////////////////////////////////
371// CListBox - client side for a Windows LISTBOX control
372
373template <class TBase>
374class CListBoxT : public TBase
375{
376public:
377// Constructors
378	CListBoxT(HWND hWnd = NULL) : TBase(hWnd)
379	{ }
380
381	CListBoxT< TBase >& operator =(HWND hWnd)
382	{
383		this->m_hWnd = hWnd;
384		return *this;
385	}
386
387	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
388			DWORD dwStyle = 0, DWORD dwExStyle = 0,
389			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
390	{
391		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
392	}
393
394// Attributes
395	static LPCTSTR GetWndClassName()
396	{
397		return _T("LISTBOX");
398	}
399
400	// for entire listbox
401	int GetCount() const
402	{
403		ATLASSERT(::IsWindow(this->m_hWnd));
404		return (int)::SendMessage(this->m_hWnd, LB_GETCOUNT, 0, 0L);
405	}
406
407	int SetCount(int cItems)
408	{
409		ATLASSERT(::IsWindow(this->m_hWnd));
410		ATLASSERT(((this->GetStyle() & LBS_NODATA) != 0) && ((this->GetStyle() & LBS_HASSTRINGS) == 0));
411		return (int)::SendMessage(this->m_hWnd, LB_SETCOUNT, cItems, 0L);
412	}
413
414	int GetHorizontalExtent() const
415	{
416		ATLASSERT(::IsWindow(this->m_hWnd));
417		return (int)::SendMessage(this->m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L);
418	}
419
420	void SetHorizontalExtent(int cxExtent)
421	{
422		ATLASSERT(::IsWindow(this->m_hWnd));
423		::SendMessage(this->m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
424	}
425
426	int GetTopIndex() const
427	{
428		ATLASSERT(::IsWindow(this->m_hWnd));
429		return (int)::SendMessage(this->m_hWnd, LB_GETTOPINDEX, 0, 0L);
430	}
431
432	int SetTopIndex(int nIndex)
433	{
434		ATLASSERT(::IsWindow(this->m_hWnd));
435		return (int)::SendMessage(this->m_hWnd, LB_SETTOPINDEX, nIndex, 0L);
436	}
437
438	LCID GetLocale() const
439	{
440		ATLASSERT(::IsWindow(this->m_hWnd));
441		return (LCID)::SendMessage(this->m_hWnd, LB_GETLOCALE, 0, 0L);
442	}
443
444	LCID SetLocale(LCID nNewLocale)
445	{
446		ATLASSERT(::IsWindow(this->m_hWnd));
447		return (LCID)::SendMessage(this->m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L);
448	}
449
450	DWORD GetListBoxInfo() const
451	{
452		ATLASSERT(::IsWindow(this->m_hWnd));
453		return (DWORD)::SendMessage(this->m_hWnd, LB_GETLISTBOXINFO, 0, 0L);
454	}
455
456	// for single-selection listboxes
457	int GetCurSel() const
458	{
459		ATLASSERT(::IsWindow(this->m_hWnd));
460		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
461		return (int)::SendMessage(this->m_hWnd, LB_GETCURSEL, 0, 0L);
462	}
463
464	int SetCurSel(int nSelect)
465	{
466		ATLASSERT(::IsWindow(this->m_hWnd));
467		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
468		return (int)::SendMessage(this->m_hWnd, LB_SETCURSEL, nSelect, 0L);
469	}
470
471	// for multiple-selection listboxes
472	int GetSel(int nIndex) const           // also works for single-selection
473	{
474		ATLASSERT(::IsWindow(this->m_hWnd));
475		return (int)::SendMessage(this->m_hWnd, LB_GETSEL, nIndex, 0L);
476	}
477
478	int SetSel(int nIndex, BOOL bSelect = TRUE)
479	{
480		ATLASSERT(::IsWindow(this->m_hWnd));
481		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
482		return (int)::SendMessage(this->m_hWnd, LB_SETSEL, bSelect, nIndex);
483	}
484
485	int GetSelCount() const
486	{
487		ATLASSERT(::IsWindow(this->m_hWnd));
488		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
489		return (int)::SendMessage(this->m_hWnd, LB_GETSELCOUNT, 0, 0L);
490	}
491
492	int GetSelItems(int nMaxItems, LPINT rgIndex) const
493	{
494		ATLASSERT(::IsWindow(this->m_hWnd));
495		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
496		return (int)::SendMessage(this->m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
497	}
498
499	int GetAnchorIndex() const
500	{
501		ATLASSERT(::IsWindow(this->m_hWnd));
502		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
503		return (int)::SendMessage(this->m_hWnd, LB_GETANCHORINDEX, 0, 0L);
504	}
505
506	void SetAnchorIndex(int nIndex)
507	{
508		ATLASSERT(::IsWindow(this->m_hWnd));
509		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
510		::SendMessage(this->m_hWnd, LB_SETANCHORINDEX, nIndex, 0L);
511	}
512
513	int GetCaretIndex() const
514	{
515		ATLASSERT(::IsWindow(this->m_hWnd));
516		return (int)::SendMessage(this->m_hWnd, LB_GETCARETINDEX, 0, 0);
517	}
518
519	int SetCaretIndex(int nIndex, BOOL bScroll = TRUE)
520	{
521		ATLASSERT(::IsWindow(this->m_hWnd));
522		return (int)::SendMessage(this->m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
523	}
524
525	// for listbox items
526	DWORD_PTR GetItemData(int nIndex) const
527	{
528		ATLASSERT(::IsWindow(this->m_hWnd));
529		return (DWORD_PTR)::SendMessage(this->m_hWnd, LB_GETITEMDATA, nIndex, 0L);
530	}
531
532	int SetItemData(int nIndex, DWORD_PTR dwItemData)
533	{
534		ATLASSERT(::IsWindow(this->m_hWnd));
535		return (int)::SendMessage(this->m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
536	}
537
538	void* GetItemDataPtr(int nIndex) const
539	{
540		ATLASSERT(::IsWindow(this->m_hWnd));
541		return (void*)::SendMessage(this->m_hWnd, LB_GETITEMDATA, nIndex, 0L);
542	}
543
544	int SetItemDataPtr(int nIndex, void* pData)
545	{
546		ATLASSERT(::IsWindow(this->m_hWnd));
547		return SetItemData(nIndex, (DWORD_PTR)pData);
548	}
549
550	int GetItemRect(int nIndex, LPRECT lpRect) const
551	{
552		ATLASSERT(::IsWindow(this->m_hWnd));
553		return (int)::SendMessage(this->m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
554	}
555
556	int GetText(int nIndex, LPTSTR lpszBuffer) const
557	{
558		ATLASSERT(::IsWindow(this->m_hWnd));
559		return (int)::SendMessage(this->m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
560	}
561
562#ifdef _OLEAUTO_H_
563	BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const
564	{
565		USES_CONVERSION;
566		ATLASSERT(::IsWindow(this->m_hWnd));
567		ATLASSERT(bstrText == NULL);
568
569		int nLen = GetTextLen(nIndex);
570		if(nLen == LB_ERR)
571			return FALSE;
572
573		ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
574		LPTSTR lpstrText = buff.Allocate(nLen + 1);
575		if(lpstrText == NULL)
576			return FALSE;
577
578		if(GetText(nIndex, lpstrText) == LB_ERR)
579			return FALSE;
580
581		bstrText = ::SysAllocString(T2OLE(lpstrText));
582		return (bstrText != NULL) ? TRUE : FALSE;
583	}
584#endif // _OLEAUTO_H_
585
586#ifdef __ATLSTR_H__
587	int GetText(int nIndex, ATL::CString& strText) const
588	{
589		ATLASSERT(::IsWindow(this->m_hWnd));
590		int cchLen = GetTextLen(nIndex);
591		if(cchLen == LB_ERR)
592			return LB_ERR;
593		int nRet = LB_ERR;
594		LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
595		if(lpstr != NULL)
596		{
597			nRet = GetText(nIndex, lpstr);
598			strText.ReleaseBuffer();
599		}
600		return nRet;
601	}
602#endif // __ATLSTR_H__
603
604	int GetTextLen(int nIndex) const
605	{
606		ATLASSERT(::IsWindow(this->m_hWnd));
607		return (int)::SendMessage(this->m_hWnd, LB_GETTEXTLEN, nIndex, 0L);
608	}
609
610	int GetItemHeight(int nIndex) const
611	{
612		ATLASSERT(::IsWindow(this->m_hWnd));
613		return (int)::SendMessage(this->m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L);
614	}
615
616	int SetItemHeight(int nIndex, UINT cyItemHeight)
617	{
618		ATLASSERT(::IsWindow(this->m_hWnd));
619		return (int)::SendMessage(this->m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
620	}
621
622	// Settable only attributes
623	void SetColumnWidth(int cxWidth)
624	{
625		ATLASSERT(::IsWindow(this->m_hWnd));
626		::SendMessage(this->m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L);
627	}
628
629	BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
630	{
631		ATLASSERT(::IsWindow(this->m_hWnd));
632		ATLASSERT((this->GetStyle() & LBS_USETABSTOPS) != 0);
633		return (BOOL)::SendMessage(this->m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
634	}
635
636	BOOL SetTabStops()
637	{
638		ATLASSERT(::IsWindow(this->m_hWnd));
639		ATLASSERT((this->GetStyle() & LBS_USETABSTOPS) != 0);
640		return (BOOL)::SendMessage(this->m_hWnd, LB_SETTABSTOPS, 0, 0L);
641	}
642
643	BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
644	{
645		ATLASSERT(::IsWindow(this->m_hWnd));
646		ATLASSERT((this->GetStyle() & LBS_USETABSTOPS) != 0);
647		return (BOOL)::SendMessage(this->m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
648	}
649
650// Operations
651	int InitStorage(int nItems, UINT nBytes)
652	{
653		ATLASSERT(::IsWindow(this->m_hWnd));
654		return (int)::SendMessage(this->m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes);
655	}
656
657	void ResetContent()
658	{
659		ATLASSERT(::IsWindow(this->m_hWnd));
660		::SendMessage(this->m_hWnd, LB_RESETCONTENT, 0, 0L);
661	}
662
663	UINT ItemFromPoint(POINT pt, BOOL& bOutside) const
664	{
665		ATLASSERT(::IsWindow(this->m_hWnd));
666		DWORD dw = (DWORD)::SendMessage(this->m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
667		bOutside = (BOOL)HIWORD(dw);
668		return (UINT)LOWORD(dw);
669	}
670
671	// manipulating listbox items
672	int AddString(LPCTSTR lpszItem)
673	{
674		ATLASSERT(::IsWindow(this->m_hWnd));
675		return (int)::SendMessage(this->m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem);
676	}
677
678	int DeleteString(UINT nIndex)
679	{
680		ATLASSERT(::IsWindow(this->m_hWnd));
681		return (int)::SendMessage(this->m_hWnd, LB_DELETESTRING, nIndex, 0L);
682	}
683
684	int InsertString(int nIndex, LPCTSTR lpszItem)
685	{
686		ATLASSERT(::IsWindow(this->m_hWnd));
687		return (int)::SendMessage(this->m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
688	}
689
690	int Dir(UINT attr, LPCTSTR lpszWildCard)
691	{
692		ATLASSERT(::IsWindow(this->m_hWnd));
693		return (int)::SendMessage(this->m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard);
694	}
695
696	int AddFile(LPCTSTR lpstrFileName)
697	{
698		ATLASSERT(::IsWindow(this->m_hWnd));
699		return (int)::SendMessage(this->m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName);
700	}
701
702	// selection helpers
703	int FindString(int nStartAfter, LPCTSTR lpszItem) const
704	{
705		ATLASSERT(::IsWindow(this->m_hWnd));
706		return (int)::SendMessage(this->m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
707	}
708
709	int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
710	{
711		ATLASSERT(::IsWindow(this->m_hWnd));
712		return (int)::SendMessage(this->m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
713	}
714
715	int SelectString(int nStartAfter, LPCTSTR lpszItem)
716	{
717		ATLASSERT(::IsWindow(this->m_hWnd));
718		return (int)::SendMessage(this->m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
719	}
720
721	int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem)
722	{
723		ATLASSERT(::IsWindow(this->m_hWnd));
724		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
725		ATLASSERT(nFirstItem <= nLastItem);
726		return bSelect ? (int)::SendMessage(this->m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(this->m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem);
727	}
728};
729
730typedef CListBoxT<ATL::CWindow>   CListBox;
731
732
733///////////////////////////////////////////////////////////////////////////////
734// CComboBox - client side for a Windows COMBOBOX control
735
736template <class TBase>
737class CComboBoxT : public TBase
738{
739public:
740// Constructors
741	CComboBoxT(HWND hWnd = NULL) : TBase(hWnd)
742	{ }
743
744	CComboBoxT< TBase >& operator =(HWND hWnd)
745	{
746		this->m_hWnd = hWnd;
747		return *this;
748	}
749
750	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
751			DWORD dwStyle = 0, DWORD dwExStyle = 0,
752			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
753	{
754		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
755	}
756
757// Attributes
758	static LPCTSTR GetWndClassName()
759	{
760		return _T("COMBOBOX");
761	}
762
763	// for entire combo box
764	int GetCount() const
765	{
766		ATLASSERT(::IsWindow(this->m_hWnd));
767		return (int)::SendMessage(this->m_hWnd, CB_GETCOUNT, 0, 0L);
768	}
769
770	int GetCurSel() const
771	{
772		ATLASSERT(::IsWindow(this->m_hWnd));
773		return (int)::SendMessage(this->m_hWnd, CB_GETCURSEL, 0, 0L);
774	}
775
776	int SetCurSel(int nSelect)
777	{
778		ATLASSERT(::IsWindow(this->m_hWnd));
779		return (int)::SendMessage(this->m_hWnd, CB_SETCURSEL, nSelect, 0L);
780	}
781
782	LCID GetLocale() const
783	{
784		ATLASSERT(::IsWindow(this->m_hWnd));
785		return (LCID)::SendMessage(this->m_hWnd, CB_GETLOCALE, 0, 0L);
786	}
787
788	LCID SetLocale(LCID nNewLocale)
789	{
790		ATLASSERT(::IsWindow(this->m_hWnd));
791		return (LCID)::SendMessage(this->m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L);
792	}
793
794	int GetTopIndex() const
795	{
796		ATLASSERT(::IsWindow(this->m_hWnd));
797		return (int)::SendMessage(this->m_hWnd, CB_GETTOPINDEX, 0, 0L);
798	}
799
800	int SetTopIndex(int nIndex)
801	{
802		ATLASSERT(::IsWindow(this->m_hWnd));
803		return (int)::SendMessage(this->m_hWnd, CB_SETTOPINDEX, nIndex, 0L);
804	}
805
806	UINT GetHorizontalExtent() const
807	{
808		ATLASSERT(::IsWindow(this->m_hWnd));
809		return (UINT)::SendMessage(this->m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L);
810	}
811
812	void SetHorizontalExtent(UINT nExtent)
813	{
814		ATLASSERT(::IsWindow(this->m_hWnd));
815		::SendMessage(this->m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L);
816	}
817
818	int GetDroppedWidth() const
819	{
820		ATLASSERT(::IsWindow(this->m_hWnd));
821		return (int)::SendMessage(this->m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L);
822	}
823
824	int SetDroppedWidth(UINT nWidth)
825	{
826		ATLASSERT(::IsWindow(this->m_hWnd));
827		return (int)::SendMessage(this->m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L);
828	}
829
830	BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const
831	{
832		ATLASSERT(::IsWindow(this->m_hWnd));
833		return (BOOL)::SendMessage(this->m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo);
834	}
835
836	// for edit control
837	DWORD GetEditSel() const
838	{
839		ATLASSERT(::IsWindow(this->m_hWnd));
840		return (DWORD)::SendMessage(this->m_hWnd, CB_GETEDITSEL, 0, 0L);
841	}
842
843	BOOL SetEditSel(int nStartChar, int nEndChar)
844	{
845		ATLASSERT(::IsWindow(this->m_hWnd));
846		return (BOOL)::SendMessage(this->m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar));
847	}
848
849	// for combobox item
850	DWORD_PTR GetItemData(int nIndex) const
851	{
852		ATLASSERT(::IsWindow(this->m_hWnd));
853		return (DWORD_PTR)::SendMessage(this->m_hWnd, CB_GETITEMDATA, nIndex, 0L);
854	}
855
856	int SetItemData(int nIndex, DWORD_PTR dwItemData)
857	{
858		ATLASSERT(::IsWindow(this->m_hWnd));
859		return (int)::SendMessage(this->m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
860	}
861
862	void* GetItemDataPtr(int nIndex) const
863	{
864		ATLASSERT(::IsWindow(this->m_hWnd));
865		return (void*)GetItemData(nIndex);
866	}
867
868	int SetItemDataPtr(int nIndex, void* pData)
869	{
870		ATLASSERT(::IsWindow(this->m_hWnd));
871		return SetItemData(nIndex, (DWORD_PTR)pData);
872	}
873
874	int GetLBText(int nIndex, LPTSTR lpszText) const
875	{
876		ATLASSERT(::IsWindow(this->m_hWnd));
877		return (int)::SendMessage(this->m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText);
878	}
879
880	BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const
881	{
882		USES_CONVERSION;
883		ATLASSERT(::IsWindow(this->m_hWnd));
884		ATLASSERT(bstrText == NULL);
885
886		int nLen = GetLBTextLen(nIndex);
887		if(nLen == CB_ERR)
888			return FALSE;
889
890		ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
891		LPTSTR lpstrText = buff.Allocate(nLen + 1);
892		if(lpstrText == NULL)
893			return FALSE;
894
895		if(GetLBText(nIndex, lpstrText) == CB_ERR)
896			return FALSE;
897
898		bstrText = ::SysAllocString(T2OLE(lpstrText));
899		return (bstrText != NULL) ? TRUE : FALSE;
900	}
901
902#ifdef __ATLSTR_H__
903	int GetLBText(int nIndex, ATL::CString& strText) const
904	{
905		ATLASSERT(::IsWindow(this->m_hWnd));
906		int cchLen = GetLBTextLen(nIndex);
907		if(cchLen == CB_ERR)
908			return CB_ERR;
909		int nRet = CB_ERR;
910		LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
911		if(lpstr != NULL)
912		{
913			nRet = GetLBText(nIndex, lpstr);
914			strText.ReleaseBuffer();
915		}
916		return nRet;
917	}
918#endif // __ATLSTR_H__
919
920	int GetLBTextLen(int nIndex) const
921	{
922		ATLASSERT(::IsWindow(this->m_hWnd));
923		return (int)::SendMessage(this->m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L);
924	}
925
926	int GetItemHeight(int nIndex) const
927	{
928		ATLASSERT(::IsWindow(this->m_hWnd));
929		return (int)::SendMessage(this->m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L);
930	}
931
932	int SetItemHeight(int nIndex, UINT cyItemHeight)
933	{
934		ATLASSERT(::IsWindow(this->m_hWnd));
935		return (int)::SendMessage(this->m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
936	}
937
938	BOOL GetExtendedUI() const
939	{
940		ATLASSERT(::IsWindow(this->m_hWnd));
941		return (BOOL)::SendMessage(this->m_hWnd, CB_GETEXTENDEDUI, 0, 0L);
942	}
943
944	int SetExtendedUI(BOOL bExtended = TRUE)
945	{
946		ATLASSERT(::IsWindow(this->m_hWnd));
947		return (int)::SendMessage(this->m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L);
948	}
949
950	void GetDroppedControlRect(LPRECT lprect) const
951	{
952		ATLASSERT(::IsWindow(this->m_hWnd));
953		::SendMessage(this->m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect);
954	}
955
956	BOOL GetDroppedState() const
957	{
958		ATLASSERT(::IsWindow(this->m_hWnd));
959		return (BOOL)::SendMessage(this->m_hWnd, CB_GETDROPPEDSTATE, 0, 0L);
960	}
961
962	int GetMinVisible() const
963	{
964		ATLASSERT(::IsWindow(this->m_hWnd));
965		return (int)::SendMessage(this->m_hWnd, CB_GETMINVISIBLE, 0, 0L);
966	}
967
968	BOOL SetMinVisible(int nMinVisible)
969	{
970		ATLASSERT(::IsWindow(this->m_hWnd));
971		return (BOOL)::SendMessage(this->m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L);
972	}
973
974	// Vista only
975	BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const
976	{
977		ATLASSERT(::IsWindow(this->m_hWnd));
978		return (BOOL)::SendMessage(this->m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText);
979	}
980
981	// Vista only
982	BOOL SetCueBannerText(LPCWSTR lpcwText)
983	{
984		ATLASSERT(::IsWindow(this->m_hWnd));
985		return (BOOL)::SendMessage(this->m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText);
986	}
987
988// Operations
989	int InitStorage(int nItems, UINT nBytes)
990	{
991		ATLASSERT(::IsWindow(this->m_hWnd));
992		return (int)::SendMessage(this->m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes);
993	}
994
995	void ResetContent()
996	{
997		ATLASSERT(::IsWindow(this->m_hWnd));
998		::SendMessage(this->m_hWnd, CB_RESETCONTENT, 0, 0L);
999	}
1000
1001	// for edit control
1002	BOOL LimitText(int nMaxChars)
1003	{
1004		ATLASSERT(::IsWindow(this->m_hWnd));
1005		return (BOOL)::SendMessage(this->m_hWnd, CB_LIMITTEXT, nMaxChars, 0L);
1006	}
1007
1008	// for drop-down combo boxes
1009	void ShowDropDown(BOOL bShowIt = TRUE)
1010	{
1011		ATLASSERT(::IsWindow(this->m_hWnd));
1012		::SendMessage(this->m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L);
1013	}
1014
1015	// manipulating listbox items
1016	int AddString(LPCTSTR lpszString)
1017	{
1018		ATLASSERT(::IsWindow(this->m_hWnd));
1019		return (int)::SendMessage(this->m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString);
1020	}
1021
1022	int DeleteString(UINT nIndex)
1023	{
1024		ATLASSERT(::IsWindow(this->m_hWnd));
1025		return (int)::SendMessage(this->m_hWnd, CB_DELETESTRING, nIndex, 0L);
1026	}
1027
1028	int InsertString(int nIndex, LPCTSTR lpszString)
1029	{
1030		ATLASSERT(::IsWindow(this->m_hWnd));
1031		return (int)::SendMessage(this->m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString);
1032	}
1033
1034	int Dir(UINT attr, LPCTSTR lpszWildCard)
1035	{
1036		ATLASSERT(::IsWindow(this->m_hWnd));
1037		return (int)::SendMessage(this->m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard);
1038	}
1039
1040	// selection helpers
1041	int FindString(int nStartAfter, LPCTSTR lpszString) const
1042	{
1043		ATLASSERT(::IsWindow(this->m_hWnd));
1044		return (int)::SendMessage(this->m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString);
1045	}
1046
1047	int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
1048	{
1049		ATLASSERT(::IsWindow(this->m_hWnd));
1050		return (int)::SendMessage(this->m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
1051	}
1052
1053	int SelectString(int nStartAfter, LPCTSTR lpszString)
1054	{
1055		ATLASSERT(::IsWindow(this->m_hWnd));
1056		return (int)::SendMessage(this->m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString);
1057	}
1058
1059	// Clipboard operations
1060	void Clear()
1061	{
1062		ATLASSERT(::IsWindow(this->m_hWnd));
1063		::SendMessage(this->m_hWnd, WM_CLEAR, 0, 0L);
1064	}
1065
1066	void Copy()
1067	{
1068		ATLASSERT(::IsWindow(this->m_hWnd));
1069		::SendMessage(this->m_hWnd, WM_COPY, 0, 0L);
1070	}
1071
1072	void Cut()
1073	{
1074		ATLASSERT(::IsWindow(this->m_hWnd));
1075		::SendMessage(this->m_hWnd, WM_CUT, 0, 0L);
1076	}
1077
1078	void Paste()
1079	{
1080		ATLASSERT(::IsWindow(this->m_hWnd));
1081		::SendMessage(this->m_hWnd, WM_PASTE, 0, 0L);
1082	}
1083};
1084
1085typedef CComboBoxT<ATL::CWindow>   CComboBox;
1086
1087
1088///////////////////////////////////////////////////////////////////////////////
1089// CEdit - client side for a Windows EDIT control
1090
1091template <class TBase>
1092class CEditT : public TBase
1093{
1094public:
1095// Constructors
1096	CEditT(HWND hWnd = NULL) : TBase(hWnd)
1097	{ }
1098
1099	CEditT< TBase >& operator =(HWND hWnd)
1100	{
1101		this->m_hWnd = hWnd;
1102		return *this;
1103	}
1104
1105	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1106			DWORD dwStyle = 0, DWORD dwExStyle = 0,
1107			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1108	{
1109		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
1110	}
1111
1112// Attributes
1113	static LPCTSTR GetWndClassName()
1114	{
1115		return _T("EDIT");
1116	}
1117
1118	BOOL CanUndo() const
1119	{
1120		ATLASSERT(::IsWindow(this->m_hWnd));
1121		return (BOOL)::SendMessage(this->m_hWnd, EM_CANUNDO, 0, 0L);
1122	}
1123
1124	int GetLineCount() const
1125	{
1126		ATLASSERT(::IsWindow(this->m_hWnd));
1127		return (int)::SendMessage(this->m_hWnd, EM_GETLINECOUNT, 0, 0L);
1128	}
1129
1130	BOOL GetModify() const
1131	{
1132		ATLASSERT(::IsWindow(this->m_hWnd));
1133		return (BOOL)::SendMessage(this->m_hWnd, EM_GETMODIFY, 0, 0L);
1134	}
1135
1136	void SetModify(BOOL bModified = TRUE)
1137	{
1138		ATLASSERT(::IsWindow(this->m_hWnd));
1139		::SendMessage(this->m_hWnd, EM_SETMODIFY, bModified, 0L);
1140	}
1141
1142	void GetRect(LPRECT lpRect) const
1143	{
1144		ATLASSERT(::IsWindow(this->m_hWnd));
1145		::SendMessage(this->m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
1146	}
1147
1148	DWORD GetSel() const
1149	{
1150		ATLASSERT(::IsWindow(this->m_hWnd));
1151		return (DWORD)::SendMessage(this->m_hWnd, EM_GETSEL, 0, 0L);
1152	}
1153
1154	void GetSel(int& nStartChar, int& nEndChar) const
1155	{
1156		ATLASSERT(::IsWindow(this->m_hWnd));
1157		::SendMessage(this->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
1158	}
1159
1160	HLOCAL GetHandle() const
1161	{
1162		ATLASSERT(::IsWindow(this->m_hWnd));
1163		return (HLOCAL)::SendMessage(this->m_hWnd, EM_GETHANDLE, 0, 0L);
1164	}
1165
1166	void SetHandle(HLOCAL hBuffer)
1167	{
1168		ATLASSERT(::IsWindow(this->m_hWnd));
1169		::SendMessage(this->m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L);
1170	}
1171
1172	DWORD GetMargins() const
1173	{
1174		ATLASSERT(::IsWindow(this->m_hWnd));
1175		return (DWORD)::SendMessage(this->m_hWnd, EM_GETMARGINS, 0, 0L);
1176	}
1177
1178	void GetMargins(UINT& nLeft, UINT& nRight) const
1179	{
1180		ATLASSERT(::IsWindow(this->m_hWnd));
1181		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, EM_GETMARGINS, 0, 0L);
1182		nLeft = LOWORD(dwRet);
1183		nRight = HIWORD(dwRet);
1184	}
1185
1186	void SetMargins(UINT nLeft, UINT nRight, WORD wFlags = EC_LEFTMARGIN | EC_RIGHTMARGIN)
1187	{
1188		ATLASSERT(::IsWindow(this->m_hWnd));
1189		::SendMessage(this->m_hWnd, EM_SETMARGINS, wFlags, MAKELONG(nLeft, nRight));
1190	}
1191
1192	UINT GetLimitText() const
1193	{
1194		ATLASSERT(::IsWindow(this->m_hWnd));
1195		return (UINT)::SendMessage(this->m_hWnd, EM_GETLIMITTEXT, 0, 0L);
1196	}
1197
1198	void SetLimitText(UINT nMax)
1199	{
1200		ATLASSERT(::IsWindow(this->m_hWnd));
1201		::SendMessage(this->m_hWnd, EM_SETLIMITTEXT, nMax, 0L);
1202	}
1203
1204	POINT PosFromChar(UINT nChar) const
1205	{
1206		ATLASSERT(::IsWindow(this->m_hWnd));
1207		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, EM_POSFROMCHAR, nChar, 0);
1208		POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
1209		return point;
1210	}
1211
1212	int CharFromPos(POINT pt, int* pLine = NULL) const
1213	{
1214		ATLASSERT(::IsWindow(this->m_hWnd));
1215		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
1216		if(pLine != NULL)
1217			*pLine = (int)(short)HIWORD(dwRet);
1218		return (int)(short)LOWORD(dwRet);
1219	}
1220
1221	// NOTE: first word in lpszBuffer must contain the size of the buffer!
1222	int GetLine(int nIndex, LPTSTR lpszBuffer) const
1223	{
1224		ATLASSERT(::IsWindow(this->m_hWnd));
1225		return (int)::SendMessage(this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
1226	}
1227
1228	int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
1229	{
1230		ATLASSERT(::IsWindow(this->m_hWnd));
1231		*(LPWORD)lpszBuffer = (WORD)nMaxLength;
1232		return (int)::SendMessage(this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
1233	}
1234
1235	TCHAR GetPasswordChar() const
1236	{
1237		ATLASSERT(::IsWindow(this->m_hWnd));
1238		return (TCHAR)::SendMessage(this->m_hWnd, EM_GETPASSWORDCHAR, 0, 0L);
1239	}
1240
1241	void SetPasswordChar(TCHAR ch)
1242	{
1243		ATLASSERT(::IsWindow(this->m_hWnd));
1244		::SendMessage(this->m_hWnd, EM_SETPASSWORDCHAR, ch, 0L);
1245	}
1246
1247	EDITWORDBREAKPROC GetWordBreakProc() const
1248	{
1249		ATLASSERT(::IsWindow(this->m_hWnd));
1250		return (EDITWORDBREAKPROC)::SendMessage(this->m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
1251	}
1252
1253	void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
1254	{
1255		ATLASSERT(::IsWindow(this->m_hWnd));
1256		::SendMessage(this->m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
1257	}
1258
1259	int GetFirstVisibleLine() const
1260	{
1261		ATLASSERT(::IsWindow(this->m_hWnd));
1262		return (int)::SendMessage(this->m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
1263	}
1264
1265	int GetThumb() const
1266	{
1267		ATLASSERT(::IsWindow(this->m_hWnd));
1268		ATLASSERT((this->GetStyle() & ES_MULTILINE) != 0);
1269		return (int)::SendMessage(this->m_hWnd, EM_GETTHUMB, 0, 0L);
1270	}
1271
1272	BOOL SetReadOnly(BOOL bReadOnly = TRUE)
1273	{
1274		ATLASSERT(::IsWindow(this->m_hWnd));
1275		return (BOOL)::SendMessage(this->m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
1276	}
1277
1278	UINT GetImeStatus(UINT uStatus) const
1279	{
1280		ATLASSERT(::IsWindow(this->m_hWnd));
1281		return (UINT)::SendMessage(this->m_hWnd, EM_GETIMESTATUS, uStatus, 0L);
1282	}
1283
1284	UINT SetImeStatus(UINT uStatus, UINT uData)
1285	{
1286		ATLASSERT(::IsWindow(this->m_hWnd));
1287		return (UINT)::SendMessage(this->m_hWnd, EM_SETIMESTATUS, uStatus, uData);
1288	}
1289
1290	BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const
1291	{
1292		ATLASSERT(::IsWindow(this->m_hWnd));
1293		return (BOOL)::SendMessage(this->m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText);
1294	}
1295
1296	// bKeepWithFocus - Vista only
1297	BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE)
1298	{
1299		ATLASSERT(::IsWindow(this->m_hWnd));
1300		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText));
1301	}
1302
1303// Operations
1304	void EmptyUndoBuffer()
1305	{
1306		ATLASSERT(::IsWindow(this->m_hWnd));
1307		::SendMessage(this->m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
1308	}
1309
1310	BOOL FmtLines(BOOL bAddEOL)
1311	{
1312		ATLASSERT(::IsWindow(this->m_hWnd));
1313		return (BOOL)::SendMessage(this->m_hWnd, EM_FMTLINES, bAddEOL, 0L);
1314	}
1315
1316	void LimitText(int nChars = 0)
1317	{
1318		ATLASSERT(::IsWindow(this->m_hWnd));
1319		::SendMessage(this->m_hWnd, EM_LIMITTEXT, nChars, 0L);
1320	}
1321
1322	int LineFromChar(int nIndex = -1) const
1323	{
1324		ATLASSERT(::IsWindow(this->m_hWnd));
1325		return (int)::SendMessage(this->m_hWnd, EM_LINEFROMCHAR, nIndex, 0L);
1326	}
1327
1328	int LineIndex(int nLine = -1) const
1329	{
1330		ATLASSERT(::IsWindow(this->m_hWnd));
1331		return (int)::SendMessage(this->m_hWnd, EM_LINEINDEX, nLine, 0L);
1332	}
1333
1334	int LineLength(int nLine = -1) const
1335	{
1336		ATLASSERT(::IsWindow(this->m_hWnd));
1337		return (int)::SendMessage(this->m_hWnd, EM_LINELENGTH, nLine, 0L);
1338	}
1339
1340	void LineScroll(int nLines, int nChars = 0)
1341	{
1342		ATLASSERT(::IsWindow(this->m_hWnd));
1343		::SendMessage(this->m_hWnd, EM_LINESCROLL, nChars, nLines);
1344	}
1345
1346	void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
1347	{
1348		ATLASSERT(::IsWindow(this->m_hWnd));
1349		::SendMessage(this->m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
1350	}
1351
1352	void SetRect(LPCRECT lpRect)
1353	{
1354		ATLASSERT(::IsWindow(this->m_hWnd));
1355		::SendMessage(this->m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
1356	}
1357
1358	void SetRectNP(LPCRECT lpRect)
1359	{
1360		ATLASSERT(::IsWindow(this->m_hWnd));
1361		::SendMessage(this->m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect);
1362	}
1363
1364	void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE)
1365	{
1366		ATLASSERT(::IsWindow(this->m_hWnd));
1367		::SendMessage(this->m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
1368		if(!bNoScroll)
1369			::SendMessage(this->m_hWnd, EM_SCROLLCARET, 0, 0L);
1370	}
1371
1372	void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE)
1373	{
1374		ATLASSERT(::IsWindow(this->m_hWnd));
1375		::SendMessage(this->m_hWnd, EM_SETSEL, nStartChar, nEndChar);
1376		if(!bNoScroll)
1377			::SendMessage(this->m_hWnd, EM_SCROLLCARET, 0, 0L);
1378	}
1379
1380	void SetSelAll(BOOL bNoScroll = FALSE)
1381	{
1382		SetSel(0, -1, bNoScroll);
1383	}
1384
1385	void SetSelNone(BOOL bNoScroll = FALSE)
1386	{
1387		SetSel(-1, 0, bNoScroll);
1388	}
1389
1390	BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
1391	{
1392		ATLASSERT(::IsWindow(this->m_hWnd));
1393		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
1394	}
1395
1396	BOOL SetTabStops()
1397	{
1398		ATLASSERT(::IsWindow(this->m_hWnd));
1399		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, 0, 0L);
1400	}
1401
1402	BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
1403	{
1404		ATLASSERT(::IsWindow(this->m_hWnd));
1405		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
1406	}
1407
1408	void ScrollCaret()
1409	{
1410		ATLASSERT(::IsWindow(this->m_hWnd));
1411		::SendMessage(this->m_hWnd, EM_SCROLLCARET, 0, 0L);
1412	}
1413
1414	int Scroll(int nScrollAction)
1415	{
1416		ATLASSERT(::IsWindow(this->m_hWnd));
1417		ATLASSERT((this->GetStyle() & ES_MULTILINE) != 0);
1418		LRESULT lRet = ::SendMessage(this->m_hWnd, EM_SCROLL, nScrollAction, 0L);
1419		if(!(BOOL)HIWORD(lRet))
1420			return -1;   // failed
1421		return (int)(short)LOWORD(lRet);
1422		
1423	}
1424
1425	void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
1426	{
1427		SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll);
1428		ReplaceSel(lpstrText, bCanUndo);
1429	}
1430
1431	void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
1432	{
1433		InsertText(this->GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo);
1434	}
1435
1436	BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip)
1437	{
1438		ATLASSERT(::IsWindow(this->m_hWnd));
1439		return (BOOL)::SendMessage(this->m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip);
1440	}
1441
1442	BOOL HideBalloonTip()
1443	{
1444		ATLASSERT(::IsWindow(this->m_hWnd));
1445		return (BOOL)::SendMessage(this->m_hWnd, EM_HIDEBALLOONTIP, 0, 0L);
1446	}
1447
1448#if (_WIN32_WINNT >= 0x0600)
1449	DWORD GetHilite() const
1450	{
1451		ATLASSERT(::IsWindow(this->m_hWnd));
1452		return (DWORD)::SendMessage(this->m_hWnd, EM_GETHILITE, 0, 0L);
1453	}
1454
1455	void GetHilite(int& nStartChar, int& nEndChar) const
1456	{
1457		ATLASSERT(::IsWindow(this->m_hWnd));
1458		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, EM_GETHILITE, 0, 0L);
1459		nStartChar = (int)(short)LOWORD(dwRet);
1460		nEndChar = (int)(short)HIWORD(dwRet);
1461	}
1462
1463	void SetHilite(int nStartChar, int nEndChar)
1464	{
1465		ATLASSERT(::IsWindow(this->m_hWnd));
1466		::SendMessage(this->m_hWnd, EM_SETHILITE, nStartChar, nEndChar);
1467	}
1468#endif // (_WIN32_WINNT >= 0x0600)
1469
1470	// Clipboard operations
1471	BOOL Undo()
1472	{
1473		ATLASSERT(::IsWindow(this->m_hWnd));
1474		return (BOOL)::SendMessage(this->m_hWnd, EM_UNDO, 0, 0L);
1475	}
1476
1477	void Clear()
1478	{
1479		ATLASSERT(::IsWindow(this->m_hWnd));
1480		::SendMessage(this->m_hWnd, WM_CLEAR, 0, 0L);
1481	}
1482
1483	void Copy()
1484	{
1485		ATLASSERT(::IsWindow(this->m_hWnd));
1486		::SendMessage(this->m_hWnd, WM_COPY, 0, 0L);
1487	}
1488
1489	void Cut()
1490	{
1491		ATLASSERT(::IsWindow(this->m_hWnd));
1492		::SendMessage(this->m_hWnd, WM_CUT, 0, 0L);
1493	}
1494
1495	void Paste()
1496	{
1497		ATLASSERT(::IsWindow(this->m_hWnd));
1498		::SendMessage(this->m_hWnd, WM_PASTE, 0, 0L);
1499	}
1500
1501	// New messages added in Windows 10.0.17763
1502#if defined(NTDDI_VERSION) && defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5)
1503	DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
1504	{
1505		ATLASSERT(::IsWindow(this->m_hWnd));
1506		return ::SendMessage(this->m_hWnd, EM_SETEXTENDEDSTYLE, dwMask, dwStyle);
1507	}
1508
1509	DWORD GetExtendedStyle() const
1510	{
1511		ATLASSERT(::IsWindow(this->m_hWnd));
1512		return ::SendMessage(this->m_hWnd, EM_GETEXTENDEDSTYLE, 0, 0L);
1513	}
1514
1515	BOOL SetEndOfLine(EC_ENDOFLINE eolType)
1516	{
1517		ATLASSERT(::IsWindow(this->m_hWnd));
1518		return (BOOL)::SendMessage(this->m_hWnd, EM_SETENDOFLINE, eolType, 0L);
1519	}
1520
1521	EC_ENDOFLINE GetEndOfLine() const
1522	{
1523		ATLASSERT(::IsWindow(this->m_hWnd));
1524		return (EC_ENDOFLINE)::SendMessage(this->m_hWnd, EM_GETENDOFLINE, 0, 0L);
1525	}
1526
1527	BOOL EnableSearchWeb(BOOL bEnable)
1528	{
1529		ATLASSERT(::IsWindow(this->m_hWnd));
1530		return (BOOL)::SendMessage(this->m_hWnd, EM_ENABLESEARCHWEB, (WPARAM)bEnable, 0L);
1531	}
1532
1533	void SearchWeb()
1534	{
1535		ATLASSERT(::IsWindow(this->m_hWnd));
1536		::SendMessage(this->m_hWnd, EM_SEARCHWEB, 0, 0L);
1537	}
1538
1539	BOOL SetCaretIndex(DWORD dwCaretIndex)
1540	{
1541		ATLASSERT(::IsWindow(this->m_hWnd));
1542		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCARETINDEX, dwCaretIndex, 0L);
1543	}
1544
1545	DWORD GetCaretIndex() const
1546	{
1547		ATLASSERT(::IsWindow(this->m_hWnd));
1548		return ::SendMessage(this->m_hWnd, EM_GETCARETINDEX, 0, 0L);
1549	}
1550
1551	BOOL GetZoom(int& nNum, int& nDen) const
1552	{
1553		ATLASSERT(::IsWindow(this->m_hWnd));
1554		return (BOOL)::SendMessage(this->m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen);
1555	}
1556
1557	BOOL SetZoom(int nNum, int nDen)
1558	{
1559		ATLASSERT(::IsWindow(this->m_hWnd));
1560		ATLASSERT((nNum >= 0) && (nNum <= 64));
1561		ATLASSERT((nDen >= 0) && (nDen <= 64));
1562		return (BOOL)::SendMessage(this->m_hWnd, EM_SETZOOM, nNum, nDen);
1563	}
1564
1565	DWORD GetFileLineFromChar(DWORD dwCharIndex) const
1566	{
1567		ATLASSERT(::IsWindow(this->m_hWnd));
1568		return ::SendMessage(this->m_hWnd, EM_FILELINEFROMCHAR, dwCharIndex, 0L);
1569	}
1570
1571	DWORD GetFileLineIndex(DWORD dwLineNum) const
1572	{
1573		ATLASSERT(::IsWindow(this->m_hWnd));
1574		return ::SendMessage(this->m_hWnd, EM_FILELINEINDEX, dwLineNum, 0L);
1575	}
1576
1577	DWORD GetFileLineLength(DWORD dwCharIndex) const
1578	{
1579		ATLASSERT(::IsWindow(this->m_hWnd));
1580		return ::SendMessage(this->m_hWnd, EM_FILELINELENGTH, dwCharIndex, 0L);
1581	}
1582
1583	DWORD GetFileLine(DWORD dwLineNum, LPTSTR lpstrLine, WORD wLen) const
1584	{
1585		ATLASSERT(::IsWindow(this->m_hWnd));
1586		WORD* pw = (WORD*)lpstrLine;
1587		*pw = wLen;
1588		return ::SendMessage(this->m_hWnd, EM_GETFILELINE, dwLineNum, (LPARAM)lpstrLine);
1589	}
1590
1591#ifdef __ATLSTR_H__
1592	ATL::CString GetFileLine(DWORD dwLineNum) const
1593	{
1594		ATL::CString strLine;
1595		DWORD dwCharIndex = GetFileLineIndex(dwLineNum);
1596		if(dwCharIndex != (DWORD)-1)
1597		{
1598			DWORD dwLen = GetFileLineLength(dwCharIndex);
1599			if(dwLen > 0)
1600			{
1601				LPTSTR lpstrLine = strLine.GetBufferSetLength(dwLen);
1602				ATLVERIFY(GetFileLine(dwLineNum, lpstrLine, (WORD)dwLen) == dwLen);
1603				strLine.ReleaseBuffer();
1604			}
1605		}
1606
1607		return strLine;
1608	}
1609#endif // __ATLSTR_H__
1610
1611	DWORD GetFileLineCount() const
1612	{
1613		ATLASSERT(::IsWindow(this->m_hWnd));
1614		return ::SendMessage(this->m_hWnd, EM_GETFILELINECOUNT, 0, 0L);
1615	}
1616#endif // defined(NTDDI_VERSION) && defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5)
1617};
1618
1619typedef CEditT<ATL::CWindow>   CEdit;
1620
1621
1622///////////////////////////////////////////////////////////////////////////////
1623// CEditCommands - message handlers for standard EDIT commands
1624
1625// Chain to CEditCommands message map. Your class must also derive from CEdit.
1626// Example:
1627// class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
1628//                 public CEditCommands<CMyEdit>
1629// {
1630// public:
1631//      BEGIN_MSG_MAP(CMyEdit)
1632//              // your handlers...
1633//              CHAIN_MSG_MAP_ALT(CEditCommands<CMyEdit>, 1)
1634//      END_MSG_MAP()
1635//      // other stuff...
1636// };
1637
1638template <class T>
1639class CEditCommands
1640{
1641public:
1642	BEGIN_MSG_MAP(CEditCommands< T >)
1643	ALT_MSG_MAP(1)
1644		COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear)
1645		COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll)
1646		COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy)
1647		COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut)
1648		COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste)
1649		COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll)
1650		COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo)
1651	END_MSG_MAP()
1652
1653	LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1654	{
1655		T* pT = static_cast<T*>(this);
1656		pT->Clear();
1657		return 0;
1658	}
1659
1660	LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1661	{
1662		T* pT = static_cast<T*>(this);
1663		pT->SetSel(0, -1);
1664		pT->Clear();
1665		return 0;
1666	}
1667
1668	LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1669	{
1670		T* pT = static_cast<T*>(this);
1671		pT->Copy();
1672		return 0;
1673	}
1674
1675	LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1676	{
1677		T* pT = static_cast<T*>(this);
1678		pT->Cut();
1679		return 0;
1680	}
1681
1682	LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1683	{
1684		T* pT = static_cast<T*>(this);
1685		pT->Paste();
1686		return 0;
1687	}
1688
1689	LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1690	{
1691		T* pT = static_cast<T*>(this);
1692		pT->SetSel(0, -1);
1693		return 0;
1694	}
1695
1696	LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1697	{
1698		T* pT = static_cast<T*>(this);
1699		pT->Undo();
1700		return 0;
1701	}
1702
1703// State (update UI) helpers
1704	BOOL CanCut() const
1705	{ return HasSelection(); }
1706
1707	BOOL CanCopy() const
1708	{ return HasSelection(); }
1709
1710	BOOL CanClear() const
1711	{ return HasSelection(); }
1712
1713	BOOL CanSelectAll() const
1714	{ return HasText(); }
1715
1716	BOOL CanFind() const
1717	{ return HasText(); }
1718
1719	BOOL CanRepeat() const
1720	{ return HasText(); }
1721
1722	BOOL CanReplace() const
1723	{ return HasText(); }
1724
1725	BOOL CanClearAll() const
1726	{ return HasText(); }
1727
1728// Implementation
1729	BOOL HasSelection() const
1730	{
1731		const T* pT = static_cast<const T*>(this);
1732		int nMin = 0, nMax = 0;
1733		::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax);
1734		return (nMin != nMax);
1735	}
1736
1737	BOOL HasText() const
1738	{
1739		const T* pT = static_cast<const T*>(this);
1740		return (pT->GetWindowTextLength() > 0);
1741	}
1742};
1743
1744
1745///////////////////////////////////////////////////////////////////////////////
1746// CScrollBar - client side for a Windows SCROLLBAR control
1747
1748template <class TBase>
1749class CScrollBarT : public TBase
1750{
1751public:
1752// Constructors
1753	CScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
1754	{ }
1755
1756	CScrollBarT< TBase >& operator =(HWND hWnd)
1757	{
1758		this->m_hWnd = hWnd;
1759		return *this;
1760	}
1761
1762	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1763			DWORD dwStyle = 0, DWORD dwExStyle = 0,
1764			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1765	{
1766		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
1767	}
1768
1769// Attributes
1770	static LPCTSTR GetWndClassName()
1771	{
1772		return _T("SCROLLBAR");
1773	}
1774
1775	int GetScrollPos() const
1776	{
1777		ATLASSERT(::IsWindow(this->m_hWnd));
1778		return ::GetScrollPos(this->m_hWnd, SB_CTL);
1779	}
1780
1781	int SetScrollPos(int nPos, BOOL bRedraw = TRUE)
1782	{
1783		ATLASSERT(::IsWindow(this->m_hWnd));
1784		return ::SetScrollPos(this->m_hWnd, SB_CTL, nPos, bRedraw);
1785	}
1786
1787	void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const
1788	{
1789		ATLASSERT(::IsWindow(this->m_hWnd));
1790		::GetScrollRange(this->m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
1791	}
1792
1793	void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
1794	{
1795		ATLASSERT(::IsWindow(this->m_hWnd));
1796		::SetScrollRange(this->m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
1797	}
1798
1799	BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const
1800	{
1801		ATLASSERT(::IsWindow(this->m_hWnd));
1802		return ::GetScrollInfo(this->m_hWnd, SB_CTL, lpScrollInfo);
1803	}
1804
1805	int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1806	{
1807		ATLASSERT(::IsWindow(this->m_hWnd));
1808		return ::SetScrollInfo(this->m_hWnd, SB_CTL, lpScrollInfo, bRedraw);
1809	}
1810
1811	int GetScrollLimit() const
1812	{
1813		SCROLLINFO info = { sizeof(SCROLLINFO), SIF_RANGE | SIF_PAGE };
1814		::GetScrollInfo(this->m_hWnd, SB_CTL, &info);
1815		if(info.nPage > 1)
1816			info.nMax -= info.nPage - 1;
1817
1818		return info.nMax;
1819	}
1820
1821	BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const
1822	{
1823		ATLASSERT(::IsWindow(this->m_hWnd));
1824		return (BOOL)::SendMessage(this->m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo);
1825	}
1826
1827// Operations
1828	void ShowScrollBar(BOOL bShow = TRUE)
1829	{
1830		ATLASSERT(::IsWindow(this->m_hWnd));
1831		::ShowScrollBar(this->m_hWnd, SB_CTL, bShow);
1832	}
1833
1834	BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH)
1835	{
1836		ATLASSERT(::IsWindow(this->m_hWnd));
1837		return ::EnableScrollBar(this->m_hWnd, SB_CTL, nArrowFlags);
1838	}
1839};
1840
1841typedef CScrollBarT<ATL::CWindow>   CScrollBar;
1842
1843
1844// --- Windows Common Controls ---
1845
1846///////////////////////////////////////////////////////////////////////////////
1847// CImageList
1848
1849// forward declarations
1850template <bool t_bManaged> class CImageListT;
1851typedef CImageListT<false>   CImageList;
1852typedef CImageListT<true>    CImageListManaged;
1853
1854
1855template <bool t_bManaged>
1856class CImageListT
1857{
1858public:
1859// Data members
1860	HIMAGELIST m_hImageList;
1861
1862// Constructor/destructor/operators
1863	CImageListT(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList)
1864	{ }
1865
1866	~CImageListT()
1867	{
1868		if(t_bManaged && (m_hImageList != NULL))
1869			Destroy();
1870	}
1871
1872	CImageListT<t_bManaged>& operator =(HIMAGELIST hImageList)
1873	{
1874		Attach(hImageList);
1875		return *this;
1876	}
1877
1878	void Attach(HIMAGELIST hImageList)
1879	{
1880		if(t_bManaged && (m_hImageList != NULL) && (m_hImageList != hImageList))
1881			ImageList_Destroy(m_hImageList);
1882		m_hImageList = hImageList;
1883	}
1884
1885	HIMAGELIST Detach()
1886	{
1887		HIMAGELIST hImageList = m_hImageList;
1888		m_hImageList = NULL;
1889		return hImageList;
1890	}
1891
1892	operator HIMAGELIST() const { return m_hImageList; }
1893
1894	bool IsNull() const { return (m_hImageList == NULL); }
1895
1896// Attributes
1897	int GetImageCount() const
1898	{
1899		ATLASSERT(m_hImageList != NULL);
1900		return ImageList_GetImageCount(m_hImageList);
1901	}
1902
1903	COLORREF GetBkColor() const
1904	{
1905		ATLASSERT(m_hImageList != NULL);
1906		return ImageList_GetBkColor(m_hImageList);
1907	}
1908
1909	COLORREF SetBkColor(COLORREF cr)
1910	{
1911		ATLASSERT(m_hImageList != NULL);
1912		return ImageList_SetBkColor(m_hImageList, cr);
1913	}
1914
1915	BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const
1916	{
1917		ATLASSERT(m_hImageList != NULL);
1918		return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo);
1919	}
1920
1921	HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const
1922	{
1923		ATLASSERT(m_hImageList != NULL);
1924		return ImageList_GetIcon(m_hImageList, nIndex, uFlags);
1925	}
1926
1927	BOOL GetIconSize(int& cx, int& cy) const
1928	{
1929		ATLASSERT(m_hImageList != NULL);
1930		return ImageList_GetIconSize(m_hImageList, &cx, &cy);
1931	}
1932
1933	BOOL GetIconSize(SIZE& size) const
1934	{
1935		ATLASSERT(m_hImageList != NULL);
1936		return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy);
1937	}
1938
1939	BOOL SetIconSize(int cx, int cy)
1940	{
1941		ATLASSERT(m_hImageList != NULL);
1942		return ImageList_SetIconSize(m_hImageList, cx, cy);
1943	}
1944
1945	BOOL SetIconSize(SIZE size)
1946	{
1947		ATLASSERT(m_hImageList != NULL);
1948		return ImageList_SetIconSize(m_hImageList, size.cx, size.cy);
1949	}
1950
1951	BOOL SetImageCount(UINT uNewCount)
1952	{
1953		ATLASSERT(m_hImageList != NULL);
1954		return ImageList_SetImageCount(m_hImageList, uNewCount);
1955	}
1956
1957	BOOL SetOverlayImage(int nImage, int nOverlay)
1958	{
1959		ATLASSERT(m_hImageList != NULL);
1960		return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay);
1961	}
1962
1963// Operations
1964	BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow)
1965	{
1966		ATLASSERT(m_hImageList == NULL);
1967		m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow);
1968		return (m_hImageList != NULL) ? TRUE : FALSE;
1969	}
1970
1971	BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask)
1972	{
1973		ATLASSERT(m_hImageList == NULL);
1974		m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask);
1975		return (m_hImageList != NULL) ? TRUE : FALSE;
1976	}
1977
1978	BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE)
1979	{
1980		ATLASSERT(m_hImageList == NULL);
1981		m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags);
1982		return (m_hImageList != NULL) ? TRUE : FALSE;
1983	}
1984
1985	BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy)
1986	{
1987		ATLASSERT(m_hImageList == NULL);
1988		m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy);
1989		return (m_hImageList != NULL) ? TRUE : FALSE;
1990	}
1991
1992#ifdef __IStream_INTERFACE_DEFINED__
1993	BOOL CreateFromStream(LPSTREAM lpStream)
1994	{
1995		ATLASSERT(m_hImageList == NULL);
1996		m_hImageList = ImageList_Read(lpStream);
1997		return (m_hImageList != NULL) ? TRUE : FALSE;
1998	}
1999#endif // __IStream_INTERFACE_DEFINED__
2000
2001	BOOL Destroy()
2002	{
2003		if (m_hImageList == NULL)
2004			return FALSE;
2005		BOOL bRet = ImageList_Destroy(m_hImageList);
2006		if(bRet)
2007			m_hImageList = NULL;
2008		return bRet;
2009	}
2010
2011	int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL)
2012	{
2013		ATLASSERT(m_hImageList != NULL);
2014		return ImageList_Add(m_hImageList, hBitmap, hBitmapMask);
2015	}
2016
2017	int Add(HBITMAP hBitmap, COLORREF crMask)
2018	{
2019		ATLASSERT(m_hImageList != NULL);
2020		return ImageList_AddMasked(m_hImageList, hBitmap, crMask);
2021	}
2022
2023	BOOL Remove(int nImage)
2024	{
2025		ATLASSERT(m_hImageList != NULL);
2026		return ImageList_Remove(m_hImageList, nImage);
2027	}
2028
2029	BOOL RemoveAll()
2030	{
2031		ATLASSERT(m_hImageList != NULL);
2032		return ImageList_RemoveAll(m_hImageList);
2033	}
2034
2035	BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask)
2036	{
2037		ATLASSERT(m_hImageList != NULL);
2038		return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask);
2039	}
2040
2041	int AddIcon(HICON hIcon)
2042	{
2043		ATLASSERT(m_hImageList != NULL);
2044		return ImageList_AddIcon(m_hImageList, hIcon);
2045	}
2046
2047	int ReplaceIcon(int nImage, HICON hIcon)
2048	{
2049		ATLASSERT(m_hImageList != NULL);
2050		return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon);
2051	}
2052
2053	HICON ExtractIcon(int nImage)
2054	{
2055		ATLASSERT(m_hImageList != NULL);
2056		return ImageList_ExtractIcon(NULL, m_hImageList, nImage);
2057	}
2058
2059	BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle)
2060	{
2061		ATLASSERT(m_hImageList != NULL);
2062		ATLASSERT(hDC != NULL);
2063		return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle);
2064	}
2065
2066	BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle)
2067	{
2068		ATLASSERT(m_hImageList != NULL);
2069		ATLASSERT(hDC != NULL);
2070		return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle);
2071	}
2072
2073	BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
2074	{
2075		ATLASSERT(m_hImageList != NULL);
2076		ATLASSERT(hDC != NULL);
2077		return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle);
2078	}
2079
2080	BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
2081	{
2082		ATLASSERT(m_hImageList != NULL);
2083		ATLASSERT(hDC != NULL);
2084		return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle);
2085	}
2086
2087	static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp)
2088	{
2089		return ImageList_DrawIndirect(pimldp);
2090	}
2091
2092	BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE)
2093	{
2094		ATLASSERT(m_hImageList != NULL);
2095		return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags);
2096	}
2097
2098#ifdef __IStream_INTERFACE_DEFINED__
2099	static HIMAGELIST Read(LPSTREAM lpStream)
2100	{
2101		return ImageList_Read(lpStream);
2102	}
2103
2104	BOOL Write(LPSTREAM lpStream)
2105	{
2106		ATLASSERT(m_hImageList != NULL);
2107		return ImageList_Write(m_hImageList, lpStream);
2108	}
2109
2110	static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv)
2111	{
2112		return ImageList_ReadEx(dwFlags, lpStream, riid, ppv);
2113	}
2114
2115	HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream)
2116	{
2117		ATLASSERT(m_hImageList != NULL);
2118		return ImageList_WriteEx(m_hImageList, dwFlags, lpStream);
2119	}
2120#endif // __IStream_INTERFACE_DEFINED__
2121
2122	// Drag operations
2123	BOOL BeginDrag(int nImage, POINT ptHotSpot)
2124	{
2125		ATLASSERT(m_hImageList != NULL);
2126		return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y);
2127	}
2128
2129	BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot)
2130	{
2131		ATLASSERT(m_hImageList != NULL);
2132		return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot);
2133	}
2134
2135	static void EndDrag()
2136	{
2137		ImageList_EndDrag();
2138	}
2139
2140	static BOOL DragMove(POINT pt)
2141	{
2142		return ImageList_DragMove(pt.x, pt.y);
2143	}
2144
2145	static BOOL DragMove(int x, int y)
2146	{
2147		return ImageList_DragMove(x, y);
2148	}
2149
2150	BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot)
2151	{
2152		ATLASSERT(m_hImageList != NULL);
2153		return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y);
2154	}
2155
2156	BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot)
2157	{
2158		ATLASSERT(m_hImageList != NULL);
2159		return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot);
2160	}
2161
2162	static BOOL DragShowNolock(BOOL bShow = TRUE)
2163	{
2164		return ImageList_DragShowNolock(bShow);
2165	}
2166
2167	static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot)
2168	{
2169		return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot));
2170	}
2171
2172	static BOOL DragEnter(HWND hWnd, POINT point)
2173	{
2174		return ImageList_DragEnter(hWnd, point.x, point.y);
2175	}
2176
2177	static BOOL DragEnter(HWND hWnd, int x, int y)
2178	{
2179		return ImageList_DragEnter(hWnd, x, y);
2180	}
2181
2182	static BOOL DragLeave(HWND hWnd)
2183	{
2184		return ImageList_DragLeave(hWnd);
2185	}
2186
2187	CImageList Duplicate() const
2188	{
2189		ATLASSERT(m_hImageList != NULL);
2190		return CImageList(ImageList_Duplicate(m_hImageList));
2191	}
2192
2193	static CImageList Duplicate(HIMAGELIST hImageList)
2194	{
2195		ATLASSERT(hImageList != NULL);
2196		return CImageList(ImageList_Duplicate(hImageList));
2197	}
2198};
2199
2200
2201///////////////////////////////////////////////////////////////////////////////
2202// CToolTipCtrl
2203
2204class CToolInfo : public TOOLINFO
2205{
2206public:
2207	CToolInfo(UINT nFlags, HWND hWnd, UINT_PTR nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
2208	{
2209		Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam);
2210	}
2211
2212	operator LPTOOLINFO() { return this; }
2213
2214	operator LPARAM() { return (LPARAM)this; }
2215
2216	void Init(UINT nFlags, HWND hWnd, UINT_PTR nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
2217	{
2218		ATLASSERT(::IsWindow(hWnd));
2219		memset(this, 0, sizeof(TOOLINFO));
2220		cbSize = RunTimeHelper::SizeOf_TOOLINFO();
2221		uFlags = nFlags;
2222		if(nIDTool == 0)
2223		{
2224			hwnd = ::GetParent(hWnd);
2225			uFlags |= TTF_IDISHWND;
2226			uId = (UINT_PTR)hWnd;
2227		}
2228		else
2229		{
2230			hwnd = hWnd;
2231			uId = nIDTool;
2232		}
2233		if(lpRect != NULL)
2234			rect = *lpRect;
2235		hinst = ModuleHelper::GetResourceInstance();
2236		lpszText = lpstrText;
2237		lParam = lUserParam;
2238	}
2239};
2240
2241template <class TBase>
2242class CToolTipCtrlT : public TBase
2243{
2244public:
2245// Constructors
2246	CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2247	{ }
2248
2249	CToolTipCtrlT< TBase >& operator =(HWND hWnd)
2250	{
2251		this->m_hWnd = hWnd;
2252		return *this;
2253	}
2254
2255	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2256			DWORD dwStyle = 0, DWORD dwExStyle = 0,
2257			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2258	{
2259		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2260	}
2261
2262// Attributes
2263	static LPCTSTR GetWndClassName()
2264	{
2265		return TOOLTIPS_CLASS;
2266	}
2267
2268	void GetText(LPTOOLINFO lpToolInfo) const
2269	{
2270		ATLASSERT(::IsWindow(this->m_hWnd));
2271		::SendMessage(this->m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo);
2272	}
2273
2274	void GetText(LPTSTR lpstrText, HWND hWnd, UINT_PTR nIDTool = 0) const
2275	{
2276		ATLASSERT(::IsWindow(this->m_hWnd));
2277		ATLASSERT(hWnd != NULL);
2278		CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
2279		::SendMessage(this->m_hWnd, TTM_GETTEXT, 0, ti);
2280	}
2281
2282	BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const
2283	{
2284		ATLASSERT(::IsWindow(this->m_hWnd));
2285		return (BOOL)::SendMessage(this->m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo);
2286	}
2287
2288	BOOL GetToolInfo(HWND hWnd, UINT_PTR nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const
2289	{
2290		ATLASSERT(::IsWindow(this->m_hWnd));
2291		ATLASSERT(hWnd != NULL);
2292		ATLASSERT(puFlags != NULL);
2293		ATLASSERT(lpRect != NULL);
2294		CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
2295		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, TTM_GETTOOLINFO, 0, ti);
2296		if(bRet != FALSE)
2297		{
2298			*puFlags = ti.uFlags;
2299			*lpRect = ti.rect;
2300		}
2301		return bRet;
2302	}
2303
2304	void SetToolInfo(LPTOOLINFO lpToolInfo)
2305	{
2306		ATLASSERT(::IsWindow(this->m_hWnd));
2307		::SendMessage(this->m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo);
2308	}
2309
2310	void SetToolRect(LPTOOLINFO lpToolInfo)
2311	{
2312		ATLASSERT(::IsWindow(this->m_hWnd));
2313		::SendMessage(this->m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo);
2314	}
2315
2316	void SetToolRect(HWND hWnd, UINT_PTR nIDTool, LPCRECT lpRect)
2317	{
2318		ATLASSERT(::IsWindow(this->m_hWnd));
2319		ATLASSERT(hWnd != NULL);
2320		ATLASSERT(nIDTool != 0);
2321
2322		CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL);
2323		::SendMessage(this->m_hWnd, TTM_NEWTOOLRECT, 0, ti);
2324	}
2325
2326	int GetToolCount() const
2327	{
2328		ATLASSERT(::IsWindow(this->m_hWnd));
2329		return (int)::SendMessage(this->m_hWnd, TTM_GETTOOLCOUNT, 0, 0L);
2330	}
2331
2332	int GetDelayTime(DWORD dwType) const
2333	{
2334		ATLASSERT(::IsWindow(this->m_hWnd));
2335		return (int)::SendMessage(this->m_hWnd, TTM_GETDELAYTIME, dwType, 0L);
2336	}
2337
2338	void SetDelayTime(DWORD dwType, int nTime)
2339	{
2340		ATLASSERT(::IsWindow(this->m_hWnd));
2341		::SendMessage(this->m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0));
2342	}
2343
2344	void GetMargin(LPRECT lpRect) const
2345	{
2346		ATLASSERT(::IsWindow(this->m_hWnd));
2347		::SendMessage(this->m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect);
2348	}
2349
2350	void SetMargin(LPRECT lpRect)
2351	{
2352		ATLASSERT(::IsWindow(this->m_hWnd));
2353		::SendMessage(this->m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect);
2354	}
2355
2356	int GetMaxTipWidth() const
2357	{
2358		ATLASSERT(::IsWindow(this->m_hWnd));
2359		return (int)::SendMessage(this->m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L);
2360	}
2361
2362	int SetMaxTipWidth(int nWidth)
2363	{
2364		ATLASSERT(::IsWindow(this->m_hWnd));
2365		return (int)::SendMessage(this->m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth);
2366	}
2367
2368	COLORREF GetTipBkColor() const
2369	{
2370		ATLASSERT(::IsWindow(this->m_hWnd));
2371		return (COLORREF)::SendMessage(this->m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L);
2372	}
2373
2374	void SetTipBkColor(COLORREF clr)
2375	{
2376		ATLASSERT(::IsWindow(this->m_hWnd));
2377		::SendMessage(this->m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L);
2378	}
2379
2380	COLORREF GetTipTextColor() const
2381	{
2382		ATLASSERT(::IsWindow(this->m_hWnd));
2383		return (COLORREF)::SendMessage(this->m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L);
2384	}
2385
2386	void SetTipTextColor(COLORREF clr)
2387	{
2388		ATLASSERT(::IsWindow(this->m_hWnd));
2389		::SendMessage(this->m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L);
2390	}
2391
2392	BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const
2393	{
2394		ATLASSERT(::IsWindow(this->m_hWnd));
2395		return (BOOL)::SendMessage(this->m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo);
2396	}
2397
2398	SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const
2399	{
2400		ATLASSERT(::IsWindow(this->m_hWnd));
2401		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo);
2402		SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
2403		return size;
2404	}
2405
2406	BOOL SetTitle(UINT_PTR uIcon, LPCTSTR lpstrTitle)
2407	{
2408		ATLASSERT(::IsWindow(this->m_hWnd));
2409		return (BOOL)::SendMessage(this->m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle);
2410	}
2411
2412
2413	BOOL SetTitle(HICON hIcon, LPCTSTR lpstrTitle)
2414	{
2415		ATLASSERT(::IsWindow(this->m_hWnd));
2416		return (BOOL)::SendMessage(this->m_hWnd, TTM_SETTITLE, (WPARAM)hIcon, (LPARAM)lpstrTitle);
2417	}
2418
2419	void GetTitle(PTTGETTITLE pTTGetTitle) const
2420	{
2421		ATLASSERT(::IsWindow(this->m_hWnd));
2422		::SendMessage(this->m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle);
2423	}
2424
2425	void SetWindowTheme(LPCWSTR lpstrTheme)
2426	{
2427		ATLASSERT(::IsWindow(this->m_hWnd));
2428		::SendMessage(this->m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
2429	}
2430
2431// Operations
2432	void Activate(BOOL bActivate)
2433	{
2434		ATLASSERT(::IsWindow(this->m_hWnd));
2435		::SendMessage(this->m_hWnd, TTM_ACTIVATE, bActivate, 0L);
2436	}
2437
2438	BOOL AddTool(LPTOOLINFO lpToolInfo)
2439	{
2440		ATLASSERT(::IsWindow(this->m_hWnd));
2441		return (BOOL)::SendMessage(this->m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo);
2442	}
2443
2444	BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0)
2445	{
2446		ATLASSERT(::IsWindow(this->m_hWnd));
2447		ATLASSERT(hWnd != NULL);
2448		// the toolrect and toolid must both be zero or both valid
2449		ATLASSERT(((lpRectTool != NULL) && (nIDTool != 0)) || ((lpRectTool == NULL) && (nIDTool == 0)));
2450
2451		CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr);
2452		return (BOOL)::SendMessage(this->m_hWnd, TTM_ADDTOOL, 0, ti);
2453	}
2454
2455	void DelTool(LPTOOLINFO lpToolInfo)
2456	{
2457		ATLASSERT(::IsWindow(this->m_hWnd));
2458		::SendMessage(this->m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo);
2459	}
2460
2461	void DelTool(HWND hWnd, UINT_PTR nIDTool = 0)
2462	{
2463		ATLASSERT(::IsWindow(this->m_hWnd));
2464		ATLASSERT(hWnd != NULL);
2465
2466		CToolInfo ti(0, hWnd, nIDTool, NULL, NULL);
2467		::SendMessage(this->m_hWnd, TTM_DELTOOL, 0, ti);
2468	}
2469
2470	BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const
2471	{
2472		ATLASSERT(::IsWindow(this->m_hWnd));
2473		return (BOOL)::SendMessage(this->m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo);
2474	}
2475
2476	BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const
2477	{
2478		ATLASSERT(::IsWindow(this->m_hWnd));
2479		ATLASSERT(hWnd != NULL);
2480		ATLASSERT(lpToolInfo != NULL);
2481
2482		TTHITTESTINFO hti = {};
2483		hti.ti.cbSize = RunTimeHelper::SizeOf_TOOLINFO();
2484		hti.hwnd = hWnd;
2485		hti.pt.x = pt.x;
2486		hti.pt.y = pt.y;
2487		if((BOOL)::SendMessage(this->m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE)
2488		{
2489			*lpToolInfo = hti.ti;
2490			return TRUE;
2491		}
2492		return FALSE;
2493	}
2494
2495	void RelayEvent(LPMSG lpMsg)
2496	{
2497		ATLASSERT(::IsWindow(this->m_hWnd));
2498		::SendMessage(this->m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg);
2499	}
2500
2501	void UpdateTipText(LPTOOLINFO lpToolInfo)
2502	{
2503		ATLASSERT(::IsWindow(this->m_hWnd));
2504		::SendMessage(this->m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo);
2505	}
2506
2507	void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT_PTR nIDTool = 0)
2508	{
2509		ATLASSERT(::IsWindow(this->m_hWnd));
2510		ATLASSERT(hWnd != NULL);
2511
2512		CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr);
2513		::SendMessage(this->m_hWnd, TTM_UPDATETIPTEXT, 0, ti);
2514	}
2515
2516	BOOL EnumTools(UINT_PTR nTool, LPTOOLINFO lpToolInfo) const
2517	{
2518		ATLASSERT(::IsWindow(this->m_hWnd));
2519		return (BOOL)::SendMessage(this->m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo);
2520	}
2521
2522	void Pop()
2523	{
2524		ATLASSERT(::IsWindow(this->m_hWnd));
2525		::SendMessage(this->m_hWnd, TTM_POP, 0, 0L);
2526	}
2527
2528	void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate)
2529	{
2530		ATLASSERT(::IsWindow(this->m_hWnd));
2531		::SendMessage(this->m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo);
2532	}
2533
2534	void TrackActivate(HWND hWnd, UINT_PTR nIDTool, BOOL bActivate)
2535	{
2536		ATLASSERT(::IsWindow(this->m_hWnd));
2537		ATLASSERT(hWnd != NULL);
2538
2539		CToolInfo ti(0, hWnd, nIDTool);
2540		::SendMessage(this->m_hWnd, TTM_TRACKACTIVATE, bActivate, ti);
2541	}
2542
2543	void TrackPosition(int xPos, int yPos)
2544	{
2545		ATLASSERT(::IsWindow(this->m_hWnd));
2546		::SendMessage(this->m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos));
2547	}
2548
2549	void Update()
2550	{
2551		ATLASSERT(::IsWindow(this->m_hWnd));
2552		::SendMessage(this->m_hWnd, TTM_UPDATE, 0, 0L);
2553	}
2554
2555	BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/)
2556	{
2557		ATLASSERT(::IsWindow(this->m_hWnd));
2558		return (BOOL)::SendMessage(this->m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
2559	}
2560
2561	void Popup()
2562	{
2563		ATLASSERT(::IsWindow(this->m_hWnd));
2564		::SendMessage(this->m_hWnd, TTM_POPUP, 0, 0L);
2565	}
2566};
2567
2568typedef CToolTipCtrlT<ATL::CWindow>   CToolTipCtrl;
2569
2570
2571///////////////////////////////////////////////////////////////////////////////
2572// CHeaderCtrl
2573
2574template <class TBase>
2575class CHeaderCtrlT : public TBase
2576{
2577public:
2578// Constructors
2579	CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2580	{ }
2581
2582	CHeaderCtrlT< TBase >& operator =(HWND hWnd)
2583	{
2584		this->m_hWnd = hWnd;
2585		return *this;
2586	}
2587
2588	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2589			DWORD dwStyle = 0, DWORD dwExStyle = 0,
2590			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2591	{
2592		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2593	}
2594
2595// Attributes
2596	static LPCTSTR GetWndClassName()
2597	{
2598		return WC_HEADER;
2599	}
2600
2601	int GetItemCount() const
2602	{
2603		ATLASSERT(::IsWindow(this->m_hWnd));
2604		return (int)::SendMessage(this->m_hWnd, HDM_GETITEMCOUNT, 0, 0L);
2605	}
2606
2607	BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const
2608	{
2609		ATLASSERT(::IsWindow(this->m_hWnd));
2610		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem);
2611	}
2612
2613	BOOL SetItem(int nIndex, LPHDITEM pHeaderItem)
2614	{
2615		ATLASSERT(::IsWindow(this->m_hWnd));
2616		return (BOOL)::SendMessage(this->m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem);
2617	}
2618
2619	CImageList GetImageList() const
2620	{
2621		ATLASSERT(::IsWindow(this->m_hWnd));
2622		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, HDM_GETIMAGELIST, 0, 0L));
2623	}
2624
2625	CImageList SetImageList(HIMAGELIST hImageList)
2626	{
2627		ATLASSERT(::IsWindow(this->m_hWnd));
2628		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList));
2629	}
2630
2631	BOOL GetOrderArray(int nSize, int* lpnArray) const
2632	{
2633		ATLASSERT(::IsWindow(this->m_hWnd));
2634		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray);
2635	}
2636
2637	BOOL SetOrderArray(int nSize, int* lpnArray)
2638	{
2639		ATLASSERT(::IsWindow(this->m_hWnd));
2640		return (BOOL)::SendMessage(this->m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray);
2641	}
2642
2643	BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const
2644	{
2645		ATLASSERT(::IsWindow(this->m_hWnd));
2646		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect);
2647	}
2648
2649	int SetHotDivider(BOOL bPos, DWORD dwInputValue)
2650	{
2651		ATLASSERT(::IsWindow(this->m_hWnd));
2652		return (int)::SendMessage(this->m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue);
2653	}
2654
2655	BOOL GetUnicodeFormat() const
2656	{
2657		ATLASSERT(::IsWindow(this->m_hWnd));
2658		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L);
2659	}
2660
2661	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
2662	{
2663		ATLASSERT(::IsWindow(this->m_hWnd));
2664		return (BOOL)::SendMessage(this->m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L);
2665	}
2666
2667	int GetBitmapMargin() const
2668	{
2669		ATLASSERT(::IsWindow(this->m_hWnd));
2670		return (int)::SendMessage(this->m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L);
2671	}
2672
2673	int SetBitmapMargin(int nWidth)
2674	{
2675		ATLASSERT(::IsWindow(this->m_hWnd));
2676		return (int)::SendMessage(this->m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L);
2677	}
2678
2679	int SetFilterChangeTimeout(DWORD dwTimeOut)
2680	{
2681		ATLASSERT(::IsWindow(this->m_hWnd));
2682		return (int)::SendMessage(this->m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut);
2683	}
2684
2685#if (_WIN32_WINNT >= 0x0600)
2686	BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const
2687	{
2688		ATLASSERT(::IsWindow(this->m_hWnd));
2689		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
2690	}
2691
2692	BOOL GetOverflowRect(LPRECT lpRect) const
2693	{
2694		ATLASSERT(::IsWindow(this->m_hWnd));
2695		return (BOOL)::SendMessage(this->m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect);
2696	}
2697
2698	int GetFocusedItem() const
2699	{
2700		ATLASSERT(::IsWindow(this->m_hWnd));
2701		return (int)::SendMessage(this->m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L);
2702	}
2703
2704	BOOL SetFocusedItem(int nIndex)
2705	{
2706		ATLASSERT(::IsWindow(this->m_hWnd));
2707		return (BOOL)::SendMessage(this->m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex);
2708	}
2709#endif // (_WIN32_WINNT >= 0x0600)
2710
2711// Operations
2712	int InsertItem(int nIndex, LPHDITEM phdi)
2713	{
2714		ATLASSERT(::IsWindow(this->m_hWnd));
2715		return (int)::SendMessage(this->m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi);
2716	}
2717
2718	int AddItem(LPHDITEM phdi)
2719	{
2720		return InsertItem(GetItemCount(), phdi);
2721	}
2722
2723	BOOL DeleteItem(int nIndex)
2724	{
2725		ATLASSERT(::IsWindow(this->m_hWnd));
2726		return (BOOL)::SendMessage(this->m_hWnd, HDM_DELETEITEM, nIndex, 0L);
2727	}
2728
2729	BOOL Layout(HD_LAYOUT* pHeaderLayout)
2730	{
2731		ATLASSERT(::IsWindow(this->m_hWnd));
2732		return (BOOL)::SendMessage(this->m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout);
2733	}
2734
2735	int HitTest(LPHDHITTESTINFO lpHitTestInfo) const
2736	{
2737		ATLASSERT(::IsWindow(this->m_hWnd));
2738		return (int)::SendMessage(this->m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo);
2739	}
2740
2741	int OrderToIndex(int nOrder)
2742	{
2743		ATLASSERT(::IsWindow(this->m_hWnd));
2744		return (int)::SendMessage(this->m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L);
2745	}
2746
2747	CImageList CreateDragImage(int nIndex)
2748	{
2749		ATLASSERT(::IsWindow(this->m_hWnd));
2750		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L));
2751	}
2752
2753	int EditFilter(int nColumn, BOOL bDiscardChanges)
2754	{
2755		ATLASSERT(::IsWindow(this->m_hWnd));
2756		return (int)::SendMessage(this->m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0));
2757	}
2758
2759	int ClearFilter(int nColumn)
2760	{
2761		ATLASSERT(::IsWindow(this->m_hWnd));
2762		return (int)::SendMessage(this->m_hWnd, HDM_CLEARFILTER, nColumn, 0L);
2763	}
2764
2765	int ClearAllFilters()
2766	{
2767		ATLASSERT(::IsWindow(this->m_hWnd));
2768		return (int)::SendMessage(this->m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L);
2769	}
2770};
2771
2772typedef CHeaderCtrlT<ATL::CWindow>   CHeaderCtrl;
2773
2774
2775///////////////////////////////////////////////////////////////////////////////
2776// CListViewCtrl
2777
2778template <class TBase>
2779class CListViewCtrlT : public TBase
2780{
2781public:
2782// Constructors
2783	CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2784	{ }
2785
2786	CListViewCtrlT< TBase >& operator =(HWND hWnd)
2787	{
2788		this->m_hWnd = hWnd;
2789		return *this;
2790	}
2791
2792	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2793			DWORD dwStyle = 0, DWORD dwExStyle = 0,
2794			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2795	{
2796		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2797	}
2798
2799// Attributes
2800	static LPCTSTR GetWndClassName()
2801	{
2802		return WC_LISTVIEW;
2803	}
2804
2805	COLORREF GetBkColor() const
2806	{
2807		ATLASSERT(::IsWindow(this->m_hWnd));
2808		return (COLORREF)::SendMessage(this->m_hWnd, LVM_GETBKCOLOR, 0, 0L);
2809	}
2810
2811	BOOL SetBkColor(COLORREF cr)
2812	{
2813		ATLASSERT(::IsWindow(this->m_hWnd));
2814		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETBKCOLOR, 0, cr);
2815	}
2816
2817	CImageList GetImageList(int nImageListType) const
2818	{
2819		ATLASSERT(::IsWindow(this->m_hWnd));
2820		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L));
2821	}
2822
2823	CImageList SetImageList(HIMAGELIST hImageList, int nImageList)
2824	{
2825		ATLASSERT(::IsWindow(this->m_hWnd)); 
2826		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList));
2827	}
2828
2829	int GetItemCount() const
2830	{
2831		ATLASSERT(::IsWindow(this->m_hWnd));
2832		return (int)::SendMessage(this->m_hWnd, LVM_GETITEMCOUNT, 0, 0L);
2833	}
2834
2835	BOOL SetItemCount(int nItems)
2836	{
2837		ATLASSERT(::IsWindow(this->m_hWnd));
2838		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMCOUNT, nItems, 0L);
2839	}
2840
2841	BOOL GetItem(LPLVITEM pItem) const
2842	{
2843		ATLASSERT(::IsWindow(this->m_hWnd));
2844		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
2845	}
2846
2847	BOOL SetItem(const LVITEM* pItem)
2848	{
2849		ATLASSERT(::IsWindow(this->m_hWnd));
2850		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem);
2851	}
2852
2853	BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
2854		int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
2855	{
2856		ATLASSERT(::IsWindow(this->m_hWnd));
2857		LVITEM lvi = {};
2858		lvi.mask = nMask;
2859		lvi.iItem = nItem;
2860		lvi.iSubItem = nSubItem;
2861		lvi.stateMask = nStateMask;
2862		lvi.state = nState;
2863		lvi.pszText = (LPTSTR) lpszItem;
2864		lvi.iImage = nImage;
2865		lvi.lParam = lParam;
2866		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi);
2867	}
2868
2869	UINT GetItemState(int nItem, UINT nMask) const
2870	{
2871		ATLASSERT(::IsWindow(this->m_hWnd));
2872		return (UINT)::SendMessage(this->m_hWnd, LVM_GETITEMSTATE, nItem, nMask);
2873	}
2874
2875	BOOL SetItemState(int nItem, UINT nState, UINT nStateMask)
2876	{
2877		ATLASSERT(::IsWindow(this->m_hWnd));
2878		LVITEM lvi = {};
2879		lvi.state = nState;
2880		lvi.stateMask = nStateMask;
2881		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi);
2882	}
2883
2884	BOOL SetItemState(int nItem, LPLVITEM pItem)
2885	{
2886		ATLASSERT(::IsWindow(this->m_hWnd));
2887		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem);
2888	}
2889
2890	BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const
2891	{
2892		USES_CONVERSION;
2893		ATLASSERT(::IsWindow(this->m_hWnd));
2894		ATLASSERT(bstrText == NULL);
2895		LVITEM lvi = {};
2896		lvi.iSubItem = nSubItem;
2897
2898		LPTSTR lpstrText = NULL;
2899		int nRes = 0;
2900		for(int nLen = 256; ; nLen *= 2)
2901		{
2902			ATLTRY(lpstrText = new TCHAR[nLen]);
2903			if(lpstrText == NULL)
2904				break;
2905			lpstrText[0] = NULL;
2906			lvi.cchTextMax = nLen;
2907			lvi.pszText = lpstrText;
2908			nRes  = (int)::SendMessage(this->m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2909			if(nRes < nLen - 1)
2910				break;
2911			delete [] lpstrText;
2912			lpstrText = NULL;
2913		}
2914
2915		if(lpstrText != NULL)
2916		{
2917			if(nRes != 0)
2918				bstrText = ::SysAllocString(T2OLE(lpstrText));
2919			delete [] lpstrText;
2920		}
2921
2922		return (bstrText != NULL) ? TRUE : FALSE;
2923	}
2924
2925#ifdef __ATLSTR_H__
2926	int GetItemText(int nItem, int nSubItem, ATL::CString& strText) const
2927	{
2928		ATLASSERT(::IsWindow(this->m_hWnd));
2929		LVITEM lvi = {};
2930		lvi.iSubItem = nSubItem;
2931
2932		strText.Empty();
2933		int nRes = 0;
2934		for(int nLen = 256; ; nLen *= 2)
2935		{
2936			lvi.cchTextMax = nLen;
2937			lvi.pszText = strText.GetBufferSetLength(nLen);
2938			if(lvi.pszText == NULL)
2939			{
2940				nRes = 0;
2941				break;
2942			}
2943			nRes  = (int)::SendMessage(this->m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2944			if(nRes < nLen - 1)
2945				break;
2946		}
2947		strText.ReleaseBuffer();
2948		return nRes;
2949	}
2950#endif // __ATLSTR_H__
2951
2952	int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const
2953	{
2954		ATLASSERT(::IsWindow(this->m_hWnd));
2955		LVITEM lvi = {};
2956		lvi.iSubItem = nSubItem;
2957		lvi.cchTextMax = nLen;
2958		lvi.pszText = lpszText;
2959		return (int)::SendMessage(this->m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2960	}
2961
2962	BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
2963	{
2964		ATLASSERT(::IsWindow(this->m_hWnd));
2965		return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0);
2966	}
2967
2968	DWORD_PTR GetItemData(int nItem) const
2969	{
2970		ATLASSERT(::IsWindow(this->m_hWnd));
2971		LVITEM lvi = {};
2972		lvi.iItem = nItem;
2973		lvi.mask = LVIF_PARAM;
2974		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi);
2975		return (DWORD_PTR)(bRet ? lvi.lParam : NULL);
2976	}
2977
2978	BOOL SetItemData(int nItem, DWORD_PTR dwData)
2979	{
2980		ATLASSERT(::IsWindow(this->m_hWnd));
2981		return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData);
2982	}
2983
2984	UINT GetCallbackMask() const
2985	{
2986		ATLASSERT(::IsWindow(this->m_hWnd));
2987		return (UINT)::SendMessage(this->m_hWnd, LVM_GETCALLBACKMASK, 0, 0L);
2988	}
2989
2990	BOOL SetCallbackMask(UINT nMask)
2991	{
2992		ATLASSERT(::IsWindow(this->m_hWnd));
2993		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L);
2994	}
2995
2996	BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const
2997	{
2998		ATLASSERT(::IsWindow(this->m_hWnd));
2999		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint);
3000	}
3001
3002	BOOL SetItemPosition(int nItem, POINT pt)
3003	{
3004		ATLASSERT(::IsWindow(this->m_hWnd));
3005		ATLASSERT(((this->GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((this->GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
3006		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
3007	}
3008
3009	BOOL SetItemPosition(int nItem, int x, int y)
3010	{
3011		ATLASSERT(::IsWindow(this->m_hWnd));
3012		ATLASSERT(((this->GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((this->GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
3013		POINT pt = { x, y };
3014		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
3015	}
3016
3017	int GetStringWidth(LPCTSTR lpsz) const
3018	{
3019		ATLASSERT(::IsWindow(this->m_hWnd));
3020		return (int)::SendMessage(this->m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz);
3021	}
3022
3023	CEdit GetEditControl() const
3024	{
3025		ATLASSERT(::IsWindow(this->m_hWnd));
3026		return CEdit((HWND)::SendMessage(this->m_hWnd, LVM_GETEDITCONTROL, 0, 0L));
3027	}
3028
3029	BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const
3030	{
3031		ATLASSERT(::IsWindow(this->m_hWnd));
3032		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn);
3033	}
3034
3035	BOOL SetColumn(int nCol, const LVCOLUMN* pColumn)
3036	{
3037		ATLASSERT(::IsWindow(this->m_hWnd));
3038		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn);
3039	}
3040
3041	int GetColumnWidth(int nCol) const
3042	{
3043		ATLASSERT(::IsWindow(this->m_hWnd));
3044		return (int)::SendMessage(this->m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L);
3045	}
3046
3047	BOOL SetColumnWidth(int nCol, int cx)
3048	{
3049		ATLASSERT(::IsWindow(this->m_hWnd));
3050		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0));
3051	}
3052
3053	BOOL GetViewRect(LPRECT lpRect) const
3054	{
3055		ATLASSERT(::IsWindow(this->m_hWnd));
3056		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect);
3057	}
3058
3059	COLORREF GetTextColor() const
3060	{
3061		ATLASSERT(::IsWindow(this->m_hWnd));
3062		return (COLORREF)::SendMessage(this->m_hWnd, LVM_GETTEXTCOLOR, 0, 0L);
3063	}
3064
3065	BOOL SetTextColor(COLORREF cr)
3066	{
3067		ATLASSERT(::IsWindow(this->m_hWnd));
3068		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETTEXTCOLOR, 0, cr);
3069	}
3070
3071	COLORREF GetTextBkColor() const
3072	{
3073		ATLASSERT(::IsWindow(this->m_hWnd));
3074		return (COLORREF)::SendMessage(this->m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L);
3075	}
3076
3077	BOOL SetTextBkColor(COLORREF cr)
3078	{
3079		ATLASSERT(::IsWindow(this->m_hWnd));
3080		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr);
3081	}
3082
3083	int GetTopIndex() const
3084	{
3085		ATLASSERT(::IsWindow(this->m_hWnd));
3086		return (int)::SendMessage(this->m_hWnd, LVM_GETTOPINDEX, 0, 0L);
3087	}
3088
3089	int GetCountPerPage() const
3090	{
3091		ATLASSERT(::IsWindow(this->m_hWnd));
3092		return (int)::SendMessage(this->m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L);
3093	}
3094
3095	BOOL GetOrigin(LPPOINT lpPoint) const
3096	{
3097		ATLASSERT(::IsWindow(this->m_hWnd));
3098		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint);
3099	}
3100
3101	UINT GetSelectedCount() const
3102	{
3103		ATLASSERT(::IsWindow(this->m_hWnd));
3104		return (UINT)::SendMessage(this->m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
3105	}
3106
3107	BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const
3108	{
3109		ATLASSERT(::IsWindow(this->m_hWnd));
3110		lpRect->left = nCode;
3111		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect);
3112	}
3113
3114	HCURSOR GetHotCursor() const
3115	{
3116		ATLASSERT(::IsWindow(this->m_hWnd));
3117		return (HCURSOR)::SendMessage(this->m_hWnd, LVM_GETHOTCURSOR, 0, 0L);
3118	}
3119
3120	HCURSOR SetHotCursor(HCURSOR hHotCursor)
3121	{
3122		ATLASSERT(::IsWindow(this->m_hWnd));
3123		return (HCURSOR)::SendMessage(this->m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor);
3124	}
3125
3126	int GetHotItem() const
3127	{
3128		ATLASSERT(::IsWindow(this->m_hWnd));
3129		return (int)::SendMessage(this->m_hWnd, LVM_GETHOTITEM, 0, 0L);
3130	}
3131
3132	int SetHotItem(int nIndex)
3133	{
3134		ATLASSERT(::IsWindow(this->m_hWnd));
3135		return (int)::SendMessage(this->m_hWnd, LVM_SETHOTITEM, nIndex, 0L);
3136	}
3137
3138	BOOL GetColumnOrderArray(int nCount, int* lpnArray) const
3139	{
3140		ATLASSERT(::IsWindow(this->m_hWnd));
3141		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
3142	}
3143
3144	BOOL SetColumnOrderArray(int nCount, int* lpnArray)
3145	{
3146		ATLASSERT(::IsWindow(this->m_hWnd));
3147		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
3148	}
3149
3150	CHeaderCtrl GetHeader() const
3151	{
3152		ATLASSERT(::IsWindow(this->m_hWnd));
3153		return CHeaderCtrl((HWND)::SendMessage(this->m_hWnd, LVM_GETHEADER, 0, 0L));
3154	}
3155
3156	BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const
3157	{
3158		ATLASSERT(::IsWindow(this->m_hWnd));
3159		ATLASSERT((this->GetStyle() & LVS_TYPEMASK) == LVS_REPORT);
3160		ATLASSERT(lpRect != NULL);
3161		lpRect->top = nSubItem;
3162		lpRect->left = nFlag;
3163		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect);
3164	}
3165
3166	DWORD SetIconSpacing(int cx, int cy)
3167	{
3168		ATLASSERT(::IsWindow(this->m_hWnd));
3169		ATLASSERT((this->GetStyle() & LVS_TYPEMASK) == LVS_ICON);
3170		return (DWORD)::SendMessage(this->m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy));
3171	}
3172
3173	int GetISearchString(LPTSTR lpstr) const
3174	{
3175		ATLASSERT(::IsWindow(this->m_hWnd));
3176		return (int)::SendMessage(this->m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
3177	}
3178
3179	void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const
3180	{
3181		ATLASSERT(::IsWindow(this->m_hWnd));
3182		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L);
3183		sizeSpacing.cx = GET_X_LPARAM(dwRet);
3184		sizeSpacing.cy = GET_Y_LPARAM(dwRet);
3185	}
3186
3187	// single-selection only
3188	int GetSelectedIndex() const
3189	{
3190		ATLASSERT(::IsWindow(this->m_hWnd));
3191		ATLASSERT((this->GetStyle() & LVS_SINGLESEL) != 0);
3192		return (int)::SendMessage(this->m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
3193	}
3194
3195	BOOL GetSelectedItem(LPLVITEM pItem) const
3196	{
3197		ATLASSERT(::IsWindow(this->m_hWnd));
3198		ATLASSERT((this->GetStyle() & LVS_SINGLESEL) != 0);
3199		ATLASSERT(pItem != NULL);
3200		pItem->iItem = (int)::SendMessage(this->m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
3201		if(pItem->iItem == -1)
3202			return FALSE;
3203		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
3204	}
3205
3206	// extended list view styles
3207	DWORD GetExtendedListViewStyle() const
3208	{
3209		ATLASSERT(::IsWindow(this->m_hWnd));
3210		return (DWORD)::SendMessage(this->m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L);
3211	}
3212
3213	// dwExMask = 0 means all styles
3214	DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0)
3215	{
3216		ATLASSERT(::IsWindow(this->m_hWnd));
3217		return (DWORD)::SendMessage(this->m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle);
3218	}
3219
3220	// checkboxes only
3221	BOOL GetCheckState(int nIndex) const
3222	{
3223		ATLASSERT(::IsWindow(this->m_hWnd));
3224		ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0);
3225		UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK);
3226		return (uRet >> 12) - 1;
3227	}
3228
3229	BOOL SetCheckState(int nItem, BOOL bCheck)
3230	{
3231		int nCheck = bCheck ? 2 : 1;   // one based index
3232		return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK);
3233	}
3234
3235	// view type
3236	DWORD GetViewType() const
3237	{
3238		ATLASSERT(::IsWindow(this->m_hWnd));
3239		return (this->GetStyle() & LVS_TYPEMASK);
3240	}
3241
3242	DWORD SetViewType(DWORD dwType)
3243	{
3244		ATLASSERT(::IsWindow(this->m_hWnd));
3245		ATLASSERT((dwType == LVS_ICON) || (dwType == LVS_SMALLICON) || (dwType == LVS_LIST) || (dwType == LVS_REPORT));
3246		DWORD dwOldType = GetViewType();
3247		if(dwType != dwOldType)
3248			this->ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK));
3249		return dwOldType;
3250	}
3251
3252	BOOL GetBkImage(LPLVBKIMAGE plvbki) const
3253	{
3254		ATLASSERT(::IsWindow(this->m_hWnd));
3255		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki);
3256	}
3257
3258	BOOL SetBkImage(LPLVBKIMAGE plvbki)
3259	{
3260		ATLASSERT(::IsWindow(this->m_hWnd));
3261		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki);
3262	}
3263
3264	int GetSelectionMark() const
3265	{
3266		ATLASSERT(::IsWindow(this->m_hWnd));
3267		return (int)::SendMessage(this->m_hWnd, LVM_GETSELECTIONMARK, 0, 0L);
3268	}
3269
3270	int SetSelectionMark(int nIndex)
3271	{
3272		ATLASSERT(::IsWindow(this->m_hWnd));
3273		return (int)::SendMessage(this->m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex);
3274	}
3275
3276	BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const
3277	{
3278		ATLASSERT(::IsWindow(this->m_hWnd));
3279		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
3280	}
3281
3282	BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect)
3283	{
3284		ATLASSERT(::IsWindow(this->m_hWnd));
3285		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
3286	}
3287
3288	DWORD GetHoverTime() const
3289	{
3290		ATLASSERT(::IsWindow(this->m_hWnd));
3291		ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
3292		return (DWORD)::SendMessage(this->m_hWnd, LVM_GETHOVERTIME, 0, 0L);
3293	}
3294
3295	DWORD SetHoverTime(DWORD dwHoverTime)
3296	{
3297		ATLASSERT(::IsWindow(this->m_hWnd));
3298		ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
3299		return (DWORD)::SendMessage(this->m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime);
3300	}
3301
3302	BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const
3303	{
3304		ATLASSERT(::IsWindow(this->m_hWnd));
3305		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas);
3306	}
3307
3308	BOOL SetItemCountEx(int nItems, DWORD dwFlags)
3309	{
3310		ATLASSERT(::IsWindow(this->m_hWnd));
3311		ATLASSERT(((this->GetStyle() & LVS_OWNERDATA) != 0) && (((this->GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((this->GetStyle() & LVS_TYPEMASK) == LVS_LIST)));
3312		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags);
3313	}
3314
3315	CToolTipCtrl GetToolTips() const
3316	{
3317		ATLASSERT(::IsWindow(this->m_hWnd));
3318		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, LVM_GETTOOLTIPS, 0, 0L));
3319	}
3320
3321	CToolTipCtrl SetToolTips(HWND hWndTT)
3322	{
3323		ATLASSERT(::IsWindow(this->m_hWnd));
3324		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
3325	}
3326
3327	BOOL GetUnicodeFormat() const
3328	{
3329		ATLASSERT(::IsWindow(this->m_hWnd));
3330		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L);
3331	}
3332
3333	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
3334	{
3335		ATLASSERT(::IsWindow(this->m_hWnd));
3336		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L);
3337	}
3338
3339	int GetSelectedColumn() const
3340	{
3341		ATLASSERT(::IsWindow(this->m_hWnd));
3342		return (int)::SendMessage(this->m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L);
3343	}
3344
3345	void SetSelectedColumn(int nColumn)
3346	{
3347		ATLASSERT(::IsWindow(this->m_hWnd));
3348		::SendMessage(this->m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L);
3349	}
3350
3351	DWORD GetView() const
3352	{
3353		ATLASSERT(::IsWindow(this->m_hWnd));
3354		return (DWORD)::SendMessage(this->m_hWnd, LVM_GETVIEW, 0, 0L);
3355	}
3356
3357	int SetView(DWORD dwView)
3358	{
3359		ATLASSERT(::IsWindow(this->m_hWnd));
3360		return (int)::SendMessage(this->m_hWnd, LVM_SETVIEW, dwView, 0L);
3361	}
3362
3363	BOOL IsGroupViewEnabled() const
3364	{
3365		ATLASSERT(::IsWindow(this->m_hWnd));
3366		return (BOOL)::SendMessage(this->m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L);
3367	}
3368
3369	int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const
3370	{
3371		ATLASSERT(::IsWindow(this->m_hWnd));
3372		return (int)::SendMessage(this->m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup);
3373	}
3374
3375	int SetGroupInfo(int nGroupID, PLVGROUP pGroup)
3376	{
3377		ATLASSERT(::IsWindow(this->m_hWnd));
3378		return (int)::SendMessage(this->m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup);
3379	}
3380
3381	void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const
3382	{
3383		ATLASSERT(::IsWindow(this->m_hWnd));
3384		::SendMessage(this->m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
3385	}
3386
3387	void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
3388	{
3389		ATLASSERT(::IsWindow(this->m_hWnd));
3390		::SendMessage(this->m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
3391	}
3392
3393	void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const
3394	{
3395		ATLASSERT(::IsWindow(this->m_hWnd));
3396		::SendMessage(this->m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
3397	}
3398
3399	BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo)
3400	{
3401		ATLASSERT(::IsWindow(this->m_hWnd));
3402		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
3403	}
3404
3405	void GetTileInfo(PLVTILEINFO pTileInfo) const
3406	{
3407		ATLASSERT(::IsWindow(this->m_hWnd));
3408		::SendMessage(this->m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo);
3409	}
3410
3411	BOOL SetTileInfo(PLVTILEINFO pTileInfo)
3412	{
3413		ATLASSERT(::IsWindow(this->m_hWnd));
3414		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo);
3415	}
3416
3417	BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const
3418	{
3419		ATLASSERT(::IsWindow(this->m_hWnd));
3420		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark);
3421	}
3422
3423	BOOL SetInsertMark(LPLVINSERTMARK pInsertMark)
3424	{
3425		ATLASSERT(::IsWindow(this->m_hWnd));
3426		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark);
3427	}
3428
3429	int GetInsertMarkRect(LPRECT lpRect) const
3430	{
3431		ATLASSERT(::IsWindow(this->m_hWnd));
3432		return (int)::SendMessage(this->m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect);
3433	}
3434
3435	COLORREF GetInsertMarkColor() const
3436	{
3437		ATLASSERT(::IsWindow(this->m_hWnd));
3438		return (COLORREF)::SendMessage(this->m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L);
3439	}
3440
3441	COLORREF SetInsertMarkColor(COLORREF clr)
3442	{
3443		ATLASSERT(::IsWindow(this->m_hWnd));
3444		return (COLORREF)::SendMessage(this->m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr);
3445	}
3446
3447	COLORREF GetOutlineColor() const
3448	{
3449		ATLASSERT(::IsWindow(this->m_hWnd));
3450		return (COLORREF)::SendMessage(this->m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L);
3451	}
3452
3453	COLORREF SetOutlineColor(COLORREF clr)
3454	{
3455		ATLASSERT(::IsWindow(this->m_hWnd));
3456		return (COLORREF)::SendMessage(this->m_hWnd, LVM_SETOUTLINECOLOR, 0, clr);
3457	}
3458
3459#if (_WIN32_WINNT >= 0x0600)
3460	int GetGroupCount() const
3461	{
3462		ATLASSERT(::IsWindow(this->m_hWnd));
3463		return (int)::SendMessage(this->m_hWnd, LVM_GETGROUPCOUNT, 0, 0L);
3464	}
3465
3466	BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const
3467	{
3468		ATLASSERT(::IsWindow(this->m_hWnd));
3469		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup);
3470	}
3471
3472	BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const
3473	{
3474		ATLASSERT(::IsWindow(this->m_hWnd));
3475		ATLASSERT(lpRect != NULL);
3476		if(lpRect != NULL)
3477			lpRect->top = nType;
3478		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect);
3479	}
3480
3481	UINT GetGroupState(int nGroupID, UINT uMask) const
3482	{
3483		ATLASSERT(::IsWindow(this->m_hWnd));
3484		return (UINT)::SendMessage(this->m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask);
3485	}
3486
3487	int GetFocusedGroup() const
3488	{
3489		ATLASSERT(::IsWindow(this->m_hWnd));
3490		return (int)::SendMessage(this->m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L);
3491	}
3492
3493	BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const
3494	{
3495		ATLASSERT(::IsWindow(this->m_hWnd));
3496		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText);
3497	}
3498
3499	BOOL GetFooterRect(LPRECT lpRect) const
3500	{
3501		ATLASSERT(::IsWindow(this->m_hWnd));
3502		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect);
3503	}
3504
3505	BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const
3506	{
3507		ATLASSERT(::IsWindow(this->m_hWnd));
3508		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo);
3509	}
3510
3511	BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const
3512	{
3513		ATLASSERT(::IsWindow(this->m_hWnd));
3514		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect);
3515	}
3516
3517	BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const
3518	{
3519		ATLASSERT(::IsWindow(this->m_hWnd));
3520		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem);
3521	}
3522
3523	BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const
3524	{
3525		ATLASSERT(::IsWindow(this->m_hWnd));
3526		ATLASSERT(pItemIndex != NULL);
3527		ATLASSERT(lpRect != NULL);
3528		if(lpRect != NULL)
3529		{
3530			lpRect->top = nSubItem;
3531			lpRect->left = nType;
3532		}
3533		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect);
3534	}
3535
3536	BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask)
3537	{
3538		ATLASSERT(::IsWindow(this->m_hWnd));
3539		LVITEM lvi = {};
3540		lvi.state = uState;
3541		lvi.stateMask = dwMask;
3542		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi);
3543	}
3544
3545	BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const
3546	{
3547		ATLASSERT(::IsWindow(this->m_hWnd));
3548		return (BOOL)::SendMessage(this->m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0));
3549	}
3550#endif // (_WIN32_WINNT >= 0x0600)
3551
3552// Operations
3553	int InsertColumn(int nCol, const LVCOLUMN* pColumn)
3554	{
3555		ATLASSERT(::IsWindow(this->m_hWnd));
3556		return (int)::SendMessage(this->m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn);
3557	}
3558
3559	int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, 
3560			int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1)
3561	{
3562		LVCOLUMN column = {};
3563		column.mask = LVCF_TEXT | LVCF_FMT;
3564		column.pszText = (LPTSTR)lpszColumnHeading;
3565		column.fmt = nFormat;
3566		if (nWidth != -1)
3567		{
3568			column.mask |= LVCF_WIDTH;
3569			column.cx = nWidth;
3570		}
3571		if (nSubItem != -1)
3572		{
3573			column.mask |= LVCF_SUBITEM;
3574			column.iSubItem = nSubItem;
3575		}
3576		if (iImage != -1)
3577		{
3578			column.mask |= LVCF_IMAGE;
3579			column.iImage = iImage;
3580		}
3581		if (iOrder != -1)
3582		{
3583			column.mask |= LVCF_ORDER;
3584			column.iOrder = iOrder;
3585		}
3586		return InsertColumn(nCol, &column);
3587	}
3588
3589	BOOL DeleteColumn(int nCol)
3590	{
3591		ATLASSERT(::IsWindow(this->m_hWnd));
3592		return (BOOL)::SendMessage(this->m_hWnd, LVM_DELETECOLUMN, nCol, 0L);
3593	}
3594
3595	int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
3596	{
3597		ATLASSERT(::IsWindow(this->m_hWnd));
3598		LVITEM item = {};
3599		item.mask = nMask;
3600		item.iItem = nItem;
3601		item.iSubItem = 0;
3602		item.pszText = (LPTSTR)lpszItem;
3603		item.state = nState;
3604		item.stateMask = nStateMask;
3605		item.iImage = nImage;
3606		item.lParam = lParam;
3607		return InsertItem(&item);
3608	}
3609
3610	int InsertItem(const LVITEM* pItem)
3611	{
3612		ATLASSERT(::IsWindow(this->m_hWnd));
3613		return (int)::SendMessage(this->m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem);
3614	}
3615
3616	int InsertItem(int nItem, LPCTSTR lpszItem)
3617	{
3618		ATLASSERT(::IsWindow(this->m_hWnd));
3619		return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0);
3620	}
3621
3622	int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
3623	{
3624		ATLASSERT(::IsWindow(this->m_hWnd));
3625		return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
3626	}
3627
3628	int GetNextItem(int nItem, int nFlags) const
3629	{
3630		ATLASSERT(::IsWindow(this->m_hWnd));
3631		return (int)::SendMessage(this->m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0));
3632	}
3633
3634	BOOL DeleteItem(int nItem)
3635	{
3636		ATLASSERT(::IsWindow(this->m_hWnd));
3637		return (BOOL)::SendMessage(this->m_hWnd, LVM_DELETEITEM, nItem, 0L);
3638	}
3639
3640	BOOL DeleteAllItems()
3641	{
3642		ATLASSERT(::IsWindow(this->m_hWnd));
3643		return (BOOL)::SendMessage(this->m_hWnd, LVM_DELETEALLITEMS, 0, 0L);
3644	}
3645
3646	int FindItem(LVFINDINFO* pFindInfo, int nStart = -1) const
3647	{
3648		ATLASSERT(::IsWindow(this->m_hWnd));
3649		return (int)::SendMessage(this->m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo);
3650	}
3651
3652	int FindItem(LPCTSTR lpstrFind, bool bPartial = true, bool bWrap = false, int nStart = -1) const
3653	{
3654		ATLASSERT(::IsWindow(this->m_hWnd));
3655		LVFINDINFO lvfi = {};
3656		lvfi.flags = LVFI_STRING | (bWrap ? LVFI_WRAP : 0) | (bPartial ? LVFI_PARTIAL : 0);
3657		lvfi.psz = lpstrFind;
3658		return (int)::SendMessage(this->m_hWnd, LVM_FINDITEM, nStart, (LPARAM)&lvfi);
3659	}
3660
3661	int HitTest(LVHITTESTINFO* pHitTestInfo) const
3662	{
3663		ATLASSERT(::IsWindow(this->m_hWnd));
3664		return (int)::SendMessage(this->m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
3665	}
3666
3667	int HitTest(POINT pt, UINT* pFlags) const
3668	{
3669		ATLASSERT(::IsWindow(this->m_hWnd));
3670		LVHITTESTINFO hti = {};
3671		hti.pt = pt;
3672		int nRes = (int)::SendMessage(this->m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti);
3673		if (pFlags != NULL)
3674			*pFlags = hti.flags;
3675		return nRes;
3676	}
3677
3678	BOOL EnsureVisible(int nItem, BOOL bPartialOK)
3679	{
3680		ATLASSERT(::IsWindow(this->m_hWnd));
3681		return (BOOL)::SendMessage(this->m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0));
3682	}
3683
3684	BOOL Scroll(int cx, int cy)
3685	{
3686		ATLASSERT(::IsWindow(this->m_hWnd));
3687		return (BOOL)::SendMessage(this->m_hWnd, LVM_SCROLL, cx, cy);
3688	}
3689
3690	BOOL Scroll(SIZE size)
3691	{
3692		ATLASSERT(::IsWindow(this->m_hWnd));
3693		return (BOOL)::SendMessage(this->m_hWnd, LVM_SCROLL, size.cx, size.cy);
3694	}
3695
3696	BOOL RedrawItems(int nFirst, int nLast)
3697	{
3698		ATLASSERT(::IsWindow(this->m_hWnd));
3699		return (BOOL)::SendMessage(this->m_hWnd, LVM_REDRAWITEMS, nFirst, nLast);
3700	}
3701
3702	BOOL Arrange(UINT nCode)
3703	{
3704		ATLASSERT(::IsWindow(this->m_hWnd));
3705		return (BOOL)::SendMessage(this->m_hWnd, LVM_ARRANGE, nCode, 0L);
3706	}
3707
3708	CEdit EditLabel(int nItem)
3709	{
3710		ATLASSERT(::IsWindow(this->m_hWnd));
3711		return CEdit((HWND)::SendMessage(this->m_hWnd, LVM_EDITLABEL, nItem, 0L));
3712	}
3713
3714	BOOL Update(int nItem)
3715	{
3716		ATLASSERT(::IsWindow(this->m_hWnd));
3717		return (BOOL)::SendMessage(this->m_hWnd, LVM_UPDATE, nItem, 0L);
3718	}
3719
3720	BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
3721	{
3722		ATLASSERT(::IsWindow(this->m_hWnd));
3723		return (BOOL)::SendMessage(this->m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare);
3724	}
3725
3726	CImageList RemoveImageList(int nImageList)
3727	{
3728		ATLASSERT(::IsWindow(this->m_hWnd));
3729		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
3730	}
3731
3732	CImageList CreateDragImage(int nItem, LPPOINT lpPoint)
3733	{
3734		ATLASSERT(::IsWindow(this->m_hWnd));
3735		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint));
3736	}
3737
3738	DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1)
3739	{
3740		ATLASSERT(::IsWindow(this->m_hWnd));
3741		return (DWORD)::SendMessage(this->m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy));
3742	}
3743
3744	int SubItemHitTest(LPLVHITTESTINFO lpInfo) const
3745	{
3746		ATLASSERT(::IsWindow(this->m_hWnd));
3747		return (int)::SendMessage(this->m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo);
3748	}
3749
3750	int AddColumn(LPCTSTR strColumn, int nItem, int nSubItem = -1,
3751			int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
3752			int nFmt = LVCFMT_LEFT)
3753	{
3754		const int cxOffset = 15;
3755		ATLASSERT(::IsWindow(this->m_hWnd));
3756		LVCOLUMN lvc = {};
3757		lvc.mask = nMask;
3758		lvc.fmt = nFmt;
3759		lvc.pszText = (LPTSTR)strColumn;
3760		lvc.cx = GetStringWidth(lvc.pszText) + cxOffset;
3761		if(nMask & LVCF_SUBITEM)
3762			lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem;
3763		return InsertColumn(nItem, &lvc);
3764	}
3765
3766	int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -3)
3767	{
3768		ATLASSERT(::IsWindow(this->m_hWnd));
3769		LVITEM lvItem = {};
3770		lvItem.mask = LVIF_TEXT;
3771		lvItem.iItem = nItem;
3772		lvItem.iSubItem = nSubItem;
3773		lvItem.pszText = (LPTSTR)strItem;
3774		if(nImageIndex != -3)
3775		{
3776			lvItem.mask |= LVIF_IMAGE;
3777			lvItem.iImage = nImageIndex;
3778		}
3779		if(nSubItem == 0)
3780			return InsertItem(&lvItem);
3781		return SetItem(&lvItem) ? nItem : -1;
3782	}
3783
3784	BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
3785	{
3786		ATLASSERT(::IsWindow(this->m_hWnd));
3787		return (BOOL)::SendMessage(this->m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare);
3788	}
3789
3790	int InsertGroup(int nItem, PLVGROUP pGroup)
3791	{
3792		ATLASSERT(::IsWindow(this->m_hWnd));
3793		return (int)::SendMessage(this->m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup);
3794	}
3795
3796	int AddGroup(PLVGROUP pGroup)
3797	{
3798		return InsertGroup(-1, pGroup);
3799	}
3800
3801	int RemoveGroup(int nGroupID)
3802	{
3803		ATLASSERT(::IsWindow(this->m_hWnd));
3804		return (int)::SendMessage(this->m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L);
3805	}
3806
3807	void MoveGroup(int nGroupID, int nItem)
3808	{
3809		ATLASSERT(::IsWindow(this->m_hWnd));
3810		::SendMessage(this->m_hWnd, LVM_MOVEGROUP, nGroupID, nItem);
3811	}
3812
3813	void MoveItemToGroup(int nItem, int nGroupID)
3814	{
3815		ATLASSERT(::IsWindow(this->m_hWnd));
3816		::SendMessage(this->m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID);
3817	}
3818
3819	int EnableGroupView(BOOL bEnable)
3820	{
3821		ATLASSERT(::IsWindow(this->m_hWnd));
3822		return (int)::SendMessage(this->m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L);
3823	}
3824
3825	int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL)
3826	{
3827		ATLASSERT(::IsWindow(this->m_hWnd));
3828		return (int)::SendMessage(this->m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid);
3829	}
3830
3831	void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted)
3832	{
3833		ATLASSERT(::IsWindow(this->m_hWnd));
3834		::SendMessage(this->m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L);
3835	}
3836
3837	void RemoveAllGroups()
3838	{
3839		ATLASSERT(::IsWindow(this->m_hWnd));
3840		::SendMessage(this->m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L);
3841	}
3842
3843	BOOL HasGroup(int nGroupID)
3844	{
3845		ATLASSERT(::IsWindow(this->m_hWnd));
3846		return (BOOL)::SendMessage(this->m_hWnd, LVM_HASGROUP, nGroupID, 0L);
3847	}
3848
3849	BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const
3850	{
3851		ATLASSERT(::IsWindow(this->m_hWnd));
3852		return (BOOL)::SendMessage(this->m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark);
3853	}
3854
3855	BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip)
3856	{
3857		ATLASSERT(::IsWindow(this->m_hWnd));
3858		return (BOOL)::SendMessage(this->m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip);
3859	}
3860
3861	void CancelEditLabel()
3862	{
3863		ATLASSERT(::IsWindow(this->m_hWnd));
3864		::SendMessage(this->m_hWnd, LVM_CANCELEDITLABEL, 0, 0L);
3865	}
3866
3867	UINT MapIndexToID(int nIndex) const
3868	{
3869		ATLASSERT(::IsWindow(this->m_hWnd));
3870		return (UINT)::SendMessage(this->m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L);
3871	}
3872
3873	int MapIDToIndex(UINT uID) const
3874	{
3875		ATLASSERT(::IsWindow(this->m_hWnd));
3876		return (int)::SendMessage(this->m_hWnd, LVM_MAPIDTOINDEX, uID, 0L);
3877	}
3878
3879	BOOL IsItemVisible(int nItem) const
3880	{
3881		ATLASSERT(::IsWindow(this->m_hWnd));
3882		return (BOOL)::SendMessage(this->m_hWnd, LVM_ISITEMVISIBLE, nItem, 0L);
3883	}
3884
3885#if (_WIN32_WINNT >= 0x0600)
3886	int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
3887	{
3888		ATLASSERT(::IsWindow(this->m_hWnd));
3889		return (int)::SendMessage(this->m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
3890	}
3891
3892	int HitTestEx(POINT pt, UINT* pFlags) const
3893	{
3894		ATLASSERT(::IsWindow(this->m_hWnd));
3895		LVHITTESTINFO hti = {};
3896		hti.pt = pt;
3897		int nRes = (int)::SendMessage(this->m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti);
3898		if (pFlags != NULL)
3899			*pFlags = hti.flags;
3900		return nRes;
3901	}
3902
3903	int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
3904	{
3905		ATLASSERT(::IsWindow(this->m_hWnd));
3906		return (int)::SendMessage(this->m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
3907	}
3908#endif // (_WIN32_WINNT >= 0x0600)
3909
3910	// Note: selects only one item
3911	BOOL SelectItem(int nIndex)   // -1 to select none
3912	{
3913		ATLASSERT(::IsWindow(this->m_hWnd));
3914
3915		BOOL bRet = FALSE;
3916		if(nIndex != -1)
3917		{
3918			// multi-selection only: de-select all items
3919			if((this->GetStyle() & LVS_SINGLESEL) == 0)
3920				SetItemState(-1, 0, LVIS_SELECTED);
3921
3922			bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
3923			if(bRet)
3924			{
3925				SetSelectionMark(nIndex);
3926				bRet = EnsureVisible(nIndex, FALSE);
3927			}
3928		}
3929		else   // no item specified, just de-select
3930		{
3931			bRet = SetItemState(-1, 0, LVIS_SELECTED);
3932		}
3933
3934		return bRet;
3935	}
3936
3937	// multi-selection only
3938	BOOL SelectAllItems(bool bSelect = true)
3939	{
3940		ATLASSERT(::IsWindow(this->m_hWnd));
3941		ATLASSERT((this->GetStyle() & LVS_SINGLESEL) == 0);
3942
3943		return SetItemState(-1, bSelect ? LVIS_SELECTED : 0, LVIS_SELECTED);
3944	}
3945};
3946
3947typedef CListViewCtrlT<ATL::CWindow>   CListViewCtrl;
3948
3949
3950///////////////////////////////////////////////////////////////////////////////
3951// CTreeViewCtrl
3952
3953template <class TBase>
3954class CTreeViewCtrlT : public TBase
3955{
3956public:
3957// Constructors
3958	CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
3959	{ }
3960
3961	CTreeViewCtrlT< TBase >& operator =(HWND hWnd)
3962	{
3963		this->m_hWnd = hWnd;
3964		return *this;
3965	}
3966
3967	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
3968			DWORD dwStyle = 0, DWORD dwExStyle = 0,
3969			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
3970	{
3971		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
3972	}
3973
3974// Attributes
3975	static LPCTSTR GetWndClassName()
3976	{
3977		return WC_TREEVIEW;
3978	}
3979
3980	UINT GetCount() const
3981	{
3982		ATLASSERT(::IsWindow(this->m_hWnd));
3983		return (UINT)::SendMessage(this->m_hWnd, TVM_GETCOUNT, 0, 0L);
3984	}
3985
3986	UINT GetIndent() const
3987	{
3988		ATLASSERT(::IsWindow(this->m_hWnd));
3989		return (UINT)::SendMessage(this->m_hWnd, TVM_GETINDENT, 0, 0L);
3990	}
3991
3992	void SetIndent(UINT nIndent)
3993	{
3994		ATLASSERT(::IsWindow(this->m_hWnd));
3995		::SendMessage(this->m_hWnd, TVM_SETINDENT, nIndent, 0L);
3996	}
3997
3998	CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const
3999	{
4000		ATLASSERT(::IsWindow(this->m_hWnd));
4001		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L));
4002	}
4003
4004	CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL)
4005	{
4006		ATLASSERT(::IsWindow(this->m_hWnd));
4007		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList));
4008	}
4009
4010	BOOL GetItem(LPTVITEM pItem) const
4011	{
4012		ATLASSERT(::IsWindow(this->m_hWnd));
4013		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
4014	}
4015
4016	BOOL SetItem(LPTVITEM pItem)
4017	{
4018		ATLASSERT(::IsWindow(this->m_hWnd));
4019		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
4020	}
4021
4022	BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage,
4023		int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
4024	{
4025		ATLASSERT(::IsWindow(this->m_hWnd));
4026		TVITEM item = {};
4027		item.hItem = hItem;
4028		item.mask = nMask;
4029		item.pszText = (LPTSTR) lpszItem;
4030		item.iImage = nImage;
4031		item.iSelectedImage = nSelectedImage;
4032		item.state = nState;
4033		item.stateMask = nStateMask;
4034		item.lParam = lParam;
4035		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETITEM, 0, (LPARAM)&item);
4036	}
4037
4038	BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const
4039	{
4040		ATLASSERT(::IsWindow(this->m_hWnd));
4041		ATLASSERT(lpstrText != NULL);
4042
4043		TVITEM item = {};
4044		item.hItem = hItem;
4045		item.mask = TVIF_TEXT;
4046		item.pszText = lpstrText;
4047		item.cchTextMax = nLen;
4048
4049		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4050	}
4051
4052	BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const
4053	{
4054		USES_CONVERSION;
4055		ATLASSERT(::IsWindow(this->m_hWnd));
4056		ATLASSERT(bstrText == NULL);
4057		TVITEM item = {};
4058		item.hItem = hItem;
4059		item.mask = TVIF_TEXT;
4060
4061		LPTSTR lpstrText = NULL;
4062		BOOL bRet = FALSE;
4063		for(int nLen = 256; ; nLen *= 2)
4064		{
4065			ATLTRY(lpstrText = new TCHAR[nLen]);
4066			if(lpstrText == NULL)
4067				break;
4068			lpstrText[0] = NULL;
4069			item.pszText = lpstrText;
4070			item.cchTextMax = nLen;
4071			bRet = (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4072			if(!bRet || (lstrlen(item.pszText) < (nLen - 1)))
4073				break;
4074			delete [] lpstrText;
4075			lpstrText = NULL;
4076		}
4077
4078		if(lpstrText != NULL)
4079		{
4080			if(bRet)
4081				bstrText = ::SysAllocString(T2OLE(lpstrText));
4082			delete [] lpstrText;
4083		}
4084
4085		return (bstrText != NULL) ? TRUE : FALSE;
4086	}
4087
4088#ifdef __ATLSTR_H__
4089	BOOL GetItemText(HTREEITEM hItem, ATL::CString& strText) const
4090	{
4091		ATLASSERT(::IsWindow(this->m_hWnd));
4092		TVITEM item = {};
4093		item.hItem = hItem;
4094		item.mask = TVIF_TEXT;
4095
4096		strText.Empty();
4097		BOOL bRet = FALSE;
4098		for(int nLen = 256; ; nLen *= 2)
4099		{
4100			item.pszText = strText.GetBufferSetLength(nLen);
4101			if(item.pszText == NULL)
4102			{
4103				bRet = FALSE;
4104				break;
4105			}
4106			item.cchTextMax = nLen;
4107			bRet = (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4108			if(!bRet || (lstrlen(item.pszText) < (nLen - 1)))
4109				break;
4110		}
4111		strText.ReleaseBuffer();
4112		return bRet;
4113	}
4114#endif // __ATLSTR_H__
4115
4116	BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem)
4117	{
4118		ATLASSERT(::IsWindow(this->m_hWnd));
4119		return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL);
4120	}
4121
4122	BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const
4123	{
4124		ATLASSERT(::IsWindow(this->m_hWnd));
4125		TVITEM item = {};
4126		item.hItem = hItem;
4127		item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE;
4128		BOOL bRes = (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4129		if (bRes)
4130		{
4131			nImage = item.iImage;
4132			nSelectedImage = item.iSelectedImage;
4133		}
4134		return bRes;
4135	}
4136
4137	BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage)
4138	{
4139		ATLASSERT(::IsWindow(this->m_hWnd));
4140		return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL);
4141	}
4142
4143	UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const
4144	{
4145		ATLASSERT(::IsWindow(this->m_hWnd));
4146		return (((UINT)::SendMessage(this->m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask);
4147	}
4148
4149	BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask)
4150	{
4151		ATLASSERT(::IsWindow(this->m_hWnd));
4152		return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL);
4153	}
4154
4155	DWORD_PTR GetItemData(HTREEITEM hItem) const
4156	{
4157		ATLASSERT(::IsWindow(this->m_hWnd));
4158		TVITEM item = {};
4159		item.hItem = hItem;
4160		item.mask = TVIF_PARAM;
4161		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4162		return (DWORD_PTR)(bRet ? item.lParam : NULL);
4163	}
4164
4165	BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData)
4166	{
4167		ATLASSERT(::IsWindow(this->m_hWnd));
4168		return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData);
4169	}
4170
4171	CEdit GetEditControl() const
4172	{
4173		ATLASSERT(::IsWindow(this->m_hWnd));
4174		return CEdit((HWND)::SendMessage(this->m_hWnd, TVM_GETEDITCONTROL, 0, 0L));
4175	}
4176
4177	UINT GetVisibleCount() const
4178	{
4179		ATLASSERT(::IsWindow(this->m_hWnd));
4180		return (UINT)::SendMessage(this->m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L);
4181	}
4182
4183	BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const
4184	{
4185		ATLASSERT(::IsWindow(this->m_hWnd));
4186		*(HTREEITEM*)lpRect = hItem;
4187		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect);
4188	}
4189
4190	BOOL ItemHasChildren(HTREEITEM hItem) const
4191	{
4192		ATLASSERT(::IsWindow(this->m_hWnd));
4193		TVITEM item = {};
4194		item.hItem = hItem;
4195		item.mask = TVIF_CHILDREN;
4196		::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4197		return item.cChildren;
4198	}
4199
4200	CToolTipCtrl GetToolTips() const
4201	{
4202		ATLASSERT(::IsWindow(this->m_hWnd));
4203		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, TVM_GETTOOLTIPS, 0, 0L));
4204	}
4205
4206	CToolTipCtrl SetToolTips(HWND hWndTT)
4207	{
4208		ATLASSERT(::IsWindow(this->m_hWnd));
4209		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
4210	}
4211
4212	int GetISearchString(LPTSTR lpstr) const
4213	{
4214		ATLASSERT(::IsWindow(this->m_hWnd));
4215		return (int)::SendMessage(this->m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
4216	}
4217
4218	// checkboxes only
4219	BOOL GetCheckState(HTREEITEM hItem) const
4220	{
4221		ATLASSERT(::IsWindow(this->m_hWnd));
4222		ATLASSERT((this->GetStyle() & TVS_CHECKBOXES) != 0);
4223		UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK);
4224		return (uRet >> 12) - 1;
4225	}
4226
4227	BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck)
4228	{
4229		ATLASSERT(::IsWindow(this->m_hWnd));
4230		ATLASSERT((this->GetStyle() & TVS_CHECKBOXES) != 0);
4231		int nCheck = bCheck ? 2 : 1;   // one based index
4232		return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK);
4233	}
4234
4235	// for standard and extended checkboxes (0 = no checkbox, 1 = unchecked, 2 = checked, >2 = optional extended check states)
4236	UINT GetCheckStateEx(HTREEITEM hItem) const
4237	{
4238		ATLASSERT(::IsWindow(this->m_hWnd));
4239		ATLASSERT(this->GetImageList(TVSIL_STATE) != NULL);
4240		UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK);
4241		return (uRet >> 12);
4242	}
4243
4244	BOOL SetCheckStateEx(HTREEITEM hItem, UINT uCheckState)
4245	{
4246		ATLASSERT(::IsWindow(this->m_hWnd));
4247		ATLASSERT(this->GetImageList(TVSIL_STATE) != NULL);
4248		ATLASSERT(uCheckState < (UINT)::ImageList_GetImageCount(this->GetImageList(TVSIL_STATE)));
4249		return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(uCheckState), TVIS_STATEIMAGEMASK);
4250	}
4251
4252	COLORREF GetBkColor() const
4253	{
4254		ATLASSERT(::IsWindow(this->m_hWnd));
4255		return (COLORREF)::SendMessage(this->m_hWnd, TVM_GETBKCOLOR, 0, 0L);
4256	}
4257
4258	COLORREF SetBkColor(COLORREF clr)
4259	{
4260		ATLASSERT(::IsWindow(this->m_hWnd));
4261		return (COLORREF)::SendMessage(this->m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr);
4262	}
4263
4264	COLORREF GetInsertMarkColor() const
4265	{
4266		ATLASSERT(::IsWindow(this->m_hWnd));
4267		return (COLORREF)::SendMessage(this->m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L);
4268	}
4269
4270	COLORREF SetInsertMarkColor(COLORREF clr)
4271	{
4272		ATLASSERT(::IsWindow(this->m_hWnd));
4273		return (COLORREF)::SendMessage(this->m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
4274	}
4275
4276	int GetItemHeight() const
4277	{
4278		ATLASSERT(::IsWindow(this->m_hWnd));
4279		return (int)::SendMessage(this->m_hWnd, TVM_GETITEMHEIGHT, 0, 0L);
4280	}
4281
4282	int SetItemHeight(int cyHeight)
4283	{
4284		ATLASSERT(::IsWindow(this->m_hWnd));
4285		return (int)::SendMessage(this->m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L);
4286	}
4287
4288	int GetScrollTime() const
4289	{
4290		ATLASSERT(::IsWindow(this->m_hWnd));
4291		return (int)::SendMessage(this->m_hWnd, TVM_GETSCROLLTIME, 0, 0L);
4292	}
4293
4294	int SetScrollTime(int nScrollTime)
4295	{
4296		ATLASSERT(::IsWindow(this->m_hWnd));
4297		return (int)::SendMessage(this->m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L);
4298	}
4299
4300	COLORREF GetTextColor() const
4301	{
4302		ATLASSERT(::IsWindow(this->m_hWnd));
4303		return (COLORREF)::SendMessage(this->m_hWnd, TVM_GETTEXTCOLOR, 0, 0L);
4304	}
4305
4306	COLORREF SetTextColor(COLORREF clr)
4307	{
4308		ATLASSERT(::IsWindow(this->m_hWnd));
4309		return (COLORREF)::SendMessage(this->m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr);
4310	}
4311
4312	BOOL GetUnicodeFormat() const
4313	{
4314		ATLASSERT(::IsWindow(this->m_hWnd));
4315		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L);
4316	}
4317
4318	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
4319	{
4320		ATLASSERT(::IsWindow(this->m_hWnd));
4321		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L);
4322	}
4323
4324	COLORREF GetLineColor() const
4325	{
4326		ATLASSERT(::IsWindow(this->m_hWnd));
4327		return (COLORREF)::SendMessage(this->m_hWnd, TVM_GETLINECOLOR, 0, 0L);
4328	}
4329
4330	COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/)
4331	{
4332		ATLASSERT(::IsWindow(this->m_hWnd));
4333		return (COLORREF)::SendMessage(this->m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew);
4334	}
4335
4336	BOOL GetItem(LPTVITEMEX pItem) const
4337	{
4338		ATLASSERT(::IsWindow(this->m_hWnd));
4339		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
4340	}
4341
4342	BOOL SetItem(LPTVITEMEX pItem)
4343	{
4344		ATLASSERT(::IsWindow(this->m_hWnd));
4345		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
4346	}
4347
4348	DWORD GetExtendedStyle() const
4349	{
4350		ATLASSERT(::IsWindow(this->m_hWnd));
4351		return (DWORD)::SendMessage(this->m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L);
4352	}
4353
4354	DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
4355	{
4356		ATLASSERT(::IsWindow(this->m_hWnd));
4357		return (DWORD)::SendMessage(this->m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle);
4358	}
4359
4360#if (_WIN32_WINNT >= 0x0600)
4361	BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime)
4362	{
4363		ATLASSERT(::IsWindow(this->m_hWnd));
4364		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime);
4365	}
4366
4367	DWORD GetSelectedCount() const
4368	{
4369		ATLASSERT(::IsWindow(this->m_hWnd));
4370		return (DWORD)::SendMessage(this->m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L);
4371	}
4372
4373	BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const
4374	{
4375		ATLASSERT(::IsWindow(this->m_hWnd));
4376		TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID };
4377		return (BOOL)::SendMessage(this->m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri);
4378	}
4379#endif // (_WIN32_WINNT >= 0x0600)
4380
4381// Operations
4382	HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
4383	{
4384		ATLASSERT(::IsWindow(this->m_hWnd));
4385		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
4386	}
4387
4388	HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage,
4389		int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
4390	{
4391		ATLASSERT(::IsWindow(this->m_hWnd));
4392		return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); 
4393	}
4394
4395	HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
4396	{
4397		ATLASSERT(::IsWindow(this->m_hWnd));
4398		return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
4399	}
4400
4401	HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
4402		int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
4403		HTREEITEM hParent, HTREEITEM hInsertAfter)
4404	{
4405		ATLASSERT(::IsWindow(this->m_hWnd));
4406		TVINSERTSTRUCT tvis = {};
4407		tvis.hParent = hParent;
4408		tvis.hInsertAfter = hInsertAfter;
4409		tvis.item.mask = nMask;
4410		tvis.item.pszText = (LPTSTR) lpszItem;
4411		tvis.item.iImage = nImage;
4412		tvis.item.iSelectedImage = nSelectedImage;
4413		tvis.item.state = nState;
4414		tvis.item.stateMask = nStateMask;
4415		tvis.item.lParam = lParam;
4416		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
4417	}
4418
4419	BOOL DeleteItem(HTREEITEM hItem)
4420	{
4421		ATLASSERT(::IsWindow(this->m_hWnd));
4422		return (BOOL)::SendMessage(this->m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem);
4423	}
4424
4425	BOOL DeleteAllItems()
4426	{
4427		ATLASSERT(::IsWindow(this->m_hWnd));
4428		return (BOOL)::SendMessage(this->m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
4429	}
4430
4431	BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND)
4432	{
4433		ATLASSERT(::IsWindow(this->m_hWnd));
4434		return (BOOL)::SendMessage(this->m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem);
4435	}
4436
4437	HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const
4438	{
4439		ATLASSERT(::IsWindow(this->m_hWnd)); 
4440		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
4441	}
4442
4443	HTREEITEM GetChildItem(HTREEITEM hItem) const
4444	{
4445		ATLASSERT(::IsWindow(this->m_hWnd)); 
4446		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
4447	}
4448
4449	HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const
4450	{
4451		ATLASSERT(::IsWindow(this->m_hWnd)); 
4452		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); 
4453	}
4454
4455	HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const
4456	{
4457		ATLASSERT(::IsWindow(this->m_hWnd)); 
4458		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
4459	}
4460
4461	HTREEITEM GetParentItem(HTREEITEM hItem) const
4462	{
4463		ATLASSERT(::IsWindow(this->m_hWnd)); 
4464		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); 
4465	}
4466
4467	HTREEITEM GetFirstVisibleItem() const
4468	{
4469		ATLASSERT(::IsWindow(this->m_hWnd)); 
4470		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
4471	}
4472
4473	HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const
4474	{
4475		ATLASSERT(::IsWindow(this->m_hWnd));
4476		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
4477	}
4478
4479	HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const
4480	{
4481		ATLASSERT(::IsWindow(this->m_hWnd));
4482		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
4483	}
4484
4485	HTREEITEM GetSelectedItem() const
4486	{
4487		ATLASSERT(::IsWindow(this->m_hWnd));
4488		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
4489	}
4490
4491	HTREEITEM GetDropHilightItem() const
4492	{
4493		ATLASSERT(::IsWindow(this->m_hWnd));
4494		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
4495	}
4496
4497	HTREEITEM GetRootItem() const
4498	{
4499		ATLASSERT(::IsWindow(this->m_hWnd));
4500		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
4501	}
4502
4503	HTREEITEM GetLastVisibleItem() const
4504	{
4505		ATLASSERT(::IsWindow(this->m_hWnd));
4506		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
4507	}
4508
4509	HTREEITEM GetNextSelectedItem(HTREEITEM hItem) const
4510	{
4511		ATLASSERT(::IsWindow(this->m_hWnd));
4512		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, (LPARAM)hItem);
4513	}
4514
4515	BOOL Select(HTREEITEM hItem, UINT nCode)
4516	{
4517		ATLASSERT(::IsWindow(this->m_hWnd));
4518		return (BOOL)::SendMessage(this->m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem);
4519	}
4520
4521	BOOL SelectItem(HTREEITEM hItem)
4522	{
4523		ATLASSERT(::IsWindow(this->m_hWnd));
4524		return (BOOL)::SendMessage(this->m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem);
4525	}
4526
4527	BOOL SelectDropTarget(HTREEITEM hItem)
4528	{
4529		ATLASSERT(::IsWindow(this->m_hWnd));
4530		return (BOOL)::SendMessage(this->m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem);
4531	}
4532
4533	BOOL SelectSetFirstVisible(HTREEITEM hItem)
4534	{
4535		ATLASSERT(::IsWindow(this->m_hWnd));
4536		return (BOOL)::SendMessage(this->m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem);
4537	}
4538
4539	CEdit EditLabel(HTREEITEM hItem)
4540	{
4541		ATLASSERT(::IsWindow(this->m_hWnd));
4542		return CEdit((HWND)::SendMessage(this->m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem));
4543	}
4544
4545	BOOL EndEditLabelNow(BOOL bCancel)
4546	{
4547		ATLASSERT(::IsWindow(this->m_hWnd));
4548		return (BOOL)::SendMessage(this->m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L);
4549	}
4550
4551	HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const
4552	{
4553		ATLASSERT(::IsWindow(this->m_hWnd));
4554		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
4555	}
4556
4557	HTREEITEM HitTest(POINT pt, UINT* pFlags) const
4558	{
4559		ATLASSERT(::IsWindow(this->m_hWnd));
4560		TVHITTESTINFO hti = {};
4561		hti.pt = pt;
4562		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
4563		if (pFlags != NULL)
4564			*pFlags = hti.flags;
4565		return hTreeItem;
4566	}
4567
4568	BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE)
4569	{
4570		ATLASSERT(::IsWindow(this->m_hWnd));
4571		return (BOOL)::SendMessage(this->m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem);
4572	}
4573
4574	BOOL EnsureVisible(HTREEITEM hItem)
4575	{
4576		ATLASSERT(::IsWindow(this->m_hWnd));
4577		return (BOOL)::SendMessage(this->m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
4578	}
4579
4580	BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE)
4581	{
4582		ATLASSERT(::IsWindow(this->m_hWnd));
4583		return (BOOL)::SendMessage(this->m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort);
4584	}
4585
4586	CImageList RemoveImageList(int nImageList)
4587	{
4588		ATLASSERT(::IsWindow(this->m_hWnd));
4589		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
4590	}
4591
4592	CImageList CreateDragImage(HTREEITEM hItem)
4593	{
4594		ATLASSERT(::IsWindow(this->m_hWnd));
4595		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem));
4596	}
4597
4598	BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter)
4599	{
4600		ATLASSERT(::IsWindow(this->m_hWnd));
4601		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem);
4602	}
4603
4604	BOOL RemoveInsertMark()
4605	{
4606		ATLASSERT(::IsWindow(this->m_hWnd));
4607		return (BOOL)::SendMessage(this->m_hWnd, TVM_SETINSERTMARK, 0, 0L);
4608	}
4609
4610	HTREEITEM MapAccIDToHTREEITEM(UINT uID) const
4611	{
4612		ATLASSERT(::IsWindow(this->m_hWnd));
4613		return (HTREEITEM)::SendMessage(this->m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
4614	}
4615
4616	UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const
4617	{
4618		ATLASSERT(::IsWindow(this->m_hWnd));
4619		return (UINT)::SendMessage(this->m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L);
4620	}
4621
4622#if (_WIN32_WINNT >= 0x0600)
4623	void ShowInfoTip(HTREEITEM hItem)
4624	{
4625		ATLASSERT(::IsWindow(this->m_hWnd));
4626		::SendMessage(this->m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem);
4627	}
4628#endif // (_WIN32_WINNT >= 0x0600)
4629};
4630
4631typedef CTreeViewCtrlT<ATL::CWindow>   CTreeViewCtrl;
4632
4633
4634///////////////////////////////////////////////////////////////////////////////
4635// CTreeViewCtrlEx
4636
4637// forward declaration
4638template <class TBase> class CTreeViewCtrlExT;
4639
4640// Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself
4641template <class TBase>
4642class CTreeItemT
4643{
4644public:
4645	HTREEITEM m_hTreeItem;
4646	CTreeViewCtrlExT<TBase>* m_pTreeView;
4647
4648// Construction
4649	CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT<TBase>* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView)
4650	{ }
4651 
4652	CTreeItemT(const CTreeItemT<TBase>& posSrc)
4653	{
4654		*this = posSrc;
4655	}
4656
4657	operator HTREEITEM() { return m_hTreeItem; }
4658
4659	CTreeItemT<TBase>& operator =(const CTreeItemT<TBase>& itemSrc)
4660	{
4661		m_hTreeItem = itemSrc.m_hTreeItem;
4662		m_pTreeView = itemSrc.m_pTreeView;
4663		return *this;
4664	}
4665
4666// Attributes
4667	CTreeViewCtrlExT<TBase>* GetTreeView() const { return m_pTreeView; }
4668
4669	BOOL operator !() const { return m_hTreeItem == NULL; }
4670
4671	BOOL IsNull() const { return m_hTreeItem == NULL; }
4672	
4673	BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const;
4674	BOOL GetText(LPTSTR lpstrText, int nLen) const;
4675	BOOL GetText(BSTR& bstrText) const;
4676#ifdef __ATLSTR_H__
4677	BOOL GetText(ATL::CString& strText) const;
4678#endif // __ATLSTR_H__
4679	BOOL SetText(LPCTSTR lpszItem);
4680	BOOL GetImage(int& nImage, int& nSelectedImage) const;
4681	BOOL SetImage(int nImage, int nSelectedImage);
4682	UINT GetState(UINT nStateMask) const;
4683	BOOL SetState(UINT nState, UINT nStateMask);
4684	DWORD_PTR GetData() const;
4685	BOOL SetData(DWORD_PTR dwData);
4686	BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam);
4687
4688// Operations
4689	CTreeItemT<TBase> InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex)
4690	{
4691		return _Insert(lpstrItem, nImageIndex, hItemAfter);
4692	}
4693
4694	CTreeItemT<TBase> AddHead(LPCTSTR lpstrItem, int nImageIndex)
4695	{
4696		return _Insert(lpstrItem, nImageIndex, TVI_FIRST);
4697	}
4698
4699	CTreeItemT<TBase> AddTail(LPCTSTR lpstrItem, int nImageIndex)
4700	{
4701		return _Insert(lpstrItem, nImageIndex, TVI_LAST);
4702	}
4703
4704	CTreeItemT<TBase> GetChild() const;
4705	CTreeItemT<TBase> GetNext(UINT nCode) const;
4706	CTreeItemT<TBase> GetNextSibling() const;
4707	CTreeItemT<TBase> GetPrevSibling() const;
4708	CTreeItemT<TBase> GetParent() const;
4709	CTreeItemT<TBase> GetFirstVisible() const;
4710	CTreeItemT<TBase> GetNextVisible() const;
4711	CTreeItemT<TBase> GetPrevVisible() const;
4712	CTreeItemT<TBase> GetSelected() const;
4713	CTreeItemT<TBase> GetDropHilight() const;
4714	CTreeItemT<TBase> GetRoot() const;
4715	CTreeItemT<TBase> GetLastVisible() const;
4716	CTreeItemT<TBase> GetNextSelected() const;
4717	BOOL HasChildren() const;
4718	BOOL Delete();
4719	BOOL Expand(UINT nCode = TVE_EXPAND);
4720	BOOL Select(UINT nCode);
4721	BOOL Select();
4722	BOOL SelectDropTarget();
4723	BOOL SelectSetFirstVisible();
4724	HWND EditLabel();
4725	HIMAGELIST CreateDragImage();
4726	BOOL SortChildren(BOOL bRecurse = FALSE);
4727	BOOL EnsureVisible();
4728	CTreeItemT<TBase> _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter);
4729	int GetImageIndex() const;
4730	BOOL SetInsertMark(BOOL bAfter);
4731	UINT MapHTREEITEMToAccID() const;
4732#if (_WIN32_WINNT >= 0x0600)
4733	void ShowInfoTip();
4734	BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const;
4735#endif // (_WIN32_WINNT >= 0x0600)
4736};
4737
4738typedef CTreeItemT<ATL::CWindow>   CTreeItem;
4739
4740
4741template <class TBase>
4742class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase >
4743{
4744public:
4745// Constructors
4746	CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd)
4747	{ }
4748
4749	CTreeViewCtrlExT< TBase >& operator =(HWND hWnd)
4750	{
4751		this->m_hWnd = hWnd;
4752		return *this;
4753	}
4754
4755// Operations (overides that return CTreeItem)
4756	CTreeItemT<TBase> InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
4757	{
4758		ATLASSERT(::IsWindow(this->m_hWnd));
4759		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
4760		return CTreeItemT<TBase>(hTreeItem, this);
4761	}
4762
4763	CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, int nImage,
4764		int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
4765	{
4766		ATLASSERT(::IsWindow(this->m_hWnd));
4767		return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); 
4768	}
4769
4770	CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
4771	{
4772		ATLASSERT(::IsWindow(this->m_hWnd));
4773		return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
4774	}
4775
4776	CTreeItemT<TBase> GetNextItem(HTREEITEM hItem, UINT nCode) const
4777	{
4778		ATLASSERT(::IsWindow(this->m_hWnd)); 
4779		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
4780		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4781	}
4782
4783	CTreeItemT<TBase> GetChildItem(HTREEITEM hItem) const
4784	{
4785		ATLASSERT(::IsWindow(this->m_hWnd)); 
4786		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
4787		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this); 
4788	}
4789
4790	CTreeItemT<TBase> GetNextSiblingItem(HTREEITEM hItem) const
4791	{
4792		ATLASSERT(::IsWindow(this->m_hWnd)); 
4793		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); 
4794		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4795	}
4796
4797	CTreeItemT<TBase> GetPrevSiblingItem(HTREEITEM hItem) const
4798	{
4799		ATLASSERT(::IsWindow(this->m_hWnd)); 
4800		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
4801		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4802	}
4803
4804	CTreeItemT<TBase> GetParentItem(HTREEITEM hItem) const
4805	{
4806		ATLASSERT(::IsWindow(this->m_hWnd)); 
4807		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); 
4808		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4809	}
4810
4811	CTreeItemT<TBase> GetFirstVisibleItem() const
4812	{
4813		ATLASSERT(::IsWindow(this->m_hWnd)); 
4814		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
4815		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4816	}
4817
4818	CTreeItemT<TBase> GetNextVisibleItem(HTREEITEM hItem) const
4819	{
4820		ATLASSERT(::IsWindow(this->m_hWnd));
4821		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
4822		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4823	}
4824
4825	CTreeItemT<TBase> GetPrevVisibleItem(HTREEITEM hItem) const
4826	{
4827		ATLASSERT(::IsWindow(this->m_hWnd));
4828		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
4829		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4830	}
4831
4832	CTreeItemT<TBase> GetSelectedItem() const
4833	{
4834		ATLASSERT(::IsWindow(this->m_hWnd));
4835		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
4836		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4837	}
4838
4839	CTreeItemT<TBase> GetDropHilightItem() const
4840	{
4841		ATLASSERT(::IsWindow(this->m_hWnd));
4842		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
4843		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4844	}
4845
4846	CTreeItemT<TBase> GetRootItem() const
4847	{
4848		ATLASSERT(::IsWindow(this->m_hWnd));
4849		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
4850		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4851	}
4852
4853	CTreeItemT<TBase> GetLastVisibleItem() const
4854	{
4855		ATLASSERT(::IsWindow(this->m_hWnd));
4856		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
4857		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4858	}
4859
4860	CTreeItemT<TBase> GetNextSelectedItem(HTREEITEM hItem) const
4861	{
4862		ATLASSERT(::IsWindow(this->m_hWnd));
4863		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, (LPARAM)hItem);
4864		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4865	}
4866
4867	CTreeItemT<TBase> HitTest(TVHITTESTINFO* pHitTestInfo) const
4868	{
4869		ATLASSERT(::IsWindow(this->m_hWnd));
4870		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
4871		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4872	}
4873
4874	CTreeItemT<TBase> InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
4875		int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
4876		HTREEITEM hParent, HTREEITEM hInsertAfter)
4877	{
4878		ATLASSERT(::IsWindow(this->m_hWnd));
4879		TVINSERTSTRUCT tvis = {};
4880		tvis.hParent = hParent;
4881		tvis.hInsertAfter = hInsertAfter;
4882		tvis.item.mask = nMask;
4883		tvis.item.pszText = (LPTSTR) lpszItem;
4884		tvis.item.iImage = nImage;
4885		tvis.item.iSelectedImage = nSelectedImage;
4886		tvis.item.state = nState;
4887		tvis.item.stateMask = nStateMask;
4888		tvis.item.lParam = lParam;
4889		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
4890		return CTreeItemT<TBase>(hTreeItem, this);
4891	}
4892
4893	CTreeItemT<TBase> HitTest(POINT pt, UINT* pFlags) const
4894	{
4895		ATLASSERT(::IsWindow(this->m_hWnd));
4896		TVHITTESTINFO hti = {};
4897		hti.pt = pt;
4898		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
4899		if (pFlags != NULL)
4900			*pFlags = hti.flags;
4901		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4902	}
4903
4904	CTreeItemT<TBase> MapAccIDToHTREEITEM(UINT uID) const
4905	{
4906		ATLASSERT(::IsWindow(this->m_hWnd));
4907		HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(this->m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
4908		return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4909	}
4910};
4911
4912typedef CTreeViewCtrlExT<ATL::CWindow>   CTreeViewCtrlEx;
4913
4914
4915// CTreeItem inline methods
4916template <class TBase>
4917inline BOOL CTreeItemT<TBase>::GetRect(LPRECT lpRect, BOOL bTextOnly) const
4918{
4919	ATLASSERT(m_pTreeView != NULL);
4920	return m_pTreeView->GetItemRect(m_hTreeItem,lpRect,bTextOnly);
4921}
4922
4923template <class TBase>
4924inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNext(UINT nCode) const
4925{
4926	ATLASSERT(m_pTreeView != NULL);
4927	return m_pTreeView->GetNextItem(m_hTreeItem,nCode);
4928}
4929
4930template <class TBase>
4931inline CTreeItemT<TBase> CTreeItemT<TBase>::GetChild() const
4932{
4933	ATLASSERT(m_pTreeView != NULL);
4934	return m_pTreeView->GetChildItem(m_hTreeItem);
4935}
4936
4937template <class TBase>
4938inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSibling() const
4939{
4940	ATLASSERT(m_pTreeView != NULL);
4941	return m_pTreeView->GetNextSiblingItem(m_hTreeItem);
4942}
4943
4944template <class TBase>
4945inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevSibling() const
4946{
4947	ATLASSERT(m_pTreeView != NULL);
4948	return m_pTreeView->GetPrevSiblingItem(m_hTreeItem);
4949}
4950
4951template <class TBase>
4952inline CTreeItemT<TBase> CTreeItemT<TBase>::GetParent() const
4953{
4954	ATLASSERT(m_pTreeView != NULL);
4955	return m_pTreeView->GetParentItem(m_hTreeItem);
4956}
4957
4958template <class TBase>
4959inline CTreeItemT<TBase> CTreeItemT<TBase>::GetFirstVisible() const
4960{
4961	ATLASSERT(m_pTreeView != NULL);
4962	return m_pTreeView->GetFirstVisibleItem();
4963}
4964
4965template <class TBase>
4966inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextVisible() const
4967{
4968	ATLASSERT(m_pTreeView != NULL);
4969	return m_pTreeView->GetNextVisibleItem(m_hTreeItem);
4970}
4971
4972template <class TBase>
4973inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevVisible() const
4974{
4975	ATLASSERT(m_pTreeView != NULL);
4976	return m_pTreeView->GetPrevVisibleItem(m_hTreeItem);
4977}
4978
4979template <class TBase>
4980inline CTreeItemT<TBase> CTreeItemT<TBase>::GetSelected() const
4981{
4982	ATLASSERT(m_pTreeView != NULL);
4983	return m_pTreeView->GetSelectedItem();
4984}
4985
4986template <class TBase>
4987inline CTreeItemT<TBase> CTreeItemT<TBase>::GetDropHilight() const
4988{
4989	ATLASSERT(m_pTreeView != NULL);
4990	return m_pTreeView->GetDropHilightItem();
4991}
4992
4993template <class TBase>
4994inline CTreeItemT<TBase> CTreeItemT<TBase>::GetRoot() const
4995{
4996	ATLASSERT(m_pTreeView != NULL);
4997	return m_pTreeView->GetRootItem();
4998}
4999
5000template <class TBase>
5001inline CTreeItemT<TBase> CTreeItemT<TBase>::GetLastVisible() const
5002{
5003	ATLASSERT(m_pTreeView != NULL);
5004	return m_pTreeView->GetLastVisibleItem();
5005}
5006
5007template <class TBase>
5008inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSelected() const
5009{
5010	ATLASSERT(m_pTreeView != NULL);
5011	return m_pTreeView->GetNextSelectedItem(m_hTreeItem);
5012}
5013
5014template <class TBase>
5015inline BOOL CTreeItemT<TBase>::GetText(LPTSTR lpstrText, int nLen) const
5016{
5017	ATLASSERT(m_pTreeView != NULL);
5018	return m_pTreeView->GetItemText(m_hTreeItem, lpstrText, nLen);
5019}
5020
5021#ifdef _OLEAUTO_H_
5022template <class TBase>
5023inline BOOL CTreeItemT<TBase>::GetText(BSTR& bstrText) const
5024{
5025	ATLASSERT(m_pTreeView != NULL);
5026	return m_pTreeView->GetItemText(m_hTreeItem, bstrText);
5027}
5028#endif // _OLEAUTO_H_
5029
5030#ifdef __ATLSTR_H__
5031template <class TBase>
5032inline BOOL CTreeItemT<TBase>::GetText(ATL::CString& strText) const
5033{
5034	ATLASSERT(m_pTreeView != NULL);
5035	return m_pTreeView->GetItemText(m_hTreeItem, strText);
5036}
5037#endif // __ATLSTR_H__
5038
5039template <class TBase>
5040inline BOOL CTreeItemT<TBase>::GetImage(int& nImage, int& nSelectedImage) const
5041{
5042	ATLASSERT(m_pTreeView != NULL);
5043	return m_pTreeView->GetItemImage(m_hTreeItem,nImage,nSelectedImage);
5044}
5045
5046template <class TBase>
5047inline UINT CTreeItemT<TBase>::GetState(UINT nStateMask) const
5048{
5049	ATLASSERT(m_pTreeView != NULL);
5050	return m_pTreeView->GetItemState(m_hTreeItem,nStateMask);
5051}
5052
5053template <class TBase>
5054inline DWORD_PTR CTreeItemT<TBase>::GetData() const
5055{
5056	ATLASSERT(m_pTreeView != NULL);
5057	return m_pTreeView->GetItemData(m_hTreeItem);
5058}
5059
5060template <class TBase>
5061inline BOOL CTreeItemT<TBase>::SetItem(UINT nMask, LPCTSTR lpszItem, int nImage,
5062		int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
5063{
5064	ATLASSERT(m_pTreeView != NULL);
5065	return m_pTreeView->SetItem(m_hTreeItem, nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam);
5066}
5067
5068template <class TBase>
5069inline BOOL CTreeItemT<TBase>::SetText(LPCTSTR lpszItem)
5070{
5071	ATLASSERT(m_pTreeView != NULL);
5072	return m_pTreeView->SetItemText(m_hTreeItem,lpszItem);
5073}
5074
5075template <class TBase>
5076inline BOOL CTreeItemT<TBase>::SetImage(int nImage, int nSelectedImage)
5077{
5078	ATLASSERT(m_pTreeView != NULL);
5079	return m_pTreeView->SetItemImage(m_hTreeItem,nImage,nSelectedImage);
5080}
5081
5082template <class TBase>
5083inline BOOL CTreeItemT<TBase>::SetState(UINT nState, UINT nStateMask)
5084{
5085	ATLASSERT(m_pTreeView != NULL);
5086	return m_pTreeView->SetItemState(m_hTreeItem,nState,nStateMask);
5087}
5088
5089template <class TBase>
5090inline BOOL CTreeItemT<TBase>::SetData(DWORD_PTR dwData)
5091{
5092	ATLASSERT(m_pTreeView != NULL);
5093	return m_pTreeView->SetItemData(m_hTreeItem,dwData);
5094}
5095
5096template <class TBase>
5097inline BOOL CTreeItemT<TBase>::HasChildren() const
5098{
5099	ATLASSERT(m_pTreeView != NULL);
5100	return m_pTreeView->ItemHasChildren(m_hTreeItem);
5101}
5102
5103template <class TBase>
5104inline BOOL CTreeItemT<TBase>::Delete()
5105{
5106	ATLASSERT(m_pTreeView != NULL);
5107	return m_pTreeView->DeleteItem(m_hTreeItem);
5108}
5109
5110template <class TBase>
5111inline BOOL CTreeItemT<TBase>::Expand(UINT nCode /*= TVE_EXPAND*/)
5112{
5113	ATLASSERT(m_pTreeView != NULL);
5114	return m_pTreeView->Expand(m_hTreeItem,nCode);
5115}
5116
5117template <class TBase>
5118inline BOOL CTreeItemT<TBase>::Select(UINT nCode)
5119{
5120	ATLASSERT(m_pTreeView != NULL);
5121	return m_pTreeView->Select(m_hTreeItem,nCode);
5122}
5123
5124template <class TBase>
5125inline BOOL CTreeItemT<TBase>::Select()
5126{
5127	ATLASSERT(m_pTreeView != NULL);
5128	return m_pTreeView->SelectItem(m_hTreeItem);
5129}
5130
5131template <class TBase>
5132inline BOOL CTreeItemT<TBase>::SelectDropTarget()
5133{
5134	ATLASSERT(m_pTreeView != NULL);
5135	return m_pTreeView->SelectDropTarget(m_hTreeItem);
5136}
5137
5138template <class TBase>
5139inline BOOL CTreeItemT<TBase>::SelectSetFirstVisible()
5140{
5141	ATLASSERT(m_pTreeView != NULL);
5142	return m_pTreeView->SelectSetFirstVisible(m_hTreeItem);
5143}
5144
5145template <class TBase>
5146inline HWND CTreeItemT<TBase>::EditLabel()
5147{
5148	ATLASSERT(m_pTreeView != NULL);
5149	return m_pTreeView->EditLabel(m_hTreeItem);
5150}
5151
5152template <class TBase>
5153inline HIMAGELIST CTreeItemT<TBase>::CreateDragImage()
5154{
5155	ATLASSERT(m_pTreeView != NULL);
5156	return m_pTreeView->CreateDragImage(m_hTreeItem);
5157}
5158
5159template <class TBase>
5160inline BOOL CTreeItemT<TBase>::SortChildren(BOOL bRecurse /*= FALSE*/)
5161{
5162	ATLASSERT(m_pTreeView != NULL);
5163	return m_pTreeView->SortChildren(m_hTreeItem, bRecurse);
5164}
5165
5166template <class TBase>
5167inline BOOL CTreeItemT<TBase>::EnsureVisible()
5168{
5169	ATLASSERT(m_pTreeView != NULL);
5170	return m_pTreeView->EnsureVisible(m_hTreeItem);
5171}
5172
5173template <class TBase>
5174inline CTreeItemT<TBase> CTreeItemT<TBase>::_Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter)
5175{
5176	ATLASSERT(m_pTreeView != NULL);
5177	TVINSERTSTRUCT ins = {};
5178	ins.hParent = m_hTreeItem;
5179	ins.hInsertAfter = hItemAfter;
5180	ins.item.mask = TVIF_TEXT;
5181	ins.item.pszText = (LPTSTR)lpstrItem;
5182	if(nImageIndex != -1)
5183	{
5184		ins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
5185		ins.item.iImage = nImageIndex;
5186		ins.item.iSelectedImage = nImageIndex;
5187	}
5188	return CTreeItemT<TBase>(m_pTreeView->InsertItem(&ins), m_pTreeView);
5189}
5190
5191template <class TBase>
5192inline int CTreeItemT<TBase>::GetImageIndex() const
5193{
5194	ATLASSERT(m_pTreeView != NULL);
5195	TVITEM item = {};
5196	item.mask = TVIF_HANDLE | TVIF_IMAGE;
5197	item.hItem = m_hTreeItem;
5198	m_pTreeView->GetItem(&item);
5199	return item.iImage;
5200}
5201
5202template <class TBase>
5203inline BOOL CTreeItemT<TBase>::SetInsertMark(BOOL bAfter)
5204{
5205	ATLASSERT(m_pTreeView != NULL);
5206	return m_pTreeView->SetInsertMark(m_hTreeItem, bAfter);
5207}
5208
5209template <class TBase>
5210inline UINT CTreeItemT<TBase>::MapHTREEITEMToAccID() const
5211{
5212	ATLASSERT(m_pTreeView != NULL);
5213	return m_pTreeView->MapHTREEITEMToAccID(m_hTreeItem);
5214}
5215
5216#if (_WIN32_WINNT >= 0x0600)
5217template <class TBase>
5218inline void CTreeItemT<TBase>::ShowInfoTip()
5219{
5220	ATLASSERT(m_pTreeView != NULL);
5221	m_pTreeView->ShowInfoTip(m_hTreeItem);
5222}
5223
5224template <class TBase>
5225inline BOOL CTreeItemT<TBase>::GetPartRect(TVITEMPART partID, LPRECT lpRect) const
5226{
5227	ATLASSERT(m_pTreeView != NULL);
5228	return m_pTreeView->GetItemPartRect(m_hTreeItem, partID, lpRect);
5229}
5230#endif // (_WIN32_WINNT >= 0x0600)
5231
5232
5233///////////////////////////////////////////////////////////////////////////////
5234// CToolBarCtrl
5235
5236template <class TBase>
5237class CToolBarCtrlT : public TBase
5238{
5239public:
5240// Construction
5241	CToolBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
5242	{ }
5243
5244	CToolBarCtrlT< TBase >& operator =(HWND hWnd)
5245	{
5246		this->m_hWnd = hWnd;
5247		return *this;
5248	}
5249
5250	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
5251			DWORD dwStyle = 0, DWORD dwExStyle = 0,
5252			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
5253	{
5254		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
5255	}
5256
5257// Attributes
5258	static LPCTSTR GetWndClassName()
5259	{
5260		return TOOLBARCLASSNAME;
5261	}
5262
5263	BOOL IsButtonEnabled(int nID) const
5264	{
5265		ATLASSERT(::IsWindow(this->m_hWnd));
5266		return (BOOL)::SendMessage(this->m_hWnd, TB_ISBUTTONENABLED, nID, 0L);
5267	}
5268
5269	BOOL IsButtonChecked(int nID) const
5270	{
5271		ATLASSERT(::IsWindow(this->m_hWnd));
5272		return (BOOL)::SendMessage(this->m_hWnd, TB_ISBUTTONCHECKED, nID, 0L);
5273	}
5274
5275	BOOL IsButtonPressed(int nID) const
5276	{
5277		ATLASSERT(::IsWindow(this->m_hWnd));
5278		return (BOOL)::SendMessage(this->m_hWnd, TB_ISBUTTONPRESSED, nID, 0L);
5279	}
5280
5281	BOOL IsButtonHidden(int nID) const
5282	{
5283		ATLASSERT(::IsWindow(this->m_hWnd));
5284		return(BOOL) ::SendMessage(this->m_hWnd, TB_ISBUTTONHIDDEN, nID, 0L);
5285	}
5286
5287	BOOL IsButtonIndeterminate(int nID) const
5288	{
5289		ATLASSERT(::IsWindow(this->m_hWnd));
5290		return (BOOL)::SendMessage(this->m_hWnd, TB_ISBUTTONINDETERMINATE, nID, 0L);
5291	}
5292
5293	int GetState(int nID) const
5294	{
5295		ATLASSERT(::IsWindow(this->m_hWnd));
5296		return (int)::SendMessage(this->m_hWnd, TB_GETSTATE, nID, 0L);
5297	}
5298
5299	BOOL SetState(int nID, UINT nState)
5300	{
5301		ATLASSERT(::IsWindow(this->m_hWnd));
5302		return (BOOL)::SendMessage(this->m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0));
5303	}
5304
5305	BOOL GetButton(int nIndex, LPTBBUTTON lpButton) const
5306	{
5307		ATLASSERT(::IsWindow(this->m_hWnd));
5308		return (BOOL)::SendMessage(this->m_hWnd, TB_GETBUTTON, nIndex, (LPARAM)lpButton);
5309	}
5310
5311	int GetButtonCount() const
5312	{
5313		ATLASSERT(::IsWindow(this->m_hWnd));
5314		return (int)::SendMessage(this->m_hWnd, TB_BUTTONCOUNT, 0, 0L);
5315	}
5316
5317	BOOL GetItemRect(int nIndex, LPRECT lpRect) const
5318	{
5319		ATLASSERT(::IsWindow(this->m_hWnd));
5320		return (BOOL)::SendMessage(this->m_hWnd, TB_GETITEMRECT, nIndex, (LPARAM)lpRect);
5321	}
5322
5323	void SetButtonStructSize(int nSize = sizeof(TBBUTTON))
5324	{
5325		ATLASSERT(::IsWindow(this->m_hWnd));
5326		::SendMessage(this->m_hWnd, TB_BUTTONSTRUCTSIZE, nSize, 0L);
5327	}
5328
5329	BOOL SetButtonSize(SIZE size)
5330	{
5331		ATLASSERT(::IsWindow(this->m_hWnd));
5332		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy));
5333	}
5334
5335	BOOL SetButtonSize(int cx, int cy)
5336	{
5337		ATLASSERT(::IsWindow(this->m_hWnd));
5338		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, cy));
5339	}
5340
5341	BOOL SetBitmapSize(SIZE size)
5342	{
5343		ATLASSERT(::IsWindow(this->m_hWnd));
5344		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy));
5345	}
5346
5347	BOOL SetBitmapSize(int cx, int cy)
5348	{
5349		ATLASSERT(::IsWindow(this->m_hWnd));
5350		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(cx, cy));
5351	}
5352
5353	CToolTipCtrl GetToolTips() const
5354	{
5355		ATLASSERT(::IsWindow(this->m_hWnd));
5356		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, TB_GETTOOLTIPS, 0, 0L));
5357	}
5358
5359	void SetToolTips(HWND hWndToolTip)
5360	{
5361		ATLASSERT(::IsWindow(this->m_hWnd));
5362		::SendMessage(this->m_hWnd, TB_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
5363	}
5364
5365	void SetNotifyWnd(HWND hWnd)
5366	{
5367		ATLASSERT(::IsWindow(this->m_hWnd));
5368		::SendMessage(this->m_hWnd, TB_SETPARENT, (WPARAM)hWnd, 0L);
5369	}
5370
5371	int GetRows() const
5372	{
5373		ATLASSERT(::IsWindow(this->m_hWnd));
5374		return (int)::SendMessage(this->m_hWnd, TB_GETROWS, 0, 0L);
5375	}
5376
5377	void SetRows(int nRows, BOOL bLarger, LPRECT lpRect)
5378	{
5379		ATLASSERT(::IsWindow(this->m_hWnd));
5380		::SendMessage(this->m_hWnd, TB_SETROWS, MAKELPARAM(nRows, bLarger), (LPARAM)lpRect);
5381	}
5382
5383	BOOL SetCmdID(int nIndex, UINT nID)
5384	{
5385		ATLASSERT(::IsWindow(this->m_hWnd));
5386		return (BOOL)::SendMessage(this->m_hWnd, TB_SETCMDID, nIndex, nID);
5387	}
5388
5389	DWORD GetBitmapFlags() const
5390	{
5391		ATLASSERT(::IsWindow(this->m_hWnd));
5392		return (DWORD)::SendMessage(this->m_hWnd, TB_GETBITMAPFLAGS, 0, 0L);
5393	}
5394
5395	int GetBitmap(int nID) const
5396	{
5397		ATLASSERT(::IsWindow(this->m_hWnd));
5398		return (int)::SendMessage(this->m_hWnd, TB_GETBITMAP, nID, 0L);
5399	}
5400
5401	int GetButtonText(int nID, LPTSTR lpstrText) const
5402	{
5403		ATLASSERT(::IsWindow(this->m_hWnd));
5404		return (int)::SendMessage(this->m_hWnd, TB_GETBUTTONTEXT, nID, (LPARAM)lpstrText);
5405	}
5406
5407	// nIndex - IE5 or higher only
5408	CImageList GetImageList(int nIndex = 0) const
5409	{
5410		ATLASSERT(::IsWindow(this->m_hWnd));
5411		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_GETIMAGELIST, nIndex, 0L));
5412	}
5413
5414	// nIndex - IE5 or higher only
5415	CImageList SetImageList(HIMAGELIST hImageList, int nIndex = 0)
5416	{
5417		ATLASSERT(::IsWindow(this->m_hWnd));
5418		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_SETIMAGELIST, nIndex, (LPARAM)hImageList));
5419	}
5420
5421	// nIndex - IE5 or higher only
5422	CImageList GetDisabledImageList(int nIndex = 0) const
5423	{
5424		ATLASSERT(::IsWindow(this->m_hWnd));
5425		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_GETDISABLEDIMAGELIST, nIndex, 0L));
5426	}
5427
5428	// nIndex - IE5 or higher only
5429	CImageList SetDisabledImageList(HIMAGELIST hImageList, int nIndex = 0)
5430	{
5431		ATLASSERT(::IsWindow(this->m_hWnd));
5432		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_SETDISABLEDIMAGELIST, nIndex, (LPARAM)hImageList));
5433	}
5434
5435	// nIndex - IE5 or higher only
5436	CImageList GetHotImageList(int nIndex = 0) const
5437	{
5438		ATLASSERT(::IsWindow(this->m_hWnd));
5439		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_GETHOTIMAGELIST, nIndex, 0L));
5440	}
5441
5442	// nIndex - IE5 or higher only
5443	CImageList SetHotImageList(HIMAGELIST hImageList, int nIndex = 0)
5444	{
5445		ATLASSERT(::IsWindow(this->m_hWnd));
5446		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_SETHOTIMAGELIST, nIndex, (LPARAM)hImageList));
5447	}
5448
5449	DWORD GetStyle() const
5450	{
5451		ATLASSERT(::IsWindow(this->m_hWnd));
5452		return (DWORD)::SendMessage(this->m_hWnd, TB_GETSTYLE, 0, 0L);
5453	}
5454
5455	void SetStyle(DWORD dwStyle)
5456	{
5457		ATLASSERT(::IsWindow(this->m_hWnd));
5458		::SendMessage(this->m_hWnd, TB_SETSTYLE, 0, dwStyle);
5459	}
5460
5461	DWORD GetButtonSize() const
5462	{
5463		ATLASSERT(::IsWindow(this->m_hWnd));
5464		return (DWORD)::SendMessage(this->m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
5465	}
5466
5467	void GetButtonSize(SIZE& size) const
5468	{
5469		ATLASSERT(::IsWindow(this->m_hWnd));
5470		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
5471		size.cx = LOWORD(dwRet);
5472		size.cy = HIWORD(dwRet);
5473	}
5474
5475	BOOL GetRect(int nID, LPRECT lpRect) const
5476	{
5477		ATLASSERT(::IsWindow(this->m_hWnd));
5478		return (BOOL)::SendMessage(this->m_hWnd, TB_GETRECT, nID, (LPARAM)lpRect);
5479	}
5480
5481	int GetTextRows() const
5482	{
5483		ATLASSERT(::IsWindow(this->m_hWnd));
5484		return (int)::SendMessage(this->m_hWnd, TB_GETTEXTROWS, 0, 0L);
5485	}
5486
5487	BOOL SetButtonWidth(int cxMin, int cxMax)
5488	{
5489		ATLASSERT(::IsWindow(this->m_hWnd));
5490		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBUTTONWIDTH, 0, MAKELPARAM(cxMin, cxMax));
5491	}
5492
5493	BOOL SetIndent(int nIndent)
5494	{
5495		ATLASSERT(::IsWindow(this->m_hWnd));
5496		return (BOOL)::SendMessage(this->m_hWnd, TB_SETINDENT, nIndent, 0L);
5497	}
5498
5499	BOOL SetMaxTextRows(int nMaxTextRows)
5500	{
5501		ATLASSERT(::IsWindow(this->m_hWnd));
5502		return (BOOL)::SendMessage(this->m_hWnd, TB_SETMAXTEXTROWS, nMaxTextRows, 0L);
5503	}
5504
5505	BOOL GetAnchorHighlight() const
5506	{
5507		ATLASSERT(::IsWindow(this->m_hWnd));
5508		return (BOOL)::SendMessage(this->m_hWnd, TB_GETANCHORHIGHLIGHT, 0, 0L);
5509	}
5510
5511	BOOL SetAnchorHighlight(BOOL bEnable = TRUE)
5512	{
5513		ATLASSERT(::IsWindow(this->m_hWnd));
5514		return (BOOL)::SendMessage(this->m_hWnd, TB_SETANCHORHIGHLIGHT, bEnable, 0L);
5515	}
5516
5517	int GetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) const
5518	{
5519		ATLASSERT(::IsWindow(this->m_hWnd));
5520		return (int)::SendMessage(this->m_hWnd, TB_GETBUTTONINFO, nID, (LPARAM)lptbbi);
5521	}
5522
5523	BOOL SetButtonInfo(int nID, LPTBBUTTONINFO lptbbi)
5524	{
5525		ATLASSERT(::IsWindow(this->m_hWnd));
5526		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)lptbbi);
5527	}
5528
5529	BOOL SetButtonInfo(int nID, DWORD dwMask, BYTE Style, BYTE State, LPCTSTR lpszItem, 
5530	                   int iImage, WORD cx, int iCommand, DWORD_PTR lParam)
5531	{
5532		ATLASSERT(::IsWindow(this->m_hWnd));
5533		TBBUTTONINFO tbbi = {};
5534		tbbi.cbSize = sizeof(TBBUTTONINFO);
5535		tbbi.dwMask = dwMask;
5536		tbbi.idCommand = iCommand;
5537		tbbi.iImage = iImage;
5538		tbbi.fsState = State;
5539		tbbi.fsStyle = Style;
5540		tbbi.cx = cx;
5541		tbbi.pszText = (LPTSTR) lpszItem;
5542		tbbi.lParam = lParam;
5543		return (BOOL)::SendMessage(this->m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)&tbbi);
5544	}
5545
5546	int GetHotItem() const
5547	{
5548		ATLASSERT(::IsWindow(this->m_hWnd));
5549		return (int)::SendMessage(this->m_hWnd, TB_GETHOTITEM, 0, 0L);
5550	}
5551
5552	int SetHotItem(int nItem)
5553	{
5554		ATLASSERT(::IsWindow(this->m_hWnd));
5555		return (int)::SendMessage(this->m_hWnd, TB_SETHOTITEM, nItem, 0L);
5556	}
5557
5558	BOOL IsButtonHighlighted(int nButtonID) const
5559	{
5560		ATLASSERT(::IsWindow(this->m_hWnd));
5561		return (BOOL)::SendMessage(this->m_hWnd, TB_ISBUTTONHIGHLIGHTED, nButtonID, 0L);
5562	}
5563
5564	DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwFlags)
5565	{
5566		ATLASSERT(::IsWindow(this->m_hWnd));
5567		return (DWORD)::SendMessage(this->m_hWnd, TB_SETDRAWTEXTFLAGS, dwMask, dwFlags);
5568	}
5569
5570	BOOL GetColorScheme(LPCOLORSCHEME lpcs) const
5571	{
5572		ATLASSERT(::IsWindow(this->m_hWnd));
5573		return (BOOL)::SendMessage(this->m_hWnd, TB_GETCOLORSCHEME, 0, (LPARAM)lpcs);
5574	}
5575
5576	void SetColorScheme(LPCOLORSCHEME lpcs)
5577	{
5578		ATLASSERT(::IsWindow(this->m_hWnd));
5579		::SendMessage(this->m_hWnd, TB_SETCOLORSCHEME, 0, (LPARAM)lpcs);
5580	}
5581
5582	DWORD GetExtendedStyle() const
5583	{
5584		ATLASSERT(::IsWindow(this->m_hWnd));
5585		return (DWORD)::SendMessage(this->m_hWnd, TB_GETEXTENDEDSTYLE, 0, 0L);
5586	}
5587
5588	DWORD SetExtendedStyle(DWORD dwStyle)
5589	{
5590		ATLASSERT(::IsWindow(this->m_hWnd));
5591		return (DWORD)::SendMessage(this->m_hWnd, TB_SETEXTENDEDSTYLE, 0, dwStyle);
5592	}
5593
5594	void GetInsertMark(LPTBINSERTMARK lptbim) const
5595	{
5596		ATLASSERT(::IsWindow(this->m_hWnd));
5597		::SendMessage(this->m_hWnd, TB_GETINSERTMARK, 0, (LPARAM)lptbim);
5598	}
5599
5600	void SetInsertMark(LPTBINSERTMARK lptbim)
5601	{
5602		ATLASSERT(::IsWindow(this->m_hWnd));
5603		::SendMessage(this->m_hWnd, TB_SETINSERTMARK, 0, (LPARAM)lptbim);
5604	}
5605
5606	COLORREF GetInsertMarkColor() const
5607	{
5608		ATLASSERT(::IsWindow(this->m_hWnd));
5609		return (COLORREF)::SendMessage(this->m_hWnd, TB_GETINSERTMARKCOLOR, 0, 0L);
5610	}
5611
5612	COLORREF SetInsertMarkColor(COLORREF clr)
5613	{
5614		ATLASSERT(::IsWindow(this->m_hWnd));
5615		return (COLORREF)::SendMessage(this->m_hWnd, TB_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
5616	}
5617
5618	BOOL GetMaxSize(LPSIZE lpSize) const
5619	{
5620		ATLASSERT(::IsWindow(this->m_hWnd));
5621		return (BOOL)::SendMessage(this->m_hWnd, TB_GETMAXSIZE, 0, (LPARAM)lpSize);
5622	}
5623
5624	void GetPadding(LPSIZE lpSizePadding) const
5625	{
5626		ATLASSERT(::IsWindow(this->m_hWnd));
5627		ATLASSERT(lpSizePadding != NULL);
5628		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, TB_GETPADDING, 0, 0L);
5629		lpSizePadding->cx = GET_X_LPARAM(dwRet);
5630		lpSizePadding->cy = GET_Y_LPARAM(dwRet);
5631	}
5632
5633	void SetPadding(int cx, int cy, LPSIZE lpSizePadding = NULL)
5634	{
5635		ATLASSERT(::IsWindow(this->m_hWnd));
5636		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, TB_SETPADDING, 0, MAKELPARAM(cx, cy));
5637		if(lpSizePadding != NULL)
5638		{
5639			lpSizePadding->cx = GET_X_LPARAM(dwRet);
5640			lpSizePadding->cy = GET_Y_LPARAM(dwRet);
5641		}
5642	}
5643
5644	BOOL GetUnicodeFormat() const
5645	{
5646		ATLASSERT(::IsWindow(this->m_hWnd));
5647		return (BOOL)::SendMessage(this->m_hWnd, TB_GETUNICODEFORMAT, 0, 0L);
5648	}
5649
5650	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
5651	{
5652		ATLASSERT(::IsWindow(this->m_hWnd));
5653		return (BOOL)::SendMessage(this->m_hWnd, TB_SETUNICODEFORMAT, bUnicode, 0L);
5654	}
5655
5656	int GetString(int nString, LPTSTR lpstrString, int cchMaxLen) const
5657	{
5658		ATLASSERT(::IsWindow(this->m_hWnd));
5659		return (int)::SendMessage(this->m_hWnd, TB_GETSTRING, MAKEWPARAM(cchMaxLen, nString), (LPARAM)lpstrString);
5660	}
5661
5662	int GetStringBSTR(int nString, BSTR& bstrString) const
5663	{
5664		USES_CONVERSION;
5665		ATLASSERT(::IsWindow(this->m_hWnd));
5666		ATLASSERT(bstrString == NULL);
5667		int nLength = (int)(short)LOWORD(::SendMessage(this->m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
5668		if(nLength != -1)
5669		{
5670			ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
5671			LPTSTR lpstrText = buff.Allocate(nLength + 1);
5672			if(lpstrText != NULL)
5673			{
5674				nLength = (int)::SendMessage(this->m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstrText);
5675				if(nLength != -1)
5676					bstrString = ::SysAllocString(T2OLE(lpstrText));
5677			}
5678			else
5679			{
5680				nLength = -1;
5681			}
5682		}
5683
5684		return nLength;
5685	}
5686
5687#ifdef __ATLSTR_H__
5688	int GetString(int nString, ATL::CString& str) const
5689	{
5690		ATLASSERT(::IsWindow(this->m_hWnd));
5691		int nLength = (int)(short)LOWORD(::SendMessage(this->m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
5692		if(nLength != -1)
5693		{
5694			LPTSTR lpstr = str.GetBufferSetLength(nLength + 1);
5695			if(lpstr != NULL)
5696				nLength = (int)::SendMessage(this->m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstr);
5697			else
5698				nLength = -1;
5699			str.ReleaseBuffer();
5700		}
5701		return nLength;
5702	}
5703#endif // __ATLSTR_H__
5704
5705	void GetMetrics(LPTBMETRICS lptbm) const
5706	{
5707		ATLASSERT(::IsWindow(this->m_hWnd));
5708		::SendMessage(this->m_hWnd, TB_GETMETRICS, 0, (LPARAM)lptbm);
5709	}
5710
5711	void SetMetrics(LPTBMETRICS lptbm)
5712	{
5713		ATLASSERT(::IsWindow(this->m_hWnd));
5714		::SendMessage(this->m_hWnd, TB_SETMETRICS, 0, (LPARAM)lptbm);
5715	}
5716
5717	void SetWindowTheme(LPCWSTR lpstrTheme)
5718	{
5719		ATLASSERT(::IsWindow(this->m_hWnd));
5720		::SendMessage(this->m_hWnd, TB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
5721	}
5722
5723#if (_WIN32_WINNT >= 0x0600)
5724	CImageList GetPressedImageList(int nIndex = 0) const
5725	{
5726		ATLASSERT(::IsWindow(this->m_hWnd));
5727		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_GETPRESSEDIMAGELIST, nIndex, 0L));
5728	}
5729
5730	CImageList SetPressedImageList(HIMAGELIST hImageList, int nIndex = 0)
5731	{
5732		ATLASSERT(::IsWindow(this->m_hWnd));
5733		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TB_SETPRESSEDIMAGELIST, nIndex, (LPARAM)hImageList));
5734	}
5735
5736	void GetItemDropDownRect(int nIndex, LPRECT lpRect) const
5737	{
5738#ifndef TB_GETITEMDROPDOWNRECT
5739		const int TB_GETITEMDROPDOWNRECT = WM_USER + 103;
5740#endif
5741		ATLASSERT(::IsWindow(this->m_hWnd));
5742		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, TB_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
5743		(void)bRet;   // avoid level 4 warning
5744		ATLASSERT(bRet != FALSE);
5745	}
5746#endif // (_WIN32_WINNT >= 0x0600)
5747
5748// Operations
5749	BOOL EnableButton(int nID, BOOL bEnable = TRUE)
5750	{
5751		ATLASSERT(::IsWindow(this->m_hWnd));
5752		return (BOOL)::SendMessage(this->m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0));
5753	}
5754
5755	BOOL CheckButton(int nID, BOOL bCheck = TRUE)
5756	{
5757		ATLASSERT(::IsWindow(this->m_hWnd));
5758		return (BOOL)::SendMessage(this->m_hWnd, TB_CHECKBUTTON, nID, MAKELPARAM(bCheck, 0));
5759	}
5760
5761	BOOL PressButton(int nID, BOOL bPress = TRUE)
5762	{
5763		ATLASSERT(::IsWindow(this->m_hWnd));
5764		return (BOOL)::SendMessage(this->m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0));
5765	}
5766
5767	BOOL HideButton(int nID, BOOL bHide = TRUE)
5768	{
5769		ATLASSERT(::IsWindow(this->m_hWnd));
5770		return (BOOL)::SendMessage(this->m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0));
5771	}
5772
5773	BOOL Indeterminate(int nID, BOOL bIndeterminate = TRUE)
5774	{
5775		ATLASSERT(::IsWindow(this->m_hWnd));
5776		return (BOOL)::SendMessage(this->m_hWnd, TB_INDETERMINATE, nID, MAKELPARAM(bIndeterminate, 0));
5777	}
5778
5779	int AddBitmap(int nNumButtons, UINT nBitmapID)
5780	{
5781		ATLASSERT(::IsWindow(this->m_hWnd));
5782		TBADDBITMAP tbab = {};
5783		tbab.hInst = ModuleHelper::GetResourceInstance();
5784		ATLASSERT(tbab.hInst != NULL);
5785		tbab.nID = nBitmapID;
5786		return (int)::SendMessage(this->m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
5787	}
5788
5789	int AddBitmap(int nNumButtons, HBITMAP hBitmap)
5790	{
5791		ATLASSERT(::IsWindow(this->m_hWnd));
5792		TBADDBITMAP tbab = {};
5793		tbab.hInst = NULL;
5794		tbab.nID = (UINT_PTR)hBitmap;
5795		return (int)::SendMessage(this->m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
5796	}
5797
5798	BOOL AddButtons(int nNumButtons, LPCTBBUTTON lpButtons)
5799	{
5800		ATLASSERT(::IsWindow(this->m_hWnd));
5801		return (BOOL)::SendMessage(this->m_hWnd, TB_ADDBUTTONS, nNumButtons, (LPARAM)lpButtons);
5802	}
5803
5804	BOOL InsertButton(int nIndex, LPCTBBUTTON lpButton)
5805	{
5806		ATLASSERT(::IsWindow(this->m_hWnd));
5807		return (BOOL)::SendMessage(this->m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)lpButton);
5808	}
5809
5810	BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, 
5811	                  INT_PTR iString, DWORD_PTR lParam)
5812	{
5813		ATLASSERT(::IsWindow(this->m_hWnd));
5814		TBBUTTON tbb = {};
5815		tbb.fsStyle = Style;
5816		tbb.fsState = State;
5817		tbb.idCommand = iCommand;
5818		tbb.iBitmap = iBitmap;
5819		tbb.iString = iString;
5820		tbb.dwData = lParam;
5821		return (BOOL)::SendMessage(this->m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)&tbb);
5822	}
5823
5824	BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, 
5825	                  LPCTSTR lpszItem, DWORD_PTR lParam)
5826	{
5827		return InsertButton(nIndex, iCommand, Style, State, iBitmap, (INT_PTR)lpszItem, lParam);
5828	}
5829
5830	BOOL AddButton(LPTBBUTTON lpButton)
5831	{
5832		return InsertButton(-1, lpButton);
5833	}
5834
5835	BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, INT_PTR iString, DWORD_PTR lParam)
5836	{
5837		return InsertButton(-1, iCommand, Style, State, iBitmap, iString, lParam);
5838	}
5839
5840	BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, LPCTSTR lpszItem, DWORD_PTR lParam)
5841	{
5842		return InsertButton(-1, iCommand, Style, State, iBitmap, lpszItem, lParam);
5843	}
5844
5845	BOOL DeleteButton(int nIndex)
5846	{
5847		ATLASSERT(::IsWindow(this->m_hWnd));
5848		return (BOOL)::SendMessage(this->m_hWnd, TB_DELETEBUTTON, nIndex, 0L);
5849	}
5850
5851	BOOL InsertSeparator(int nIndex, int cxWidth = 8)
5852	{
5853		return InsertButton(nIndex, 0, BTNS_SEP, 0, cxWidth, (INT_PTR)0, 0);
5854	}
5855
5856	BOOL AddSeparator(int cxWidth = 8)
5857	{
5858		return AddButton(0, BTNS_SEP, 0, cxWidth, (INT_PTR)0, 0);
5859	}
5860
5861	int CommandToIndex(UINT nID) const
5862	{
5863		ATLASSERT(::IsWindow(this->m_hWnd));
5864		return (int)::SendMessage(this->m_hWnd, TB_COMMANDTOINDEX, nID, 0L);
5865	}
5866
5867	void SaveState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
5868	{
5869		ATLASSERT(::IsWindow(this->m_hWnd));
5870		TBSAVEPARAMS tbs = {};
5871		tbs.hkr = hKeyRoot;
5872		tbs.pszSubKey = lpszSubKey;
5873		tbs.pszValueName = lpszValueName;
5874		::SendMessage(this->m_hWnd, TB_SAVERESTORE, (WPARAM)TRUE, (LPARAM)&tbs);
5875	}
5876
5877	void RestoreState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
5878	{
5879		ATLASSERT(::IsWindow(this->m_hWnd));
5880		TBSAVEPARAMS tbs = {};
5881		tbs.hkr = hKeyRoot;
5882		tbs.pszSubKey = lpszSubKey;
5883		tbs.pszValueName = lpszValueName;
5884		::SendMessage(this->m_hWnd, TB_SAVERESTORE, (WPARAM)FALSE, (LPARAM)&tbs);
5885	}
5886
5887	void Customize()
5888	{
5889		ATLASSERT(::IsWindow(this->m_hWnd));
5890		::SendMessage(this->m_hWnd, TB_CUSTOMIZE, 0, 0L);
5891	}
5892
5893	int AddString(UINT nStringID)
5894	{
5895		ATLASSERT(::IsWindow(this->m_hWnd));
5896		return (int)::SendMessage(this->m_hWnd, TB_ADDSTRING, (WPARAM)ModuleHelper::GetResourceInstance(), (LPARAM)nStringID);
5897	}
5898
5899	int AddStrings(LPCTSTR lpszStrings)
5900	{
5901		ATLASSERT(::IsWindow(this->m_hWnd));
5902		return (int)::SendMessage(this->m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings);
5903	}
5904
5905	void AutoSize()
5906	{
5907		ATLASSERT(::IsWindow(this->m_hWnd));
5908		::SendMessage(this->m_hWnd, TB_AUTOSIZE, 0, 0L);
5909	}
5910
5911	BOOL ChangeBitmap(int nID, int nBitmap)
5912	{
5913		ATLASSERT(::IsWindow(this->m_hWnd));
5914		return (BOOL)::SendMessage(this->m_hWnd, TB_CHANGEBITMAP, nID, MAKELPARAM(nBitmap, 0));
5915	}
5916
5917	int LoadImages(int nBitmapID)
5918	{
5919		ATLASSERT(::IsWindow(this->m_hWnd));
5920		return (int)::SendMessage(this->m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)ModuleHelper::GetResourceInstance());
5921	}
5922
5923	int LoadStdImages(int nBitmapID)
5924	{
5925		ATLASSERT(::IsWindow(this->m_hWnd));
5926		return (int)::SendMessage(this->m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)HINST_COMMCTRL);
5927	}
5928
5929	BOOL ReplaceBitmap(LPTBREPLACEBITMAP ptbrb)
5930	{
5931		ATLASSERT(::IsWindow(this->m_hWnd));
5932		return (BOOL)::SendMessage(this->m_hWnd, TB_REPLACEBITMAP, 0, (LPARAM)ptbrb);
5933	}
5934
5935	int HitTest(LPPOINT lpPoint) const
5936	{
5937		ATLASSERT(::IsWindow(this->m_hWnd));
5938		return (int)::SendMessage(this->m_hWnd, TB_HITTEST, 0, (LPARAM)lpPoint);
5939	}
5940
5941	BOOL InsertMarkHitTest(LPPOINT lpPoint, LPTBINSERTMARK lptbim) const
5942	{
5943		ATLASSERT(::IsWindow(this->m_hWnd));
5944		return (BOOL)::SendMessage(this->m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)lptbim);
5945	}
5946
5947	BOOL InsertMarkHitTest(int x, int y, LPTBINSERTMARK lptbim) const
5948	{
5949		ATLASSERT(::IsWindow(this->m_hWnd));
5950		POINT pt = { x, y };
5951		return (BOOL)::SendMessage(this->m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)&pt, (LPARAM)lptbim);
5952	}
5953
5954	BOOL MapAccelerator(TCHAR chAccel, int& nID) const
5955	{
5956		ATLASSERT(::IsWindow(this->m_hWnd));
5957		return (BOOL)::SendMessage(this->m_hWnd, TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&nID);
5958	}
5959
5960	BOOL MarkButton(int nID, BOOL bHighlight = TRUE)
5961	{
5962		ATLASSERT(::IsWindow(this->m_hWnd));
5963		return (BOOL)::SendMessage(this->m_hWnd, TB_MARKBUTTON, nID, MAKELPARAM(bHighlight, 0));
5964	}
5965
5966	BOOL MoveButton(int nOldPos, int nNewPos)
5967	{
5968		ATLASSERT(::IsWindow(this->m_hWnd));
5969		return (BOOL)::SendMessage(this->m_hWnd, TB_MOVEBUTTON, nOldPos, nNewPos);
5970	}
5971
5972	HRESULT GetObject(REFIID iid, LPVOID* ppvObject)
5973	{
5974		ATLASSERT(::IsWindow(this->m_hWnd));
5975		return (HRESULT)::SendMessage(this->m_hWnd, TB_GETOBJECT, (WPARAM)&iid, (LPARAM)ppvObject);
5976	}
5977};
5978
5979typedef CToolBarCtrlT<ATL::CWindow>   CToolBarCtrl;
5980
5981
5982///////////////////////////////////////////////////////////////////////////////
5983// CStatusBarCtrl
5984
5985template <class TBase>
5986class CStatusBarCtrlT : public TBase
5987{
5988public:
5989// Constructors
5990	CStatusBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
5991	{ }
5992
5993	CStatusBarCtrlT< TBase >& operator =(HWND hWnd)
5994	{
5995		this->m_hWnd = hWnd;
5996		return *this;
5997	}
5998
5999	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6000			DWORD dwStyle = 0, DWORD dwExStyle = 0,
6001			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6002	{
6003		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6004	}
6005
6006// Methods
6007	static LPCTSTR GetWndClassName()
6008	{
6009		return STATUSCLASSNAME;
6010	}
6011
6012	int GetParts(int nParts, int* pParts) const
6013	{
6014		ATLASSERT(::IsWindow(this->m_hWnd));
6015		return (int)::SendMessage(this->m_hWnd, SB_GETPARTS, nParts, (LPARAM)pParts);
6016	}
6017
6018	BOOL SetParts(int nParts, int* pWidths)
6019	{
6020		ATLASSERT(::IsWindow(this->m_hWnd));
6021		return (BOOL)::SendMessage(this->m_hWnd, SB_SETPARTS, nParts, (LPARAM)pWidths);
6022	}
6023
6024	int GetTextLength(int nPane, int* pType = NULL) const
6025	{
6026		ATLASSERT(::IsWindow(this->m_hWnd));
6027		ATLASSERT(nPane < 256);
6028		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L);
6029		if (pType != NULL)
6030			*pType = (int)(short)HIWORD(dwRet);
6031		return (int)(short)LOWORD(dwRet);
6032	}
6033
6034	int GetText(int nPane, LPTSTR lpszText, int* pType = NULL) const
6035	{
6036		ATLASSERT(::IsWindow(this->m_hWnd));
6037		ATLASSERT(nPane < 256);
6038		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, SB_GETTEXT, (WPARAM)nPane, (LPARAM)lpszText);
6039		if(pType != NULL)
6040			*pType = (int)(short)HIWORD(dwRet);
6041		return (int)(short)LOWORD(dwRet);
6042	}
6043
6044	BOOL GetTextBSTR(int nPane, BSTR& bstrText, int* pType = NULL) const
6045	{
6046		USES_CONVERSION;
6047		ATLASSERT(::IsWindow(this->m_hWnd));
6048		ATLASSERT(nPane < 256);
6049		ATLASSERT(bstrText == NULL);
6050		int nLength = (int)(short)LOWORD(::SendMessage(this->m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
6051		if(nLength == 0)
6052			return FALSE;
6053
6054		ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
6055		LPTSTR lpstrText = buff.Allocate(nLength + 1);
6056		if(lpstrText == NULL)
6057			return FALSE;
6058
6059		if(!GetText(nPane, lpstrText, pType))
6060			return FALSE;
6061
6062		bstrText = ::SysAllocString(T2OLE(lpstrText));
6063		return (bstrText != NULL) ? TRUE : FALSE;
6064	}
6065
6066#ifdef __ATLSTR_H__
6067	int GetText(int nPane, ATL::CString& strText, int* pType = NULL) const
6068	{
6069		ATLASSERT(::IsWindow(this->m_hWnd));
6070		ATLASSERT(nPane < 256);
6071		int nLength = (int)(short)LOWORD(::SendMessage(this->m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
6072		if(nLength == 0)
6073			return 0;
6074
6075		LPTSTR lpstr = strText.GetBufferSetLength(nLength);
6076		if(lpstr == NULL)
6077			return 0;
6078		return GetText(nPane, lpstr, pType);
6079	}
6080#endif // __ATLSTR_H__
6081
6082	BOOL SetText(int nPane, LPCTSTR lpszText, int nType = 0)
6083	{
6084		ATLASSERT(::IsWindow(this->m_hWnd));
6085		ATLASSERT(nPane < 256);
6086		return (BOOL)::SendMessage(this->m_hWnd, SB_SETTEXT, (nPane | nType), (LPARAM)lpszText);
6087	}
6088
6089	BOOL GetRect(int nPane, LPRECT lpRect) const
6090	{
6091		ATLASSERT(::IsWindow(this->m_hWnd));
6092		ATLASSERT(nPane < 256);
6093		return (BOOL)::SendMessage(this->m_hWnd, SB_GETRECT, nPane, (LPARAM)lpRect);
6094	}
6095
6096	BOOL GetBorders(int* pBorders) const
6097	{
6098		ATLASSERT(::IsWindow(this->m_hWnd));
6099		return (BOOL)::SendMessage(this->m_hWnd, SB_GETBORDERS, 0, (LPARAM)pBorders);
6100	}
6101
6102	BOOL GetBorders(int& nHorz, int& nVert, int& nSpacing) const
6103	{
6104		ATLASSERT(::IsWindow(this->m_hWnd));
6105		int borders[3] = {};
6106		BOOL bResult = (BOOL)::SendMessage(this->m_hWnd, SB_GETBORDERS, 0, (LPARAM)&borders);
6107		if(bResult)
6108		{
6109			nHorz = borders[0];
6110			nVert = borders[1];
6111			nSpacing = borders[2];
6112		}
6113		return bResult;
6114	}
6115
6116	void SetMinHeight(int nMin)
6117	{
6118		ATLASSERT(::IsWindow(this->m_hWnd));
6119		::SendMessage(this->m_hWnd, SB_SETMINHEIGHT, nMin, 0L);
6120	}
6121
6122	BOOL SetSimple(BOOL bSimple = TRUE)
6123	{
6124		ATLASSERT(::IsWindow(this->m_hWnd));
6125		return (BOOL)::SendMessage(this->m_hWnd, SB_SIMPLE, bSimple, 0L);
6126	}
6127
6128	BOOL IsSimple() const
6129	{
6130		ATLASSERT(::IsWindow(this->m_hWnd));
6131		return (BOOL)::SendMessage(this->m_hWnd, SB_ISSIMPLE, 0, 0L);
6132	}
6133
6134	BOOL GetUnicodeFormat() const
6135	{
6136		ATLASSERT(::IsWindow(this->m_hWnd));
6137		return (BOOL)::SendMessage(this->m_hWnd, SB_GETUNICODEFORMAT, 0, 0L);
6138	}
6139
6140	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6141	{
6142		ATLASSERT(::IsWindow(this->m_hWnd));
6143		return (BOOL)::SendMessage(this->m_hWnd, SB_SETUNICODEFORMAT, bUnicode, 0L);
6144	}
6145
6146	void GetTipText(int nPane, LPTSTR lpstrText, int nSize) const
6147	{
6148		ATLASSERT(::IsWindow(this->m_hWnd));
6149		ATLASSERT(nPane < 256);
6150		::SendMessage(this->m_hWnd, SB_GETTIPTEXT, MAKEWPARAM(nPane, nSize), (LPARAM)lpstrText);
6151	}
6152
6153	void SetTipText(int nPane, LPCTSTR lpstrText)
6154	{
6155		ATLASSERT(::IsWindow(this->m_hWnd));
6156		ATLASSERT(nPane < 256);
6157		::SendMessage(this->m_hWnd, SB_SETTIPTEXT, nPane, (LPARAM)lpstrText);
6158	}
6159
6160	COLORREF SetBkColor(COLORREF clrBk)
6161	{
6162		ATLASSERT(::IsWindow(this->m_hWnd));
6163		return (COLORREF)::SendMessage(this->m_hWnd, SB_SETBKCOLOR, 0, (LPARAM)clrBk);
6164	}
6165
6166	HICON GetIcon(int nPane) const
6167	{
6168		ATLASSERT(::IsWindow(this->m_hWnd));
6169		ATLASSERT(nPane < 256);
6170		return (HICON)::SendMessage(this->m_hWnd, SB_GETICON, nPane, 0L);
6171	}
6172
6173	BOOL SetIcon(int nPane, HICON hIcon)
6174	{
6175		ATLASSERT(::IsWindow(this->m_hWnd));
6176		ATLASSERT(nPane < 256);
6177		return (BOOL)::SendMessage(this->m_hWnd, SB_SETICON, nPane, (LPARAM)hIcon);
6178	}
6179};
6180
6181typedef CStatusBarCtrlT<ATL::CWindow>   CStatusBarCtrl;
6182
6183
6184///////////////////////////////////////////////////////////////////////////////
6185// CTabCtrl
6186
6187template <class TBase>
6188class CTabCtrlT : public TBase
6189{
6190public:
6191// Constructors
6192	CTabCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6193	{ }
6194
6195	CTabCtrlT< TBase >& operator =(HWND hWnd)
6196	{
6197		this->m_hWnd = hWnd;
6198		return *this;
6199	}
6200
6201	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6202			DWORD dwStyle = 0, DWORD dwExStyle = 0,
6203			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6204	{
6205		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6206	}
6207
6208// Attributes
6209	static LPCTSTR GetWndClassName()
6210	{
6211		return WC_TABCONTROL;
6212	}
6213
6214	CImageList GetImageList() const
6215	{
6216		ATLASSERT(::IsWindow(this->m_hWnd));
6217		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TCM_GETIMAGELIST, 0, 0L));
6218	}
6219
6220	CImageList SetImageList(HIMAGELIST hImageList)
6221	{
6222		ATLASSERT(::IsWindow(this->m_hWnd));
6223		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, TCM_SETIMAGELIST, 0, (LPARAM)hImageList));
6224	}
6225
6226	int GetItemCount() const
6227	{
6228		ATLASSERT(::IsWindow(this->m_hWnd));
6229		return (int)::SendMessage(this->m_hWnd, TCM_GETITEMCOUNT, 0, 0L);
6230	}
6231
6232	BOOL GetItem(int nItem, LPTCITEM pTabCtrlItem) const
6233	{
6234		ATLASSERT(::IsWindow(this->m_hWnd));
6235		return (BOOL)::SendMessage(this->m_hWnd, TCM_GETITEM, nItem, (LPARAM)pTabCtrlItem);
6236	}
6237
6238	BOOL SetItem(int nItem, LPTCITEM pTabCtrlItem)
6239	{
6240		ATLASSERT(::IsWindow(this->m_hWnd));
6241		return (BOOL)::SendMessage(this->m_hWnd, TCM_SETITEM, nItem, (LPARAM)pTabCtrlItem);
6242	}
6243
6244	int SetItem(int nItem, UINT mask, LPCTSTR lpszItem, DWORD dwState, DWORD dwStateMask, int iImage, LPARAM lParam)
6245	{
6246		ATLASSERT(::IsWindow(this->m_hWnd));
6247		TCITEM tci = {};
6248		tci.mask = mask;
6249		tci.pszText = (LPTSTR) lpszItem;
6250		tci.dwState = dwState;
6251		tci.dwStateMask = dwStateMask;
6252		tci.iImage = iImage;
6253		tci.lParam = lParam;
6254		return (int)::SendMessage(this->m_hWnd, TCM_SETITEM, nItem, (LPARAM)&tci);
6255	}
6256
6257	BOOL GetItemRect(int nItem, LPRECT lpRect) const
6258	{
6259		ATLASSERT(::IsWindow(this->m_hWnd));
6260		return (BOOL)::SendMessage(this->m_hWnd, TCM_GETITEMRECT, nItem, (LPARAM)lpRect);
6261	}
6262
6263	int GetCurSel() const
6264	{
6265		ATLASSERT(::IsWindow(this->m_hWnd));
6266		return (int)::SendMessage(this->m_hWnd, TCM_GETCURSEL, 0, 0L);
6267	}
6268
6269	int SetCurSel(int nItem)
6270	{
6271		ATLASSERT(::IsWindow(this->m_hWnd));
6272		return (int)::SendMessage(this->m_hWnd, TCM_SETCURSEL, nItem, 0L);
6273	}
6274
6275	SIZE SetItemSize(SIZE size)
6276	{
6277		ATLASSERT(::IsWindow(this->m_hWnd));
6278		DWORD dwSize = (DWORD)::SendMessage(this->m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(size.cx, size.cy));
6279		SIZE sizeRet = { GET_X_LPARAM(dwSize), GET_Y_LPARAM(dwSize) };
6280		return sizeRet;
6281	}
6282
6283	void SetItemSize(int cx, int cy)
6284	{
6285		ATLASSERT(::IsWindow(this->m_hWnd));
6286		::SendMessage(this->m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(cx, cy));
6287	}
6288
6289	void SetPadding(SIZE size)
6290	{
6291		ATLASSERT(::IsWindow(this->m_hWnd));
6292		::SendMessage(this->m_hWnd, TCM_SETPADDING, 0, MAKELPARAM(size.cx, size.cy));
6293	}
6294
6295	int GetRowCount() const
6296	{
6297		ATLASSERT(::IsWindow(this->m_hWnd));
6298		return (int)::SendMessage(this->m_hWnd, TCM_GETROWCOUNT, 0, 0L);
6299	}
6300
6301	CToolTipCtrl GetToolTips() const
6302	{
6303		ATLASSERT(::IsWindow(this->m_hWnd));
6304		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, TCM_GETTOOLTIPS, 0, 0L));
6305	}
6306
6307	// this method is deprecated, please use GetToolTips
6308	CToolTipCtrl GetTooltips() const { return GetToolTips(); }
6309
6310	void SetToolTips(HWND hWndToolTip)
6311	{
6312		ATLASSERT(::IsWindow(this->m_hWnd));
6313		::SendMessage(this->m_hWnd, TCM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
6314	}
6315
6316	// this method is deprecated, please use SetToolTips
6317	void SetTooltips(HWND hWndToolTip) { SetToolTips(hWndToolTip); }
6318
6319	int GetCurFocus() const
6320	{
6321		ATLASSERT(::IsWindow(this->m_hWnd));
6322		return (int)::SendMessage(this->m_hWnd, TCM_GETCURFOCUS, 0, 0L);
6323	}
6324
6325	void SetCurFocus(int nItem)
6326	{
6327		ATLASSERT(::IsWindow(this->m_hWnd));
6328		::SendMessage(this->m_hWnd, TCM_SETCURFOCUS, nItem, 0L);
6329	}
6330
6331	BOOL SetItemExtra(int cbExtra)
6332	{
6333		ATLASSERT(::IsWindow(this->m_hWnd));
6334		ATLASSERT(GetItemCount() == 0);   // must be empty
6335		return (BOOL)::SendMessage(this->m_hWnd, TCM_SETITEMEXTRA, cbExtra, 0L);
6336	}
6337
6338	int SetMinTabWidth(int nWidth = -1)
6339	{
6340		ATLASSERT(::IsWindow(this->m_hWnd));
6341		return (int)::SendMessage(this->m_hWnd, TCM_SETMINTABWIDTH, 0, nWidth);
6342	}
6343
6344	DWORD GetExtendedStyle() const
6345	{
6346		ATLASSERT(::IsWindow(this->m_hWnd));
6347		return (DWORD)::SendMessage(this->m_hWnd, TCM_GETEXTENDEDSTYLE, 0, 0L);
6348	}
6349
6350	DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
6351	{
6352		ATLASSERT(::IsWindow(this->m_hWnd));
6353		return (DWORD)::SendMessage(this->m_hWnd, TCM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
6354	}
6355
6356	BOOL GetUnicodeFormat() const
6357	{
6358		ATLASSERT(::IsWindow(this->m_hWnd));
6359		return (BOOL)::SendMessage(this->m_hWnd, TCM_GETUNICODEFORMAT, 0, 0L);
6360	}
6361
6362	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6363	{
6364		ATLASSERT(::IsWindow(this->m_hWnd));
6365		return (BOOL)::SendMessage(this->m_hWnd, TCM_SETUNICODEFORMAT, bUnicode, 0L);
6366	}
6367
6368// Operations
6369	int InsertItem(int nItem, LPTCITEM pTabCtrlItem)
6370	{
6371		ATLASSERT(::IsWindow(this->m_hWnd));
6372		return (int)::SendMessage(this->m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)pTabCtrlItem);
6373	}
6374
6375	int InsertItem(int nItem, UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
6376	{
6377		ATLASSERT(::IsWindow(this->m_hWnd));
6378		TCITEM tci = {};
6379		tci.mask = mask;
6380		tci.pszText = (LPTSTR) lpszItem;
6381		tci.iImage = iImage;
6382		tci.lParam = lParam;
6383		return (int)::SendMessage(this->m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
6384	}
6385
6386	int InsertItem(int nItem, LPCTSTR lpszItem)
6387	{
6388		ATLASSERT(::IsWindow(this->m_hWnd));
6389		TCITEM tci = {};
6390		tci.mask = TCIF_TEXT;
6391		tci.pszText = (LPTSTR) lpszItem;
6392		return (int)::SendMessage(this->m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
6393	}
6394
6395	int AddItem(LPTCITEM pTabCtrlItem)
6396	{
6397		return InsertItem(GetItemCount(), pTabCtrlItem);
6398	}
6399
6400	int AddItem(UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
6401	{
6402		return InsertItem(GetItemCount(), mask, lpszItem, iImage, lParam);
6403	}
6404
6405	int AddItem(LPCTSTR lpszItem)
6406	{
6407		return InsertItem(GetItemCount(), lpszItem);
6408	}
6409
6410	BOOL DeleteItem(int nItem)
6411	{
6412		ATLASSERT(::IsWindow(this->m_hWnd));
6413		return (BOOL)::SendMessage(this->m_hWnd, TCM_DELETEITEM, nItem, 0L);
6414	}
6415
6416	BOOL DeleteAllItems()
6417	{
6418		ATLASSERT(::IsWindow(this->m_hWnd));
6419		return (BOOL)::SendMessage(this->m_hWnd, TCM_DELETEALLITEMS, 0, 0L);
6420	}
6421
6422	void AdjustRect(BOOL bLarger, LPRECT lpRect)
6423	{
6424		ATLASSERT(::IsWindow(this->m_hWnd));
6425		::SendMessage(this->m_hWnd, TCM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
6426	}
6427
6428	void RemoveImage(int nImage)
6429	{
6430		ATLASSERT(::IsWindow(this->m_hWnd));
6431		::SendMessage(this->m_hWnd, TCM_REMOVEIMAGE, nImage, 0L);
6432	}
6433
6434	int HitTest(TC_HITTESTINFO* pHitTestInfo) const
6435	{
6436		ATLASSERT(::IsWindow(this->m_hWnd));
6437		return (int)::SendMessage(this->m_hWnd, TCM_HITTEST, 0, (LPARAM)pHitTestInfo);
6438	}
6439
6440	void DeselectAll(BOOL bExcludeFocus = TRUE)
6441	{
6442		ATLASSERT(::IsWindow(this->m_hWnd));
6443		::SendMessage(this->m_hWnd, TCM_DESELECTALL, bExcludeFocus, 0L);
6444	}
6445
6446	BOOL HighlightItem(int nIndex, BOOL bHighlight = TRUE)
6447	{
6448		ATLASSERT(::IsWindow(this->m_hWnd));
6449		return (BOOL)::SendMessage(this->m_hWnd, TCM_HIGHLIGHTITEM, nIndex, MAKELPARAM(bHighlight, 0));
6450	}
6451};
6452
6453typedef CTabCtrlT<ATL::CWindow>   CTabCtrl;
6454
6455
6456///////////////////////////////////////////////////////////////////////////////
6457// CTrackBarCtrl
6458
6459template <class TBase>
6460class CTrackBarCtrlT : public TBase
6461{
6462public:
6463// Constructors
6464	CTrackBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6465	{ }
6466
6467	CTrackBarCtrlT< TBase >& operator =(HWND hWnd)
6468	{
6469		this->m_hWnd = hWnd;
6470		return *this;
6471	}
6472
6473	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6474			DWORD dwStyle = 0, DWORD dwExStyle = 0,
6475			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6476	{
6477		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6478	}
6479
6480// Attributes
6481	static LPCTSTR GetWndClassName()
6482	{
6483		return TRACKBAR_CLASS;
6484	}
6485
6486	int GetLineSize() const
6487	{
6488		ATLASSERT(::IsWindow(this->m_hWnd));
6489		return (int)::SendMessage(this->m_hWnd, TBM_GETLINESIZE, 0, 0L);
6490	}
6491
6492	int SetLineSize(int nSize)
6493	{
6494		ATLASSERT(::IsWindow(this->m_hWnd));
6495		return (int)::SendMessage(this->m_hWnd, TBM_SETLINESIZE, 0, nSize);
6496	}
6497
6498	int GetPageSize() const
6499	{
6500		ATLASSERT(::IsWindow(this->m_hWnd));
6501		return (int)::SendMessage(this->m_hWnd, TBM_GETPAGESIZE, 0, 0L);
6502	}
6503
6504	int SetPageSize(int nSize)
6505	{
6506		ATLASSERT(::IsWindow(this->m_hWnd));
6507		return (int)::SendMessage(this->m_hWnd, TBM_SETPAGESIZE, 0, nSize);
6508	}
6509
6510	int GetRangeMin() const
6511	{
6512		ATLASSERT(::IsWindow(this->m_hWnd));
6513		return (int)::SendMessage(this->m_hWnd, TBM_GETRANGEMIN, 0, 0L);
6514	}
6515
6516	void SetRangeMin(int nMin, BOOL bRedraw = FALSE)
6517	{
6518		ATLASSERT(::IsWindow(this->m_hWnd));
6519		::SendMessage(this->m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin);
6520	}
6521
6522	int GetRangeMax() const
6523	{
6524		ATLASSERT(::IsWindow(this->m_hWnd));
6525		return (int)::SendMessage(this->m_hWnd, TBM_GETRANGEMAX, 0, 0L);
6526	}
6527
6528	void SetRangeMax(int nMax, BOOL bRedraw = FALSE)
6529	{
6530		ATLASSERT(::IsWindow(this->m_hWnd));
6531		::SendMessage(this->m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax);
6532	}
6533
6534	void GetRange(int& nMin, int& nMax) const
6535	{
6536		nMin = GetRangeMin();
6537		nMax = GetRangeMax();
6538	}
6539
6540	void SetRange(int nMin, int nMax, BOOL bRedraw = TRUE)
6541	{
6542		ATLASSERT(::IsWindow(this->m_hWnd));
6543		::SendMessage(this->m_hWnd, TBM_SETRANGE, bRedraw, MAKELPARAM(nMin, nMax));
6544	}
6545
6546	int GetSelStart() const
6547	{
6548		ATLASSERT(::IsWindow(this->m_hWnd));
6549		return (int)::SendMessage(this->m_hWnd, TBM_GETSELSTART, 0, 0L);
6550	}
6551
6552	void SetSelStart(int nMin, BOOL bRedraw = FALSE)
6553	{
6554		ATLASSERT(::IsWindow(this->m_hWnd));
6555		::SendMessage(this->m_hWnd, TBM_SETSELSTART, bRedraw, (LPARAM)nMin);
6556	}
6557
6558	int GetSelEnd() const
6559	{
6560		ATLASSERT(::IsWindow(this->m_hWnd));
6561		return (int)::SendMessage(this->m_hWnd, TBM_GETSELEND, 0, 0L);
6562	}
6563
6564	void SetSelEnd(int nMax, BOOL bRedraw = FALSE)
6565	{
6566		ATLASSERT(::IsWindow(this->m_hWnd));
6567		::SendMessage(this->m_hWnd, TBM_SETSELEND, bRedraw, (LPARAM)nMax);
6568	}
6569
6570	void GetSelection(int& nMin, int& nMax) const
6571	{
6572		nMin = GetSelStart();
6573		nMax = GetSelEnd();
6574	}
6575
6576	void SetSelection(int nMin, int nMax, BOOL bRedraw = TRUE)
6577	{
6578		SetSelStart(nMin, FALSE);
6579		SetSelEnd(nMax, bRedraw);
6580	}
6581
6582	void GetChannelRect(LPRECT lprc) const
6583	{
6584		ATLASSERT(::IsWindow(this->m_hWnd));
6585		::SendMessage(this->m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)lprc);
6586	}
6587
6588	void GetThumbRect(LPRECT lprc) const
6589	{
6590		ATLASSERT(::IsWindow(this->m_hWnd));
6591		::SendMessage(this->m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)lprc);
6592	}
6593
6594	int GetPos() const
6595	{
6596		ATLASSERT(::IsWindow(this->m_hWnd));
6597		return (int)::SendMessage(this->m_hWnd, TBM_GETPOS, 0, 0L);
6598	}
6599
6600	void SetPos(int nPos)
6601	{
6602		ATLASSERT(::IsWindow(this->m_hWnd));
6603		::SendMessage(this->m_hWnd, TBM_SETPOS, TRUE, nPos);
6604	}
6605
6606	UINT GetNumTics() const
6607	{
6608		ATLASSERT(::IsWindow(this->m_hWnd));
6609		return (UINT)::SendMessage(this->m_hWnd, TBM_GETNUMTICS, 0, 0L);
6610	}
6611
6612	DWORD* GetTicArray() const
6613	{
6614		ATLASSERT(::IsWindow(this->m_hWnd));
6615		return (DWORD*)::SendMessage(this->m_hWnd, TBM_GETPTICS, 0, 0L);
6616	}
6617
6618	int GetTic(int nTic) const
6619	{
6620		ATLASSERT(::IsWindow(this->m_hWnd));
6621		return (int)::SendMessage(this->m_hWnd, TBM_GETTIC, nTic, 0L);
6622	}
6623
6624	BOOL SetTic(int nTic)
6625	{
6626		ATLASSERT(::IsWindow(this->m_hWnd));
6627		return (BOOL)::SendMessage(this->m_hWnd, TBM_SETTIC, 0, nTic);
6628	}
6629
6630	int GetTicPos(int nTic) const
6631	{
6632		ATLASSERT(::IsWindow(this->m_hWnd));
6633		return (int)::SendMessage(this->m_hWnd, TBM_GETTICPOS, nTic, 0L);
6634	}
6635
6636	void SetTicFreq(int nFreq)
6637	{
6638		ATLASSERT(::IsWindow(this->m_hWnd));
6639		::SendMessage(this->m_hWnd, TBM_SETTICFREQ, nFreq, 0L);
6640	}
6641
6642	int GetThumbLength() const
6643	{
6644		ATLASSERT(::IsWindow(this->m_hWnd));
6645		return (int)::SendMessage(this->m_hWnd, TBM_GETTHUMBLENGTH, 0, 0L);
6646	}
6647
6648	void SetThumbLength(int nLength)
6649	{
6650		ATLASSERT(::IsWindow(this->m_hWnd));
6651		::SendMessage(this->m_hWnd, TBM_SETTHUMBLENGTH, nLength, 0L);
6652	}
6653
6654	void SetSel(int nStart, int nEnd, BOOL bRedraw = TRUE)
6655	{
6656		ATLASSERT(::IsWindow(this->m_hWnd));
6657		ATLASSERT((this->GetStyle() & TBS_ENABLESELRANGE) != 0);
6658		::SendMessage(this->m_hWnd, TBM_SETSEL, bRedraw, MAKELPARAM(nStart, nEnd));
6659	}
6660
6661	ATL::CWindow GetBuddy(BOOL bLeft = TRUE) const
6662	{
6663		ATLASSERT(::IsWindow(this->m_hWnd));
6664		return ATL::CWindow((HWND)::SendMessage(this->m_hWnd, TBM_GETBUDDY, bLeft, 0L));
6665	}
6666
6667	ATL::CWindow SetBuddy(HWND hWndBuddy, BOOL bLeft = TRUE)
6668	{
6669		ATLASSERT(::IsWindow(this->m_hWnd));
6670		return ATL::CWindow((HWND)::SendMessage(this->m_hWnd, TBM_SETBUDDY, bLeft, (LPARAM)hWndBuddy));
6671	}
6672
6673	CToolTipCtrl GetToolTips() const
6674	{
6675		ATLASSERT(::IsWindow(this->m_hWnd));
6676		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, TBM_GETTOOLTIPS, 0, 0L));
6677	}
6678
6679	void SetToolTips(HWND hWndTT)
6680	{
6681		ATLASSERT(::IsWindow(this->m_hWnd));
6682		::SendMessage(this->m_hWnd, TBM_SETTOOLTIPS, (WPARAM)hWndTT, 0L);
6683	}
6684
6685	int SetTipSide(int nSide)
6686	{
6687		ATLASSERT(::IsWindow(this->m_hWnd));
6688		return (int)::SendMessage(this->m_hWnd, TBM_SETTIPSIDE, nSide, 0L);
6689	}
6690
6691	BOOL GetUnicodeFormat() const
6692	{
6693		ATLASSERT(::IsWindow(this->m_hWnd));
6694		return (BOOL)::SendMessage(this->m_hWnd, TBM_GETUNICODEFORMAT, 0, 0L);
6695	}
6696
6697	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6698	{
6699		ATLASSERT(::IsWindow(this->m_hWnd));
6700		return (BOOL)::SendMessage(this->m_hWnd, TBM_SETUNICODEFORMAT, bUnicode, 0L);
6701	}
6702
6703// Operations
6704	void ClearSel(BOOL bRedraw = FALSE)
6705	{
6706		ATLASSERT(::IsWindow(this->m_hWnd));
6707		::SendMessage(this->m_hWnd, TBM_CLEARSEL, bRedraw, 0L);
6708	}
6709
6710	void VerifyPos()
6711	{
6712		ATLASSERT(::IsWindow(this->m_hWnd));
6713		::SendMessage(this->m_hWnd, TBM_SETPOS, FALSE, 0L);
6714	}
6715
6716	void ClearTics(BOOL bRedraw = FALSE)
6717	{
6718		ATLASSERT(::IsWindow(this->m_hWnd));
6719		::SendMessage(this->m_hWnd, TBM_CLEARTICS, bRedraw, 0L);
6720	}
6721};
6722
6723typedef CTrackBarCtrlT<ATL::CWindow>   CTrackBarCtrl;
6724
6725
6726///////////////////////////////////////////////////////////////////////////////
6727// CUpDownCtrl
6728
6729template <class TBase>
6730class CUpDownCtrlT : public TBase
6731{
6732public:
6733// Constructors
6734	CUpDownCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6735	{ }
6736
6737	CUpDownCtrlT< TBase >& operator =(HWND hWnd)
6738	{
6739		this->m_hWnd = hWnd;
6740		return *this;
6741	}
6742
6743	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6744			DWORD dwStyle = 0, DWORD dwExStyle = 0,
6745			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6746	{
6747		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6748	}
6749
6750// Attributes
6751	static LPCTSTR GetWndClassName()
6752	{
6753		return UPDOWN_CLASS;
6754	}
6755
6756	UINT GetAccel(int nAccel, UDACCEL* pAccel) const
6757	{
6758		ATLASSERT(::IsWindow(this->m_hWnd));
6759		return (UINT)LOWORD(::SendMessage(this->m_hWnd, UDM_GETACCEL, nAccel, (LPARAM)pAccel));
6760	}
6761
6762	BOOL SetAccel(int nAccel, UDACCEL* pAccel)
6763	{
6764		ATLASSERT(::IsWindow(this->m_hWnd));
6765		return (BOOL)LOWORD(::SendMessage(this->m_hWnd, UDM_SETACCEL, nAccel, (LPARAM)pAccel));
6766	}
6767
6768	UINT GetBase() const
6769	{
6770		ATLASSERT(::IsWindow(this->m_hWnd));
6771		return (UINT)LOWORD(::SendMessage(this->m_hWnd, UDM_GETBASE, 0, 0L));
6772	}
6773
6774	int SetBase(int nBase)
6775	{
6776		ATLASSERT(::IsWindow(this->m_hWnd));
6777		return (int)::SendMessage(this->m_hWnd, UDM_SETBASE, nBase, 0L);
6778	}
6779
6780	ATL::CWindow GetBuddy() const
6781	{
6782		ATLASSERT(::IsWindow(this->m_hWnd));
6783		return ATL::CWindow((HWND)::SendMessage(this->m_hWnd, UDM_GETBUDDY, 0, 0L));
6784	}
6785
6786	ATL::CWindow SetBuddy(HWND hWndBuddy)
6787	{
6788		ATLASSERT(::IsWindow(this->m_hWnd));
6789		return ATL::CWindow((HWND)::SendMessage(this->m_hWnd, UDM_SETBUDDY, (WPARAM)hWndBuddy, 0L));
6790	}
6791
6792	int GetPos(LPBOOL lpbError = NULL) const
6793	{
6794		ATLASSERT(::IsWindow(this->m_hWnd));
6795		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, UDM_GETPOS, 0, 0L);
6796		// Note: Seems that Windows always sets error to TRUE if
6797		// UDS_SETBUDDYINT style is not used
6798		if(lpbError != NULL)
6799			*lpbError = (HIWORD(dwRet) != 0) ? TRUE : FALSE;
6800		return (int)(short)LOWORD(dwRet);
6801	}
6802
6803	int SetPos(int nPos)
6804	{
6805		ATLASSERT(::IsWindow(this->m_hWnd));
6806		return (int)(short)LOWORD(::SendMessage(this->m_hWnd, UDM_SETPOS, 0, MAKELPARAM(nPos, 0)));
6807	}
6808
6809	DWORD GetRange() const
6810	{
6811		ATLASSERT(::IsWindow(this->m_hWnd));
6812		return (DWORD)::SendMessage(this->m_hWnd, UDM_GETRANGE, 0, 0L);
6813	}
6814
6815	void GetRange(int& nLower, int& nUpper) const
6816	{
6817		ATLASSERT(::IsWindow(this->m_hWnd));
6818		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, UDM_GETRANGE, 0, 0L);
6819		nLower = (int)(short)HIWORD(dwRet);
6820		nUpper = (int)(short)LOWORD(dwRet);
6821	}
6822
6823	void SetRange(int nLower, int nUpper)
6824	{
6825		ATLASSERT(::IsWindow(this->m_hWnd));
6826		::SendMessage(this->m_hWnd, UDM_SETRANGE, 0, MAKELPARAM(nUpper, nLower));
6827	}
6828
6829	void SetRange32(int nLower, int nUpper)
6830	{
6831		ATLASSERT(::IsWindow(this->m_hWnd));
6832		::SendMessage(this->m_hWnd, UDM_SETRANGE32, nLower, nUpper);
6833	}
6834
6835	void GetRange32(int& nLower, int& nUpper) const
6836	{
6837		ATLASSERT(::IsWindow(this->m_hWnd));
6838		::SendMessage(this->m_hWnd, UDM_GETRANGE32, (WPARAM)&nLower, (LPARAM)&nUpper);
6839	}
6840
6841	BOOL GetUnicodeFormat() const
6842	{
6843		ATLASSERT(::IsWindow(this->m_hWnd));
6844		return (BOOL)::SendMessage(this->m_hWnd, UDM_GETUNICODEFORMAT, 0, 0L);
6845	}
6846
6847	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6848	{
6849		ATLASSERT(::IsWindow(this->m_hWnd));
6850		return (BOOL)::SendMessage(this->m_hWnd, UDM_SETUNICODEFORMAT, bUnicode, 0L);
6851	}
6852
6853	int GetPos32(LPBOOL lpbError = NULL) const
6854	{
6855		ATLASSERT(::IsWindow(this->m_hWnd));
6856		// Note: Seems that Windows always sets error to TRUE if
6857		// UDS_SETBUDDYINT style is not used
6858		return (int)::SendMessage(this->m_hWnd, UDM_GETPOS32, 0, (LPARAM)lpbError);
6859	}
6860
6861	int SetPos32(int nPos)
6862	{
6863		ATLASSERT(::IsWindow(this->m_hWnd));
6864		return (int)::SendMessage(this->m_hWnd, UDM_SETPOS32, 0, (LPARAM)nPos);
6865	}
6866};
6867
6868typedef CUpDownCtrlT<ATL::CWindow>   CUpDownCtrl;
6869
6870
6871///////////////////////////////////////////////////////////////////////////////
6872// CProgressBarCtrl
6873
6874template <class TBase>
6875class CProgressBarCtrlT : public TBase
6876{
6877public:
6878// Constructors
6879	CProgressBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6880	{ }
6881
6882	CProgressBarCtrlT< TBase >& operator =(HWND hWnd)
6883	{
6884		this->m_hWnd = hWnd;
6885		return *this;
6886	}
6887
6888	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6889			DWORD dwStyle = 0, DWORD dwExStyle = 0,
6890			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6891	{
6892		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6893	}
6894
6895// Attributes
6896	static LPCTSTR GetWndClassName()
6897	{
6898		return PROGRESS_CLASS;
6899	}
6900
6901	DWORD SetRange(int nLower, int nUpper)
6902	{
6903		ATLASSERT(::IsWindow(this->m_hWnd));
6904		return (DWORD)::SendMessage(this->m_hWnd, PBM_SETRANGE, 0, MAKELPARAM(nLower, nUpper));
6905	}
6906
6907	int SetPos(int nPos)
6908	{
6909		ATLASSERT(::IsWindow(this->m_hWnd));
6910		return (int)(short)LOWORD(::SendMessage(this->m_hWnd, PBM_SETPOS, nPos, 0L));
6911	}
6912
6913	int OffsetPos(int nPos)
6914	{
6915		ATLASSERT(::IsWindow(this->m_hWnd));
6916		return (int)(short)LOWORD(::SendMessage(this->m_hWnd, PBM_DELTAPOS, nPos, 0L));
6917	}
6918
6919	int SetStep(int nStep)
6920	{
6921		ATLASSERT(::IsWindow(this->m_hWnd));
6922		return (int)(short)LOWORD(::SendMessage(this->m_hWnd, PBM_SETSTEP, nStep, 0L));
6923	}
6924
6925	UINT GetPos() const
6926	{
6927		ATLASSERT(::IsWindow(this->m_hWnd));
6928		return (UINT)::SendMessage(this->m_hWnd, PBM_GETPOS, 0, 0L);
6929	}
6930
6931	void GetRange(PPBRANGE pPBRange) const
6932	{
6933		ATLASSERT(::IsWindow(this->m_hWnd));
6934		ATLASSERT(pPBRange != NULL);
6935		::SendMessage(this->m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)pPBRange);
6936	}
6937
6938	void GetRange(int& nLower, int& nUpper) const
6939	{
6940		ATLASSERT(::IsWindow(this->m_hWnd));
6941		PBRANGE range = {};
6942		::SendMessage(this->m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)&range);
6943		nLower = range.iLow;
6944		nUpper = range.iHigh;
6945	}
6946
6947	int GetRangeLimit(BOOL bLowLimit) const
6948	{
6949		ATLASSERT(::IsWindow(this->m_hWnd));
6950		return (int)::SendMessage(this->m_hWnd, PBM_GETRANGE, bLowLimit, (LPARAM)NULL);
6951	}
6952
6953	DWORD SetRange32(int nMin, int nMax)
6954	{
6955		ATLASSERT(::IsWindow(this->m_hWnd));
6956		return (DWORD)::SendMessage(this->m_hWnd, PBM_SETRANGE32, nMin, nMax);
6957	}
6958
6959	COLORREF SetBarColor(COLORREF clr)
6960	{
6961		ATLASSERT(::IsWindow(this->m_hWnd));
6962		return (COLORREF)::SendMessage(this->m_hWnd, PBM_SETBARCOLOR, 0, (LPARAM)clr);
6963	}
6964
6965	COLORREF SetBkColor(COLORREF clr)
6966	{
6967		ATLASSERT(::IsWindow(this->m_hWnd));
6968		return (COLORREF)::SendMessage(this->m_hWnd, PBM_SETBKCOLOR, 0, (LPARAM)clr);
6969	}
6970
6971#ifdef PBM_SETMARQUEE
6972	BOOL SetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U)
6973	{
6974		ATLASSERT(::IsWindow(this->m_hWnd));
6975		return (BOOL)::SendMessage(this->m_hWnd, PBM_SETMARQUEE, (WPARAM)bMarquee, (LPARAM)uUpdateTime);
6976	}
6977#endif
6978
6979#if (_WIN32_WINNT >= 0x0600)
6980	int GetStep() const
6981	{
6982		ATLASSERT(::IsWindow(this->m_hWnd));
6983		return (int)::SendMessage(this->m_hWnd, PBM_GETSTEP, 0, 0L);
6984	}
6985
6986	COLORREF GetBkColor() const
6987	{
6988		ATLASSERT(::IsWindow(this->m_hWnd));
6989		return (COLORREF)::SendMessage(this->m_hWnd, PBM_GETBKCOLOR, 0, 0L);
6990	}
6991
6992	COLORREF GetBarColor() const
6993	{
6994		ATLASSERT(::IsWindow(this->m_hWnd));
6995		return (COLORREF)::SendMessage(this->m_hWnd, PBM_GETBARCOLOR, 0, 0L);
6996	}
6997
6998	int GetState() const
6999	{
7000		ATLASSERT(::IsWindow(this->m_hWnd));
7001		return (int)::SendMessage(this->m_hWnd, PBM_GETSTATE, 0, 0L);
7002	}
7003
7004	int SetState(int nState)
7005	{
7006		ATLASSERT(::IsWindow(this->m_hWnd));
7007		return (int)::SendMessage(this->m_hWnd, PBM_SETSTATE, nState, 0L);
7008	}
7009#endif // (_WIN32_WINNT >= 0x0600)
7010
7011// Operations
7012	int StepIt()
7013	{
7014		ATLASSERT(::IsWindow(this->m_hWnd));
7015		return (int)(short)LOWORD(::SendMessage(this->m_hWnd, PBM_STEPIT, 0, 0L));
7016	}
7017};
7018
7019typedef CProgressBarCtrlT<ATL::CWindow>   CProgressBarCtrl;
7020
7021
7022///////////////////////////////////////////////////////////////////////////////
7023// CHotKeyCtrl
7024
7025template <class TBase>
7026class CHotKeyCtrlT : public TBase
7027{
7028public:
7029// Constructors
7030	CHotKeyCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7031	{ }
7032
7033	CHotKeyCtrlT< TBase >& operator =(HWND hWnd)
7034	{
7035		this->m_hWnd = hWnd;
7036		return *this;
7037	}
7038
7039	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7040			DWORD dwStyle = 0, DWORD dwExStyle = 0,
7041			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7042	{
7043		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7044	}
7045
7046// Attributes
7047	static LPCTSTR GetWndClassName()
7048	{
7049		return HOTKEY_CLASS;
7050	}
7051
7052	DWORD GetHotKey() const
7053	{
7054		ATLASSERT(::IsWindow(this->m_hWnd));
7055		return (DWORD)::SendMessage(this->m_hWnd, HKM_GETHOTKEY, 0, 0L);
7056	}
7057
7058	void GetHotKey(WORD &wVirtualKeyCode, WORD &wModifiers) const
7059	{
7060		ATLASSERT(::IsWindow(this->m_hWnd));
7061		DWORD dw = (DWORD)::SendMessage(this->m_hWnd, HKM_GETHOTKEY, 0, 0L);
7062		wVirtualKeyCode = LOBYTE(LOWORD(dw));
7063		wModifiers = HIBYTE(LOWORD(dw));
7064	}
7065
7066	void SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
7067	{
7068		ATLASSERT(::IsWindow(this->m_hWnd));
7069		::SendMessage(this->m_hWnd, HKM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0L);
7070	}
7071
7072	void SetRules(WORD wInvalidComb, WORD wModifiers)
7073	{
7074		ATLASSERT(::IsWindow(this->m_hWnd));
7075		::SendMessage(this->m_hWnd, HKM_SETRULES, wInvalidComb, MAKELPARAM(wModifiers, 0));
7076	}
7077};
7078
7079typedef CHotKeyCtrlT<ATL::CWindow>   CHotKeyCtrl;
7080
7081
7082///////////////////////////////////////////////////////////////////////////////
7083// CAnimateCtrl
7084
7085template <class TBase>
7086class CAnimateCtrlT : public TBase
7087{
7088public:
7089// Constructors
7090	CAnimateCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7091	{ }
7092
7093	CAnimateCtrlT< TBase >& operator =(HWND hWnd)
7094	{
7095		this->m_hWnd = hWnd;
7096		return *this;
7097	}
7098
7099	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7100			DWORD dwStyle = 0, DWORD dwExStyle = 0,
7101			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7102	{
7103		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7104	}
7105
7106// Attributes
7107	static LPCTSTR GetWndClassName()
7108	{
7109		return ANIMATE_CLASS;
7110	}
7111
7112// Operations
7113	BOOL Open(ATL::_U_STRINGorID FileName)
7114	{
7115		ATLASSERT(::IsWindow(this->m_hWnd));
7116		return (BOOL)::SendMessage(this->m_hWnd, ACM_OPEN, 0, (LPARAM)FileName.m_lpstr);
7117	}
7118
7119	BOOL Play(UINT nFrom, UINT nTo, UINT nRep)
7120	{
7121		ATLASSERT(::IsWindow(this->m_hWnd));
7122		return (BOOL)::SendMessage(this->m_hWnd, ACM_PLAY, nRep, MAKELPARAM(nFrom, nTo));
7123	}
7124
7125	BOOL Stop()
7126	{
7127		ATLASSERT(::IsWindow(this->m_hWnd));
7128		return (BOOL)::SendMessage(this->m_hWnd, ACM_STOP, 0, 0L);
7129	}
7130
7131	BOOL Close()
7132	{
7133		ATLASSERT(::IsWindow(this->m_hWnd));
7134		return (BOOL)::SendMessage(this->m_hWnd, ACM_OPEN, 0, 0L);
7135	}
7136
7137	BOOL Seek(UINT nTo)
7138	{
7139		ATLASSERT(::IsWindow(this->m_hWnd));
7140		return (BOOL)::SendMessage(this->m_hWnd, ACM_PLAY, 0, MAKELPARAM(nTo, nTo));
7141	}
7142
7143	// Vista only
7144	BOOL IsPlaying() const
7145	{
7146		ATLASSERT(::IsWindow(this->m_hWnd));
7147		return (BOOL)::SendMessage(this->m_hWnd, ACM_ISPLAYING, 0, 0L);
7148	}
7149};
7150
7151typedef CAnimateCtrlT<ATL::CWindow>   CAnimateCtrl;
7152
7153
7154///////////////////////////////////////////////////////////////////////////////
7155// CRichEditCtrl
7156
7157#if !defined(_UNICODE) && (_RICHEDIT_VER >= 0x0500)
7158  #undef MSFTEDIT_CLASS
7159  #define MSFTEDIT_CLASS	"RICHEDIT50W"
7160#endif
7161
7162template <class TBase>
7163class CRichEditCtrlT : public TBase
7164{
7165public:
7166// Constructors
7167	CRichEditCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7168	{ }
7169
7170	CRichEditCtrlT< TBase >& operator =(HWND hWnd)
7171	{
7172		this->m_hWnd = hWnd;
7173		return *this;
7174	}
7175
7176	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7177			DWORD dwStyle = 0, DWORD dwExStyle = 0,
7178			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7179	{
7180		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7181	}
7182
7183// Attributes
7184	static LPCTSTR GetWndClassName()
7185	{
7186#if (_RICHEDIT_VER >= 0x0500)
7187		return MSFTEDIT_CLASS;
7188#else
7189		return RICHEDIT_CLASS;
7190#endif
7191	}
7192
7193	static LPCTSTR GetLibraryName()
7194	{
7195#if (_RICHEDIT_VER >= 0x0500)
7196		return _T("MSFTEDIT.DLL");
7197#else
7198		return _T("RICHED20.DLL");
7199#endif
7200	}
7201
7202	int GetLineCount() const
7203	{
7204		ATLASSERT(::IsWindow(this->m_hWnd));
7205		return (int)::SendMessage(this->m_hWnd, EM_GETLINECOUNT, 0, 0L);
7206	}
7207
7208	BOOL GetModify() const
7209	{
7210		ATLASSERT(::IsWindow(this->m_hWnd));
7211		return (BOOL)::SendMessage(this->m_hWnd, EM_GETMODIFY, 0, 0L);
7212	}
7213
7214	void SetModify(BOOL bModified = TRUE)
7215	{
7216		ATLASSERT(::IsWindow(this->m_hWnd));
7217		::SendMessage(this->m_hWnd, EM_SETMODIFY, bModified, 0L);
7218	}
7219
7220	void GetRect(LPRECT lpRect) const
7221	{
7222		ATLASSERT(::IsWindow(this->m_hWnd));
7223		::SendMessage(this->m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
7224	}
7225
7226	DWORD GetOptions() const
7227	{
7228		ATLASSERT(::IsWindow(this->m_hWnd));
7229		return (DWORD)::SendMessage(this->m_hWnd, EM_GETOPTIONS, 0, 0L);
7230	}
7231
7232	DWORD SetOptions(WORD wOperation, DWORD dwOptions)
7233	{
7234		ATLASSERT(::IsWindow(this->m_hWnd));
7235		return (DWORD)::SendMessage(this->m_hWnd, EM_SETOPTIONS, wOperation, dwOptions);
7236	}
7237
7238	// NOTE: first word in lpszBuffer must contain the size of the buffer!
7239	int GetLine(int nIndex, LPTSTR lpszBuffer) const
7240	{
7241		ATLASSERT(::IsWindow(this->m_hWnd));
7242		return (int)::SendMessage(this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
7243	}
7244
7245	int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
7246	{
7247		ATLASSERT(::IsWindow(this->m_hWnd));
7248		*(LPWORD)lpszBuffer = (WORD)nMaxLength;
7249		return (int)::SendMessage(this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
7250	}
7251
7252	BOOL CanUndo() const
7253	{
7254		ATLASSERT(::IsWindow(this->m_hWnd));
7255		return (BOOL)::SendMessage(this->m_hWnd, EM_CANUNDO, 0, 0L);
7256	}
7257
7258	BOOL CanPaste(UINT nFormat = 0) const
7259	{
7260		ATLASSERT(::IsWindow(this->m_hWnd));
7261		return (BOOL)::SendMessage(this->m_hWnd, EM_CANPASTE, nFormat, 0L);
7262	}
7263
7264	void GetSel(LONG& nStartChar, LONG& nEndChar) const
7265	{
7266		ATLASSERT(::IsWindow(this->m_hWnd));
7267		CHARRANGE cr = {};
7268		::SendMessage(this->m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7269		nStartChar = cr.cpMin;
7270		nEndChar = cr.cpMax;
7271	}
7272
7273	void GetSel(CHARRANGE &cr) const
7274	{
7275		ATLASSERT(::IsWindow(this->m_hWnd));
7276		::SendMessage(this->m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7277	}
7278
7279	int SetSel(LONG nStartChar, LONG nEndChar)
7280	{
7281		ATLASSERT(::IsWindow(this->m_hWnd));
7282		CHARRANGE cr = { nStartChar, nEndChar };
7283		return (int)::SendMessage(this->m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
7284	}
7285
7286	int SetSel(CHARRANGE &cr)
7287	{
7288		ATLASSERT(::IsWindow(this->m_hWnd));
7289		return (int)::SendMessage(this->m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
7290	}
7291
7292	int SetSelAll()
7293	{
7294		return SetSel(0, -1);
7295	}
7296
7297	int SetSelNone()
7298	{
7299		return SetSel(-1, 0);
7300	}
7301
7302	DWORD GetDefaultCharFormat(CHARFORMAT& cf) const
7303	{
7304		ATLASSERT(::IsWindow(this->m_hWnd));
7305		cf.cbSize = sizeof(CHARFORMAT);
7306		return (DWORD)::SendMessage(this->m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
7307	}
7308
7309	DWORD GetSelectionCharFormat(CHARFORMAT& cf) const
7310	{
7311		ATLASSERT(::IsWindow(this->m_hWnd));
7312		cf.cbSize = sizeof(CHARFORMAT);
7313		return (DWORD)::SendMessage(this->m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
7314	}
7315
7316	DWORD GetEventMask() const
7317	{
7318		ATLASSERT(::IsWindow(this->m_hWnd));
7319		return (DWORD)::SendMessage(this->m_hWnd, EM_GETEVENTMASK, 0, 0L);
7320	}
7321
7322	LONG GetLimitText() const
7323	{
7324		ATLASSERT(::IsWindow(this->m_hWnd));
7325		return (LONG)::SendMessage(this->m_hWnd, EM_GETLIMITTEXT, 0, 0L);
7326	}
7327
7328	DWORD GetParaFormat(PARAFORMAT& pf) const
7329	{
7330		ATLASSERT(::IsWindow(this->m_hWnd));
7331		pf.cbSize = sizeof(PARAFORMAT);
7332		return (DWORD)::SendMessage(this->m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
7333	}
7334
7335	LONG GetSelText(LPTSTR lpstrBuff) const
7336	{
7337		ATLASSERT(::IsWindow(this->m_hWnd));
7338		return (LONG)::SendMessage(this->m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff);
7339	}
7340
7341	BOOL GetSelTextBSTR(BSTR& bstrText) const
7342	{
7343		USES_CONVERSION;
7344		ATLASSERT(::IsWindow(this->m_hWnd));
7345		ATLASSERT(bstrText == NULL);
7346
7347		CHARRANGE cr = {};
7348		::SendMessage(this->m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7349
7350		ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
7351		LPTSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
7352		if(lpstrText == NULL)
7353			return FALSE;
7354		if(::SendMessage(this->m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0)
7355			return FALSE;
7356
7357		bstrText = ::SysAllocString(T2W(lpstrText));
7358
7359		return (bstrText != NULL) ? TRUE : FALSE;
7360	}
7361
7362#ifdef __ATLSTR_H__
7363	LONG GetSelText(ATL::CString& strText) const
7364	{
7365		ATLASSERT(::IsWindow(this->m_hWnd));
7366
7367		CHARRANGE cr = {};
7368		::SendMessage(this->m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7369
7370		LONG lLen = 0;
7371		LPTSTR lpstrText = strText.GetBufferSetLength(cr.cpMax - cr.cpMin);
7372		if(lpstrText != NULL)
7373		{
7374			lLen = (LONG)::SendMessage(this->m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText);
7375			strText.ReleaseBuffer();
7376		}
7377
7378		return lLen;
7379	}
7380#endif // __ATLSTR_H__
7381
7382	WORD GetSelectionType() const
7383	{
7384		ATLASSERT(::IsWindow(this->m_hWnd));
7385		return (WORD)::SendMessage(this->m_hWnd, EM_SELECTIONTYPE, 0, 0L);
7386	}
7387
7388	COLORREF SetBackgroundColor(COLORREF cr)
7389	{
7390		ATLASSERT(::IsWindow(this->m_hWnd));
7391		return (COLORREF)::SendMessage(this->m_hWnd, EM_SETBKGNDCOLOR, 0, cr);
7392	}
7393
7394	COLORREF SetBackgroundColor()   // sets to system background
7395	{
7396		ATLASSERT(::IsWindow(this->m_hWnd));
7397		return (COLORREF)::SendMessage(this->m_hWnd, EM_SETBKGNDCOLOR, 1, 0);
7398	}
7399
7400	BOOL SetCharFormat(CHARFORMAT& cf, WORD wFlags)
7401	{
7402		ATLASSERT(::IsWindow(this->m_hWnd));
7403		cf.cbSize = sizeof(CHARFORMAT);
7404		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
7405	}
7406
7407	BOOL SetDefaultCharFormat(CHARFORMAT& cf)
7408	{
7409		ATLASSERT(::IsWindow(this->m_hWnd));
7410		cf.cbSize = sizeof(CHARFORMAT);
7411		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
7412	}
7413
7414	BOOL SetSelectionCharFormat(CHARFORMAT& cf)
7415	{
7416		ATLASSERT(::IsWindow(this->m_hWnd));
7417		cf.cbSize = sizeof(CHARFORMAT);
7418		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
7419	}
7420
7421	BOOL SetWordCharFormat(CHARFORMAT& cf)
7422	{
7423		ATLASSERT(::IsWindow(this->m_hWnd));
7424		cf.cbSize = sizeof(CHARFORMAT);
7425		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
7426	}
7427
7428	DWORD SetEventMask(DWORD dwEventMask)
7429	{
7430		ATLASSERT(::IsWindow(this->m_hWnd));
7431		return (DWORD)::SendMessage(this->m_hWnd, EM_SETEVENTMASK, 0, dwEventMask);
7432	}
7433
7434	BOOL SetParaFormat(PARAFORMAT& pf)
7435	{
7436		ATLASSERT(::IsWindow(this->m_hWnd));
7437		pf.cbSize = sizeof(PARAFORMAT);
7438		return (BOOL)::SendMessage(this->m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
7439	}
7440
7441	BOOL SetTargetDevice(HDC hDC, int cxLineWidth)
7442	{
7443		ATLASSERT(::IsWindow(this->m_hWnd));
7444		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTARGETDEVICE, (WPARAM)hDC, cxLineWidth);
7445	}
7446
7447	int GetTextLength() const
7448	{
7449		ATLASSERT(::IsWindow(this->m_hWnd));
7450		return (int)::SendMessage(this->m_hWnd, WM_GETTEXTLENGTH, 0, 0L);
7451	}
7452
7453	BOOL SetReadOnly(BOOL bReadOnly = TRUE)
7454	{
7455		ATLASSERT(::IsWindow(this->m_hWnd));
7456		return (BOOL)::SendMessage(this->m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
7457	}
7458
7459	int GetFirstVisibleLine() const
7460	{
7461		ATLASSERT(::IsWindow(this->m_hWnd));
7462		return (int)::SendMessage(this->m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
7463	}
7464
7465	int GetTextRange(TEXTRANGE* pTextRange) const
7466	{
7467		ATLASSERT(::IsWindow(this->m_hWnd));
7468		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)pTextRange);
7469	}
7470
7471	int GetTextRange(LONG nStartChar, LONG nEndChar, LPTSTR lpstrText) const
7472	{
7473		ATLASSERT(::IsWindow(this->m_hWnd));
7474		TEXTRANGE tr = {};
7475		tr.chrg.cpMin = nStartChar;
7476		tr.chrg.cpMax = nEndChar;
7477		tr.lpstrText = lpstrText;
7478		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
7479	}
7480
7481	DWORD GetDefaultCharFormat(CHARFORMAT2& cf) const
7482	{
7483		ATLASSERT(::IsWindow(this->m_hWnd));
7484		cf.cbSize = sizeof(CHARFORMAT2);
7485		return (DWORD)::SendMessage(this->m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
7486	}
7487
7488	BOOL SetCharFormat(CHARFORMAT2& cf, WORD wFlags)
7489	{
7490		ATLASSERT(::IsWindow(this->m_hWnd));
7491		cf.cbSize = sizeof(CHARFORMAT2);
7492		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
7493	}
7494
7495	BOOL SetDefaultCharFormat(CHARFORMAT2& cf)
7496	{
7497		ATLASSERT(::IsWindow(this->m_hWnd));
7498		cf.cbSize = sizeof(CHARFORMAT2);
7499		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
7500	}
7501
7502	DWORD GetSelectionCharFormat(CHARFORMAT2& cf) const
7503	{
7504		ATLASSERT(::IsWindow(this->m_hWnd));
7505		cf.cbSize = sizeof(CHARFORMAT2);
7506		return (DWORD)::SendMessage(this->m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
7507	}
7508
7509	BOOL SetSelectionCharFormat(CHARFORMAT2& cf)
7510	{
7511		ATLASSERT(::IsWindow(this->m_hWnd));
7512		cf.cbSize = sizeof(CHARFORMAT2);
7513		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
7514	}
7515
7516	BOOL SetWordCharFormat(CHARFORMAT2& cf)
7517	{
7518		ATLASSERT(::IsWindow(this->m_hWnd));
7519		cf.cbSize = sizeof(CHARFORMAT2);
7520		return (BOOL)::SendMessage(this->m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
7521	}
7522
7523	DWORD GetParaFormat(PARAFORMAT2& pf) const
7524	{
7525		ATLASSERT(::IsWindow(this->m_hWnd));
7526		pf.cbSize = sizeof(PARAFORMAT2);
7527		return (DWORD)::SendMessage(this->m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
7528	}
7529
7530	BOOL SetParaFormat(PARAFORMAT2& pf)
7531	{
7532		ATLASSERT(::IsWindow(this->m_hWnd));
7533		pf.cbSize = sizeof(PARAFORMAT2);
7534		return (BOOL)::SendMessage(this->m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
7535	}
7536
7537	TEXTMODE GetTextMode() const
7538	{
7539		ATLASSERT(::IsWindow(this->m_hWnd));
7540		return (TEXTMODE)::SendMessage(this->m_hWnd, EM_GETTEXTMODE, 0, 0L);
7541	}
7542
7543	BOOL SetTextMode(TEXTMODE enumTextMode)
7544	{
7545		ATLASSERT(::IsWindow(this->m_hWnd));
7546		return !(BOOL)::SendMessage(this->m_hWnd, EM_SETTEXTMODE, enumTextMode, 0L);
7547	}
7548
7549	UNDONAMEID GetUndoName() const
7550	{
7551		ATLASSERT(::IsWindow(this->m_hWnd));
7552		return (UNDONAMEID)::SendMessage(this->m_hWnd, EM_GETUNDONAME, 0, 0L);
7553	}
7554
7555	UNDONAMEID GetRedoName() const
7556	{
7557		ATLASSERT(::IsWindow(this->m_hWnd));
7558		return (UNDONAMEID)::SendMessage(this->m_hWnd, EM_GETREDONAME, 0, 0L);
7559	}
7560
7561	BOOL CanRedo() const
7562	{
7563		ATLASSERT(::IsWindow(this->m_hWnd));
7564		return (BOOL)::SendMessage(this->m_hWnd, EM_CANREDO, 0, 0L);
7565	}
7566
7567	BOOL GetAutoURLDetect() const
7568	{
7569		ATLASSERT(::IsWindow(this->m_hWnd));
7570		return (BOOL)::SendMessage(this->m_hWnd, EM_GETAUTOURLDETECT, 0, 0L);
7571	}
7572
7573	BOOL SetAutoURLDetect(BOOL bAutoDetect = TRUE)
7574	{
7575		ATLASSERT(::IsWindow(this->m_hWnd));
7576		return !(BOOL)::SendMessage(this->m_hWnd, EM_AUTOURLDETECT, bAutoDetect, 0L);
7577	}
7578
7579	// this method is deprecated, please use SetAutoURLDetect
7580	BOOL EnableAutoURLDetect(BOOL bEnable = TRUE) { return SetAutoURLDetect(bEnable); }
7581
7582	UINT SetUndoLimit(UINT uUndoLimit)
7583	{
7584		ATLASSERT(::IsWindow(this->m_hWnd));
7585		return (UINT)::SendMessage(this->m_hWnd, EM_SETUNDOLIMIT, uUndoLimit, 0L);
7586	}
7587
7588	void SetPalette(HPALETTE hPalette)
7589	{
7590		ATLASSERT(::IsWindow(this->m_hWnd));
7591		::SendMessage(this->m_hWnd, EM_SETPALETTE, (WPARAM)hPalette, 0L);
7592	}
7593
7594	int GetTextEx(GETTEXTEX* pGetTextEx, LPTSTR lpstrText) const
7595	{
7596		ATLASSERT(::IsWindow(this->m_hWnd));
7597		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTEX, (WPARAM)pGetTextEx, (LPARAM)lpstrText);
7598	}
7599
7600	int GetTextEx(LPTSTR lpstrText, int nTextLen, DWORD dwFlags = GT_DEFAULT, UINT uCodePage = CP_ACP, LPCSTR lpDefaultChar = NULL, LPBOOL lpUsedDefChar = NULL) const
7601	{
7602		ATLASSERT(::IsWindow(this->m_hWnd));
7603		GETTEXTEX gte = {};
7604		gte.cb = nTextLen * sizeof(TCHAR);
7605		gte.codepage = uCodePage;
7606		gte.flags = dwFlags;
7607		gte.lpDefaultChar = lpDefaultChar;
7608		gte.lpUsedDefChar = lpUsedDefChar;
7609		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTEX, (WPARAM)&gte, (LPARAM)lpstrText);
7610	}
7611
7612	int GetTextLengthEx(GETTEXTLENGTHEX* pGetTextLengthEx) const
7613	{
7614		ATLASSERT(::IsWindow(this->m_hWnd));
7615		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)pGetTextLengthEx, 0L);
7616	}
7617
7618	int GetTextLengthEx(DWORD dwFlags = GTL_DEFAULT, UINT uCodePage = CP_ACP) const
7619	{
7620		ATLASSERT(::IsWindow(this->m_hWnd));
7621		GETTEXTLENGTHEX gtle = {};
7622		gtle.codepage = uCodePage;
7623		gtle.flags = dwFlags;
7624		return (int)::SendMessage(this->m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtle, 0L);
7625	}
7626
7627	EDITWORDBREAKPROC GetWordBreakProc() const
7628	{
7629		ATLASSERT(::IsWindow(this->m_hWnd));
7630		return (EDITWORDBREAKPROC)::SendMessage(this->m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
7631	}
7632
7633	void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
7634	{
7635		ATLASSERT(::IsWindow(this->m_hWnd));
7636		::SendMessage(this->m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
7637	}
7638
7639	int SetTextEx(SETTEXTEX* pSetTextEx, LPCTSTR lpstrText)
7640	{
7641		ATLASSERT(::IsWindow(this->m_hWnd));
7642		return (int)::SendMessage(this->m_hWnd, EM_SETTEXTEX, (WPARAM)pSetTextEx, (LPARAM)lpstrText);
7643	}
7644
7645	int SetTextEx(LPCTSTR lpstrText, DWORD dwFlags = ST_DEFAULT, UINT uCodePage = CP_ACP)
7646	{
7647		ATLASSERT(::IsWindow(this->m_hWnd));
7648		SETTEXTEX ste = {};
7649		ste.flags = dwFlags;
7650		ste.codepage = uCodePage;
7651		return (int)::SendMessage(this->m_hWnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpstrText);
7652	}
7653
7654	int GetEditStyle() const
7655	{
7656		ATLASSERT(::IsWindow(this->m_hWnd));
7657		return (int)::SendMessage(this->m_hWnd, EM_GETEDITSTYLE, 0, 0L);
7658	}
7659
7660	int SetEditStyle(int nStyle, int nMask = -1)
7661	{
7662		ATLASSERT(::IsWindow(this->m_hWnd));
7663		if(nMask == -1)
7664			nMask = nStyle;   // set everything specified
7665		return (int)::SendMessage(this->m_hWnd, EM_SETEDITSTYLE, nStyle, nMask);
7666	}
7667
7668	BOOL SetFontSize(int nFontSizeDelta)
7669	{
7670		ATLASSERT(::IsWindow(this->m_hWnd));
7671		ATLASSERT((nFontSizeDelta >= -1637) && (nFontSizeDelta <= 1638));
7672		return (BOOL)::SendMessage(this->m_hWnd, EM_SETFONTSIZE, nFontSizeDelta, 0L);
7673	}
7674
7675	void GetScrollPos(LPPOINT lpPoint) const
7676	{
7677		ATLASSERT(::IsWindow(this->m_hWnd));
7678		ATLASSERT(lpPoint != NULL);
7679		::SendMessage(this->m_hWnd, EM_GETSCROLLPOS, 0, (LPARAM)lpPoint);
7680	}
7681
7682	void SetScrollPos(LPPOINT lpPoint)
7683	{
7684		ATLASSERT(::IsWindow(this->m_hWnd));
7685		ATLASSERT(lpPoint != NULL);
7686		::SendMessage(this->m_hWnd, EM_SETSCROLLPOS, 0, (LPARAM)lpPoint);
7687	}
7688
7689	BOOL GetZoom(int& nNum, int& nDen) const
7690	{
7691		ATLASSERT(::IsWindow(this->m_hWnd));
7692		return (BOOL)::SendMessage(this->m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen);
7693	}
7694
7695	BOOL SetZoom(int nNum, int nDen)
7696	{
7697		ATLASSERT(::IsWindow(this->m_hWnd));
7698		ATLASSERT((nNum >= 0) && (nNum <= 64));
7699		ATLASSERT((nDen >= 0) && (nDen <= 64));
7700		return (BOOL)::SendMessage(this->m_hWnd, EM_SETZOOM, nNum, nDen);
7701	}
7702
7703	BOOL SetZoomOff()
7704	{
7705		ATLASSERT(::IsWindow(this->m_hWnd));
7706		return (BOOL)::SendMessage(this->m_hWnd, EM_SETZOOM, 0, 0L);
7707	}
7708
7709	void SetMargins(UINT nLeft, UINT nRight, WORD wFlags = EC_LEFTMARGIN | EC_RIGHTMARGIN)
7710	{
7711		ATLASSERT(::IsWindow(this->m_hWnd));
7712		::SendMessage(this->m_hWnd, EM_SETMARGINS, wFlags, MAKELONG(nLeft, nRight));
7713	}
7714
7715	WORD GetTypographyOptions() const
7716	{
7717		ATLASSERT(::IsWindow(this->m_hWnd));
7718		return (WORD)::SendMessage(this->m_hWnd, EM_GETTYPOGRAPHYOPTIONS, 0, 0L);
7719	}
7720
7721	BOOL SetTypographyOptions(WORD wOptions, WORD wMask) const
7722	{
7723		ATLASSERT(::IsWindow(this->m_hWnd));
7724		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTYPOGRAPHYOPTIONS, wOptions, wMask);
7725	}
7726
7727// Operations
7728	void LimitText(LONG nChars = 0)
7729	{
7730		ATLASSERT(::IsWindow(this->m_hWnd));
7731		::SendMessage(this->m_hWnd, EM_EXLIMITTEXT, 0, nChars);
7732	}
7733
7734	int LineFromChar(LONG nIndex) const
7735	{
7736		ATLASSERT(::IsWindow(this->m_hWnd));
7737		return (int)::SendMessage(this->m_hWnd, EM_EXLINEFROMCHAR, 0, nIndex);
7738	}
7739
7740	POINT PosFromChar(LONG nChar) const
7741	{
7742		ATLASSERT(::IsWindow(this->m_hWnd));
7743		POINT point = {};
7744		::SendMessage(this->m_hWnd, EM_POSFROMCHAR, (WPARAM)&point, nChar);
7745		return point;
7746	}
7747
7748	int CharFromPos(POINT pt) const
7749	{
7750		ATLASSERT(::IsWindow(this->m_hWnd));
7751		POINTL ptl = { pt.x, pt.y };
7752		return (int)::SendMessage(this->m_hWnd, EM_CHARFROMPOS, 0, (LPARAM)&ptl);
7753	}
7754
7755	void EmptyUndoBuffer()
7756	{
7757		ATLASSERT(::IsWindow(this->m_hWnd));
7758		::SendMessage(this->m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
7759	}
7760
7761	int LineIndex(int nLine = -1) const
7762	{
7763		ATLASSERT(::IsWindow(this->m_hWnd));
7764		return (int)::SendMessage(this->m_hWnd, EM_LINEINDEX, nLine, 0L);
7765	}
7766
7767	int LineLength(int nLine = -1) const
7768	{
7769		ATLASSERT(::IsWindow(this->m_hWnd));
7770		return (int)::SendMessage(this->m_hWnd, EM_LINELENGTH, nLine, 0L);
7771	}
7772
7773	BOOL LineScroll(int nLines)
7774	{
7775		ATLASSERT(::IsWindow(this->m_hWnd));
7776		return (BOOL)::SendMessage(this->m_hWnd, EM_LINESCROLL, 0, nLines);
7777	}
7778
7779	void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
7780	{
7781		ATLASSERT(::IsWindow(this->m_hWnd));
7782		::SendMessage(this->m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
7783	}
7784
7785	void SetRect(LPCRECT lpRect)
7786	{
7787		ATLASSERT(::IsWindow(this->m_hWnd));
7788		::SendMessage(this->m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
7789	}
7790
7791	BOOL DisplayBand(LPRECT pDisplayRect)
7792	{
7793		ATLASSERT(::IsWindow(this->m_hWnd));
7794		return (BOOL)::SendMessage(this->m_hWnd, EM_DISPLAYBAND, 0, (LPARAM)pDisplayRect);
7795	}
7796
7797	LONG FindText(DWORD dwFlags, FINDTEXT& ft) const
7798	{
7799		ATLASSERT(::IsWindow(this->m_hWnd));
7800#ifdef _UNICODE
7801		return (LONG)::SendMessage(this->m_hWnd, EM_FINDTEXTW, dwFlags, (LPARAM)&ft);
7802#else
7803		return (LONG)::SendMessage(this->m_hWnd, EM_FINDTEXT, dwFlags, (LPARAM)&ft);
7804#endif
7805	}
7806
7807	LONG FindText(DWORD dwFlags, FINDTEXTEX& ft) const
7808	{
7809		ATLASSERT(::IsWindow(this->m_hWnd));
7810#ifdef _UNICODE
7811		return (LONG)::SendMessage(this->m_hWnd, EM_FINDTEXTEXW, dwFlags, (LPARAM)&ft);
7812#else
7813		return (LONG)::SendMessage(this->m_hWnd, EM_FINDTEXTEX, dwFlags, (LPARAM)&ft);
7814#endif
7815	}
7816
7817	LONG FormatRange(FORMATRANGE& fr, BOOL bDisplay = TRUE)
7818	{
7819		ATLASSERT(::IsWindow(this->m_hWnd));
7820		return (LONG)::SendMessage(this->m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)&fr);
7821	}
7822
7823	LONG FormatRange(FORMATRANGE* pFormatRange, BOOL bDisplay = TRUE)
7824	{
7825		ATLASSERT(::IsWindow(this->m_hWnd));
7826		return (LONG)::SendMessage(this->m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)pFormatRange);
7827	}
7828
7829	void HideSelection(BOOL bHide = TRUE, BOOL bChangeStyle = FALSE)
7830	{
7831		ATLASSERT(::IsWindow(this->m_hWnd));
7832		::SendMessage(this->m_hWnd, EM_HIDESELECTION, bHide, bChangeStyle);
7833	}
7834
7835	void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0)
7836	{
7837		ATLASSERT(::IsWindow(this->m_hWnd));
7838		REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF };
7839		::SendMessage(this->m_hWnd, EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps);
7840	}
7841
7842	void RequestResize()
7843	{
7844		ATLASSERT(::IsWindow(this->m_hWnd));
7845		::SendMessage(this->m_hWnd, EM_REQUESTRESIZE, 0, 0L);
7846	}
7847
7848	LONG StreamIn(UINT uFormat, EDITSTREAM& es)
7849	{
7850		ATLASSERT(::IsWindow(this->m_hWnd));
7851		return (LONG)::SendMessage(this->m_hWnd, EM_STREAMIN, uFormat, (LPARAM)&es);
7852	}
7853
7854	LONG StreamOut(UINT uFormat, EDITSTREAM& es)
7855	{
7856		ATLASSERT(::IsWindow(this->m_hWnd));
7857		return (LONG)::SendMessage(this->m_hWnd, EM_STREAMOUT, uFormat, (LPARAM)&es);
7858	}
7859
7860	DWORD FindWordBreak(int nCode, LONG nStartChar)
7861	{
7862		ATLASSERT(::IsWindow(this->m_hWnd));
7863		return (DWORD)::SendMessage(this->m_hWnd, EM_FINDWORDBREAK, nCode, nStartChar);
7864	}
7865
7866	// Additional operations
7867	void ScrollCaret()
7868	{
7869		ATLASSERT(::IsWindow(this->m_hWnd));
7870		::SendMessage(this->m_hWnd, EM_SCROLLCARET, 0, 0L);
7871	}
7872
7873	int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
7874	{
7875		int nRet = SetSel(nInsertAfterChar, nInsertAfterChar);
7876		ReplaceSel(lpstrText, bCanUndo);
7877		return nRet;
7878	}
7879
7880	int AppendText(LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
7881	{
7882		return InsertText(this->GetWindowTextLength(), lpstrText, bCanUndo);
7883	}
7884
7885	// Clipboard operations
7886	BOOL Undo()
7887	{
7888		ATLASSERT(::IsWindow(this->m_hWnd));
7889		return (BOOL)::SendMessage(this->m_hWnd, EM_UNDO, 0, 0L);
7890	}
7891
7892	void Clear()
7893	{
7894		ATLASSERT(::IsWindow(this->m_hWnd));
7895		::SendMessage(this->m_hWnd, WM_CLEAR, 0, 0L);
7896	}
7897
7898	void Copy()
7899	{
7900		ATLASSERT(::IsWindow(this->m_hWnd));
7901		::SendMessage(this->m_hWnd, WM_COPY, 0, 0L);
7902	}
7903
7904	void Cut()
7905	{
7906		ATLASSERT(::IsWindow(this->m_hWnd));
7907		::SendMessage(this->m_hWnd, WM_CUT, 0, 0L);
7908	}
7909
7910	void Paste()
7911	{
7912		ATLASSERT(::IsWindow(this->m_hWnd));
7913		::SendMessage(this->m_hWnd, WM_PASTE, 0, 0L);
7914	}
7915
7916	// OLE support
7917	IRichEditOle* GetOleInterface() const
7918	{
7919		ATLASSERT(::IsWindow(this->m_hWnd));
7920		IRichEditOle *pRichEditOle = NULL;
7921		::SendMessage(this->m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
7922		return pRichEditOle;
7923	}
7924
7925	BOOL SetOleCallback(IRichEditOleCallback* pCallback)
7926	{
7927		ATLASSERT(::IsWindow(this->m_hWnd));
7928		return (BOOL)::SendMessage(this->m_hWnd, EM_SETOLECALLBACK, 0, (LPARAM)pCallback);
7929	}
7930
7931	BOOL Redo()
7932	{
7933		ATLASSERT(::IsWindow(this->m_hWnd));
7934		return (BOOL)::SendMessage(this->m_hWnd, EM_REDO, 0, 0L);
7935	}
7936
7937	void StopGroupTyping()
7938	{
7939		ATLASSERT(::IsWindow(this->m_hWnd));
7940		::SendMessage(this->m_hWnd, EM_STOPGROUPTYPING, 0, 0L);
7941	}
7942
7943	void ShowScrollBar(int nBarType, BOOL bVisible = TRUE)
7944	{
7945		ATLASSERT(::IsWindow(this->m_hWnd));
7946		::SendMessage(this->m_hWnd, EM_SHOWSCROLLBAR, nBarType, bVisible);
7947	}
7948
7949	BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
7950	{
7951		ATLASSERT(::IsWindow(this->m_hWnd));
7952		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
7953	}
7954
7955	BOOL SetTabStops()
7956	{
7957		ATLASSERT(::IsWindow(this->m_hWnd));
7958		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, 0, 0L);
7959	}
7960
7961	BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
7962	{
7963		ATLASSERT(::IsWindow(this->m_hWnd));
7964		return (BOOL)::SendMessage(this->m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
7965	}
7966
7967#if (_RICHEDIT_VER >= 0x0800)
7968	AutoCorrectProc GetAutoCorrectProc() const
7969	{
7970		ATLASSERT(::IsWindow(this->m_hWnd));
7971		return (AutoCorrectProc)::SendMessage(this->m_hWnd, EM_GETAUTOCORRECTPROC, 0, 0L);
7972	}
7973
7974	BOOL SetAutoCorrectProc(AutoCorrectProc pfn)
7975	{
7976		ATLASSERT(::IsWindow(this->m_hWnd));
7977		return (BOOL)::SendMessage(this->m_hWnd, EM_SETAUTOCORRECTPROC, (WPARAM)pfn, 0L);
7978	}
7979
7980	BOOL CallAutoCorrectProc(WCHAR ch)
7981	{
7982		ATLASSERT(::IsWindow(this->m_hWnd));
7983		return (BOOL)::SendMessage(this->m_hWnd, EM_CALLAUTOCORRECTPROC, (WPARAM)ch, 0L);
7984	}
7985
7986	DWORD GetEditStyleEx() const
7987	{
7988		ATLASSERT(::IsWindow(this->m_hWnd));
7989		return (DWORD)::SendMessage(this->m_hWnd, EM_GETEDITSTYLEEX, 0, 0L);
7990	}
7991
7992	DWORD SetEditStyleEx(DWORD dwStyleEx, DWORD dwMask)
7993	{
7994		ATLASSERT(::IsWindow(this->m_hWnd));
7995		return (DWORD)::SendMessage(this->m_hWnd, EM_SETEDITSTYLEEX, dwStyleEx, dwMask);
7996	}
7997
7998	DWORD GetStoryType(int nStoryIndex) const
7999	{
8000		ATLASSERT(::IsWindow(this->m_hWnd));
8001		return (DWORD)::SendMessage(this->m_hWnd, EM_GETSTORYTYPE, nStoryIndex, 0L);
8002	}
8003
8004	DWORD SetStoryType(int nStoryIndex, DWORD dwStoryType)
8005	{
8006		ATLASSERT(::IsWindow(this->m_hWnd));
8007		return (DWORD)::SendMessage(this->m_hWnd, EM_SETSTORYTYPE, nStoryIndex, dwStoryType);
8008	}
8009
8010	DWORD GetEllipsisMode() const
8011	{
8012		ATLASSERT(::IsWindow(this->m_hWnd));
8013
8014		DWORD dwMode = 0;
8015		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, EM_GETELLIPSISMODE, 0, (LPARAM)&dwMode);
8016		(void)bRet;   // avoid level 4 warning
8017		ATLASSERT(bRet != FALSE);
8018
8019		return dwMode;
8020	}
8021
8022	BOOL SetEllipsisMode(DWORD dwEllipsisMode)
8023	{
8024		ATLASSERT(::IsWindow(this->m_hWnd));
8025		return (BOOL)::SendMessage(this->m_hWnd, EM_SETELLIPSISMODE, 0, dwEllipsisMode);
8026	}
8027
8028	BOOL GetEllipsisState() const
8029	{
8030		ATLASSERT(::IsWindow(this->m_hWnd));
8031		return (BOOL)::SendMessage(this->m_hWnd, EM_GETELLIPSISSTATE, 0, 0L);
8032	}
8033
8034	BOOL GetTouchOptions(int nTouchOptions) const
8035	{
8036		ATLASSERT(::IsWindow(this->m_hWnd));
8037		return (BOOL)::SendMessage(this->m_hWnd, EM_GETTOUCHOPTIONS, nTouchOptions, 0L);
8038	}
8039
8040	void SetTouchOptions(int nTouchOptions, BOOL bEnable)
8041	{
8042		ATLASSERT(::IsWindow(this->m_hWnd));
8043		::SendMessage(this->m_hWnd, EM_SETTOUCHOPTIONS, nTouchOptions, bEnable);
8044	}
8045
8046	HRESULT InsertTable(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams)
8047	{
8048		ATLASSERT(::IsWindow(this->m_hWnd));
8049		return (HRESULT)::SendMessage(this->m_hWnd, EM_INSERTTABLE, (WPARAM)pRowParams, (LPARAM)pCellParams);
8050	}
8051
8052	HRESULT GetTableParams(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams) const
8053	{
8054		ATLASSERT(::IsWindow(this->m_hWnd));
8055		return (HRESULT)::SendMessage(this->m_hWnd, EM_GETTABLEPARMS, (WPARAM)pRowParams, (LPARAM)pCellParams);
8056	}
8057
8058	HRESULT SetTableParams(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams)
8059	{
8060		ATLASSERT(::IsWindow(this->m_hWnd));
8061		return (HRESULT)::SendMessage(this->m_hWnd, EM_SETTABLEPARMS, (WPARAM)pRowParams, (LPARAM)pCellParams);
8062	}
8063
8064	HRESULT InsertImage(RICHEDIT_IMAGE_PARAMETERS* pParams)
8065	{
8066		ATLASSERT(::IsWindow(this->m_hWnd));
8067		return (HRESULT)::SendMessage(this->m_hWnd, EM_INSERTIMAGE, 0, (LPARAM)pParams);
8068	}
8069
8070	BOOL SetUiaName(LPCTSTR lpstrName)
8071	{
8072		ATLASSERT(::IsWindow(this->m_hWnd));
8073		return (BOOL)::SendMessage(this->m_hWnd, EM_SETUIANAME, 0, (LPARAM)lpstrName);
8074	}
8075#endif // (_RICHEDIT_VER >= 0x0800)
8076};
8077
8078typedef CRichEditCtrlT<ATL::CWindow>   CRichEditCtrl;
8079
8080
8081///////////////////////////////////////////////////////////////////////////////
8082// CRichEditCommands - message handlers for standard EDIT commands
8083
8084// Chain to CRichEditCommands message map. Your class must also derive from CRichEditCtrl.
8085// Example:
8086// class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
8087//                     public CRichEditCommands<CMyRichEdit>
8088// {
8089// public:
8090//      BEGIN_MSG_MAP(CMyRichEdit)
8091//              // your handlers...
8092//              CHAIN_MSG_MAP_ALT(CRichEditCommands<CMyRichEdit>, 1)
8093//      END_MSG_MAP()
8094//      // other stuff...
8095// };
8096
8097template <class T>
8098class CRichEditCommands : public CEditCommands< T >
8099{
8100public:
8101	BEGIN_MSG_MAP(CRichEditCommands< T >)
8102	ALT_MSG_MAP(1)
8103		COMMAND_ID_HANDLER(ID_EDIT_CLEAR, CEditCommands< T >::OnEditClear)
8104		COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, CEditCommands< T >::OnEditClearAll)
8105		COMMAND_ID_HANDLER(ID_EDIT_COPY, CEditCommands< T >::OnEditCopy)
8106		COMMAND_ID_HANDLER(ID_EDIT_CUT, CEditCommands< T >::OnEditCut)
8107		COMMAND_ID_HANDLER(ID_EDIT_PASTE, CEditCommands< T >::OnEditPaste)
8108		COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, CEditCommands< T >::OnEditSelectAll)
8109		COMMAND_ID_HANDLER(ID_EDIT_UNDO, CEditCommands< T >::OnEditUndo)
8110		COMMAND_ID_HANDLER(ID_EDIT_REDO, OnEditRedo)
8111	END_MSG_MAP()
8112
8113	LRESULT OnEditRedo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
8114	{
8115		T* pT = static_cast<T*>(this);
8116		pT->Redo();
8117		return 0;
8118	}
8119
8120// State (update UI) helpers
8121	BOOL CanCut() const
8122	{ return HasSelection(); }
8123
8124	BOOL CanCopy() const
8125	{ return HasSelection(); }
8126
8127	BOOL CanClear() const
8128	{ return HasSelection(); }
8129
8130// Implementation
8131	BOOL HasSelection() const
8132	{
8133		const T* pT = static_cast<const T*>(this);
8134		return (pT->GetSelectionType() != SEL_EMPTY);
8135	}
8136};
8137
8138
8139///////////////////////////////////////////////////////////////////////////////
8140// CDragListBox
8141
8142template <class TBase>
8143class CDragListBoxT : public CListBoxT< TBase >
8144{
8145public:
8146// Constructors
8147	CDragListBoxT(HWND hWnd = NULL) : CListBoxT< TBase >(hWnd)
8148	{ }
8149
8150	CDragListBoxT< TBase >& operator =(HWND hWnd)
8151	{
8152		this->m_hWnd = hWnd;
8153		return *this;
8154	}
8155
8156	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8157			DWORD dwStyle = 0, DWORD dwExStyle = 0,
8158			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8159	{
8160		HWND hWnd = TBase::Create(TBase::GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8161		if(hWnd != NULL)
8162			MakeDragList();
8163		return hWnd;
8164	}
8165
8166// Operations
8167	BOOL MakeDragList()
8168	{
8169		ATLASSERT(::IsWindow(this->m_hWnd));
8170		ATLASSERT((this->GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
8171		return ::MakeDragList(this->m_hWnd);
8172	}
8173
8174	int LBItemFromPt(POINT pt, BOOL bAutoScroll = TRUE)
8175	{
8176		ATLASSERT(::IsWindow(this->m_hWnd));
8177		return ::LBItemFromPt(this->m_hWnd, pt, bAutoScroll);
8178	}
8179
8180	void DrawInsert(int nItem)
8181	{
8182		ATLASSERT(::IsWindow(this->m_hWnd));
8183		::DrawInsert(this->GetParent(), this->m_hWnd, nItem);
8184	}
8185
8186	static UINT GetDragListMessage()
8187	{
8188		static UINT uDragListMessage = 0;
8189		if(uDragListMessage == 0)
8190		{
8191			CStaticDataInitCriticalSectionLock lock;
8192			if(FAILED(lock.Lock()))
8193			{
8194				ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDragListBox::GetDragListMessage.\n"));
8195				ATLASSERT(FALSE);
8196				return 0;
8197			}
8198
8199			if(uDragListMessage == 0)
8200				uDragListMessage = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
8201
8202			lock.Unlock();
8203		}
8204		ATLASSERT(uDragListMessage != 0);
8205		return uDragListMessage;
8206	}
8207};
8208
8209typedef CDragListBoxT<ATL::CWindow>   CDragListBox;
8210
8211template <class T>
8212class CDragListNotifyImpl
8213{
8214public:
8215	BEGIN_MSG_MAP(CDragListNotifyImpl< T >)
8216		MESSAGE_HANDLER(CDragListBox::GetDragListMessage(), OnDragListNotify)
8217	END_MSG_MAP()
8218
8219	LRESULT OnDragListNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
8220	{
8221		(void)uMsg;   // avoid level 4 warning
8222		ATLASSERT(uMsg == CDragListBox::GetDragListMessage());
8223		T* pT = static_cast<T*>(this);
8224		LPDRAGLISTINFO lpDragListInfo = (LPDRAGLISTINFO)lParam;
8225		LRESULT lRet = 0;
8226		switch(lpDragListInfo->uNotification)
8227		{
8228		case DL_BEGINDRAG:
8229			lRet = (LPARAM)pT->OnBeginDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8230			break;
8231		case DL_CANCELDRAG:
8232			pT->OnCancelDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8233			break;
8234		case DL_DRAGGING:
8235			lRet = (LPARAM)pT->OnDragging((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8236			break;
8237		case DL_DROPPED:
8238			pT->OnDropped((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8239			break;
8240		default:
8241			ATLTRACE2(atlTraceUI, 0, _T("Unknown DragListBox notification\n"));
8242			bHandled = FALSE;   // don't handle it
8243			break;
8244		}
8245		return lRet;
8246	}
8247
8248// Overrideables
8249	BOOL OnBeginDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8250	{
8251		return TRUE;   // allow dragging
8252	}
8253
8254	void OnCancelDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8255	{
8256		// nothing to do
8257	}
8258
8259	int OnDragging(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8260	{
8261		return 0;   // don't change cursor
8262	}
8263
8264	void OnDropped(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8265	{
8266		// nothing to do
8267	}
8268};
8269
8270
8271///////////////////////////////////////////////////////////////////////////////
8272// CReBarCtrl
8273
8274template <class TBase>
8275class CReBarCtrlT : public TBase
8276{
8277public:
8278// Constructors
8279	CReBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
8280	{ }
8281
8282	CReBarCtrlT< TBase >& operator =(HWND hWnd)
8283	{
8284		this->m_hWnd = hWnd;
8285		return *this;
8286	}
8287
8288	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8289			DWORD dwStyle = 0, DWORD dwExStyle = 0,
8290			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8291	{
8292		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8293	}
8294
8295// Attributes
8296	static LPCTSTR GetWndClassName()
8297	{
8298		return REBARCLASSNAME;
8299	}
8300
8301	UINT GetBandCount() const
8302	{
8303		ATLASSERT(::IsWindow(this->m_hWnd));
8304		return (UINT)::SendMessage(this->m_hWnd, RB_GETBANDCOUNT, 0, 0L);
8305	}
8306
8307	BOOL GetBandInfo(int nBand, LPREBARBANDINFO lprbbi) const
8308	{
8309		ATLASSERT(::IsWindow(this->m_hWnd));
8310		return (BOOL)::SendMessage(this->m_hWnd, RB_GETBANDINFO, nBand, (LPARAM)lprbbi);
8311	}
8312
8313	BOOL SetBandInfo(int nBand, LPREBARBANDINFO lprbbi)
8314	{
8315		ATLASSERT(::IsWindow(this->m_hWnd));
8316		return (BOOL)::SendMessage(this->m_hWnd, RB_SETBANDINFO, nBand, (LPARAM)lprbbi);
8317	}
8318
8319	BOOL GetBarInfo(LPREBARINFO lprbi) const
8320	{
8321		ATLASSERT(::IsWindow(this->m_hWnd));
8322		return (BOOL)::SendMessage(this->m_hWnd, RB_GETBARINFO, 0, (LPARAM)lprbi);
8323	}
8324
8325	BOOL SetBarInfo(LPREBARINFO lprbi)
8326	{
8327		ATLASSERT(::IsWindow(this->m_hWnd));
8328		return (BOOL)::SendMessage(this->m_hWnd, RB_SETBARINFO, 0, (LPARAM)lprbi);
8329	}
8330
8331	CImageList GetImageList() const
8332	{
8333		ATLASSERT(::IsWindow(this->m_hWnd));
8334		REBARINFO rbi = {};
8335		rbi.cbSize = sizeof(REBARINFO);
8336		rbi.fMask = RBIM_IMAGELIST;
8337		BOOL bRet = (BOOL)::SendMessage(this->m_hWnd, RB_GETBARINFO, 0, (LPARAM)&rbi);
8338		return CImageList((bRet != FALSE) ? rbi.himl : NULL);
8339	}
8340
8341	BOOL SetImageList(HIMAGELIST hImageList)
8342	{
8343		ATLASSERT(::IsWindow(this->m_hWnd));
8344		REBARINFO rbi = {};
8345		rbi.cbSize = sizeof(REBARINFO);
8346		rbi.fMask = RBIM_IMAGELIST;
8347		rbi.himl = hImageList;
8348		return (BOOL)::SendMessage(this->m_hWnd, RB_SETBARINFO, 0, (LPARAM)&rbi);
8349	}
8350
8351	UINT GetRowCount() const
8352	{
8353		ATLASSERT(::IsWindow(this->m_hWnd));
8354		return (UINT)::SendMessage(this->m_hWnd, RB_GETROWCOUNT, 0, 0L);
8355	}
8356
8357	UINT GetRowHeight(int nBand) const
8358	{
8359		ATLASSERT(::IsWindow(this->m_hWnd));
8360		return (UINT)::SendMessage(this->m_hWnd, RB_GETROWHEIGHT, nBand, 0L);
8361	}
8362
8363	COLORREF GetTextColor() const
8364	{
8365		ATLASSERT(::IsWindow(this->m_hWnd));
8366		return (COLORREF)::SendMessage(this->m_hWnd, RB_GETTEXTCOLOR, 0, 0L);
8367	}
8368
8369	COLORREF SetTextColor(COLORREF clr)
8370	{
8371		ATLASSERT(::IsWindow(this->m_hWnd));
8372		return (COLORREF)::SendMessage(this->m_hWnd, RB_SETTEXTCOLOR, 0, (LPARAM)clr);
8373	}
8374
8375	COLORREF GetBkColor() const
8376	{
8377		ATLASSERT(::IsWindow(this->m_hWnd));
8378		return (COLORREF)::SendMessage(this->m_hWnd, RB_GETBKCOLOR, 0, 0L);
8379	}
8380
8381	COLORREF SetBkColor(COLORREF clr)
8382	{
8383		ATLASSERT(::IsWindow(this->m_hWnd));
8384		return (COLORREF)::SendMessage(this->m_hWnd, RB_SETBKCOLOR, 0, (LPARAM)clr);
8385	}
8386
8387	UINT GetBarHeight() const
8388	{
8389		ATLASSERT(::IsWindow(this->m_hWnd));
8390		return (UINT)::SendMessage(this->m_hWnd, RB_GETBARHEIGHT, 0, 0L);
8391	}
8392
8393	BOOL GetRect(int nBand, LPRECT lpRect) const
8394	{
8395		ATLASSERT(::IsWindow(this->m_hWnd));
8396		return (BOOL)::SendMessage(this->m_hWnd, RB_GETRECT, nBand, (LPARAM)lpRect);
8397	}
8398
8399	CToolTipCtrl GetToolTips() const
8400	{
8401		ATLASSERT(::IsWindow(this->m_hWnd));
8402		return CToolTipCtrl((HWND)::SendMessage(this->m_hWnd, RB_GETTOOLTIPS, 0, 0L));
8403	}
8404
8405	void SetToolTips(HWND hwndToolTip)
8406	{
8407		ATLASSERT(::IsWindow(this->m_hWnd));
8408		::SendMessage(this->m_hWnd, RB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L);
8409	}
8410
8411	void GetBandBorders(int nBand, LPRECT lpRect) const
8412	{
8413		ATLASSERT(::IsWindow(this->m_hWnd));
8414		ATLASSERT(lpRect != NULL);
8415		::SendMessage(this->m_hWnd, RB_GETBANDBORDERS, nBand, (LPARAM)lpRect);
8416	}
8417
8418	BOOL GetColorScheme(LPCOLORSCHEME lpColorScheme) const
8419	{
8420		ATLASSERT(::IsWindow(this->m_hWnd));
8421		ATLASSERT(lpColorScheme != NULL);
8422		return (BOOL)::SendMessage(this->m_hWnd, RB_GETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
8423	}
8424
8425	void SetColorScheme(LPCOLORSCHEME lpColorScheme)
8426	{
8427		ATLASSERT(::IsWindow(this->m_hWnd));
8428		ATLASSERT(lpColorScheme != NULL);
8429		::SendMessage(this->m_hWnd, RB_SETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
8430	}
8431
8432	HPALETTE GetPalette() const
8433	{
8434		ATLASSERT(::IsWindow(this->m_hWnd));
8435		return (HPALETTE)::SendMessage(this->m_hWnd, RB_GETPALETTE, 0, 0L);
8436	}
8437
8438	HPALETTE SetPalette(HPALETTE hPalette)
8439	{
8440		ATLASSERT(::IsWindow(this->m_hWnd));
8441		return (HPALETTE)::SendMessage(this->m_hWnd, RB_SETPALETTE, 0, (LPARAM)hPalette);
8442	}
8443
8444	BOOL GetUnicodeFormat() const
8445	{
8446		ATLASSERT(::IsWindow(this->m_hWnd));
8447		return (BOOL)::SendMessage(this->m_hWnd, RB_GETUNICODEFORMAT, 0, 0L);
8448	}
8449
8450	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
8451	{
8452		ATLASSERT(::IsWindow(this->m_hWnd));
8453		return (BOOL)::SendMessage(this->m_hWnd, RB_SETUNICODEFORMAT, bUnicode, 0L);
8454	}
8455
8456	// requires uxtheme.h to be included to use MARGINS struct
8457#ifndef _UXTHEME_H_
8458	typedef struct _MARGINS*   PMARGINS;
8459#endif // !_UXTHEME_H_
8460	void GetBandMargins(PMARGINS pMargins) const
8461	{
8462		ATLASSERT(::IsWindow(this->m_hWnd));
8463		::SendMessage(this->m_hWnd, RB_GETBANDMARGINS, 0, (LPARAM)pMargins);
8464	}
8465
8466	void SetWindowTheme(LPCWSTR lpstrTheme)
8467	{
8468		ATLASSERT(::IsWindow(this->m_hWnd));
8469		::SendMessage(this->m_hWnd, RB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
8470	}
8471
8472	DWORD GetExtendedStyle() const
8473	{
8474		ATLASSERT(::IsWindow(this->m_hWnd));
8475		return (DWORD)::SendMessage(this->m_hWnd, RB_GETEXTENDEDSTYLE, 0, 0L);
8476	}
8477
8478	DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
8479	{
8480		ATLASSERT(::IsWindow(this->m_hWnd));
8481		return (DWORD)::SendMessage(this->m_hWnd, RB_SETEXTENDEDSTYLE, dwMask, dwStyle);
8482	}
8483
8484// Operations
8485	BOOL InsertBand(int nBand, LPREBARBANDINFO lprbbi)
8486	{
8487		ATLASSERT(::IsWindow(this->m_hWnd));
8488		return (BOOL)::SendMessage(this->m_hWnd, RB_INSERTBAND, nBand, (LPARAM)lprbbi);
8489	}
8490
8491	BOOL AddBand(LPREBARBANDINFO lprbbi)
8492	{
8493		return InsertBand(-1, lprbbi);
8494	}
8495
8496	BOOL DeleteBand(int nBand)
8497	{
8498		ATLASSERT(::IsWindow(this->m_hWnd));
8499		return (BOOL)::SendMessage(this->m_hWnd, RB_DELETEBAND, nBand, 0L);
8500	}
8501
8502	ATL::CWindow SetNotifyWnd(HWND hWnd)
8503	{
8504		ATLASSERT(::IsWindow(this->m_hWnd));
8505		return ATL::CWindow((HWND)::SendMessage(this->m_hWnd, RB_SETPARENT, (WPARAM)hWnd, 0L));
8506	}
8507
8508	void BeginDrag(int nBand, DWORD dwPos)
8509	{
8510		ATLASSERT(::IsWindow(this->m_hWnd));
8511		::SendMessage(this->m_hWnd, RB_BEGINDRAG, nBand, dwPos);
8512	}
8513
8514	void BeginDrag(int nBand, int xPos, int yPos)
8515	{
8516		ATLASSERT(::IsWindow(this->m_hWnd));
8517		::SendMessage(this->m_hWnd, RB_BEGINDRAG, nBand, MAKELPARAM(xPos, yPos));
8518	}
8519
8520	void EndDrag()
8521	{
8522		ATLASSERT(::IsWindow(this->m_hWnd));
8523		::SendMessage(this->m_hWnd, RB_ENDDRAG, 0, 0L);
8524	}
8525
8526	void DragMove(DWORD dwPos)
8527	{
8528		ATLASSERT(::IsWindow(this->m_hWnd));
8529		::SendMessage(this->m_hWnd, RB_DRAGMOVE, 0, dwPos);
8530	}
8531
8532	void DragMove(int xPos, int yPos)
8533	{
8534		ATLASSERT(::IsWindow(this->m_hWnd));
8535		::SendMessage(this->m_hWnd, RB_DRAGMOVE, 0, MAKELPARAM(xPos, yPos));
8536	}
8537
8538	void GetDropTarget(IDropTarget** ppDropTarget) const
8539	{
8540		ATLASSERT(::IsWindow(this->m_hWnd));
8541		::SendMessage(this->m_hWnd, RB_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
8542	}
8543
8544	void MaximizeBand(int nBand, BOOL bIdeal = FALSE)
8545	{
8546		ATLASSERT(::IsWindow(this->m_hWnd));
8547		::SendMessage(this->m_hWnd, RB_MAXIMIZEBAND, nBand, bIdeal);
8548	}
8549
8550	void MinimizeBand(int nBand)
8551	{
8552		ATLASSERT(::IsWindow(this->m_hWnd));
8553		::SendMessage(this->m_hWnd, RB_MINIMIZEBAND, nBand, 0L);
8554	}
8555
8556	BOOL SizeToRect(LPRECT lpRect)
8557	{
8558		ATLASSERT(::IsWindow(this->m_hWnd));
8559		return (BOOL)::SendMessage(this->m_hWnd, RB_SIZETORECT, 0, (LPARAM)lpRect);
8560	}
8561
8562	int IdToIndex(UINT uBandID) const
8563	{
8564		ATLASSERT(::IsWindow(this->m_hWnd));
8565		return (int)::SendMessage(this->m_hWnd, RB_IDTOINDEX, uBandID, 0L);
8566	}
8567
8568	int HitTest(LPRBHITTESTINFO lprbht) const
8569	{
8570		ATLASSERT(::IsWindow(this->m_hWnd));
8571		return (int)::SendMessage(this->m_hWnd, RB_HITTEST, 0, (LPARAM)lprbht);
8572	}
8573
8574	BOOL ShowBand(int nBand, BOOL bShow)
8575	{
8576		ATLASSERT(::IsWindow(this->m_hWnd));
8577		return (BOOL)::SendMessage(this->m_hWnd, RB_SHOWBAND, nBand, bShow);
8578	}
8579
8580	BOOL MoveBand(int nBand, int nNewPos)
8581	{
8582		ATLASSERT(::IsWindow(this->m_hWnd));
8583		ATLASSERT((nNewPos >= 0) && (nNewPos <= ((int)GetBandCount() - 1)));
8584		return (BOOL)::SendMessage(this->m_hWnd, RB_MOVEBAND, nBand, nNewPos);
8585	}
8586
8587	void PushChevron(int nBand, LPARAM lAppValue)
8588	{
8589		ATLASSERT(::IsWindow(this->m_hWnd));
8590		::SendMessage(this->m_hWnd, RB_PUSHCHEVRON, nBand, lAppValue);
8591	}
8592
8593// Extra operations
8594	void LockBands(bool bLock)
8595	{
8596		int nBandCount = GetBandCount();
8597		for(int i =0; i < nBandCount; i++)
8598		{
8599			REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
8600			rbbi.fMask = RBBIM_STYLE;
8601			BOOL bRet = GetBandInfo(i, &rbbi);
8602			ATLASSERT(bRet);
8603
8604			if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0)
8605			{
8606				rbbi.fStyle |= RBBS_GRIPPERALWAYS;
8607				bRet = SetBandInfo(i, &rbbi);
8608				ATLASSERT(bRet);
8609				rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
8610			}
8611
8612			if(bLock)
8613				rbbi.fStyle |= RBBS_NOGRIPPER;
8614			else
8615				rbbi.fStyle &= ~RBBS_NOGRIPPER;
8616
8617			bRet = SetBandInfo(i, &rbbi);
8618			ATLASSERT(bRet);
8619		}
8620	}
8621
8622#if (_WIN32_WINNT >= 0x0600)
8623	BOOL SetBandWidth(int nBand, int cxWidth)
8624	{
8625		ATLASSERT(::IsWindow(this->m_hWnd));
8626		return (BOOL)::SendMessage(this->m_hWnd, RB_SETBANDWIDTH, nBand, cxWidth);
8627	}
8628#endif // (_WIN32_WINNT >= 0x0600)
8629};
8630
8631typedef CReBarCtrlT<ATL::CWindow>   CReBarCtrl;
8632
8633
8634///////////////////////////////////////////////////////////////////////////////
8635// CComboBoxEx
8636
8637template <class TBase>
8638class CComboBoxExT : public CComboBoxT< TBase >
8639{
8640public:
8641// Constructors
8642	CComboBoxExT(HWND hWnd = NULL) : CComboBoxT< TBase >(hWnd)
8643	{ }
8644
8645	CComboBoxExT< TBase >& operator =(HWND hWnd)
8646	{
8647		this->m_hWnd = hWnd;
8648		return *this;
8649	}
8650
8651	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8652			DWORD dwStyle = 0, DWORD dwExStyle = 0,
8653			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8654	{
8655		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8656	}
8657
8658// Attributes
8659	static LPCTSTR GetWndClassName()
8660	{
8661		return WC_COMBOBOXEX;
8662	}
8663
8664	CImageList GetImageList() const
8665	{
8666		ATLASSERT(::IsWindow(this->m_hWnd));
8667		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, CBEM_GETIMAGELIST, 0, 0L));
8668	}
8669
8670	CImageList SetImageList(HIMAGELIST hImageList)
8671	{
8672		ATLASSERT(::IsWindow(this->m_hWnd));
8673		return CImageList((HIMAGELIST)::SendMessage(this->m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)hImageList));
8674	}
8675
8676	DWORD GetExtendedStyle() const
8677	{
8678		ATLASSERT(::IsWindow(this->m_hWnd));
8679		return (DWORD)::SendMessage(this->m_hWnd, CBEM_GETEXTENDEDSTYLE, 0, 0L);
8680	}
8681
8682	DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
8683	{
8684		ATLASSERT(::IsWindow(this->m_hWnd));
8685		return (DWORD)::SendMessage(this->m_hWnd, CBEM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
8686	}
8687
8688	BOOL GetUnicodeFormat() const
8689	{
8690		ATLASSERT(::IsWindow(this->m_hWnd));
8691		return (BOOL)::SendMessage(this->m_hWnd, CBEM_GETUNICODEFORMAT, 0, 0L);
8692	}
8693
8694	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
8695	{
8696		ATLASSERT(::IsWindow(this->m_hWnd));
8697		return (BOOL)::SendMessage(this->m_hWnd, CBEM_SETUNICODEFORMAT, bUnicode, 0L);
8698	}
8699
8700	void SetWindowTheme(LPCWSTR lpstrTheme)
8701	{
8702		ATLASSERT(::IsWindow(this->m_hWnd));
8703		::SendMessage(this->m_hWnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
8704	}
8705
8706// Operations
8707	int InsertItem(const COMBOBOXEXITEM* lpcCBItem)
8708	{
8709		ATLASSERT(::IsWindow(this->m_hWnd));
8710		return (int)::SendMessage(this->m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem);
8711	}
8712
8713	int InsertItem(UINT nMask, int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, 
8714	               int iIndent, int iOverlay, LPARAM lParam)
8715	{
8716		ATLASSERT(::IsWindow(this->m_hWnd));
8717		COMBOBOXEXITEM cbex = {};
8718		cbex.mask = nMask;
8719		cbex.iItem = nIndex;
8720		cbex.pszText = (LPTSTR) lpszItem;
8721		cbex.iImage = nImage;
8722		cbex.iSelectedImage = nSelImage;
8723		cbex.iIndent = iIndent;
8724		cbex.iOverlay = iOverlay;
8725		cbex.lParam = lParam;
8726		return (int)::SendMessage(this->m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
8727	}
8728
8729	int InsertItem(int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
8730	{
8731		ATLASSERT(::IsWindow(this->m_hWnd));
8732		COMBOBOXEXITEM cbex = {};
8733		cbex.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_INDENT | CBEIF_LPARAM;
8734		cbex.iItem = nIndex;
8735		cbex.pszText = (LPTSTR) lpszItem;
8736		cbex.iImage = nImage;
8737		cbex.iSelectedImage = nSelImage;
8738		cbex.iIndent = iIndent;
8739		cbex.lParam = lParam;
8740		return (int)::SendMessage(this->m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
8741	}
8742
8743	int AddItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, int iOverlay, LPARAM lParam)
8744	{
8745		return InsertItem(nMask, -1, lpszItem, nImage, nSelImage, iIndent, iOverlay, lParam);
8746	}
8747
8748	int AddItem(LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
8749	{
8750		return InsertItem(-1, lpszItem, nImage, nSelImage, iIndent, lParam);
8751	}
8752
8753	int DeleteItem(int nIndex)
8754	{
8755		ATLASSERT(::IsWindow(this->m_hWnd));
8756		return (int)::SendMessage(this->m_hWnd, CBEM_DELETEITEM, nIndex, 0L);
8757	}
8758
8759	BOOL GetItem(PCOMBOBOXEXITEM pCBItem) const
8760	{
8761		ATLASSERT(::IsWindow(this->m_hWnd));
8762		return (BOOL)::SendMessage(this->m_hWnd, CBEM_GETITEM, 0, (LPARAM)pCBItem);
8763	}
8764
8765	BOOL SetItem(const COMBOBOXEXITEM* lpcCBItem)
8766	{
8767		ATLASSERT(::IsWindow(this->m_hWnd));
8768		return (BOOL)::SendMessage(this->m_hWnd, CBEM_SETITEM, 0, (LPARAM)lpcCBItem);
8769	}
8770
8771	int SetItem(int nIndex, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, 
8772	            int iIndent, int iOverlay, LPARAM lParam)
8773	{
8774		ATLASSERT(::IsWindow(this->m_hWnd));
8775		COMBOBOXEXITEM cbex = {};
8776		cbex.mask = nMask;
8777		cbex.iItem = nIndex;
8778		cbex.pszText = (LPTSTR) lpszItem;
8779		cbex.iImage = nImage;
8780		cbex.iSelectedImage = nSelImage;
8781		cbex.iIndent = iIndent;
8782		cbex.iOverlay = iOverlay;
8783		cbex.lParam = lParam;
8784		return (int)::SendMessage(this->m_hWnd, CBEM_SETITEM, 0, (LPARAM)&cbex);
8785	}
8786
8787	BOOL GetItemText(int nIndex, LPTSTR lpszItem, int nLen) const
8788	{
8789		ATLASSERT(::IsWindow(this->m_hWnd));
8790		ATLASSERT(lpszItem != NULL);
8791
8792		COMBOBOXEXITEM cbex = {};
8793		cbex.mask = CBEIF_TEXT;
8794		cbex.iItem = nIndex;
8795		cbex.pszText = lpszItem;
8796		cbex.cchTextMax = nLen;
8797
8798		return (BOOL)::SendMessage(this->m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
8799	}
8800
8801	BOOL GetItemText(int nIndex, BSTR& bstrText) const
8802	{
8803		USES_CONVERSION;
8804		ATLASSERT(::IsWindow(this->m_hWnd));
8805		ATLASSERT(bstrText == NULL);
8806
8807		COMBOBOXEXITEM cbex = {};
8808		cbex.mask = CBEIF_TEXT;
8809		cbex.iItem = nIndex;
8810
8811		LPTSTR lpstrText = NULL;
8812		BOOL bRet = FALSE;
8813		for(int nLen = 256; ; nLen *= 2)
8814		{
8815			ATLTRY(lpstrText = new TCHAR[nLen]);
8816			if(lpstrText == NULL)
8817				break;
8818			lpstrText[0] = NULL;
8819			cbex.pszText = lpstrText;
8820			cbex.cchTextMax = nLen;
8821			bRet = (BOOL)::SendMessage(this->m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
8822			if(!bRet || (lstrlen(cbex.pszText) < (nLen - 1)))
8823				break;
8824			delete [] lpstrText;
8825			lpstrText = NULL;
8826		}
8827
8828		if(lpstrText != NULL)
8829		{
8830			if(bRet)
8831				bstrText = ::SysAllocString(T2OLE(lpstrText));
8832			delete [] lpstrText;
8833		}
8834
8835		return (bstrText != NULL) ? TRUE : FALSE;
8836	}
8837
8838#ifdef __ATLSTR_H__
8839	BOOL GetItemText(int nIndex, ATL::CString& strText) const
8840	{
8841		ATLASSERT(::IsWindow(this->m_hWnd));
8842
8843		COMBOBOXEXITEM cbex = {};
8844		cbex.mask = CBEIF_TEXT;
8845		cbex.iItem = nIndex;
8846
8847		strText.Empty();
8848		BOOL bRet = FALSE;
8849		for(int nLen = 256; ; nLen *= 2)
8850		{
8851			cbex.pszText = strText.GetBufferSetLength(nLen);
8852			if(cbex.pszText == NULL)
8853			{
8854				bRet = FALSE;
8855				break;
8856			}
8857			cbex.cchTextMax = nLen;
8858			bRet = (BOOL)::SendMessage(this->m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
8859			if(!bRet || (lstrlen(cbex.pszText) < (nLen - 1)))
8860				break;
8861		}
8862		strText.ReleaseBuffer();
8863		return bRet;
8864	}
8865#endif // __ATLSTR_H__
8866
8867	BOOL SetItemText(int nIndex, LPCTSTR lpszItem)
8868	{
8869		ATLASSERT(::IsWindow(this->m_hWnd));
8870		return SetItem(nIndex, CBEIF_TEXT, lpszItem, 0, 0, 0, 0, 0);
8871	}
8872
8873	CComboBox GetComboCtrl() const
8874	{
8875		ATLASSERT(::IsWindow(this->m_hWnd));
8876		return CComboBox((HWND)::SendMessage(this->m_hWnd, CBEM_GETCOMBOCONTROL, 0, 0L));
8877	}
8878
8879	CEdit GetEditCtrl() const
8880	{
8881		ATLASSERT(::IsWindow(this->m_hWnd));
8882		return CEdit((HWND)::SendMessage(this->m_hWnd, CBEM_GETEDITCONTROL, 0, 0L));
8883	}
8884
8885	BOOL HasEditChanged() const
8886	{
8887		ATLASSERT(::IsWindow(this->m_hWnd));
8888		return (BOOL)::SendMessage(this->m_hWnd, CBEM_HASEDITCHANGED, 0, 0L);
8889	}
8890
8891// Non-functional
8892	int AddString(LPCTSTR /*lpszItem*/)
8893	{
8894		ATLASSERT(FALSE);  // Not available in CComboBoxEx; use InsertItem
8895		return 0;
8896	}
8897
8898	int InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/)
8899	{
8900		ATLASSERT(FALSE);  // Not available in CComboBoxEx; use InsertItem
8901		return 0;
8902	}
8903
8904	int Dir(UINT /*attr*/, LPCTSTR /*lpszWildCard*/)
8905	{
8906		ATLASSERT(FALSE);  // Not available in CComboBoxEx
8907		return 0;
8908	}
8909
8910	int FindString(int /*nStartAfter*/, LPCTSTR /*lpszString*/) const
8911	{
8912		ATLASSERT(FALSE);  // Not available in CComboBoxEx; try FindStringExact
8913		return 0;
8914	}
8915};
8916
8917typedef CComboBoxExT<ATL::CWindow>   CComboBoxEx;
8918
8919
8920///////////////////////////////////////////////////////////////////////////////
8921// CMonthCalendarCtrl
8922
8923template <class TBase>
8924class CMonthCalendarCtrlT : public TBase
8925{
8926public:
8927// Constructors
8928	CMonthCalendarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
8929	{ }
8930
8931	CMonthCalendarCtrlT< TBase >& operator =(HWND hWnd)
8932	{
8933		this->m_hWnd = hWnd;
8934		return *this;
8935	}
8936
8937	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8938			DWORD dwStyle = 0, DWORD dwExStyle = 0,
8939			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8940	{
8941		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8942	}
8943
8944// Attributes
8945	static LPCTSTR GetWndClassName()
8946	{
8947		return MONTHCAL_CLASS;
8948	}
8949
8950	COLORREF GetColor(int nColorType) const
8951	{
8952		ATLASSERT(::IsWindow(this->m_hWnd));
8953		return (COLORREF)::SendMessage(this->m_hWnd, MCM_GETCOLOR, nColorType, 0L);
8954	}
8955
8956	COLORREF SetColor(int nColorType, COLORREF clr)
8957	{
8958		ATLASSERT(::IsWindow(this->m_hWnd));
8959		return (COLORREF)::SendMessage(this->m_hWnd, MCM_SETCOLOR, nColorType, clr);
8960	}
8961
8962	BOOL GetCurSel(LPSYSTEMTIME lpSysTime) const
8963	{
8964		ATLASSERT(::IsWindow(this->m_hWnd));
8965		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETCURSEL, 0, (LPARAM)lpSysTime);
8966	}
8967
8968	BOOL SetCurSel(LPSYSTEMTIME lpSysTime)
8969	{
8970		ATLASSERT(::IsWindow(this->m_hWnd));
8971		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETCURSEL, 0, (LPARAM)lpSysTime);
8972	}
8973
8974	int GetFirstDayOfWeek(BOOL* pbLocaleVal = NULL) const
8975	{
8976		ATLASSERT(::IsWindow(this->m_hWnd));
8977		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0L);
8978		if(pbLocaleVal != NULL)
8979			*pbLocaleVal = (BOOL)HIWORD(dwRet);
8980		return (int)(short)LOWORD(dwRet);
8981	}
8982
8983	int SetFirstDayOfWeek(int nDay, BOOL* pbLocaleVal = NULL)
8984	{
8985		ATLASSERT(::IsWindow(this->m_hWnd));
8986		DWORD dwRet = (DWORD)::SendMessage(this->m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, nDay);
8987		if(pbLocaleVal != NULL)
8988			*pbLocaleVal = (BOOL)HIWORD(dwRet);
8989		return (int)(short)LOWORD(dwRet);
8990	}
8991
8992	int GetMaxSelCount() const
8993	{
8994		ATLASSERT(::IsWindow(this->m_hWnd));
8995		return (int)::SendMessage(this->m_hWnd, MCM_GETMAXSELCOUNT, 0, 0L);
8996	}
8997
8998	BOOL SetMaxSelCount(int nMax)
8999	{
9000		ATLASSERT(::IsWindow(this->m_hWnd));
9001		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETMAXSELCOUNT, nMax, 0L);
9002	}
9003
9004	int GetMonthDelta() const
9005	{
9006		ATLASSERT(::IsWindow(this->m_hWnd));
9007		return (int)::SendMessage(this->m_hWnd, MCM_GETMONTHDELTA, 0, 0L);
9008	}
9009
9010	int SetMonthDelta(int nDelta)
9011	{
9012		ATLASSERT(::IsWindow(this->m_hWnd));
9013		return (int)::SendMessage(this->m_hWnd, MCM_SETMONTHDELTA, nDelta, 0L);
9014	}
9015
9016	DWORD GetRange(LPSYSTEMTIME lprgSysTimeArray) const
9017	{
9018		ATLASSERT(::IsWindow(this->m_hWnd));
9019		return (DWORD)::SendMessage(this->m_hWnd, MCM_GETRANGE, 0, (LPARAM)lprgSysTimeArray);
9020	}
9021
9022	BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray)
9023	{
9024		ATLASSERT(::IsWindow(this->m_hWnd));
9025		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
9026	}
9027
9028	BOOL GetSelRange(LPSYSTEMTIME lprgSysTimeArray) const
9029	{
9030		ATLASSERT(::IsWindow(this->m_hWnd));
9031		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
9032	}
9033
9034	BOOL SetSelRange(LPSYSTEMTIME lprgSysTimeArray)
9035	{
9036		ATLASSERT(::IsWindow(this->m_hWnd));
9037		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
9038	}
9039
9040	BOOL GetToday(LPSYSTEMTIME lpSysTime) const
9041	{
9042		ATLASSERT(::IsWindow(this->m_hWnd));
9043		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETTODAY, 0, (LPARAM)lpSysTime);
9044	}
9045
9046	void SetToday(LPSYSTEMTIME lpSysTime)
9047	{
9048		ATLASSERT(::IsWindow(this->m_hWnd));
9049		::SendMessage(this->m_hWnd, MCM_SETTODAY, 0, (LPARAM)lpSysTime);
9050	}
9051
9052	BOOL GetMinReqRect(LPRECT lpRectInfo) const
9053	{
9054		ATLASSERT(::IsWindow(this->m_hWnd));
9055		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETMINREQRECT, 0, (LPARAM)lpRectInfo);
9056	}
9057
9058	int GetMaxTodayWidth() const
9059	{
9060		ATLASSERT(::IsWindow(this->m_hWnd));
9061		return (int)::SendMessage(this->m_hWnd, MCM_GETMAXTODAYWIDTH, 0, 0L);
9062	}
9063
9064	BOOL GetUnicodeFormat() const
9065	{
9066		ATLASSERT(::IsWindow(this->m_hWnd));
9067		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETUNICODEFORMAT, 0, 0L);
9068	}
9069
9070	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
9071	{
9072		ATLASSERT(::IsWindow(this->m_hWnd));
9073		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETUNICODEFORMAT, bUnicode, 0L);
9074	}
9075
9076#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9077	DWORD GetCurrentView() const
9078	{
9079		ATLASSERT(::IsWindow(this->m_hWnd));
9080		return (DWORD)::SendMessage(this->m_hWnd, MCM_GETCURRENTVIEW, 0, 0L);
9081	}
9082
9083	BOOL SetCurrentView(DWORD dwView)
9084	{
9085		ATLASSERT(::IsWindow(this->m_hWnd));
9086		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETCURRENTVIEW, 0, dwView);
9087	}
9088
9089	DWORD GetCalendarCount() const
9090	{
9091		ATLASSERT(::IsWindow(this->m_hWnd));
9092		return (DWORD)::SendMessage(this->m_hWnd, MCM_GETCALENDARCOUNT, 0, 0L);
9093	}
9094
9095	BOOL GetCalendarGridInfo(PMCGRIDINFO pGridInfo) const
9096	{
9097		ATLASSERT(::IsWindow(this->m_hWnd));
9098		return (BOOL)::SendMessage(this->m_hWnd, MCM_GETCALENDARGRIDINFO, 0, (LPARAM)pGridInfo);
9099	}
9100
9101	CALID GetCALID() const
9102	{
9103		ATLASSERT(::IsWindow(this->m_hWnd));
9104		return (CALID)::SendMessage(this->m_hWnd, MCM_GETCALID, 0, 0L);
9105	}
9106
9107	void SetCALID(CALID calid)
9108	{
9109		ATLASSERT(::IsWindow(this->m_hWnd));
9110		::SendMessage(this->m_hWnd, MCM_SETCALID, (LPARAM)calid, 0L);
9111	}
9112
9113	int GetCalendarBorder() const
9114	{
9115		ATLASSERT(::IsWindow(this->m_hWnd));
9116		return (int)::SendMessage(this->m_hWnd, MCM_GETCALENDARBORDER, 0, 0L);
9117	}
9118
9119	void SetCalendarBorder(int cxyBorder, BOOL bSet = TRUE)
9120	{
9121		ATLASSERT(::IsWindow(this->m_hWnd));
9122		::SendMessage(this->m_hWnd, MCM_SETCALENDARBORDER, (WPARAM)bSet, (LPARAM)cxyBorder);
9123	}
9124#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9125
9126// Operations
9127	int GetMonthRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) const
9128	{
9129		ATLASSERT(::IsWindow(this->m_hWnd));
9130		return (int)::SendMessage(this->m_hWnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
9131	}
9132
9133	BOOL SetDayState(int nMonths, LPMONTHDAYSTATE lpDayStateArray)
9134	{
9135		ATLASSERT(::IsWindow(this->m_hWnd));
9136		return (BOOL)::SendMessage(this->m_hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM)lpDayStateArray);
9137	}
9138
9139	DWORD HitTest(PMCHITTESTINFO pMCHitTest) const
9140	{
9141		ATLASSERT(::IsWindow(this->m_hWnd));
9142		return (DWORD)::SendMessage(this->m_hWnd, MCM_HITTEST, 0, (LPARAM)pMCHitTest);
9143	}
9144
9145#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9146	void SizeRectToMin(LPRECT lpRect)
9147	{
9148		ATLASSERT(::IsWindow(this->m_hWnd));
9149		::SendMessage(this->m_hWnd, MCM_SIZERECTTOMIN, 0, (LPARAM)lpRect);
9150	}
9151#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9152};
9153
9154typedef CMonthCalendarCtrlT<ATL::CWindow>   CMonthCalendarCtrl;
9155
9156
9157///////////////////////////////////////////////////////////////////////////////
9158// CDateTimePickerCtrl
9159
9160template <class TBase>
9161class CDateTimePickerCtrlT : public TBase
9162{
9163public:
9164// Constructors
9165	CDateTimePickerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9166	{ }
9167
9168	CDateTimePickerCtrlT< TBase >& operator =(HWND hWnd)
9169	{
9170		this->m_hWnd = hWnd;
9171		return *this;
9172	}
9173
9174	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9175			DWORD dwStyle = 0, DWORD dwExStyle = 0,
9176			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9177	{
9178		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9179	}
9180
9181// Operations
9182	static LPCTSTR GetWndClassName()
9183	{
9184		return DATETIMEPICK_CLASS;
9185	}
9186
9187	BOOL SetFormat(LPCTSTR lpszFormat)
9188	{
9189		ATLASSERT(::IsWindow(this->m_hWnd));
9190		return (BOOL)::SendMessage(this->m_hWnd, DTM_SETFORMAT, 0, (LPARAM)lpszFormat);
9191	}
9192
9193	COLORREF GetMonthCalColor(int nColorType) const
9194	{
9195		ATLASSERT(::IsWindow(this->m_hWnd));
9196		return (COLORREF)::SendMessage(this->m_hWnd, DTM_GETMCCOLOR, nColorType, 0L);
9197	}
9198
9199	COLORREF SetMonthCalColor(int nColorType, COLORREF clr)
9200	{
9201		ATLASSERT(::IsWindow(this->m_hWnd));
9202		return (COLORREF)::SendMessage(this->m_hWnd, DTM_SETMCCOLOR, nColorType, clr);
9203	}
9204
9205	DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const
9206	{
9207		ATLASSERT(::IsWindow(this->m_hWnd));
9208		return (DWORD)::SendMessage(this->m_hWnd, DTM_GETRANGE, 0, (LPARAM)lpSysTimeArray);
9209	}
9210
9211	BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lpSysTimeArray)
9212	{
9213		ATLASSERT(::IsWindow(this->m_hWnd));
9214		return (BOOL)::SendMessage(this->m_hWnd, DTM_SETRANGE, dwFlags, (LPARAM)lpSysTimeArray);
9215	}
9216
9217	DWORD GetSystemTime(LPSYSTEMTIME lpSysTime) const
9218	{
9219		ATLASSERT(::IsWindow(this->m_hWnd));
9220		return (DWORD)::SendMessage(this->m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)lpSysTime);
9221	}
9222
9223	BOOL SetSystemTime(DWORD dwFlags, LPSYSTEMTIME lpSysTime)
9224	{
9225		ATLASSERT(::IsWindow(this->m_hWnd));
9226		return (BOOL)::SendMessage(this->m_hWnd, DTM_SETSYSTEMTIME, dwFlags, (LPARAM)lpSysTime);
9227	}
9228
9229	CMonthCalendarCtrl GetMonthCal() const
9230	{
9231		ATLASSERT(::IsWindow(this->m_hWnd));
9232		return CMonthCalendarCtrl((HWND)::SendMessage(this->m_hWnd, DTM_GETMONTHCAL, 0, 0L));
9233	}
9234
9235	CFontHandle GetMonthCalFont() const
9236	{
9237		ATLASSERT(::IsWindow(this->m_hWnd));
9238		return CFontHandle((HFONT)::SendMessage(this->m_hWnd, DTM_GETMCFONT, 0, 0L));
9239	}
9240
9241	void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE)
9242	{
9243		ATLASSERT(::IsWindow(this->m_hWnd));
9244		::SendMessage(this->m_hWnd, DTM_SETMCFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0));
9245	}
9246
9247#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9248	DWORD GetMonthCalStyle() const
9249	{
9250		ATLASSERT(::IsWindow(this->m_hWnd));
9251		return (DWORD)::SendMessage(this->m_hWnd, DTM_GETMCSTYLE, 0, 0L);
9252	}
9253
9254	DWORD SetMonthCalStyle(DWORD dwStyle)
9255	{
9256		ATLASSERT(::IsWindow(this->m_hWnd));
9257		return (DWORD)::SendMessage(this->m_hWnd, DTM_SETMCSTYLE, 0, (LPARAM)dwStyle);
9258	}
9259
9260	void GetDateTimePickerInfo(LPDATETIMEPICKERINFO lpPickerInfo) const
9261	{
9262		ATLASSERT(::IsWindow(this->m_hWnd));
9263		::SendMessage(this->m_hWnd, DTM_GETDATETIMEPICKERINFO, 0, (LPARAM)lpPickerInfo);
9264	}
9265
9266	BOOL GetIdealSize(LPSIZE lpSize) const
9267	{
9268		ATLASSERT(::IsWindow(this->m_hWnd));
9269		return (BOOL)::SendMessage(this->m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)lpSize);
9270	}
9271
9272	void CloseMonthCal()
9273	{
9274		ATLASSERT(::IsWindow(this->m_hWnd));
9275		::SendMessage(this->m_hWnd, DTM_CLOSEMONTHCAL, 0, 0L);
9276	}
9277#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9278};
9279
9280typedef CDateTimePickerCtrlT<ATL::CWindow>   CDateTimePickerCtrl;
9281
9282
9283///////////////////////////////////////////////////////////////////////////////
9284// CFlatScrollBarImpl - support for flat scroll bars
9285
9286template <class T>
9287class CFlatScrollBarImpl
9288{
9289public:
9290// Initialization
9291	BOOL FlatSB_Initialize()
9292	{
9293		T* pT = static_cast<T*>(this);
9294		ATLASSERT(::IsWindow(pT->m_hWnd));
9295		return ::InitializeFlatSB(pT->m_hWnd);
9296	}
9297
9298	HRESULT FlatSB_Uninitialize()
9299	{
9300		T* pT = static_cast<T*>(this);
9301		ATLASSERT(::IsWindow(pT->m_hWnd));
9302		return ::UninitializeFlatSB(pT->m_hWnd);
9303	}
9304
9305// Flat scroll bar properties
9306	BOOL FlatSB_GetScrollProp(UINT uIndex, LPINT lpnValue) const
9307	{
9308		const T* pT = static_cast<const T*>(this);
9309		ATLASSERT(::IsWindow(pT->m_hWnd));
9310		return ::FlatSB_GetScrollProp(pT->m_hWnd, uIndex, lpnValue);
9311	}
9312
9313	BOOL FlatSB_SetScrollProp(UINT uIndex, int nValue, BOOL bRedraw = TRUE)
9314	{
9315		T* pT = static_cast<T*>(this);
9316		ATLASSERT(::IsWindow(pT->m_hWnd));
9317		return ::FlatSB_SetScrollProp(pT->m_hWnd, uIndex, nValue, bRedraw);
9318	}
9319
9320// Attributes
9321	int FlatSB_GetScrollPos(int nBar) const
9322	{
9323		const T* pT = static_cast<const T*>(this);
9324		ATLASSERT(::IsWindow(pT->m_hWnd));
9325		return ::FlatSB_GetScrollPos(pT->m_hWnd, nBar);
9326	}
9327
9328	int FlatSB_SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
9329	{
9330		T* pT = static_cast<T*>(this);
9331		ATLASSERT(::IsWindow(pT->m_hWnd));
9332		return ::FlatSB_SetScrollPos(pT->m_hWnd, nBar, nPos, bRedraw);
9333	}
9334
9335	BOOL FlatSB_GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
9336	{
9337		const T* pT = static_cast<const T*>(this);
9338		ATLASSERT(::IsWindow(pT->m_hWnd));
9339		return ::FlatSB_GetScrollRange(pT->m_hWnd, nBar, lpMinPos, lpMaxPos);
9340	}
9341
9342	BOOL FlatSB_SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
9343	{
9344		T* pT = static_cast<T*>(this);
9345		ATLASSERT(::IsWindow(pT->m_hWnd));
9346		return ::FlatSB_SetScrollRange(pT->m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
9347	}
9348
9349	BOOL FlatSB_GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) const
9350	{
9351		const T* pT = static_cast<const T*>(this);
9352		ATLASSERT(::IsWindow(pT->m_hWnd));
9353		return ::FlatSB_GetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo);
9354	}
9355
9356	int FlatSB_SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
9357	{
9358		T* pT = static_cast<T*>(this);
9359		ATLASSERT(::IsWindow(pT->m_hWnd));
9360		return ::FlatSB_SetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo, bRedraw);
9361	}
9362
9363// Operations
9364	BOOL FlatSB_ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
9365	{
9366		T* pT = static_cast<T*>(this);
9367		ATLASSERT(::IsWindow(pT->m_hWnd));
9368		return ::FlatSB_ShowScrollBar(pT->m_hWnd, nBar, bShow);
9369	}
9370
9371	BOOL FlatSB_EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH)
9372	{
9373		T* pT = static_cast<T*>(this);
9374		ATLASSERT(::IsWindow(pT->m_hWnd));
9375		return ::FlatSB_EnableScrollBar(pT->m_hWnd, uSBFlags, uArrowFlags);
9376	}
9377};
9378
9379template <class TBase>
9380class CFlatScrollBarT : public TBase, public CFlatScrollBarImpl<CFlatScrollBarT< TBase > >
9381{
9382public:
9383	CFlatScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
9384	{ }
9385
9386	CFlatScrollBarT< TBase >& operator =(HWND hWnd)
9387	{
9388		this->m_hWnd = hWnd;
9389		return *this;
9390	}
9391};
9392
9393typedef CFlatScrollBarT<ATL::CWindow>   CFlatScrollBar;
9394
9395
9396///////////////////////////////////////////////////////////////////////////////
9397// CIPAddressCtrl
9398
9399template <class TBase>
9400class CIPAddressCtrlT : public TBase
9401{
9402public:
9403// Constructors
9404	CIPAddressCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9405	{ }
9406
9407	CIPAddressCtrlT< TBase >& operator =(HWND hWnd)
9408	{
9409		this->m_hWnd = hWnd;
9410		return *this;
9411	}
9412
9413	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9414			DWORD dwStyle = 0, DWORD dwExStyle = 0,
9415			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9416	{
9417		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9418	}
9419
9420// Atteributes
9421	static LPCTSTR GetWndClassName()
9422	{
9423		return WC_IPADDRESS;
9424	}
9425
9426	BOOL IsBlank() const
9427	{
9428		ATLASSERT(::IsWindow(this->m_hWnd));
9429		return (BOOL)::SendMessage(this->m_hWnd, IPM_ISBLANK, 0, 0L);
9430	}
9431
9432	int GetAddress(LPDWORD lpdwAddress) const
9433	{
9434		ATLASSERT(::IsWindow(this->m_hWnd));
9435		return (int)::SendMessage(this->m_hWnd, IPM_GETADDRESS, 0, (LPARAM)lpdwAddress);
9436	}
9437
9438	void SetAddress(DWORD dwAddress)
9439	{
9440		ATLASSERT(::IsWindow(this->m_hWnd));
9441		::SendMessage(this->m_hWnd, IPM_SETADDRESS, 0, dwAddress);
9442	}
9443
9444	void ClearAddress()
9445	{
9446		ATLASSERT(::IsWindow(this->m_hWnd));
9447		::SendMessage(this->m_hWnd, IPM_CLEARADDRESS, 0, 0L);
9448	}
9449
9450	void SetRange(int nField, WORD wRange)
9451	{
9452		ATLASSERT(::IsWindow(this->m_hWnd));
9453		::SendMessage(this->m_hWnd, IPM_SETRANGE, nField, wRange);
9454	}
9455
9456	void SetRange(int nField, BYTE nMin, BYTE nMax)
9457	{
9458		ATLASSERT(::IsWindow(this->m_hWnd));
9459		::SendMessage(this->m_hWnd, IPM_SETRANGE, nField, MAKEIPRANGE(nMin, nMax));
9460	}
9461
9462	void SetFocus(int nField)
9463	{
9464		ATLASSERT(::IsWindow(this->m_hWnd));
9465		::SendMessage(this->m_hWnd, IPM_SETFOCUS, nField, 0L);
9466	}
9467};
9468
9469typedef CIPAddressCtrlT<ATL::CWindow>   CIPAddressCtrl;
9470
9471
9472///////////////////////////////////////////////////////////////////////////////
9473// CPagerCtrl
9474
9475template <class TBase>
9476class CPagerCtrlT : public TBase
9477{
9478public:
9479// Constructors
9480	CPagerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9481	{ }
9482
9483	CPagerCtrlT< TBase >& operator =(HWND hWnd)
9484	{
9485		this->m_hWnd = hWnd;
9486		return *this;
9487	}
9488
9489	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9490			DWORD dwStyle = 0, DWORD dwExStyle = 0,
9491			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9492	{
9493		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9494	}
9495
9496// Attributes
9497	static LPCTSTR GetWndClassName()
9498	{
9499		return WC_PAGESCROLLER;
9500	}
9501
9502	int GetButtonSize() const
9503	{
9504		ATLASSERT(::IsWindow(this->m_hWnd));
9505		return (int)::SendMessage(this->m_hWnd, PGM_GETBUTTONSIZE, 0, 0L);
9506	}
9507
9508	int SetButtonSize(int nButtonSize)
9509	{
9510		ATLASSERT(::IsWindow(this->m_hWnd));
9511		return (int)::SendMessage(this->m_hWnd, PGM_SETBUTTONSIZE, 0, nButtonSize);
9512	}
9513
9514	DWORD GetButtonState(int nButton) const
9515	{
9516		ATLASSERT(::IsWindow(this->m_hWnd));
9517		ATLASSERT((nButton == PGB_TOPORLEFT) || (nButton == PGB_BOTTOMORRIGHT));
9518		return (DWORD)::SendMessage(this->m_hWnd, PGM_GETBUTTONSTATE, 0, nButton);
9519	}
9520
9521	COLORREF GetBkColor() const
9522	{
9523		ATLASSERT(::IsWindow(this->m_hWnd));
9524		return (COLORREF)::SendMessage(this->m_hWnd, PGM_GETBKCOLOR, 0, 0L);
9525	}
9526
9527	COLORREF SetBkColor(COLORREF clrBk)
9528	{
9529		ATLASSERT(::IsWindow(this->m_hWnd));
9530		return (COLORREF)::SendMessage(this->m_hWnd, PGM_SETBKCOLOR, 0, (LPARAM)clrBk);
9531	}
9532
9533	int GetBorder() const
9534	{
9535		ATLASSERT(::IsWindow(this->m_hWnd));
9536		return (int)::SendMessage(this->m_hWnd, PGM_GETBORDER, 0, 0L);
9537	}
9538
9539	int SetBorder(int nBorderSize)
9540	{
9541		ATLASSERT(::IsWindow(this->m_hWnd));
9542		return (int)::SendMessage(this->m_hWnd, PGM_SETBORDER, 0, nBorderSize);
9543	}
9544
9545	int GetPos() const
9546	{
9547		ATLASSERT(::IsWindow(this->m_hWnd));
9548		return (int)::SendMessage(this->m_hWnd, PGM_GETPOS, 0, 0L);
9549	}
9550
9551	int SetPos(int nPos)
9552	{
9553		ATLASSERT(::IsWindow(this->m_hWnd));
9554		return (int)::SendMessage(this->m_hWnd, PGM_SETPOS, 0, nPos);
9555	}
9556
9557// Operations
9558	void SetChild(HWND hWndChild)
9559	{
9560		ATLASSERT(::IsWindow(this->m_hWnd));
9561		::SendMessage(this->m_hWnd, PGM_SETCHILD, 0, (LPARAM)hWndChild);
9562	}
9563
9564	void ForwardMouse(BOOL bForward = TRUE)
9565	{
9566		ATLASSERT(::IsWindow(this->m_hWnd));
9567		::SendMessage(this->m_hWnd, PGM_FORWARDMOUSE, bForward, 0L);
9568	}
9569
9570	void RecalcSize()
9571	{
9572		ATLASSERT(::IsWindow(this->m_hWnd));
9573		::SendMessage(this->m_hWnd, PGM_RECALCSIZE, 0, 0L);
9574	}
9575
9576	void GetDropTarget(IDropTarget** ppDropTarget)
9577	{
9578		ATLASSERT(::IsWindow(this->m_hWnd));
9579		ATLASSERT(ppDropTarget != NULL);
9580		::SendMessage(this->m_hWnd, PGM_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
9581	}
9582};
9583
9584typedef CPagerCtrlT<ATL::CWindow>   CPagerCtrl;
9585
9586
9587///////////////////////////////////////////////////////////////////////////////
9588// CLinkCtrl - Windows SYSLINK control
9589
9590template <class TBase>
9591class CLinkCtrlT : public TBase
9592{
9593public:
9594// Constructors
9595	CLinkCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9596	{ }
9597
9598	CLinkCtrlT< TBase >& operator =(HWND hWnd)
9599	{
9600		this->m_hWnd = hWnd;
9601		return *this;
9602	}
9603
9604	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9605			DWORD dwStyle = 0, DWORD dwExStyle = 0,
9606			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9607	{
9608		return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9609	}
9610
9611// Attributes
9612	static LPCTSTR GetWndClassName()
9613	{
9614#ifdef _UNICODE
9615		return WC_LINK;
9616#else // !_UNICODE
9617		return "SysLink";
9618#endif // !_UNICODE
9619	}
9620
9621	int GetIdealHeight(int cxMaxWidth = 0) const
9622	{
9623		ATLASSERT(::IsWindow(this->m_hWnd));
9624		return (int)::SendMessage(this->m_hWnd, LM_GETIDEALHEIGHT, cxMaxWidth, 0L);
9625	}
9626
9627	BOOL GetItem(PLITEM pLItem) const
9628	{
9629		ATLASSERT(::IsWindow(this->m_hWnd));
9630		return (BOOL)::SendMessage(this->m_hWnd, LM_GETITEM, 0, (LPARAM)pLItem);
9631	}
9632
9633	BOOL SetItem(PLITEM pLItem)
9634	{
9635		ATLASSERT(::IsWindow(this->m_hWnd));
9636		return (BOOL)::SendMessage(this->m_hWnd, LM_SETITEM, 0, (LPARAM)pLItem);
9637	}
9638
9639	// Vista only
9640	int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const
9641	{
9642		ATLASSERT(::IsWindow(this->m_hWnd));
9643		return (int)::SendMessage(this->m_hWnd, LM_GETIDEALSIZE, cxMaxWidth, (LPARAM)&size);
9644	}
9645
9646// Operations
9647	BOOL HitTest(PLHITTESTINFO pLHitTestInfo) const
9648	{
9649		ATLASSERT(::IsWindow(this->m_hWnd));
9650		return (BOOL)::SendMessage(this->m_hWnd, LM_HITTEST, 0, (LPARAM)pLHitTestInfo);
9651	}
9652};
9653
9654typedef CLinkCtrlT<ATL::CWindow>   CLinkCtrl;
9655
9656
9657///////////////////////////////////////////////////////////////////////////////
9658// CCustomDraw - MI class for custom-draw support
9659
9660template <class T>
9661class CCustomDraw
9662{
9663public:
9664// Message map and handlers
9665	BEGIN_MSG_MAP(CCustomDraw< T >)
9666		NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
9667	ALT_MSG_MAP(1)
9668		REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
9669	END_MSG_MAP()
9670
9671// message handler
9672	LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
9673	{
9674		T* pT = static_cast<T*>(this);
9675		pT->SetMsgHandled(TRUE);
9676		LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh;
9677		DWORD dwRet = 0;
9678		switch(lpNMCustomDraw->dwDrawStage)
9679		{
9680		case CDDS_PREPAINT:
9681			dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw);
9682			break;
9683		case CDDS_POSTPAINT:
9684			dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw);
9685			break;
9686		case CDDS_PREERASE:
9687			dwRet = pT->OnPreErase(idCtrl, lpNMCustomDraw);
9688			break;
9689		case CDDS_POSTERASE:
9690			dwRet = pT->OnPostErase(idCtrl, lpNMCustomDraw);
9691			break;
9692		case CDDS_ITEMPREPAINT:
9693			dwRet = pT->OnItemPrePaint(idCtrl, lpNMCustomDraw);
9694			break;
9695		case CDDS_ITEMPOSTPAINT:
9696			dwRet = pT->OnItemPostPaint(idCtrl, lpNMCustomDraw);
9697			break;
9698		case CDDS_ITEMPREERASE:
9699			dwRet = pT->OnItemPreErase(idCtrl, lpNMCustomDraw);
9700			break;
9701		case CDDS_ITEMPOSTERASE:
9702			dwRet = pT->OnItemPostErase(idCtrl, lpNMCustomDraw);
9703			break;
9704		case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
9705			dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw);
9706			break;
9707		default:
9708			pT->SetMsgHandled(FALSE);
9709			break;
9710		}
9711		bHandled = pT->IsMsgHandled();
9712		return dwRet;
9713	}
9714
9715// Overrideables
9716	DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9717	{
9718		return CDRF_DODEFAULT;
9719	}
9720
9721	DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9722	{
9723		return CDRF_DODEFAULT;
9724	}
9725
9726	DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9727	{
9728		return CDRF_DODEFAULT;
9729	}
9730
9731	DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9732	{
9733		return CDRF_DODEFAULT;
9734	}
9735
9736	DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9737	{
9738		return CDRF_DODEFAULT;
9739	}
9740
9741	DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9742	{
9743		return CDRF_DODEFAULT;
9744	}
9745
9746	DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9747	{
9748		return CDRF_DODEFAULT;
9749	}
9750
9751	DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9752	{
9753		return CDRF_DODEFAULT;
9754	}
9755
9756	DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
9757	{
9758		return CDRF_DODEFAULT;
9759	}
9760};
9761
9762} // namespace WTL
9763
9764#endif // __ATLCTRLS_H__