Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » ClistView loses header control maximised Collapse All
Subject Author Date
Marc Thompson Jul 28, 2008 - 12:40 AM

We have a standard MFC application with the latest Prof-UIS extensions added (2.83), which has fixed the problem with child windows not correctly skinned (excellent work), but we have a CListView derived view class now loses its header control when the view is maximised. I tried the

CExtNCSB wrapping the CListView, but this caused assertions during the subclassing of the view.


Have you had experience of this, and is there a simple fix to it? I dont really want to change to a grid for this.


Thanks


Marc Thompson


Marc Thompson Jul 28, 2008 - 5:28 PM

Thanks for the quick response, but unfortunately it hasnt solved the problem. The class is still causing an assertion in the PreSubclassWindow function. Below is the call stack immediately before the assertion.


 


  mfc80d.dll!AfxAssertFailedLine(const char * lpszFileName=0x781d54e0, int nLine=626)  Line 25 + 0x14 bytes C++

  mfc80d.dll!AfxHookWindowCreate(CWnd * pWnd=0x04c1c190)  Line 626 + 0x18 bytes C++

  mfc80d.dll!CWnd::CreateEx(unsigned long dwExStyle=1048576, const char * lpszClassName=0x03028bb4, const char * lpszWindowName=0x03028b94, unsigned long dwStyle=1174405120, int x=0, int y=0, int nWidth=0, int nHeight=0, HWND__ * hWndParent=0x00010016, HMENU__ * nIDorHMenu=0xffffffff, void * lpParam=0x00000000)  Line 694 C++

  mfc80d.dll!CWnd::CreateEx(unsigned long dwExStyle=1048576, const char * lpszClassName=0x03028bb4, const char * lpszWindowName=0x03028b94, unsigned long dwStyle=1174405120, const tagRECT & rect={...}, CWnd * pParentWnd=0x0656ecb0, unsigned int nID=4294967295, void * lpParam=0x00000000)  Line 659 C++

  ProfUIS283md.dll!CExtNCSB_ScrollContainer::Create(CWnd * pWndParent=0x0656ecb0)  Line 2628 + 0x28 bytes C++

  3DOffice.exe!CExtNCSB_Impl<CListView>::NCSB_InstantiateAndCreateContainer(CExtNCSB_ScrollContainer::e_mode_t eMode=__EM_HORIZONTAL_SCROLL_BAR, CWnd * pWndParent=0x0656ecb0)  Line 556 + 0x14 bytes C++

  3DOffice.exe!CExtNCSB_Impl<CListView>::NCSB_EnsureContainersCreated()  Line 591 + 0x16 bytes C++

  3DOffice.exe!CExtNCSB_Impl<CListView>::NCSB_RepositionContainers(bool bRescanScrollPositions=true)  Line 772 + 0x10 bytes C++

  3DOffice.exe!CExtNCSB_Impl<CListView>::PreSubclassWindow()  Line 930 C++

  mfc80d.dll!_AfxCbtFilterHook(int code=3, unsigned int wParam=134894, long lParam=1236256)  Line 532 C++


Cheers


Marc Thompson

Technical Support Jul 29, 2008 - 12:54 PM

Please add explicit invocation of parent class constructor to your list view class constructor:

CYourListView::CYourListView()
      : CExtNCSB < CListView > ( true )
{
}


This informs the CExtNCSB template class that it should initialize its scroll bar windows with delay to avoid conflicts with window creation sequences implemented inside MFC.

There is another feature in the CExtNCSB template class: it can create a middle container window between the control with skinned scroll bars and the control’s parent window. This feature is required for using CExtNCSB template class inside control bars. The CExtControlBar control bar window requires only one child window inside it and it resizes its single child window automatically to cover the entire control bar’s client area. If you need to create a list view control with CExtNCSB-based skinned scroll bars inside a control bar, there are three windows will appear inside the bar: the list view common control and two CExtScrollBar windows (horizontal and vertical). To avoid such a conflict with the design of CExtControlBar window, you should allow the CExtNCSB template class to create a dynamic container window which will be a child of the control bar and the parent of list view common control with its skinned scroll bars. In this case, you also need explicit parent constructor invocation in list view control’s constructor:
CYourListCtrl::CYourListCtrl()
      : CExtNCSB < CListCtrl > ( true, true )
{
}


Technical Support Jul 28, 2008 - 9:23 AM

You can use CExtNCSB for skinning any windows except CListCtrl and CListView. The list view common control uses very specific scrolling behavior implementation. The new CExtListCtrl class with skinned CExtHeaderCtrl will appear in v.2.84. Here is the beta preview:

NewControls-beta-test2.zip

The list view common control requires a specialized version of CExtNCSB

