⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comnctrl.cxx

📁 windows mobile phone source code
💻 CXX
字号:
/*
 * comnctrl.cxx
 *
 * Common control interactor classes implementation.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: comnctrl.cxx,v $
 * Revision 1.5  1999/04/18 14:21:40  robertj
 * MSVC 5 backward compatibility
 *
 * Revision 1.4  1999/02/16 08:08:07  robertj
 * MSVC 6.0 compatibility changes.
 *
 * Revision 1.3  1998/09/24 03:42:34  robertj
 * Added open software license.
 *
 * Revision 1.2  1998/09/22 15:09:14  robertj
 * Added OnDraw functions.
 *
 * Revision 1.1  1998/09/21 14:02:34  robertj
 * Initial revision
 *
 */

#include <pwlib.h>
#include <commctrl.h>

typedef struct _DllVersionInfo {         DWORD cbSize; 
        DWORD dwMajorVersion;                   // Major version 
        DWORD dwMinorVersion;                   // Minor version 
        DWORD dwBuildNumber;                    // Build number 
        DWORD dwPlatformID;                     // DLLVER_PLATFORM_* 
} DLLVERSIONINFO; 
typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);

static HRESULT GetComCtlVersion(DWORD & dwMajor, DWORD & dwMinor)
{
  //load the DLL
  HINSTANCE hComCtl = LoadLibrary(TEXT("comctl32.dll"));
  if (hComCtl == NULL)
    return E_FAIL;

  HRESULT hr = S_OK;
  DLLGETVERSIONPROC pDllGetVersion;
  /* You must get this function explicitly because earlier versions of the DLL 
  don't implement this function. That makes the lack of implementation of the 
  function a version marker in itself.   */
  pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, TEXT("DllGetVersion"));
  if (pDllGetVersion) {
    DLLVERSIONINFO dvi;
    ZeroMemory(&dvi, sizeof(dvi));
    dvi.cbSize = sizeof(dvi);
    hr = (*pDllGetVersion)(&dvi);
    if (SUCCEEDED(hr)) {
      dwMajor = dvi.dwMajorVersion;
      dwMinor = dvi.dwMinorVersion;
    }
    else {
      hr = E_FAIL;
    }
   }
   else {
    /* If GetProcAddress failed, then the DLL is a version previous to the one
       shipped with IE 3.x.      */
    dwMajor = 4;
    dwMinor = 0;
  }

  FreeLibrary(hComCtl);
  return hr;
}

//////////////////////////////////////////////////////////////////////////////
// PListViewControl

PListViewControl::PListViewControl(PInteractor * parent,
                                   unsigned styles,
                                   PINDEX columnCount,
                                   const char * const * headings)
  : PControl(parent, PNotifier(), NULL)
{
  DWORD maj, min;
  GetComCtlVersion(maj, min);

  defaultStyles = styles;
  deleteObjects = TRUE;

  numColumns = 0;
  for (PINDEX col = 0; col < columnCount; col++) {
    if (headings != NULL)
      InsertColumn(headings[col]);
    else
      InsertColumn(psprintf("%u", col+1));
  }

  if (headings != NULL)
    SetColumnHeading(0, headings[0]);

  SetForegroundColour(parent->GetForegroundColour());
  SetBackgroundColour(parent->GetBackgroundColour());
}


void PListViewControl::SetForegroundColour(const PColour & newColour)
{
  PControl::SetForegroundColour(newColour);
  ::SendMessage(GetHWND(), LVM_SETTEXTCOLOR, 0, newColour.ToCOLORREF());
}


void PListViewControl::SetBackgroundColour(const PColour & newColour)
{
  PControl::SetBackgroundColour(newColour);
  ::SendMessage(GetHWND(), LVM_SETBKCOLOR, 0, newColour.ToCOLORREF());
  ::SendMessage(_hWnd, LVM_SETTEXTBKCOLOR, 0, newColour.ToCOLORREF());
}


void PListViewControl::TransferValue(int option)
{
  if (valuePointer != NULL)
    if (option == NotifyUpdate)
      SetSelection(*(PINDEX *)valuePointer);
    else
      *(PINDEX *)valuePointer = GetSelection();
}


void PListViewControl::AllowDeleteObjects(BOOL yes)
{
  deleteObjects = yes;
}


