comnctrl.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:15k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * comnctrl.cxx
  3.  *
  4.  * Common control interactor classes implementation.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: comnctrl.cxx,v $
  30.  * Revision 1.5  1999/04/18 14:21:40  robertj
  31.  * MSVC 5 backward compatibility
  32.  *
  33.  * Revision 1.4  1999/02/16 08:08:07  robertj
  34.  * MSVC 6.0 compatibility changes.
  35.  *
  36.  * Revision 1.3  1998/09/24 03:42:34  robertj
  37.  * Added open software license.
  38.  *
  39.  * Revision 1.2  1998/09/22 15:09:14  robertj
  40.  * Added OnDraw functions.
  41.  *
  42.  * Revision 1.1  1998/09/21 14:02:34  robertj
  43.  * Initial revision
  44.  *
  45.  */
  46. #include <pwlib.h>
  47. #include <commctrl.h>
  48. typedef struct _DllVersionInfo {         DWORD cbSize; 
  49.         DWORD dwMajorVersion;                   // Major version 
  50.         DWORD dwMinorVersion;                   // Minor version 
  51.         DWORD dwBuildNumber;                    // Build number 
  52.         DWORD dwPlatformID;                     // DLLVER_PLATFORM_* 
  53. } DLLVERSIONINFO; 
  54. typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
  55. static HRESULT GetComCtlVersion(DWORD & dwMajor, DWORD & dwMinor)
  56. {
  57.   //load the DLL
  58.   HINSTANCE hComCtl = LoadLibrary(TEXT("comctl32.dll"));
  59.   if (hComCtl == NULL)
  60.     return E_FAIL;
  61.   HRESULT hr = S_OK;
  62.   DLLGETVERSIONPROC pDllGetVersion;
  63.   /* You must get this function explicitly because earlier versions of the DLL 
  64.   don't implement this function. That makes the lack of implementation of the 
  65.   function a version marker in itself.   */
  66.   pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, TEXT("DllGetVersion"));
  67.   if (pDllGetVersion) {
  68.     DLLVERSIONINFO dvi;
  69.     ZeroMemory(&dvi, sizeof(dvi));
  70.     dvi.cbSize = sizeof(dvi);
  71.     hr = (*pDllGetVersion)(&dvi);
  72.     if (SUCCEEDED(hr)) {
  73.       dwMajor = dvi.dwMajorVersion;
  74.       dwMinor = dvi.dwMinorVersion;
  75.     }
  76.     else {
  77.       hr = E_FAIL;
  78.     }
  79.    }
  80.    else {
  81.     /* If GetProcAddress failed, then the DLL is a version previous to the one
  82.        shipped with IE 3.x.      */
  83.     dwMajor = 4;
  84.     dwMinor = 0;
  85.   }
  86.   FreeLibrary(hComCtl);
  87.   return hr;
  88. }
  89. //////////////////////////////////////////////////////////////////////////////
  90. // PListViewControl
  91. PListViewControl::PListViewControl(PInteractor * parent,
  92.                                    unsigned styles,
  93.                                    PINDEX columnCount,
  94.                                    const char * const * headings)
  95.   : PControl(parent, PNotifier(), NULL)
  96. {
  97.   DWORD maj, min;
  98.   GetComCtlVersion(maj, min);
  99.   defaultStyles = styles;
  100.   deleteObjects = TRUE;
  101.   numColumns = 0;
  102.   for (PINDEX col = 0; col < columnCount; col++) {
  103.     if (headings != NULL)
  104.       InsertColumn(headings[col]);
  105.     else
  106.       InsertColumn(psprintf("%u", col+1));
  107.   }
  108.   if (headings != NULL)
  109.     SetColumnHeading(0, headings[0]);
  110.   SetForegroundColour(parent->GetForegroundColour());
  111.   SetBackgroundColour(parent->GetBackgroundColour());
  112. }
  113. void PListViewControl::SetForegroundColour(const PColour & newColour)
  114. {
  115.   PControl::SetForegroundColour(newColour);
  116.   ::SendMessage(GetHWND(), LVM_SETTEXTCOLOR, 0, newColour.ToCOLORREF());
  117. }
  118. void PListViewControl::SetBackgroundColour(const PColour & newColour)
  119. {
  120.   PControl::SetBackgroundColour(newColour);
  121.   ::SendMessage(GetHWND(), LVM_SETBKCOLOR, 0, newColour.ToCOLORREF());
  122.   ::SendMessage(_hWnd, LVM_SETTEXTBKCOLOR, 0, newColour.ToCOLORREF());
  123. }
  124. void PListViewControl::TransferValue(int option)
  125. {
  126.   if (valuePointer != NULL)
  127.     if (option == NotifyUpdate)
  128.       SetSelection(*(PINDEX *)valuePointer);
  129.     else
  130.       *(PINDEX *)valuePointer = GetSelection();
  131. }
  132. void PListViewControl::AllowDeleteObjects(BOOL yes)
  133. {
  134.   deleteObjects = yes;
  135. }
  136. LRESULT PListViewControl::LVChangeItem(int action,
  137.                                        PListViewItem * obj,
  138.                                        PINDEX index,
  139.                                        BOOL update)
  140. {
  141.   SendMessage(GetHWND(), WM_SETREDRAW, update && numColumns == 1, 0L);
  142.   LVITEM lv;
  143.   lv.iItem = index;
  144.   lv.iSubItem = 0;
  145.   lv.mask = LVIF_TEXT;
  146.   if (obj == NULL)
  147.     obj = GetEntry(index);
  148.   else {
  149.     lv.mask |= LVIF_PARAM;
  150.     lv.lParam = (DWORD)obj;
  151.   }
  152.   PString str = obj->GetColumn(0);
  153.   lv.pszText = str.GetPointer();
  154.   LRESULT retval = SendMessage(_hWnd, action, 0, (DWORD)&lv);
  155.   if (action == LVM_INSERTITEM)
  156.     lv.iItem = retval;
  157.   lv.mask = LVIF_TEXT;
  158.   for (PINDEX col = 1; col < numColumns; col++) {
  159.     lv.iSubItem = col;
  160.     str = obj->GetColumn(col);
  161.     lv.pszText = str.GetPointer();
  162.     if (update && col == numColumns - 1)
  163.       SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  164.     SendMessage(_hWnd, LVM_SETITEM, 0, (DWORD)&lv);
  165.   }
  166.   if (!update)
  167.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  168.   return retval;
  169. }
  170. PINDEX PListViewControl::AddEntry(PListViewItem * obj, BOOL update)
  171. {
  172.   if (PAssertNULL(obj) != NULL)
  173.     return (PINDEX)LVChangeItem(LVM_INSERTITEM, obj, P_MAX_INDEX, update);
  174.   return -1;
  175. }
  176. void PListViewControl::AddEntries(const PCollection & objects, BOOL update)
  177. {
  178.   PINDEX last = objects.GetSize() - 1;
  179.   for (PINDEX i = 0; i <= last; i++) {
  180.     PObject * obj = objects.GetAt(i);
  181.     if (obj->IsDescendant(PListViewItem::Class()))
  182.       AddEntry((PListViewItem*)obj, update && i < last);
  183.   }
  184. }
  185. void PListViewControl::InsertEntry(PListViewItem * obj, PINDEX index, BOOL update)
  186. {
  187.   if (PAssertNULL(obj) != NULL)
  188.     LVChangeItem(LVM_INSERTITEM, obj, index, update);
  189. }
  190. void PListViewControl::DeleteEntry(PINDEX index, BOOL update)
  191. {
  192.   SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);
  193.   BOOL doNotify = GetSelection() == index;
  194.   SendMessage(_hWnd, LVM_DELETEITEM, index, 0L);
  195.   if (!update)
  196.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  197.   if (doNotify)
  198.     parent->OnControlNotify(*this, NewSelection);
  199. }
  200. void PListViewControl::DeleteAllEntries(BOOL update)
  201. {
  202.   SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);
  203.   BOOL doNotify = GetSelection() != P_MAX_INDEX;
  204.   SendMessage(_hWnd, LVM_DELETEALLITEMS, 0, 0L);
  205.   if (!update)
  206.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  207.   if (doNotify)
  208.     parent->OnControlNotify(*this, NewSelection);
  209. }
  210. PINDEX PListViewControl::FindEntry(const PListViewItem & obj, PINDEX startIndex) const
  211. {
  212.   if (startIndex == P_MAX_INDEX)
  213.     startIndex = -1;
  214.   PString str = obj.GetColumn(0);
  215.   LVFINDINFO lv;
  216.   lv.flags = LVFI_STRING;
  217.   lv.psz = str.GetPointer();
  218.   long retVal = SendMessage(GetHWND(), LVM_FINDITEM, startIndex, (DWORD)&lv);
  219.   return retVal != -1 ? (PINDEX)retVal : P_MAX_INDEX;
  220. }
  221. void PListViewControl::UpdateEntry(PINDEX index, BOOL update)
  222. {
  223.   LVChangeItem(LVM_SETITEM, NULL, index, update);
  224. }
  225. void PListViewControl::SetEntry(PListViewItem * obj, PINDEX index, BOOL update)
  226. {
  227.   BOOL doNotify = GetSelection() == index;
  228.   LVChangeItem(LVM_SETITEM, obj, index, update);
  229.   if (doNotify)
  230.     parent->OnControlNotify(*this, NewSelection);
  231. }
  232. PListViewItem * PListViewControl::GetEntry(PINDEX index) const
  233. {
  234.   LVITEM lv;
  235.   lv.mask = LVIF_PARAM;
  236.   lv.iItem = index;
  237.   lv.iSubItem = 0;
  238.   long retVal = SendMessage(GetHWND(), LVM_GETITEM, 0, (LPARAM)&lv);
  239.   return retVal ? (PListViewItem *)lv.lParam : NULL;
  240. }
  241. PINDEX PListViewControl::GetCount() const
  242. {
  243.   return (PINDEX)SendMessage(GetHWND(), LVM_GETITEMCOUNT, 0, 0L);
  244. }
  245. PINDEX PListViewControl::GetTopIndex() const
  246. {
  247. return (PINDEX)SendMessage(GetHWND(), LVM_GETTOPINDEX, 0, 0L);
  248. }
  249. void PListViewControl::InsertColumn(const PString & heading, PINDEX before, BOOL update)
  250. {
  251.   SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);
  252.   LVCOLUMN lvc;
  253.   lvc.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
  254.   lvc.pszText = (LPSTR)(const char *)heading;
  255.   lvc.fmt = LVCFMT_LEFT;
  256.   lvc.cx = GetStringWidth(heading+"    ");
  257.   lvc.iSubItem = numColumns++;
  258.   SendMessage(_hWnd, LVM_INSERTCOLUMN, before, (DWORD)&lvc);
  259.   for (PINDEX entry = 0; entry < GetCount(); entry++) {
  260.     LVITEM lv;
  261.     lv.mask = LVIF_TEXT|LVCF_SUBITEM;
  262.     lv.iItem = entry;
  263.     lv.iSubItem = lvc.iSubItem;
  264.     PString str = GetEntry(entry)->GetColumn(lvc.iSubItem);
  265.     lv.pszText = str.GetPointer();
  266.     SendMessage(_hWnd, LVM_SETITEM, 0, (DWORD)&lv);
  267.   }
  268.   if (!update)
  269.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  270. }
  271. void PListViewControl::DeleteColumn(PINDEX column, BOOL update)
  272. {
  273.   SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);
  274.   SendMessage(_hWnd, LVM_DELETECOLUMN, column, 0);
  275.   numColumns--;
  276.   if (!update)
  277.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  278. }
  279. PINDEX PListViewControl::GetColumnCount()
  280. {
  281.   return numColumns;
  282. }
  283. void PListViewControl::SetColumnHeading(PINDEX column, const PString & str)
  284. {
  285.   LVCOLUMN lv;
  286.   lv.mask = LVCF_TEXT;
  287.   lv.pszText = (LPSTR)(const char *)str;
  288.   SendMessage(GetHWND(), LVM_SETCOLUMN, column, (DWORD)&lv);
  289. }
  290. PDIMENSION PListViewControl::GetColumnWidth(PINDEX column)
  291. {
  292.   return (PDIMENSION)SendMessage(GetHWND(), LVM_GETCOLUMNWIDTH, column, 0L);
  293. }
  294. void PListViewControl::SetColumnWidth(PINDEX column, PDIMENSION newWidth, BOOL update)
  295. {
  296.   SendMessage(_hWnd, WM_SETREDRAW, update, 0L);
  297.   if (newWidth == 0)
  298.     newWidth = (PDIMENSION)LVSCW_AUTOSIZE_USEHEADER;
  299.   SendMessage(_hWnd, LVM_SETCOLUMNWIDTH, column, newWidth);
  300.   if (!update)
  301.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  302. }
  303. PDIMENSION PListViewControl::GetStringWidth(const PString & str)
  304. {
  305.   return (PDIMENSION)SendMessage(GetHWND(), LVM_GETSTRINGWIDTH, 0, (DWORD)(const char *)str);
  306. }
  307. void PListViewControl::SetSelection(PINDEX index)
  308. {
  309.   PINDEX last = GetCount() - 1;
  310.   for (PINDEX entry = 0; entry <= last; entry++)
  311.     Select(entry, entry == last, entry == index);
  312.   parent->OnControlNotify(*this, NewSelection);
  313. }
  314. PINDEX PListViewControl::GetSelection() const
  315. {
  316.   PINDEX last = GetCount() - 1;
  317.   for (PINDEX entry = 0; entry <= last; entry++) {
  318.     if (IsSelected(entry))
  319.       return entry;
  320.   }
  321.   return P_MAX_INDEX;
  322. }
  323. void PListViewControl::Select(PINDEX index, BOOL update, BOOL sel)
  324. {
  325.   SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);
  326.   LVITEM lv;
  327.   lv.stateMask = LVIS_SELECTED;
  328.   lv.state = sel ? LVIS_SELECTED : 0;
  329.   SendMessage(_hWnd, LVM_SETITEMSTATE, index, (DWORD)&lv);
  330.   if (!update)
  331.     SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
  332. }
  333. BOOL PListViewControl::IsSelected(PINDEX index) const
  334. {
  335.   return SendMessage(GetHWND(), LVM_GETITEMSTATE, index, LVIS_SELECTED) != 0;
  336. }
  337. PINDEX PListViewControl::GetSelCount() const
  338. {
  339.   return (PINDEX)SendMessage(GetHWND(), LVM_GETSELECTEDCOUNT, 0, 0);
  340. }
  341. static int CALLBACK LVCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  342. {
  343.   PListViewItem * obj1 = (PListViewItem *)lParam1;
  344.   PListViewItem * obj2 = (PListViewItem *)lParam2;
  345.   return obj1->GetColumn(lParamSort).Compare(obj2->GetColumn(lParamSort));
  346. }
  347. void PListViewControl::OnColumnClick(PINDEX column)
  348. {
  349.   SendMessage(GetHWND(), LVM_SORTITEMS, column, (DWORD)LVCompareFunc);
  350. }
  351. void PListViewControl::OnRightClick(PINDEX)
  352. {
  353. }
  354. void PListViewControl::OnBeginDrag(BOOL, PINDEX)
  355. {
  356. }
  357. BOOL PListViewControl::OnDrawControl(PCanvas &, BOOL)
  358. {
  359.   return FALSE;
  360. }
  361. BOOL PListViewControl::OnDrawEntry(PINDEX, PINDEX, PListViewItem &, PCanvas &, unsigned)
  362. {
  363.   return FALSE;
  364. }
  365. void PListViewControl::GetCreateWinInfo(WNDCLASS & wndClass)
  366. {
  367.   PControl::GetCreateWinInfo(wndClass);
  368.   wndClass.lpszClassName = WC_LISTVIEW;
  369.   if ((defaultStyles&ShowHeadings) == 0)
  370.     _styleBits |= LVS_NOCOLUMNHEADER;
  371.   if ((defaultStyles&CanHeadingSort) == 0)
  372.     _styleBits |= LVS_NOSORTHEADER;
  373.   if ((defaultStyles&SingleSelection) != 0)
  374.     _styleBits |= LVS_SINGLESEL;
  375.   _styleBits |= WS_BORDER|WS_HSCROLL|WS_VSCROLL|LVS_REPORT;
  376. }
  377. int PListViewControl::LVCustomDraw(NMHDR & msg)
  378. {
  379.   NMLVCUSTOMDRAW & draw = (NMLVCUSTOMDRAW &)msg;
  380.   PDrawCanvas canvas((PListViewControl*)this, draw.nmcd.hdc, FALSE, TRUE);
  381.   switch (draw.nmcd.dwDrawStage) {
  382.     case CDDS_PREPAINT :
  383.       if (OnDrawControl(canvas, FALSE))
  384.         return CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
  385.       break;
  386.     case CDDS_POSTPAINT :
  387.       OnDrawControl(canvas, TRUE);
  388.       break;
  389.     case CDDS_ITEMPREPAINT :
  390.       if (OnDrawEntry(draw.nmcd.dwItemSpec, P_MAX_INDEX,
  391.                       *(PListViewItem *)draw.nmcd.lItemlParam,
  392.                       canvas, draw.nmcd.uItemState))
  393.         return CDRF_SKIPDEFAULT;
  394. #ifdef CDRF_NOTIFYSUBITEMDRAW
  395.       return CDRF_NOTIFYSUBITEMDRAW;
  396.     case CDDS_ITEMPREPAINT|CDDS_SUBITEM :
  397.       if (OnDrawEntry(draw.nmcd.dwItemSpec, draw.iSubItem,
  398.                       *(PListViewItem *)draw.nmcd.lItemlParam,
  399.                       canvas, draw.nmcd.uItemState))
  400. #else
  401. #pragma message("Later version of commctrl.h required!")
  402. #endif
  403.         return CDRF_SKIPDEFAULT;
  404.   }
  405.   draw.clrText   = canvas.GetTextFgColour().ToCOLORREF();
  406.   draw.clrTextBk = canvas.GetTextBkColour().ToCOLORREF();
  407.   return CDRF_DODEFAULT ;
  408. }
  409. int PListViewControl::TranslateOption(NMHDR & msg) const
  410. {
  411.   NMLISTVIEW & lv = (NMLISTVIEW &)msg;
  412.   switch (msg.code) {
  413.     case LVN_DELETEITEM :
  414.       delete GetEntry(lv.iItem);
  415.       break;
  416.     case LVN_ITEMCHANGED :
  417.       return NewSelection;
  418.     case NM_DBLCLK :
  419.       return DoubleClick;
  420.     case LVN_BEGINDRAG :
  421.       ((PListViewControl*)this)->OnBeginDrag(FALSE, lv.iItem);
  422.       break;
  423.     case LVN_BEGINRDRAG :
  424.       ((PListViewControl*)this)->OnBeginDrag(TRUE, lv.iItem);
  425.       break;
  426.     case LVN_COLUMNCLICK :
  427.       ((PListViewControl*)this)->OnColumnClick(lv.iSubItem);
  428.       break;
  429.     case NM_RCLICK :
  430.       ((PListViewControl*)this)->OnRightClick(lv.iItem);
  431.       return RightClick;
  432.     case NM_CUSTOMDRAW :
  433.       _msg->lResult = ((PListViewControl*)this)->LVCustomDraw(msg);
  434.       return -2;
  435.   }
  436.   return -1;
  437. }
  438. void PListViewControl::WndProc()
  439. {
  440.   if (_msg->event == WM_DESTROY && deleteObjects) {
  441.     for (PINDEX i = 0; i < GetCount(); i++)
  442.       delete GetEntry(i);
  443.   }
  444.   PControl::WndProc();
  445. }
  446. // End Of File ///////////////////////////////////////////////////////////////