• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1582
  • Last Modified:

Overriding OnSize in class derived from CSplitterWnd

I have a splitter window (CCustomSplitterWnd) embedded in a CWnd.  I have written my own version of Create so that before the view is created, the splitter is resized to the size of its parent using MoveWindow.
The problem is that CSplitterWnd's implementation of OnSize calls RecalcLayout, which fails because there is no view to layout.  
My solution was to override OnSize in CCustomSplitterWnd and not call RecalcLayout when I MoveWindow (using a bool flag).
The resulting problem is that my implementation is not getting called.  It's still calling CSplitterWnd::OnSize.  I have rebuilt all and double checked my declaration in the AFX_MSG_MAP.  I will post my source in a comment
0
sosedada
Asked:
sosedada
  • 4
1 Solution
 
sosedadaAuthor Commented:
Edited text of question.
0
 
sosedadaAuthor Commented:
//CustomSplitWnd.h

class CCustomSplitWnd : public CSplitterWnd
{
      DECLARE_DYNAMIC(CCustomSplitWnd)

// Implementation
public:
      CCustomSplitWnd(bool allow_sizing = false);
      virtual ~CCustomSplitWnd();

      //for dynamic ones
      virtual bool CustomCreate(CWnd* pParentWnd,
                                int nMaxRows, int nMaxCols, SIZE sizeMin,
                                CCreateContext* pContext, DWORD dwStyle=WS_CHILD | WS_VISIBLE | SPLS_DYNAMIC_SPLIT);

      void ChangeViewClass(CRuntimeClass *pNewView)
      {
            m_pDynamicViewClass = pNewView;
      }

      // Generated message map functions
      //{{AFX_MSG(CCustomSplitWnd)
      afx_msg UINT OnNcHitTest(CPoint point);
      afx_msg void OnSize(UINT nType, int cx, int cy);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()

public:
      // for customizing DYNAMIC_SPLIT behavior
      // default asserts that it is deleting a view.
      virtual void DeleteView(int row, int col);

private:
      bool m_bResizable;
      bool m_bDeferRecalcLayout;
};

//returns the id of the pane this view is in
//will return AFX_IDW_PANE_FIRST if not in a splitter
extern int GetViewIDFromParentSplitter(CWnd* view);


//CustomSplitWnd.cpp
#include "stdafx.h"
#include "CustomSplitWnd.h"


IMPLEMENT_DYNAMIC(CCustomSplitWnd, CSplitterWnd)

BEGIN_MESSAGE_MAP(CCustomSplitWnd, CSplitterWnd)
      //{{AFX_MSG_MAP(CPCAcqSplitWnd)
      ON_WM_NCHITTEST()
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()


CCustomSplitWnd::CCustomSplitWnd(bool allow_sizing):
      m_bResizable(allow_sizing),
      m_bDeferRecalcLayout(false)
{
      if (!m_bResizable)
      {
      /*      m_cxSplitter=3;      // put your own values here, to make the splitter fit your needs
            m_cySplitter=3;
            m_cxBorderShare=0;
            m_cyBorderShare=0;      
            m_cxSplitterGap=3;
            m_cySplitterGap=3;*/
      }
}

CCustomSplitWnd::~CCustomSplitWnd()
{
}