LRESULT PListViewControl::LVChangeItem(int action,
                                       PListViewItem * obj,
                                       PINDEX index,
                                       BOOL update)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update && numColumns == 1, 0L);

  LVITEM lv;
  lv.iItem = index;
  lv.iSubItem = 0;

  lv.mask = LVIF_TEXT;
  if (obj == NULL)
    obj = GetEntry(index);
  else {
    lv.mask |= LVIF_PARAM;
    lv.lParam = (DWORD)obj;
  }

  PString str = obj->GetColumn(0);
  lv.pszText = str.GetPointer();

  LRESULT retval = SendMessage(_hWnd, action, 0, (DWORD)&lv);
  if (action == LVM_INSERTITEM)
    lv.iItem = retval;

  lv.mask = LVIF_TEXT;
  for (PINDEX col = 1; col < numColumns; col++) {
    lv.iSubItem = col;
    str = obj->GetColumn(col);
    lv.pszText = str.GetPointer();
    if (update && col == numColumns - 1)
      SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
    SendMessage(_hWnd, LVM_SETITEM, 0, (DWORD)&lv);
  }

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);

  return retval;
}


PINDEX PListViewControl::AddEntry(PListViewItem * obj, BOOL update)
{
  if (PAssertNULL(obj) != NULL)
    return (PINDEX)LVChangeItem(LVM_INSERTITEM, obj, P_MAX_INDEX, update);
  return -1;
}


void PListViewControl::AddEntries(const PCollection & objects, BOOL update)
{
  PINDEX last = objects.GetSize() - 1;
  for (PINDEX i = 0; i <= last; i++) {
    PObject * obj = objects.GetAt(i);
    if (obj->IsDescendant(PListViewItem::Class()))
      AddEntry((PListViewItem*)obj, update && i < last);
  }
}


void PListViewControl::InsertEntry(PListViewItem * obj, PINDEX index, BOOL update)
{
  if (PAssertNULL(obj) != NULL)
    LVChangeItem(LVM_INSERTITEM, obj, index, update);
}


void PListViewControl::DeleteEntry(PINDEX index, BOOL update)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);

  BOOL doNotify = GetSelection() == index;
  SendMessage(_hWnd, LVM_DELETEITEM, index, 0L);

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);

  if (doNotify)
    parent->OnControlNotify(*this, NewSelection);
}


void PListViewControl::DeleteAllEntries(BOOL update)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);

  BOOL doNotify = GetSelection() != P_MAX_INDEX;
  SendMessage(_hWnd, LVM_DELETEALLITEMS, 0, 0L);

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);

  if (doNotify)
    parent->OnControlNotify(*this, NewSelection);
}


PINDEX PListViewControl::FindEntry(const PListViewItem & obj, PINDEX startIndex) const
{
  if (startIndex == P_MAX_INDEX)
    startIndex = -1;

  PString str = obj.GetColumn(0);
  LVFINDINFO lv;
  lv.flags = LVFI_STRING;
  lv.psz = str.GetPointer();
  long retVal = SendMessage(GetHWND(), LVM_FINDITEM, startIndex, (DWORD)&lv);

  return retVal != -1 ? (PINDEX)retVal : P_MAX_INDEX;
}


void PListViewControl::UpdateEntry(PINDEX index, BOOL update)
{
  LVChangeItem(LVM_SETITEM, NULL, index, update);
}


void PListViewControl::SetEntry(PListViewItem * obj, PINDEX index, BOOL update)
{
  BOOL doNotify = GetSelection() == index;

  LVChangeItem(LVM_SETITEM, obj, index, update);

  if (doNotify)
    parent->OnControlNotify(*this, NewSelection);
}


PListViewItem * PListViewControl::GetEntry(PINDEX index) const
{
  LVITEM lv;
  lv.mask = LVIF_PARAM;
  lv.iItem = index;
  lv.iSubItem = 0;
  long retVal = SendMessage(GetHWND(), LVM_GETITEM, 0, (LPARAM)&lv);
  return retVal ? (PListViewItem *)lv.lParam : NULL;
}


PINDEX PListViewControl::GetCount() const
{
  return (PINDEX)SendMessage(GetHWND(), LVM_GETITEMCOUNT, 0, 0L);
}