template < > class CExtNCSB < CListCtrl > : public CExtNCSB_Impl < CListCtrl >
{
public:
      CExtNCSB(
                  bool bNcsbDelayedInitialization = false,
                  bool bNcsbForceMiddleContainerMode = false
                  )
                  : CExtNCSB_Impl < CListCtrl > (
                        bNcsbDelayedInitialization,
                        bNcsbForceMiddleContainerMode
                        )
      {
      }
      virtual ~CExtNCSB()
      {
      }
      virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
      {
            switch( message )
            {
            case WM_HSCROLL:
            {
                  UINT nSBCode = UINT(LOWORD(DWORD(wParam))), nPos = UINT(HIWORD(DWORD(wParam)));
                  //TRACE2( "WM_HSCROLL, nSBCode = %d, nPos = %d\r\n", nSBCode, nPos );
                  INT nItemExtent = 1;
                  DWORD dwStyle = GetStyle();
                  DWORD dwListCtrlType = dwStyle&LVS_TYPEMASK;
                  switch( dwListCtrlType )
                  {
                  case LVS_ICON:
                  case LVS_SMALLICON:
                  case LVS_REPORT:
                  break;
                  case LVS_LIST:
                  {
                        CRect rcItem( 0, 0, 0, 0 );
                        INT nTopIndex = GetTopIndex();
                        if(         nTopIndex >= 0
                              &&    CListCtrl::GetItemRect( nTopIndex, &rcItem, LVIR_BOUNDS )
                              )
                              nItemExtent = rcItem.Width();
                  }
                  break;
                  } // switch( dwListCtrlType )
                  if( nSBCode == SB_THUMBTRACK || nSBCode == SB_THUMBPOSITION )
                  {
                        INT nPosOld = GetScrollPos( SB_HORZ );
                        INT nPosShift = nPos*nItemExtent - nPosOld*nItemExtent;
                        Scroll( CSize( nPosShift, 0 ) );
                        return 0L;
                  }
                  if(         nSBCode == SB_LINELEFT
                        ||    nSBCode == SB_LINERIGHT
                        ||    nSBCode == SB_PAGELEFT
                        ||    nSBCode == SB_PAGERIGHT
                        ||    nSBCode == SB_LEFT
                        ||    nSBCode == SB_RIGHT
                        ||    nSBCode == SB_ENDSCROLL
                        )
                        return 0L;
            } // case WM_HSCROLL:
            break; // case WM_VSCROLL
            case WM_VSCROLL:
            {
                  UINT nSBCode = UINT(LOWORD(DWORD(wParam))), nPos = UINT(HIWORD(DWORD(wParam)));
                  //TRACE2( "WM_VSCROLL, nSBCode = %d, nPos = %d\r\n", nSBCode, nPos );
                  INT nItemExtent = 1;
                  DWORD dwStyle = GetStyle();
                  DWORD dwListCtrlType = dwStyle&LVS_TYPEMASK;
                  switch( dwListCtrlType )
                  {
                  case LVS_ICON:
                  case LVS_SMALLICON:
                  case LVS_LIST:
                  break;
                  case LVS_REPORT:
                  {
                        CRect rcItem( 0, 0, 0, 0 );
                        INT nTopIndex = GetTopIndex();
                        if(         nTopIndex >= 0
                              &&    CListCtrl::GetItemRect( nTopIndex, &rcItem, LVIR_BOUNDS )
                              )
                              nItemExtent = rcItem.Height();
                        else
                        {
                              TEXTMETRIC _tm;
                              ::memset( &_tm, 0, sizeof(TEXTMETRIC) );
                              CClientDC dc( this );
                              CFont * pFont = GetFont();
                              int nSave = dc.SaveDC();
                              dc.SelectObject( pFont );
                              dc.GetTextMetrics( &_tm );
                              nItemExtent = _tm.tmHeight + _tm.tmExternalLeading + 1;
                              dc.RestoreDC( nSave );
                        }
                  }
                  break;
                  } // switch( dwListCtrlType )
                  if( nSBCode == SB_THUMBTRACK || nSBCode == SB_THUMBPOSITION )
                  {
                        INT nPosOld = GetScrollPos( SB_VERT );
                        INT nPosShift = nPos*nItemExtent - nPosOld*nItemExtent;
                        Scroll( CSize( 0, nPosShift ) );
                        return 0L;
                  }
                  if(         nSBCode == SB_LINEUP
                        ||    nSBCode == SB_LINEDOWN
                        ||    nSBCode == SB_PAGEUP
                        ||    nSBCode == SB_PAGEDOWN
                        ||    nSBCode == SB_TOP
                        ||    nSBCode == SB_BOTTOM
                        ||    nSBCode == SB_ENDSCROLL
                        )
                        return 0L;
            }
            break; // case WM_VSCROLL
            } // switch( message )
            LRESULT lResult = CExtNCSB_Impl < CListCtrl > :: WindowProc( message, wParam, lParam );
            return lResult;
      }
}; // template < > class CExtNCSB < CListCtrl >
The specialized version above is designed for the CListCtrl class. You can copy it into your project and replace the CListCtrl class name with the CListView class name. As a result, you will have the CExtNCSB < CListView > specialized template class in scope of your project. The CExtNCSB < CListView > class should be before its usage in your project and you should rebuild your project completely to see correctly working list view.