bool CCustomSplitWnd::CustomCreate(CWnd* pParentWnd,
                                                   int nMaxRows, int nMaxCols, SIZE sizeMin,
                                                   CCreateContext* pContext, DWORD dwStyle/*, UINT nID*/)
{
      ASSERT(pParentWnd != NULL);
      ASSERT(sizeMin.cx > 0 && sizeMin.cy > 0);   // minimum must be non-zero

      ASSERT(pContext != NULL);
      ASSERT(pContext->m_pNewViewClass != NULL);
      ASSERT(dwStyle & WS_CHILD);
      ASSERT(dwStyle & SPLS_DYNAMIC_SPLIT);   // must have dynamic split behavior

      // Dynamic splitters are limited to 2x2
      ASSERT(nMaxRows >= 1 && nMaxRows <= 2);
      ASSERT(nMaxCols >= 1 && nMaxCols <= 2);
      ASSERT(nMaxCols > 1 || nMaxRows > 1);       // 1x1 is not permitted

      UINT nID = GetViewIDFromParentSplitter(pParentWnd);

      m_nMaxRows = nMaxRows;
      m_nMaxCols = nMaxCols;
      ASSERT(m_nRows == 0 && m_nCols == 0);       // none yet
      m_nRows = m_nCols = 1;      // start off as 1x1
      if (!CreateCommon(pParentWnd, sizeMin, dwStyle, nID))
            return false;
      ASSERT(m_nRows == 1 && m_nCols == 1);       // still 1x1

      CRect rect;
      pParentWnd->GetClientRect(&rect);

      m_bDeferRecalcLayout = true;
      MoveWindow(0, 0, rect.right, rect.bottom);
      m_bDeferRecalcLayout = false;

      ASSERT(pContext->m_pNewViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
      m_pDynamicViewClass = pContext->m_pNewViewClass;
            // save for later dynamic creations

      // add the first initial pane
      if (!CreateView(0, 0, m_pDynamicViewClass, sizeMin, pContext))
      {
            DestroyWindow(); // will clean up child windows
            return false;
      }
      m_pColInfo[0].nIdealSize = sizeMin.cx;
      m_pRowInfo[0].nIdealSize = sizeMin.cy;

      return true;
}

void CCustomSplitWnd::OnSize(UINT nType, int cx, int cy)
{
      if (nType != SIZE_MINIMIZED && cx > 0 && cy > 0 && !m_bDeferRecalcLayout)
            RecalcLayout();

      CWnd::OnSize(nType, cx, cy);
}

UINT CCustomSplitWnd::OnNcHitTest(CPoint point)
{
      if (m_bResizable)
            return CSplitterWnd::OnNcHitTest(point);
      else
            return 0; //this stops all messages from getting through
}

void CCustomSplitWnd::DeleteView(int row, int col)
{
      ASSERT_VALID(this);

      // if active child is being deleted - activate next
      CWnd* pPane = GetPane(row, col);
      /*ASSERT_KINDOF(CView, pPane);
      if (GetActivePane() == pPane)
            ActivateNext(FALSE);
*/
      // default implementation assumes view will auto delete in PostNcDestroy
      pPane->DestroyWindow();
      /*didn't work on shutdown, will continue putting delete this in PostNcDestroy()
      if (!pPane->IsKindOf(RUNTIME_CLASS(CView)))
            delete pPane;
            */
}


int GetViewIDFromParentSplitter(CWnd* view)
{
      CSplitterWnd* parent = dynamic_cast<CSplitterWnd*>(view->GetParent());

      if (parent == 0)
            return AFX_IDW_PANE_FIRST;

      int rows, cols;

      rows = parent->GetRowCount();
      cols = parent->GetColumnCount();
      for(int row = 0; row < rows; row++)      
      {
            for(int col = 0; col < cols; col++)            
            {
                  if(view == parent->GetPane(row,col))
                  {
                        return parent->IdFromRowCol(row, col);
                  }
            }
      }

      ASSERT(true == false);
      return 0;
}
0
 
Gandalf32Commented:
You have to add:

BEGIN_MESSAGE_MAP(CCustomSplitWnd, CSplitterWnd)
//{{AFX_MSG_MAP(CPCAcqSplitWnd)
ON_WM_NCHITTEST()
ON_WM_SIZE()   <-- Added line
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


This adds the event to the window's message map.
0
 
sosedadaAuthor Commented:
DUH!!!!!  I guess thats what happens when you rely on class wizard too much.  Please answer for your points.
0
 
sosedadaAuthor Commented:
thanks
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now