PINDEX PListViewControl::GetTopIndex() const
{
return (PINDEX)SendMessage(GetHWND(), LVM_GETTOPINDEX, 0, 0L);
}


void PListViewControl::InsertColumn(const PString & heading, PINDEX before, BOOL update)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);

  LVCOLUMN lvc;
  lvc.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
  lvc.pszText = (LPSTR)(const char *)heading;
  lvc.fmt = LVCFMT_LEFT;
  lvc.cx = GetStringWidth(heading+"    ");
  lvc.iSubItem = numColumns++;

  SendMessage(_hWnd, LVM_INSERTCOLUMN, before, (DWORD)&lvc);

  for (PINDEX entry = 0; entry < GetCount(); entry++) {
    LVITEM lv;
    lv.mask = LVIF_TEXT|LVCF_SUBITEM;
    lv.iItem = entry;
    lv.iSubItem = lvc.iSubItem;
    PString str = GetEntry(entry)->GetColumn(lvc.iSubItem);
    lv.pszText = str.GetPointer();
    SendMessage(_hWnd, LVM_SETITEM, 0, (DWORD)&lv);
  }

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
}


void PListViewControl::DeleteColumn(PINDEX column, BOOL update)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);

  SendMessage(_hWnd, LVM_DELETECOLUMN, column, 0);
  numColumns--;

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
}


PINDEX PListViewControl::GetColumnCount()
{
  return numColumns;
}


void PListViewControl::SetColumnHeading(PINDEX column, const PString & str)
{
  LVCOLUMN lv;
  lv.mask = LVCF_TEXT;
  lv.pszText = (LPSTR)(const char *)str;
  SendMessage(GetHWND(), LVM_SETCOLUMN, column, (DWORD)&lv);
}


PDIMENSION PListViewControl::GetColumnWidth(PINDEX column)
{
  return (PDIMENSION)SendMessage(GetHWND(), LVM_GETCOLUMNWIDTH, column, 0L);
}


void PListViewControl::SetColumnWidth(PINDEX column, PDIMENSION newWidth, BOOL update)
{
  SendMessage(_hWnd, WM_SETREDRAW, update, 0L);

  if (newWidth == 0)
    newWidth = (PDIMENSION)LVSCW_AUTOSIZE_USEHEADER;

  SendMessage(_hWnd, LVM_SETCOLUMNWIDTH, column, newWidth);

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
}


PDIMENSION PListViewControl::GetStringWidth(const PString & str)
{
  return (PDIMENSION)SendMessage(GetHWND(), LVM_GETSTRINGWIDTH, 0, (DWORD)(const char *)str);
}


void PListViewControl::SetSelection(PINDEX index)
{
  PINDEX last = GetCount() - 1;
  for (PINDEX entry = 0; entry <= last; entry++)
    Select(entry, entry == last, entry == index);

  parent->OnControlNotify(*this, NewSelection);
}


PINDEX PListViewControl::GetSelection() const
{
  PINDEX last = GetCount() - 1;
  for (PINDEX entry = 0; entry <= last; entry++) {
    if (IsSelected(entry))
      return entry;
  }
  return P_MAX_INDEX;
}


void PListViewControl::Select(PINDEX index, BOOL update, BOOL sel)
{
  SendMessage(GetHWND(), WM_SETREDRAW, update, 0L);

  LVITEM lv;
  lv.stateMask = LVIS_SELECTED;
  lv.state = sel ? LVIS_SELECTED : 0;
  SendMessage(_hWnd, LVM_SETITEMSTATE, index, (DWORD)&lv);

  if (!update)
    SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0L);
}


BOOL PListViewControl::IsSelected(PINDEX index) const
{
  return SendMessage(GetHWND(), LVM_GETITEMSTATE, index, LVIS_SELECTED) != 0;
}


PINDEX PListViewControl::GetSelCount() const
{
  return (PINDEX)SendMessage(GetHWND(), LVM_GETSELECTEDCOUNT, 0, 0);
}


static int CALLBACK LVCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
  PListViewItem * obj1 = (PListViewItem *)lParam1;
  PListViewItem * obj2 = (PListViewItem *)lParam2;
  return obj1->GetColumn(lParamSort).Compare(obj2->GetColumn(lParamSort));
}


