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

📄 propertylist.h

📁 一款最完整的工业组态软源代码
💻 H
📖 第 1 页 / 共 3 页
字号:
            if( (m_dwExtStyle & PLS_EX_CATEGORIZED) && GET_X_LPARAM(lParam) < CATEGORY_INDENT ) {
               prop->Activate(PACT_EXPAND, 0);
            }
            else {
               if( prop->IsEnabled() ) prop->Activate(PACT_CLICK, lParam);
            }
         }
      }
      return lRes;
   }
   LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
   {
      int x = _GetDragPos(GET_X_LPARAM(lParam));
      if( m_iPrevious > 0 ) {
         m_iMiddle += x - m_iPrevious;
         Invalidate();
      }
      m_iPrevious = 0;
      m_iPrevXGhostBar = 0;
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
   {
      LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
      int idx = GetCurSel();
      if( idx != -1 ) {
         IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(idx));
         ATLASSERT(prop);
         // Ask owner first
         NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_DBLCLICK, prop };
         if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
            // Send DblClick action
            if( prop->IsEnabled() ) prop->Activate(PACT_DBLCLICK, lParam);
         }
      }
      return lRes;
   }
   LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL &bHandled)
   {
      // Column resize code added by Remco Verhoef, thanks.
      if( m_iPrevious > 0 ) {
         int x = _GetDragPos(GET_X_LPARAM(lParam));
         if( m_iPrevXGhostBar != x ) {
            if( m_iPrevXGhostBar ) _DrawGhostBar(m_iPrevXGhostBar);
            m_iPrevXGhostBar = x;
            _DrawGhostBar(m_iPrevXGhostBar);
         }
         return 0;
      }
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
   {
      POINT pt = { 0 };
      ::GetCursorPos(&pt);
      ScreenToClient(&pt);
      int iIndent = m_dwExtStyle & PLS_EX_CATEGORIZED ? CATEGORY_INDENT : 0;
      if( pt.x == m_iMiddle + iIndent ) {
         ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
         return FALSE;
      } 
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      // Custom styles
      m_di.dwExtStyle = m_dwExtStyle;
      // Standard colors
      m_di.clrText = ::GetSysColor(COLOR_WINDOWTEXT);
      m_di.clrBack = ::GetSysColor(COLOR_WINDOW);
      m_di.clrSelText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
      m_di.clrSelBack = ::GetSysColor(COLOR_HIGHLIGHT);
      m_di.clrDisabled = ::GetSysColor(COLOR_GRAYTEXT);
      // Border
      m_di.clrBorder = ::GetSysColor(COLOR_BTNFACE);
      if( !m_BorderPen.IsNull() ) m_BorderPen.DeleteObject();
      m_di.Border = m_BorderPen.CreatePen(PS_SOLID, 1, m_di.clrBorder);
      // Fonts
      if( !m_TextFont.IsNull() ) m_TextFont.DeleteObject();
      if( !m_CategoryFont.IsNull() ) m_CategoryFont.DeleteObject();
      LOGFONT lf;
      HFONT hFont = (HFONT)::SendMessage(GetParent(), WM_GETFONT, 0, 0);
      if( hFont == NULL ) hFont = AtlGetDefaultGuiFont();
      ::GetObject(hFont, sizeof(lf), &lf);
      m_di.TextFont = m_TextFont.CreateFontIndirect(&lf);
      SetFont(m_di.TextFont);
      if( (m_dwExtStyle & PLS_EX_XPLOOK) == 0 ) lf.lfWeight += FW_BOLD;
      m_di.CategoryFont = m_CategoryFont.CreateFontIndirect(&lf);
      // Text metrics
      CClientDC dc(m_hWnd);
      HFONT hOldFont = dc.SelectFont(m_di.TextFont);
      dc.GetTextMetrics(&m_di.tmText);
      dc.SelectFont(hOldFont);
      // Repaint
      Invalidate();
      return 0;
   }

   LRESULT OnNavigate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      switch( wParam ) {
      case VK_UP:
      case VK_DOWN:
         {
            _DestroyInplaceWindow();
            SetCurSel(GetCurSel() + (wParam == VK_UP ? -1 : 1));
            BOOL bDummy;
            OnSelChange(0, 0, NULL, bDummy);
         }
         break;
      }
      return 0;
   }
   LRESULT OnUpdateProperty(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Updates a property value using an active editor window.
      // The editor window uses this message to update the attached property class.
      HWND hWnd = reinterpret_cast<HWND>(lParam);
      ATLASSERT(hWnd);
      if( !::IsWindow(hWnd) || m_iInplaceIndex == -1 ) return 0;
      ATLASSERT(hWnd==m_hwndInplace);
      IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(m_iInplaceIndex));
      ATLASSERT(prop);
      if( prop == NULL ) return 0;
      // Ask owner about change
      NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_ITEMCHANGING, prop };
      if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
         // Set new value
         if( !prop->SetValue(hWnd) ) ::MessageBeep((UINT)-1);
         // Let owner know
         nmh.hdr.code = PIN_ITEMCHANGED;
         ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
         // Repaint item
         InvalidateItem(m_iInplaceIndex);
         // Recycle in-place control so it displays the new value
         // TODO: Traps condition where the SetValue() fails!
         int idx = FindProperty(prop);
         if( idx >= 0 && idx == m_iInplaceIndex ) _SpawnInplaceWindow(prop, idx);
      }
      return 0;
   }
   LRESULT OnCancelProperty(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Updates a property value using an active editor window.
      // The editor window uses this message to update the attached property class.
      HWND hWnd = reinterpret_cast<HWND>(lParam);
      ATLASSERT(hWnd);
      if( !::IsWindow(hWnd) || m_iInplaceIndex == -1 ) return 0;
      ATLASSERT(hWnd==m_hwndInplace);
      IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(m_iInplaceIndex));
      ATLASSERT(prop);
      if( prop == NULL ) return 0;
      // Repaint item
      InvalidateItem(m_iInplaceIndex);
      // Recycle in-place control so it displays the (old) value
      int idx = FindProperty(prop);
      if( idx >= 0 && idx == m_iInplaceIndex ) _SpawnInplaceWindow(prop, idx);
      return 0;
   }
   LRESULT OnChangedProperty(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Updates a property value.
      // A property class uses this message to make sure the corresponding editor window
      // is updated as well.
      IProperty* prop = reinterpret_cast<IProperty*>(lParam);
      VARIANT* pVariant = reinterpret_cast<VARIANT*>(wParam);
      ATLASSERT(prop && pVariant);
      if( prop == NULL || pVariant == NULL ) return 0;
      // Ask owner about change
      NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_ITEMCHANGING, prop };
      if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
         // Set new value
         // NOTE: Do not call this from IProperty::SetValue(VARIANT*) = endless loop
         if( !prop->SetValue(*pVariant) ) ::MessageBeep((UINT)-1);
         // Let owner know
         nmh.hdr.code = PIN_ITEMCHANGED;
         ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
      }
      // Locate the updated property index
      int idx = FindProperty(prop);
      // Repaint item
      InvalidateItem(idx);
      // Recycle in-place control so it displays the new value
      if( idx >= 0 && idx == m_iInplaceIndex ) _SpawnInplaceWindow(prop, idx);
      return 0;
   }
   LRESULT OnExpand(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      ATLASSERT(lParam);
      ExpandItem(reinterpret_cast<IProperty*>(lParam));
      return 0;
   }
   LRESULT OnCollapse(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      ATLASSERT(lParam);
      CollapseItem(reinterpret_cast<IProperty*>(lParam));
      return 0;
   }

   LRESULT OnSelChange(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
   {
      if( m_iPrevXGhostBar > 0 ) _DrawGhostBar(m_iPrevXGhostBar);

      IProperty* prop = NULL;
      int idx = GetCurSel();
      if( idx != -1 ) {
         prop = reinterpret_cast<IProperty*>(TBase::GetItemData(idx));
         ATLASSERT(prop);
         if( prop->GetKind() != PROPKIND_CATEGORY && prop->IsEnabled() ) {
            _SpawnInplaceWindow(prop, idx);
            prop->Activate(PACT_ACTIVATE, 0);
            if( m_dwExtStyle & PLS_EX_SINGLECLICKEDIT ) {
               if( prop->GetKind() == PROPKIND_EDIT ) prop->Activate(PACT_DBLCLICK, 0);
            }
         }
         else {
            _DestroyInplaceWindow();
         }
      }
      // Let owner know
      NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_SELCHANGED, prop };
      ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);

      if( m_iPrevXGhostBar > 0 ) _DrawGhostBar(m_iPrevXGhostBar);
      return 0;
   }

   // Owner draw methods

   void DeleteItem(LPDELETEITEMSTRUCT lpDIS)
   {
      _DestroyInplaceWindow();
      if( lpDIS->itemData ) delete reinterpret_cast<IProperty*>(lpDIS->itemData);
   }
   void MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
   {
      lpMIS->itemHeight = m_di.tmText.tmHeight + 3;
   }
   void DrawItem(LPDRAWITEMSTRUCT lpDIS)
   {
      if( lpDIS->itemID == -1 ) return; // If there are no list box items, skip this message. 

      CDCHandle dc(lpDIS->hDC);
      RECT rc = lpDIS->rcItem;

      IProperty* prop = reinterpret_cast<IProperty*>(lpDIS->itemData);
      ATLASSERT(prop);
      BYTE kind = prop->GetKind();

      // Customize item
      PROPERTYDRAWINFO di = m_di;
      di.hDC = dc;
      di.state = lpDIS->itemState & ~ODS_DISABLED;
      if( lpDIS->itemID == (UINT) m_iInplaceIndex ) di.state |= ODS_COMBOBOXEDIT;

      // Special style for removing selection when control hasn't focus
      if( (di.dwExtStyle & PLS_EX_SHOWSELALWAYS) == 0 && (::GetFocus() != m_hWnd) ) {
         di.state &= ~ODS_SELECTED;
      }

      // Prepare drawing
      HFONT hOldFont = dc.SelectFont(di.TextFont);

      // If this control is painted with categories
      if( m_dwExtStyle & PLS_EX_CATEGORIZED ) {
         // We paint a nice border in the gap with the plus/minus signs
         HPEN hOldPen = dc.SelectPen(di.Border);
         dc.MoveTo(rc.left + CATEGORY_INDENT - 1, rc.top);
         dc.LineTo(rc.left + CATEGORY_INDENT - 1, rc.bottom);
         if( m_dwExtStyle & PLS_EX_XPLOOK ) {
            RECT rcIndent = { rc.left, rc.top, rc.left + CATEGORY_INDENT, rc.bottom };
            dc.FillRect(&rcIndent, ::GetSysColorBrush(COLOR_3DFACE));
         }
         // Paint plus/minus sign if it's actually a category item
         if( kind == PROPKIND_CATEGORY ) {
            dc.SelectFont(di.CategoryFont);
            CCategoryProperty* pCategory = static_cast<CCategoryProperty*>(prop);
            POINT ptMiddle = { rc.left + (CATEGORY_INDENT / 2), rc.top + ((rc.bottom - rc.top) / 2) };
            RECT rcSymbol = { ptMiddle.x - 4, ptMiddle.y - 4, ptMiddle.x + 5, ptMiddle.y + 5 };
            dc.SelectStockPen(BLACK_PEN);
            HBRUSH hOldBrush = dc.SelectStockBrush(NULL_BRUSH);
            dc.Rectangle(&rcSymbol);
            dc.SelectBrush(hOldBrush);
            if( !pCategory->IsExpanded() ) {
               dc.MoveTo(ptMiddle.x, ptMiddle.y - 2);
               dc.LineTo(ptMiddle.x, ptMiddle.y + 3);
            }
            dc.MoveTo(ptMiddle.x - 2, ptMiddle.y);
            dc.LineTo(ptMiddle.x + 3, ptMiddle.y);
         }
         dc.SelectPen(hOldPen);
         rc.left += CATEGORY_INDENT;
      }
     
      // Calculate rectangles for the two sides
      RECT rcName = rc;
      RECT rcValue = rc;
      rcName.right = rc.left + m_iMiddle;
      rcValue.left = rc.left + m_iMiddle + 1;

      // Special handling of XP-like categories
      if( kind == PROPKIND_CATEGORY && (m_dwExtStyle & PLS_EX_XPLOOK) != 0 ) {
         rcName.right = rcValue.left = rc.right;
      }

      // Draw name
      di.rcItem = rcName;
      prop->DrawName(di);
           
      // Draw value
      // Thanks to Pascal Binggeli who suggested the Inplace-editor
      // check below...
      if( (int) lpDIS->itemID != m_iInplaceIndex ) {
         di.rcItem = rcValue;
         dc.FillSolidRect(&rcValue, di.clrBack);

         if( !prop->IsEnabled() ) di.state |= ODS_DISABLED;
         prop->DrawValue(di);
      }

      // Paint borders
      HPEN hOldPen = dc.SelectPen(di.Border);
      dc.MoveTo(rc.left, rc.bottom - 1);
      dc.LineTo(rc.right, rc.bottom - 1);     
      // Not painting middle border if XP look (thanks to Ludvig A Norin)
      if( !(kind == PROPKIND_CATEGORY && (m_dwExtStyle & PLS_EX_XPLOOK) != 0) ) {
         dc.MoveTo(rc.left + m_iMiddle, rc.top);
         dc.LineTo(rc.left + m_iMiddle, rc.bottom - 1);
      }
      dc.SelectPen(hOldPen);

      dc.SelectFont(hOldFont);
   }
};


class CPropertyListCtrl : public CPropertyListImpl<CPropertyListCtrl>
{
public:
   DECLARE_WND_SUPERCLASS(_T("WTL_PropertyList"), GetWndClassName())
};


#endif __PROPERTYLIST__H

⌨️ 快捷键说明

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