WinapiExtension
 All Classes Files Functions Variables Typedefs Pages
control.h
1 #ifndef WINAPI_EX_CONTROL_H
2 #define WINAPI_EX_CONTROL_H
3 
4 namespace WinapiExtension
5 {
6  // both combobox and edit controls have cue banners
7  template<UINT MESSAGE>
8  const TCHAR* GetCueBanner(HWND handle, std::vector<TCHAR>& buffer)
9  {
10  // don't risk integer overflow
11  for(DWORD len = 256; len < 0x8000000; len *= 2)
12  {
13  buffer.resize(len);
14  BOOL success = (BOOL)SendMessage(handle, MESSAGE, (WPARAM)&buffer[0], len);
15  if(!success){
16  buffer[0] = _T('\0');
17  break;
18  }
19  // if the buffer is completely full, the text could have been truncated
20  if(_tcslen(&buffer[0]) < size_t(len - 1))
21  break;
22  }
23  return &buffer[0];
24  }
25 
26  // both combobox and listbox have this message
27  template<UINT GETLENGTH_MESSAGE, UINT GET_MESSAGE>
28  const TCHAR* GetListBoxText(HWND handle, int index, std::vector<TCHAR>& buffer)
29  {
30  LRESULT len = SendMessage(handle, GETLENGTH_MESSAGE, index, 0);
31  if(len < 0)
32  buffer.push_back(_T('\0'));
33  else
34  {
35  buffer.resize(len + 1);
36  SendMessage(handle, GET_MESSAGE, index, (LPARAM)&buffer[0]);
37  }
38 
39  return &buffer[0];
40  }
41 }
42 
57 class Control : public IWindow
58 {
59 public:
61  Control(HWND hwnd = NULL) : handle(hwnd) {}
63  Control& operator= (HWND hwnd) { handle = hwnd; return *this; }
65  operator HWND() { return handle; }
66 
67  HWND handle;
69  HWND _InternalGetHandle() { return handle; }
70 };
71 
75 class Button : public Control
76 {
77 public:
79  Button(HWND hwnd = NULL) : Control(hwnd) {}
80 
82  bool IsChecked() { return SendMessage(handle, BM_GETCHECK, 0, 0) == BST_CHECKED; }
84  void SetChecked(bool check) { SendMessage(handle, BM_SETCHECK, check ? BST_CHECKED : BST_UNCHECKED, 0); }
85 
87  void SetBitmap(HBITMAP bitmap) { SendMessage(handle, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmap); }
89  HBITMAP GetBitmap() { return (HBITMAP)SendMessage(handle, BM_GETIMAGE, IMAGE_BITMAP, 0); }
90 
92  void Click() { SendMessage(handle, BM_CLICK, 0, 0); }
93 
94 #ifdef WINAPI_EX_COMMCTRL
95 
98  void Shrink()
99  {
100  Size idealSize(0, 0);
101  // this function only works if the common control library is linked
102  // otherwise it will return false and do nothing
103  BOOL idealSizeReturned = Button_GetIdealSize(handle, &idealSize);
104 
105  // this can only fail if comctrl32.lib was not linked
106  assert(idealSizeReturned);
107 
108  if(idealSizeReturned)
109  {
110  Rect buttonRect = RectOnParent();
111  idealSize.cx = idealSize.cx < buttonRect.Width() ? idealSize.cx : buttonRect.Width();
112  Move(buttonRect.left, buttonRect.top, idealSize.cx, buttonRect.Height());
113  }
114  }
115 #endif // WINAPI_EX_COMMCTRL
116 };
117 
119 class ComboBox : public Control
120 {
121 public:
123  ComboBox(HWND hwnd = NULL) : Control(hwnd) {}
124 
126  int AddString(const tstring& text)
127  {
128  return (int)SendMessage(handle, CB_ADDSTRING, 0, (LPARAM)text.c_str());
129  }
130 
132  int DeleteString(int index)
133  {
134  return (int)SendMessage(handle, CB_DELETESTRING, index, 0);
135  }
136 
138  int FindString(const tstring& text, int startIndex = -1)
139  {
140  return (int)SendMessage(handle, CB_FINDSTRING, startIndex, (LPARAM)text.c_str());
141  }
142 
144  int FindStringExact(const tstring& text, int startIndex = -1)
145  {
146  return (int)SendMessage(handle, CB_FINDSTRINGEXACT, startIndex, (LPARAM)text.c_str());
147  }
148 
150  int GetCount()
151  {
152  return (int)SendMessage(handle, CB_GETCOUNT, 0, 0);
153  }
154 
157  {
158  RECT r;
159  SendMessage(handle, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
160  return r;
161  }
162 
165  {
166  return SendMessage(handle, CB_GETDROPPEDSTATE, 0, 0) == TRUE;
167  }
168 
170  tstring GetLBText(int index)
171  {
172  std::vector<TCHAR> buffer;
173  return WinapiExtension::GetListBoxText<CB_GETLBTEXTLEN, CB_GETLBTEXT>(handle, index, buffer);
174  }
175 
177  int InsertString(int index, const tstring& text)
178  {
179  return (int)SendMessage(handle, CB_INSERTSTRING, index, (LPARAM)text.c_str());
180  }
181 
183  void LimitText(int limit)
184  {
185  SendMessage(handle, CB_LIMITTEXT, limit, 0);
186  }
187 
190  {
191  (int)SendMessage(handle, CB_RESETCONTENT, 0, 0);
192  }
193 
195  void ShowDropDown(BOOL show)
196  {
197  SendMessage(handle, CB_SHOWDROPDOWN, show, 0);
198  }
199 
200 #ifdef CB_GETCUEBANNER
201 
202  tstring GetCueBanner()
203  {
204  std::vector<TCHAR> buffer;
205  return WinapiExtension::GetCueBanner<CB_GETCUEBANNER>(handle, buffer);
206  }
208  void SetCueBanner(const tstring& text)
209  {
210  SendMessage(handle, CB_SETCUEBANNER, 0, (LPARAM)text.c_str());
211  }
212 #endif
213 
214 #ifdef CB_GETMINVISIBLE
215 
218  int GetMinVisible() { return (int)SendMessage(handle, CB_GETMINVISIBLE, 0, 0); }
222  BOOL SetMinVisible(int count) { return (BOOL)SendMessage(handle, CB_SETMINVISIBLE, count, 0); }
223 #endif
224 
226  int GetCurSel() { return (int)SendMessage(handle, CB_GETCURSEL, 0, 0); }
228  int SetCurSel(int index) { return (int)SendMessage(handle, CB_SETCURSEL, index, 0); }
229 
231  int GetDroppedWidth() { return (int)SendMessage(handle, CB_GETDROPPEDWIDTH, 0, 0); }
233  int SetDroppedWidth(int width) { return (int)SendMessage(handle, CB_SETDROPPEDWIDTH, width, 0); }
234 
236  void GetEditSel(DWORD* start, DWORD* end) { SendMessage(handle, CB_GETEDITSEL, (WPARAM)start, (LPARAM)end); }
238  BOOL SetEditSel(SHORT start, SHORT end) { return (BOOL)SendMessage(handle, CB_SETEDITSEL, 0, MAKELPARAM(start, end)); }
239 
241  BOOL GetExtendedUI() { return SendMessage(handle, CB_GETEXTENDEDUI, 0, 0) == TRUE; }
243  BOOL SetExtendedUI(BOOL extended) { return SendMessage(handle, CB_SETEXTENDEDUI, extended, 0) != CB_ERR; }
244 
246  int GetHorizontalExtent() { return (int)SendMessage(handle, CB_GETHORIZONTALEXTENT, 0, 0); }
248  void SetHorizontalExtent(int scrollableWidth) { SendMessage(handle, CB_SETHORIZONTALEXTENT, scrollableWidth, 0); }
249 
251  LONG_PTR GetItemData(int index) { return SendMessage(handle, CB_GETITEMDATA, index, 0); }
253  BOOL SetItemData(int index, LONG_PTR data) { return SendMessage(handle, CB_SETITEMDATA, index, data) != CB_ERR; }
254 
256  LCID GetLocale() { return (LCID)SendMessage(handle, CB_GETLOCALE, 0, 0); }
258  LCID SetLocale(LCID locale) { return (LCID)SendMessage(handle, CB_SETLOCALE, locale, 0); }
259 
261  int GetTopIndex() { return (int)SendMessage(handle, CB_GETTOPINDEX, 0, 0); }
263  BOOL SetTopIndex(int index) { return (int)SendMessage(handle, CB_SETTOPINDEX, index, 0) != CB_ERR; }
264 
265  // unimplemented functions
266  // CB_DIR
267  // CB_GETCOMBOBOXINFO
268  // CB_INITSTORAGE
269  // CB_GETITEMHEIGHT
270  // CB_SETITEMHEIGHT
271 };
272 
274 class Edit : public Control
275 {
276 public:
278  Edit(HWND hwnd = NULL) : Control(hwnd) {}
279 
281  BOOL CanUndo()
282  {
283  return SendMessage(handle, EM_CANUNDO, 0, 0) > 0;
284  }
285 
288  {
289  SendMessage(handle, EM_EMPTYUNDOBUFFER, 0, 0);
290  }
291 
293  void FmtLines(BOOL allowSoftLinebreaks)
294  {
295  SendMessage(handle, EM_FMTLINES, allowSoftLinebreaks, 0);
296  }
297 
300  {
301  return (int)SendMessage(handle, EM_GETFIRSTVISIBLELINE, 0, 0);
302  }
303 
306  {
307  return (int)SendMessage(handle, EM_GETLINECOUNT, 0, 0);
308  }
309 
311  LRESULT GetThumb()
312  {
313  return SendMessage(handle, EM_GETTHUMB, 0, 0);
314  }
315 
317  int LineFromChar(int charIndex)
318  {
319  return (int)SendMessage(handle, EM_LINEFROMCHAR, charIndex, 0);
320  }
322  int CurrentLine() { return LineFromChar(-1); }
323 
325  int LineIndex(int line)
326  {
327  return (int)SendMessage(handle, EM_LINEINDEX, line, 0);
328  }
330  int CurrentCharIndex() { return LineIndex(-1); }
331 
333  tstring GetLine(int line)
334  {
335  std::vector<TCHAR> buffer;
336 
337  WORD len = (WORD)SendMessage(handle, EM_LINELENGTH, LineIndex(line), 0);
338  buffer.resize(len + 1);
339  *(WORD*)(&buffer[0]) = len;
340 
341  SendMessage(handle, EM_GETLINE, line, (LPARAM)&buffer[0]);
342 
343  return &buffer[0];
344  }
345 
347  BOOL LineScroll(int scrollChars, int scrollLines)
348  {
349  return (BOOL)SendMessage(handle, EM_LINESCROLL, scrollChars, scrollLines);
350  }
351 
353  Point PosFromChar(int charIndex)
354  {
355  LRESULT ret = SendMessage(handle, EM_POSFROMCHAR, charIndex, 0);
356  return Point(LOWORD(ret), HIWORD(ret));
357  }
358 
360  void ReplaceSel(const tstring& text, BOOL canUndo = TRUE)
361  {
362  SendMessage(handle, EM_REPLACESEL, canUndo, (LPARAM)text.c_str());
363  }
364 
366  void ScrollCaret()
367  {
368  SendMessage(handle, EM_SCROLLCARET, 0, 0);
369  }
370 
371 #ifdef EM_HIDEBALLOONTIP
372 
373  BOOL HideBalloonTip() { return (BOOL)SendMessage(handle, EM_HIDEBALLOONTIP, 0, 0); }
375  BOOL ShowBalloonTip(EDITBALLOONTIP& tip) { return (BOOL)SendMessage(handle, EM_SHOWBALLOONTIP, 0, (LPARAM)&tip); }
376 #endif
377 
378 #ifdef EM_GETCUEBANNER
379 
380  tstring GetCueBanner()
381  {
382  std::vector<TCHAR> buffer;
383  return WinapiExtension::GetCueBanner<EM_GETCUEBANNER>(handle, buffer);
384  }
386  void SetCueBanner(const tstring& text, BOOL showOnFocus = FALSE)
387  {
388  SendMessage(handle, EM_SETCUEBANNER, showOnFocus, (LPARAM)text.c_str());
389  }
390 #endif
391 
393  LRESULT GetLimitText() { return SendMessage(handle, EM_GETLIMITTEXT, 0, 0); }
397  void SetLimitText(int maxChars) { SendMessage(handle, EM_SETLIMITTEXT, maxChars, 0); }
398 
400  BOOL GetModify() { return (BOOL)SendMessage(handle, EM_GETMODIFY, 0, 0); }
402  void SetModify(BOOL modified) { SendMessage(handle, EM_SETMODIFY, modified, 0); }
403 
405  TCHAR GetPasswordChar() { return (TCHAR)SendMessage(handle, EM_GETPASSWORDCHAR, 0, 0); }
407  void SetPasswordChar(TCHAR c) { SendMessage(handle, EM_SETPASSWORDCHAR, c, 0); }
408 
410  BOOL GetSel(DWORD* selectionStart, DWORD* selectionEnd) { return SendMessage(handle, EM_GETSEL, (WPARAM)selectionStart, (LPARAM)selectionEnd) != -1; }
412  void SetSel(int selectionStart, int selectionEnd) { SendMessage(handle, EM_SETSEL, selectionStart, selectionEnd); }
414  void SetSelAll() { SetSel(0, -1); }
416  void SetSelNone() { SetSel(-1, 0); }
417 
419  EDITWORDBREAKPROC GetWordBreakProc() { return (EDITWORDBREAKPROC)SendMessage(handle, EM_GETWORDBREAKPROC, 0, 0); }
421  void SetWordBreakProc(EDITWORDBREAKPROC proc) { SendMessage(handle, EM_SETWORDBREAKPROC, 0, (LPARAM)proc); }
422 
423  // not implemented
424  // EM_CHARFROMPOS
425  // EM_GETLINE
426  // EM_LIMITTEXT
427  // EM_LINELENGTH
428  // EM_SCROLL
429  // EM_GETHANDLE
430  // EM_SETHANDLE
431  // EM_GETTIMESTATUS
432  // EM_SETTIMESTATUS
433  // EM_GETMARGINS
434  // EM_SETMARGINS
435  // EM_GETRECT
436  // EM_SETRECT
437 };
438 
440 class ListBox : public Control
441 {
442 public:
444  ListBox(HWND hwnd = NULL) : Control(hwnd) {}
445 
447  int AddString(const tstring& text)
448  {
449  return (int)SendMessage(handle, LB_ADDSTRING, 0, (LPARAM)text.c_str());
450  }
451 
453  int DeleteString(int index)
454  {
455  return (int)SendMessage(handle, LB_DELETESTRING, index, 0);
456  }
457 
459  int FindString(const tstring& text, int precedingIndex = -1)
460  {
461  return (int)SendMessage(handle, LB_FINDSTRING, precedingIndex, (LPARAM)text.c_str());
462  }
463 
465  int FindStringExact(const tstring& text, int precedingIndex = -1)
466  {
467  return (int)SendMessage(handle, LB_FINDSTRINGEXACT, precedingIndex, (LPARAM)text.c_str());
468  }
469 
471  BOOL GetItemRect(int index, RECT& r)
472  {
473  return SendMessage(handle, LB_GETITEMRECT, index, (LPARAM)&r) != LB_ERR;
474  }
475 
478  {
479  return (int)SendMessage(handle, LB_GETSELCOUNT, 0, 0);
480  }
481 
483  BOOL GetSelItems(std::vector<LONG_PTR>& items)
484  {
485  LRESULT count = GetSelCount();
486  if(count == LB_ERR)
487  return FALSE;
488 
489  items.resize(count);
490  LRESULT ret = SendMessage(handle, LB_GETSELITEMS, count, (LPARAM)&items[0]);
491  if(ret == LB_ERR)
492  return FALSE;
493 
494  return TRUE;
495  }
496 
498  tstring GetItemText(int index)
499  {
500  std::vector<TCHAR> buffer;
501  return WinapiExtension::GetListBoxText<LB_GETTEXTLEN, LB_GETTEXT>(handle, index, buffer);
502  }
503 
505  int InsertString(int index, const tstring& text)
506  {
507  return (int)SendMessage(handle, LB_INSERTSTRING, index, (LPARAM)text.c_str());
508  }
509 
511  WORD ItemFromPoint(POINT relativePos, BOOL& outside)
512  {
513  LRESULT ret = SendMessage(handle, LB_ITEMFROMPOINT, 0, MAKELPARAM(relativePos.x, relativePos.y));
514  outside = HIWORD(ret);
515  return LOWORD(ret);
516  }
517 
520  {
521  SendMessage(handle, LB_RESETCONTENT, 0, 0);
522  }
523 
525  int SelectString(const tstring& text, int precedingIndex)
526  {
527  return (int)SendMessage(handle, LB_SELECTSTRING, precedingIndex, (LPARAM)text.c_str());
528  }
529 
531  BOOL SelItemRange(DWORD first, DWORD last, BOOL select)
532  {
533  return SendMessage(handle, LB_SELITEMRANGE, select, MAKELPARAM(first, last)) != LB_ERR;
534  }
535 
537  int GetAnchorIndex() { return (int)SendMessage(handle, LB_GETANCHORINDEX, 0, 0); }
539  BOOL SetAnchorIndex(int index) { return SendMessage(handle, LB_SETANCHORINDEX, index, 0) != LB_ERR; }
540 
542  int GetCaretIndex() { return (int)SendMessage(handle, LB_GETCARETINDEX, 0, 0); }
544  BOOL SetCaretIndex(int index, BOOL scrollPartiallyIntoView = TRUE) { return SendMessage(handle, LB_SETCARETINDEX, index, scrollPartiallyIntoView) != LB_ERR; }
545 
547  int GetCount() { return (int)SendMessage(handle, LB_GETCOUNT, 0, 0); }
549  BOOL SetCount(int count) { return SendMessage(handle, LB_SETCOUNT, count, 0) < 0; }
550 
552  int GetCurSel() { return (int)SendMessage(handle, LB_GETCURSEL, 0, 0); }
554  int SetCurSel(int index) { return (int)SendMessage(handle, LB_SETCURSEL, index, 0); }
555 
557  int GetHorizontalExtent() { return (int)SendMessage(handle, LB_GETHORIZONTALEXTENT, 0, 0); }
559  void SetHorizontalExtent(int scrollableWidth) { SendMessage(handle, LB_SETHORIZONTALEXTENT, scrollableWidth, 0); }
560 
562  LONG_PTR GetItemData(int index) { return SendMessage(handle, LB_GETITEMDATA, index, 0); }
564  BOOL SetItemData(int index, LONG_PTR data) { return SendMessage(handle, LB_SETITEMDATA, index, data) != LB_ERR; }
565 
567  int GetItemHeight(int index) { return (int)SendMessage(handle, LB_GETITEMHEIGHT, index, 0); }
569  BOOL SetItemHeight(int index, BYTE height) { return SendMessage(handle, LB_SETITEMHEIGHT, index, height) != LB_ERR; }
570 
572  LCID GetLocale() { return (LCID)SendMessage(handle, LB_GETLOCALE, 0, 0); }
574  LCID SetLocale(LCID locale) { return (LCID)SendMessage(handle, LB_SETLOCALE, locale, 0); }
575 
577  BOOL GetSel(int index) { return SendMessage(handle, LB_GETSEL, index, 0) > 0; }
579  BOOL SetSel(int index, BOOL select) { return SendMessage(handle, LB_SETSEL, select, index) != LB_ERR; }
580 
582  int GetTopIndex() { return (int)SendMessage(handle, LB_GETTOPINDEX, 0, 0); }
584  BOOL SetTopIndex(int index) { return SendMessage(handle, LB_SETTOPINDEX, index, 0) != LB_ERR; }
585 
586  // not implemented
587  // LB_ADDFILE
588  // LB_DIR
589  // LB_GETLISTBOXINFO
590  // LB_INITSTORAGE
591  // LB_SETTABSTOPS
592 };
593 
595 class ScrollBar : public Control
596 {
597 public:
599  ScrollBar(HWND hwnd = NULL, int scrollBarType = SB_CTL) : Control(hwnd), bar(scrollBarType) {}
604  void Reset(HWND hwnd, int scrollBarType = SB_CTL) { handle = hwnd; bar = scrollBarType; }
605 
607  int GetPos() { return GetScrollPos(handle, bar); }
609  int SetPos(int pos, BOOL redraw = TRUE) { return SetScrollPos(handle, bar, pos, redraw); }
610 
612  BOOL GetRange(int* minPos, int* maxPos) { return GetScrollRange(handle, bar, minPos, maxPos); }
614  BOOL SetRange(int minPos, int maxPos, BOOL redraw = TRUE) { return SetScrollRange(handle, bar, minPos, maxPos, redraw); }
615 
617  BOOL GetScrollInfo(SCROLLINFO& info) { return ::GetScrollInfo(handle, bar, &info); }
619  int SetScrollInfo(SCROLLINFO& info, BOOL redraw = TRUE) { return ::SetScrollInfo(handle, bar, &info, redraw); }
620 
621  int bar;
622 };
623 
625 class StaticCtrl : public Control
626 {
627 public:
629  StaticCtrl(HWND hwnd = NULL) : Control(hwnd) {}
630 
634  void Shrink()
635  {
636  tstring text = GetText();
637 
638  ClientDC dc(handle);
639  SaveRestoreDC save(dc);
640  dc.SetFont(GetFont());
641 
642  int textWidth = dc.GetTextSize(text, 0, 0).cx;
643 
644  Rect rectOnParent = RectOnParent();
645 
646  int newWidth = textWidth < rectOnParent.Width() ? textWidth : rectOnParent.Width();
647 
648  Move(rectOnParent.left, rectOnParent.top, newWidth, rectOnParent.Height());
649  }
650 
652  HBITMAP GetBitmap() { return (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); }
654  HBITMAP SetBitmap(HBITMAP bitmap) { return (HBITMAP)SendMessage(handle, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmap); }
655 
657  HCURSOR GetCursor() { return (HCURSOR)SendMessage(handle, STM_GETIMAGE, IMAGE_CURSOR, 0); }
659  HCURSOR SetCursor(HCURSOR cursor) { return (HCURSOR)SendMessage(handle, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)cursor); }
660 
662  HENHMETAFILE GetEnhMetaFile() { return (HENHMETAFILE)SendMessage(handle, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0); }
664  HENHMETAFILE SetEnhMetaFile(HENHMETAFILE metafile) { return (HENHMETAFILE)SendMessage(handle, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)metafile); }
665 
667  HICON GetIcon() { return (HICON)SendMessage(handle, STM_GETIMAGE, IMAGE_ICON, 0); }
669  HICON SetIcon(HICON icon) { return (HICON)SendMessage(handle, STM_SETIMAGE, IMAGE_ICON, (LPARAM)icon); }
670 };
671 
672 #ifdef WINAPI_EX_COMMCTRL
673 
675 class ListView : public Control
676 {
677 public:
679  ListView(HWND hwnd = NULL) : Control(hwnd) {}
680 
684  struct ColumnData : public LVCOLUMN
685  {
686  ColumnData() { ZeroMemory(this, sizeof(ColumnData)); }
687 
688  ColumnData& GetFmt() { mask |= LVCF_FMT; return *this; }
689  ColumnData& SetFmt(int pFmt) { mask |= LVCF_FMT; fmt = pFmt; return *this; }
690  ColumnData& GetWidth() { mask |= LVCF_WIDTH; return *this; }
691  ColumnData& SetWidth(int width) { mask |= LVCF_WIDTH; cx = width; return *this; }
692  ColumnData& GetText(TCHAR* buffer, int bufferSize) { mask |= LVCF_TEXT; pszText = buffer; cchTextMax = bufferSize; return *this; }
693  ColumnData& SetText(const TCHAR* text) { mask |= LVCF_TEXT; pszText = const_cast<TCHAR*>(text); return *this; }
694  ColumnData& GetSubItem() { mask |= LVCF_SUBITEM; return *this; }
695  ColumnData& SetSubItem(int subitem) { mask |= LVCF_SUBITEM; iSubItem = subitem; return *this; }
696  };
697 
701  struct ItemData : public LVITEM
702  {
703  ItemData() { ZeroMemory(this, sizeof(ItemData)); }
704 
705  ItemData& Item(int item, int subItem) { iItem = item; iSubItem = subItem; return *this; }
706  ItemData& GetText(TCHAR* buffer, int bufferSize) { mask |= LVIF_TEXT; pszText = buffer; cchTextMax = bufferSize; return *this; }
707  ItemData& SetText(const TCHAR* text) { mask |= LVIF_TEXT; pszText = const_cast<TCHAR*>(text); return *this; }
708  ItemData& GetParam() { mask |= LVIF_PARAM; return *this; }
709  ItemData& SetParam(LPARAM param) { mask |= LVIF_PARAM; lParam = param; return *this; }
710  ItemData& GetState(UINT pStateMask) { mask |= LVIF_STATE; stateMask = pStateMask; return *this; }
711  ItemData& SetState(UINT pState, UINT pStateMask) { mask |= LVIF_STATE; state = pState; stateMask = pStateMask; return *this; }
712  };
713 
715  int GetColumnCount() { return Header_GetItemCount(GetHeader()); }
716 
718  void GetColumn(int index, ColumnData& data) { ListView_GetColumn(handle, index, &data); }
720  void SetColumn(int index, ColumnData& data) { ListView_SetColumn(handle, index, &data); }
721 
723  int InsertColumn(int index, ColumnData& data) { return ListView_InsertColumn(handle, index, &data); }
725  int InsertColumn(int index, const tstring& text, int format = LVCFMT_LEFT, int width = LVSCW_AUTOSIZE_USEHEADER)
726  {
727  ColumnData data;
728  data.SetText(text.c_str()).SetFmt(format);
729  // only set the width if the user specified one
730  // otherwise the column will have minimum width
731  if(width != LVSCW_AUTOSIZE_USEHEADER)
732  data.SetWidth(width);
733  return InsertColumn(index, data);
734  }
735 
737  int AppendColumn(const tstring& text, int format = LVCFMT_LEFT, int width = LVSCW_AUTOSIZE_USEHEADER)
738  {
739  return InsertColumn(GetColumnCount(), text, format, width);
740  }
741 
743  void DeleteColumn(int index) { ListView_DeleteColumn(handle, index); }
744 
750  void SetColumnWidth(int index, int width) { ListView_SetColumnWidth(handle, index, width); }
752  int GetColumnWidth(int index) { return ListView_GetColumnWidth(handle, index); }
753 
757  void AutoSizeColumns(int col = -1)
758  {
759  SetRedraw(FALSE);
760  int start = col < 0 ? 0 : col;
761  int end = col < 0 ? GetColumnCount() : col + 1;
762  for(int c = start; c < end; ++c)
763  {
764  SetColumnWidth(c, LVSCW_AUTOSIZE);
765  int w1 = GetColumnWidth(c);
766  SetColumnWidth(c, LVSCW_AUTOSIZE_USEHEADER);
767  int w2 = GetColumnWidth(c);
768 
769  int w = w1 > w2 ? w1 : w2;
770  SetColumnWidth(c, w);
771  }
772  SetRedraw(TRUE);
773  }
774 
776  int GetItemCount() { return ListView_GetItemCount(handle); }
778  void SetItemCount(int count) { ListView_SetItemCount(handle, count); }
779 
783  void GetItem(ItemData& data) { ListView_GetItem(handle, &data); }
784 
788  void SetItem(ItemData& data) { ListView_SetItem(handle, &data); }
790  void SetItem(int index, int column, const tstring& text) { SetItem(ItemData().Item(index, column).SetText(text.c_str())); }
791 
795  int InsertItem(ItemData& data) { return ListView_InsertItem(handle, &data); }
797  int InsertItem(int index, const tstring& text) { return InsertItem( ItemData().Item(index, 0).SetText(text.c_str()) ); }
798 
800  int AppendItem(const tstring& text) { return InsertItem(GetItemCount(), text); }
801 
803  void DeleteItem(int index) { ListView_DeleteItem(handle, index); }
804 
806  UINT GetItemState(int index, LPARAM stateMask) { return ListView_GetItemState(handle, index, stateMask); }
808  void SetItemState(int index, UINT state, UINT stateMask) { ListView_SetItemState(handle, index, state, stateMask); }
809 
811  tstring GetItemText(int index, int column = 0)
812  {
813  std::vector<TCHAR> buffer;
814  ItemData data;
815  data.Item(index, column);
816 
817  for(DWORD len = 256; len < 0x8000000; len *= 2)
818  {
819  buffer.resize(len);
820  data.GetText(&buffer[0], len);
821  DWORD ret = (int)SendMessage(handle, LVM_GETITEMTEXT, index, (LPARAM)&data);
822  // try again until the buffer isn't completely filled
823  if(ret < len - 1)
824  break;
825  }
826  return &buffer[0];
827  }
829  void SetItemText(const tstring& text, int index, int column = 0)
830  {
831  ListView_SetItemText(handle, index, column, const_cast<TCHAR*>(text.c_str()));
832  }
833 
835  BOOL IsItemSelected(int item) { return GetItemState(item, LVIS_SELECTED) != 0; }
837  void SelectItem(BOOL select, int item) { SetItemState(item, select ? LVIS_SELECTED : 0, LVIS_SELECTED); }
838 
842  HWND BeginEdit(int index) { return ListView_EditLabel(handle, index); }
844  void EndEdit() { BeginEdit(-1); }
845 
847  COLORREF GetBkColor() { return ListView_GetBkColor(handle); }
849  void SetBkColor(COLORREF color) { ListView_SetBkColor(handle, color); }
850 
852  COLORREF GetTextColor() { return ListView_GetTextColor(handle); }
854  void SetTextColor(COLORREF color) { ListView_SetTextColor(handle, color); }
855 
857  COLORREF GetTextBkColor() { return ListView_GetTextBkColor(handle); }
859  void SetTextBkColor(COLORREF color) { ListView_SetTextBkColor(handle, color); }
860 
864  HWND GetHeader() { return ListView_GetHeader(handle); }
865 
869  void EnsureVisible(int index, BOOL partialOk = FALSE) { ListView_EnsureVisible(handle, index, partialOk); }
870 
872  void SortItems(PFNLVCOMPARE compare, LPARAM param) { ListView_SortItems(handle, compare, param); }
873 };
874 
876 class ProgressBar : public Control
877 {
878 public:
880  ProgressBar(HWND hwnd = NULL) : Control(hwnd) {}
881 
883  LRESULT DeltaPos(LONG_PTR delta) { return SendMessage(handle, PBM_DELTAPOS, delta, 0); }
884 
886  void SetMarquee(BOOL on, LONG_PTR updateInterval = 0)
887  {
888  // need to send the message AND change the style, otherwise it won't work
889  ModifyStyle(on ? PBS_MARQUEE : 0, on ? 0 : PBS_MARQUEE);
890  SendMessage(handle, PBM_SETMARQUEE, on, updateInterval);
891  }
892 
894  LRESULT StepIt() { return SendMessage(handle, PBM_STEPIT, 0, 0); }
895 
897  LRESULT GetPos() { return SendMessage(handle, PBM_GETPOS, 0, 0); }
899  LRESULT SetPos(LONG_PTR newPos) { return SendMessage(handle, PBM_SETPOS, newPos, 0); }
900 
902  LRESULT GetRangeMin() { return SendMessage(handle, PBM_GETRANGE, TRUE, 0); }
904  LRESULT GetRangeMax() { return SendMessage(handle, PBM_GETRANGE, FALSE, 0); }
906  void SetRange(LONG_PTR min, LONG_PTR max) { SendMessage(handle, PBM_SETRANGE32, min, max); }
907 
909  LRESULT GetState() { return SendMessage(handle, PBM_GETSTATE, 0, 0); }
911  LRESULT SetState(WPARAM state) { return SendMessage(handle, PBM_SETSTATE, state, 0); }
912 
914  LRESULT GetStep() { return SendMessage(handle, PBM_GETSTEP, 0, 0); }
916  LRESULT SetStep(LONG_PTR step) { return SendMessage(handle, PBM_SETSTEP, step, 0); }
917 
918  // not implemented
919  // PBM_GETBARCOLOR
920  // PBM_SETBARCOLOR
921  // PBM_GETBKCOLOR
922  // PBM_SETBKCOLOR
923 };
924 
926 class StatusBar : public Control
927 {
928 public:
930  StatusBar(HWND hwnd = NULL) : Control(hwnd) {}
931 
933  BOOL GetBorders(int& horizontalBorder, int& verticalBorder, int& borderBetweenParts)
934  {
935  int buffer[3] = { horizontalBorder, verticalBorder, borderBetweenParts };
936  BOOL ret = (BOOL)SendMessage(handle, SB_GETBORDERS, 0, (LPARAM)buffer);
937  horizontalBorder = buffer[0];
938  verticalBorder = buffer[1];
939  borderBetweenParts = buffer[2];
940  return ret;
941  }
942 
944  BOOL GetRect(LONG_PTR part, RECT& r)
945  {
946  return (BOOL)SendMessage(handle, SB_GETRECT, part, (LPARAM)&r);
947  }
948 
950  HICON GetIcon(LONG_PTR part) { return (HICON)SendMessage(handle, SB_GETICON, part, 0); }
952  BOOL SetIcon(LONG_PTR part, HICON icon) { return (BOOL)SendMessage(handle, SB_SETICON, part, (LPARAM)icon); }
953 
955  void GetParts(std::vector<int>& partCoordinates)
956  {
957  LRESULT numParts = SendMessage(handle, SB_GETPARTS, 0, 0);
958  partCoordinates.resize(numParts);
959  SendMessage(handle, SB_GETPARTS, numParts, (LPARAM)&partCoordinates[0]);
960  }
962  BOOL SetParts(int* partCoordinates, int numParts)
963  {
964  return (BOOL)SendMessage(handle, SB_SETPARTS, numParts, (LPARAM)partCoordinates);
965  }
966 
968  BOOL GetSimple() { return (BOOL)SendMessage(handle, SB_ISSIMPLE, 0, 0); }
970  void SetSimple(BOOL simpleMode) { SendMessage(handle, SB_SIMPLE, simpleMode, 0); }
971 
973  tstring GetText(LONG_PTR part)
974  {
975  std::vector<TCHAR> buffer;
976  WORD len = LOWORD(SendMessage(handle, SB_GETTEXTLENGTH, part, 0));
977  buffer.resize(len + 1);
978  SendMessage(handle, SB_GETTEXT, part, (LPARAM)&buffer[0]);
979  return &buffer[0];
980  }
982  BOOL SetText(BYTE part, const tstring& text, BYTE drawingOperation = 0)
983  {
984  return (BOOL)SendMessage(handle, SB_SETTEXT, MAKEWPARAM(MAKEWORD(part, drawingOperation), 0), (LPARAM)text.c_str());
985  }
986 
988  tstring GetTipText(WORD part, WORD bufferSize = 256)
989  {
990  std::vector<TCHAR> buffer;
991  buffer.resize(bufferSize);
992  SendMessage(handle, SB_GETTIPTEXT, MAKEWPARAM(part, bufferSize), (LPARAM)&buffer[0]);
993  return &buffer[0];
994  }
996  void SetTipText(LONG_PTR part, const tstring& text)
997  {
998  SendMessage(handle, SB_SETTIPTEXT, part, (LPARAM)text.c_str());
999  }
1000 };
1001 
1003 class TabCtrl : public Control
1004 {
1005 public:
1007  TabCtrl(HWND hwnd = NULL) : Control(hwnd) {}
1008 
1012  Rect CalculateDisplayArea(const RECT& windowRect)
1013  {
1014  Rect r = windowRect;
1015  TabCtrl_AdjustRect(handle, FALSE, &r);
1016  return r;
1017  }
1018 
1024 
1028  Rect CalculateWindowRect(const RECT& displayArea)
1029  {
1030  Rect r = displayArea;
1031  TabCtrl_AdjustRect(handle, TRUE, &r);
1032  return r;
1033  }
1034 
1036  int GetItemCount() { return TabCtrl_GetItemCount(handle); }
1037 
1039  int InsertItem(int index, const TCITEM& item) { return TabCtrl_InsertItem(handle, index, &item); }
1041  int InsertItem(int index, const tstring& text)
1042  {
1043  TCITEM item;
1044  item.mask |= TCIF_TEXT;
1045  item.pszText = const_cast<TCHAR*>(text.c_str());
1046  return InsertItem(index, item);
1047  }
1048 
1050  int AppendItem(const tstring& text) { return InsertItem(GetItemCount(), text); }
1051 
1053  void DeleteItem(int index) { TabCtrl_DeleteItem(handle, index); }
1055  void DeleteAllItems() { TabCtrl_DeleteAllItems(handle); }
1056 
1058  void GetItem(int index, TCITEM& item) { TabCtrl_GetItem(handle, index, &item); }
1059 
1061  void SetItem(int index, TCITEM& item) { TabCtrl_SetItem(handle, index, &item); }
1063  void SetItem(int index, const tstring& text)
1064  {
1065  TCITEM item;
1066  item.mask |= TCIF_TEXT;
1067  item.pszText = const_cast<TCHAR*>(text.c_str());
1068  SetItem(index, item);
1069  }
1070 
1074  Rect GetItemRect(int index)
1075  {
1076  Rect r;
1077  TabCtrl_GetItemRect(handle, index, &r);
1078  return r;
1079  }
1080 
1084  void SetItemSize(int width, int height) { TabCtrl_SetItemSize(handle, width, height); }
1085 
1087  void SetMinTabWidth(int width) { TabCtrl_SetMinTabWidth(handle, width); }
1088 
1090  void SetPadding(int width, int height) { TabCtrl_SetPadding(handle, width, height); }
1091 
1095  int GetRowCount() { return TabCtrl_GetRowCount(handle); }
1096 
1098  int GetCurSel() { return TabCtrl_GetCurSel(handle); }
1100  int SetCurSel(int index) { return TabCtrl_SetCurSel(handle, index); }
1101 
1105  int GetCurFocus() { return TabCtrl_GetCurFocus(handle); }
1109  void SetCurFocus(int index) { TabCtrl_SetCurFocus(handle, index); }
1110 
1112  void DeselectAll(BOOL excludeFocus = TRUE) { TabCtrl_DeselectAll(handle, excludeFocus); }
1113 };
1114 
1116 class TreeView : public Control
1117 {
1118 public:
1120  TreeView(HWND hwnd = NULL) : Control(hwnd) {}
1121 
1125  struct ItemData : public TVITEM
1126  {
1127  ItemData() { ZeroMemory(this, sizeof(ItemData)); }
1128 
1129  ItemData& Handle(HTREEITEM handle) { mask |= TVIF_HANDLE; hItem = handle; return *this; }
1130  ItemData& GetText(TCHAR* buffer, int bufferSize) { mask |= TVIF_TEXT; pszText = buffer; cchTextMax = bufferSize; return *this; }
1131  ItemData& SetText(const TCHAR* text) { mask |= TVIF_TEXT; pszText = const_cast<TCHAR*>(text); return *this; }
1132  ItemData& GetParam() { mask |= TVIF_PARAM; return *this; }
1133  ItemData& SetParam(LPARAM param) { mask |= TVIF_PARAM; lParam = param; return *this; }
1134  ItemData& GetState(UINT pStateMask) { mask |= TVIF_STATE; stateMask = pStateMask; return *this; }
1135  ItemData& SetState(UINT pState, UINT pStateMask) { mask |= TVIF_STATE; state = pState; stateMask = pStateMask; return *this; }
1136  };
1137 
1141  struct Item
1142  {
1144  Item(HTREEITEM pItem, HWND pTree) : item(pItem), tree(pTree) {}
1146  Item(const Item& other) { item = other.item; tree = other.tree; }
1148  Item& operator=(const Item& other) { item = other.item; tree = other.tree; return *this; }
1149 
1151  operator HTREEITEM() { return item; }
1152 
1154  Item InsertItem(HTREEITEM insertAfter, const ItemData& data)
1155  {
1156  TVINSERTSTRUCT is = {0};
1157  is.hParent = item;
1158  is.hInsertAfter = insertAfter;
1159  is.item = data;
1160  return Item(TreeView_InsertItem(tree, &is), tree);
1161  }
1162 
1164  Item InsertItemFirst(const ItemData& data) { return InsertItem(TVI_FIRST, data); }
1166  Item InsertItemLast(const ItemData& data) { return InsertItem(TVI_LAST, data); }
1168  Item InsertItemSort(const ItemData& data) { return InsertItem(TVI_SORT, data); }
1169 
1171  void GetData(ItemData& data) { data.Handle(item); TreeView_GetItem(tree, &data); }
1173  void SetData(ItemData& data) { data.Handle(item); TreeView_SetItem(tree, &data); }
1174 
1177  {
1178  std::vector<TCHAR> buffer;
1179  ItemData data;
1180 
1181  for(DWORD len = 256; len < 0x8000000; len *= 2)
1182  {
1183  buffer.resize(len);
1184  GetData(ItemData().GetText(&buffer[0], (int)buffer.size()));
1185  // try again until the buffer isn't completely filled
1186  if(_tcslen(&buffer[0]) < len - 1)
1187  break;
1188  }
1189  return &buffer[0];
1190  }
1192  void SetText(const TCHAR* text) { SetData(ItemData().SetText(text)); }
1193 
1195  LPARAM GetParam()
1196  {
1197  ItemData data;
1198  GetData(data.GetParam());
1199  return data.lParam;
1200  }
1202  void SetParam(LPARAM param) { SetData(ItemData().SetParam(param)); }
1203 
1205  UINT GetState(UINT stateMask)
1206  {
1207  ItemData data;
1208  GetData(data.GetState(stateMask));
1209  return data.state;
1210  }
1212  void SetState(UINT state, UINT stateMask) { SetData(ItemData().SetState(state, stateMask)); }
1213 
1215  void Select() { TreeView_SelectItem(tree, item); }
1216 
1218  Item GetNextItem(WPARAM flag) { return Item(TreeView_GetNextItem(tree, item, flag), tree); }
1220  Item GetParent() { return GetNextItem(TVGN_PARENT); }
1222  Item GetFirstChild() { return GetNextItem(TVGN_CHILD); }
1224  Item GetPrevious() { return GetNextItem(TVGN_PREVIOUS); }
1226  Item GetNext() { return GetNextItem(TVGN_NEXT); }
1227 
1229  void BeginEdit() { TreeView_EditLabel(tree, item); }
1230 
1239  void Expand(WPARAM flag = TVE_EXPAND) { TreeView_Expand(tree, item, flag); }
1240 
1242  BOOL GetRect(RECT& r, BOOL onlyText = FALSE) { return TreeView_GetItemRect(tree, item, &r, onlyText); }
1243 
1245  void SortChildren(BOOL recursive = FALSE) { TreeView_SortChildren(tree, item, recursive); }
1246 
1248  void SortChildrenCallback(PFNTVCOMPARE callback, LPARAM param, BOOL recursive = FALSE)
1249  {
1250  TVSORTCB sort = {0};
1251  sort.hParent = item;
1252  sort.lpfnCompare = callback;
1253  sort.lParam = param;
1254  TreeView_SortChildrenCB(tree, &sort, recursive);
1255  }
1256 
1257  HTREEITEM item;
1258  HWND tree;
1259  };
1260 
1262  Item InsertItem(HTREEITEM parent, HTREEITEM insertAfter, const ItemData& item)
1263  {
1264  TVINSERTSTRUCT is = {0};
1265  is.hParent = parent;
1266  is.hInsertAfter = insertAfter;
1267  is.item = item;
1268  return Item(TreeView_InsertItem(handle, &is), handle);
1269  }
1270 
1272  Item InsertItemRoot(const ItemData& data) { return InsertItem(TVI_ROOT, TVI_ROOT, data); }
1274  Item InsertItemFirst(HTREEITEM parent, const ItemData& data) { return InsertItem(parent, TVI_FIRST, data); }
1276  Item InsertItemLast(HTREEITEM parent, const ItemData& data) { return InsertItem(parent, TVI_LAST, data); }
1278  Item InsertItemSort(HTREEITEM parent, const ItemData& data) { return InsertItem(parent, TVI_SORT, data); }
1279 
1281  void DeleteItem(HTREEITEM item) { TreeView_DeleteItem(handle, item); }
1283  void DeleteAllItems() { TreeView_DeleteAllItems(handle); }
1284 
1286  UINT GetCount() { return TreeView_GetCount(handle); }
1287 
1289  Item GetNextItem(WPARAM flag, HTREEITEM item) { return Item(TreeView_GetNextItem(handle, item, flag), handle); }
1291  Item GetRoot() { return GetNextItem(TVGN_ROOT, 0); }
1293  Item GetSelection() { return GetNextItem(TVGN_CARET, 0); }
1294 
1298  HWND GetEditControl() { return TreeView_GetEditControl(handle); }
1299 
1301  COLORREF GetBkColor() { return TreeView_GetBkColor(handle); }
1303  void SetBkColor(COLORREF color) { TreeView_SetBkColor(handle, color); }
1304 
1306  COLORREF GetTextColor() { return TreeView_GetTextColor(handle); }
1308  void SetTextColor(COLORREF color) { TreeView_SetTextColor(handle, color); }
1309 };
1310 
1311 #endif // WINAPI_EX_COMMCTRL
1312 
1313 #endif