void PListViewControl::OnColumnClick(PINDEX column)
{
  SendMessage(GetHWND(), LVM_SORTITEMS, column, (DWORD)LVCompareFunc);
}


void PListViewControl::OnRightClick(PINDEX)
{
}


void PListViewControl::OnBeginDrag(BOOL, PINDEX)
{
}


BOOL PListViewControl::OnDrawControl(PCanvas &, BOOL)
{
  return FALSE;
}


BOOL PListViewControl::OnDrawEntry(PINDEX, PINDEX, PListViewItem &, PCanvas &, unsigned)
{
  return FALSE;
}


void PListViewControl::GetCreateWinInfo(WNDCLASS & wndClass)
{
  PControl::GetCreateWinInfo(wndClass);

  wndClass.lpszClassName = WC_LISTVIEW;

  if ((defaultStyles&ShowHeadings) == 0)
    _styleBits |= LVS_NOCOLUMNHEADER;

  if ((defaultStyles&CanHeadingSort) == 0)
    _styleBits |= LVS_NOSORTHEADER;

  if ((defaultStyles&SingleSelection) != 0)
    _styleBits |= LVS_SINGLESEL;

  _styleBits |= WS_BORDER|WS_HSCROLL|WS_VSCROLL|LVS_REPORT;
}


int PListViewControl::LVCustomDraw(NMHDR & msg)
{
  NMLVCUSTOMDRAW & draw = (NMLVCUSTOMDRAW &)msg;
  PDrawCanvas canvas((PListViewControl*)this, draw.nmcd.hdc, FALSE, TRUE);

  switch (draw.nmcd.dwDrawStage) {
    case CDDS_PREPAINT :
      if (OnDrawControl(canvas, FALSE))
        return CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
      break;

    case CDDS_POSTPAINT :
      OnDrawControl(canvas, TRUE);
      break;

    case CDDS_ITEMPREPAINT :
      if (OnDrawEntry(draw.nmcd.dwItemSpec, P_MAX_INDEX,
                      *(PListViewItem *)draw.nmcd.lItemlParam,
                      canvas, draw.nmcd.uItemState))
        return CDRF_SKIPDEFAULT;
#ifdef CDRF_NOTIFYSUBITEMDRAW
      return CDRF_NOTIFYSUBITEMDRAW;

    case CDDS_ITEMPREPAINT|CDDS_SUBITEM :
      if (OnDrawEntry(draw.nmcd.dwItemSpec, draw.iSubItem,
                      *(PListViewItem *)draw.nmcd.lItemlParam,
                      canvas, draw.nmcd.uItemState))
#else
#pragma message("Later version of commctrl.h required!")
#endif
        return CDRF_SKIPDEFAULT;
  }

  draw.clrText   = canvas.GetTextFgColour().ToCOLORREF();
  draw.clrTextBk = canvas.GetTextBkColour().ToCOLORREF();

  return CDRF_DODEFAULT ;
}


int PListViewControl::TranslateOption(NMHDR & msg) const
{
  NMLISTVIEW & lv = (NMLISTVIEW &)msg;

  switch (msg.code) {
    case LVN_DELETEITEM :
      delete GetEntry(lv.iItem);
      break;

    case LVN_ITEMCHANGED :
      return NewSelection;

    case NM_DBLCLK :
      return DoubleClick;

    case LVN_BEGINDRAG :
      ((PListViewControl*)this)->OnBeginDrag(FALSE, lv.iItem);
      break;

    case LVN_BEGINRDRAG :
      ((PListViewControl*)this)->OnBeginDrag(TRUE, lv.iItem);
      break;

    case LVN_COLUMNCLICK :
      ((PListViewControl*)this)->OnColumnClick(lv.iSubItem);
      break;

    case NM_RCLICK :
      ((PListViewControl*)this)->OnRightClick(lv.iItem);
      return RightClick;

    case NM_CUSTOMDRAW :
      _msg->lResult = ((PListViewControl*)this)->LVCustomDraw(msg);
      return -2;
  }
  return -1;
}


void PListViewControl::WndProc()
{
  if (_msg->event == WM_DESTROY && deleteObjects) {
    for (PINDEX i = 0; i < GetCount(); i++)
      delete GetEntry(i);
  }
  PControl::WndProc();
}


// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -