Creating views for static splitter

I have a working shell namespace extension with a listview in the shellview window in the windows explorer. Now, I want to make a static 2 row,1 col splitter in the shellview with the previous list in a top row and another CWnd derived class in the lower. The problem occurs later, read on.

Here's what I have in the CreateViewWindow:

STDMETHODIMP CIsdShellView::CreateViewWindow(LPSHELLVIEW pPrevView,
                                                LPCFOLDERSETTINGS lpfs,
                                                LPSHELLBROWSER psb,
                                                LPRECT prcView,
                                                HWND *phWnd)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Needed because AfxGetModuleInstance crashes in mfc classes otherwise
    *phWnd = NULL;
   
    // Set up the member variables
    m_FolderSettings = *lpfs;
   
    // Get the parent window from Explorer. 
    m_pShellBrowser = psb;
    m_pShellBrowser->GetWindow(&m_hWndParent);
   
    // Create a container window, which will be the parent of the list control.
    WNDCLASS wc;
    if(!GetClassInfo(m_Global.GetHInstance(), NS_CLASS_NAME, &wc) )
    {
        ZeroMemory(&wc, sizeof(WNDCLASS));
        wc.style             = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc         = (WNDPROC)WindowProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = m_Global.GetHInstance();
        wc.hIcon            = NULL;
        wc.hCursor            = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = NS_CLASS_NAME;
       
        if(!RegisterClass(&wc))
          return E_FAIL;
    }
   
    // create the window, parent of the listview
    m_hWnd = CreateWindowEx(0, NS_CLASS_NAME, NULL,
                            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
                            prcView->left, prcView->top,
                            prcView->right - prcView->left,
                            prcView->bottom - prcView->top,
                            m_hWndParent, NULL, m_Global.GetHInstance(), this);
   
    // Initialize a context for the view. CSplitListView is my view and
    // is defined as :  class CSplitListView : public CListView.
    CCreateContext ccc;
    ccc.m_pNewViewClass   = RUNTIME_CLASS(CSplitListView);
    ccc.m_pCurrentDoc     = NULL;
    ccc.m_pNewDocTemplate = NULL;
    ccc.m_pLastView       = NULL;
    ccc.m_pCurrentFrame   = NULL;
   
    if(m_pWindow)
        m_pWindow->Detach();
   
    RELEASE_VAR(m_pWindow);
    m_pWindow = new CWnd;
    m_pWindow->Attach(m_hWnd);
   
    m_Splitter.CreateStatic(m_pWindow, 2, 1);
    m_Splitter.CreateView(0, 0, RUNTIME_CLASS(CSplitListView), CSize(prcView->right - prcView->left, (prcView->top - prcView->bottom) / 2), &ccc);
    m_Splitter.CreateView(1, 0, RUNTIME_CLASS(CSplitListView), CSize(prcView->right - prcView->left, (prcView->top - prcView->bottom) / 2), &ccc);
       
    if(!m_hWnd)
        return E_FAIL;
   
    m_pShellBrowser->AddRef();
   
    *phWnd = m_hWnd;
    return S_OK;
}

The problem occurs in m_Splitter.CreateView where an assert fires on these lines in wincore.cpp function CWnd::AssertValid():

        ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
            (p = pMap->LookupTemporary(m_hWnd)) != NULL);

Apparently there is no cwnd associated with m_hWnd. What did I miss



Answer this question

Creating views for static splitter

  • Crypto_N

    Just a guess: The CSplitterWnd m_Splitter was never created The object exists but you need to call m_Splitter.Create!

  • st23am23

    Yes the question is why it isn't. I'm beginning to think you can't use a splitter in a ishellview. I haven't found anyone all over the internet that has done it before.

  • Michael_SHG

    Thanks for the reply.

    I call CreateStatic. According to MSDN:

    1. Embed a CSplitterWnd member variable in the parent frame.

    2. Override the parent frame’s CFrameWnd::OnCreateClient member function.

    3. From within the overridden OnCreateClient, call the Create or CreateStatic member function of CSplitterWnd.


    I'm guessing the problem is that I'm not embedding it in a CFrameWnd but I shouldn't have to since I've seen it done in CDialogs.

    It's a mess to add mfc things to a namespace extension. No experts on the subject around =D Don't mean to offend you Martin if you have any other suggestions I really want to hear them!


  • JOESOL643

    But something is wrong with m_Splitter. The m_hWnd is in some way not correct, because its not in the message map. I can say nothing else. Something with the basic MFC algorithms is going wrong here. After creation of the m_Splitter window it must be in the window handle map of the MFCs current thread.



  • JRaue

    Sorry for my last post. Just ignore it. I just read your quote from the MSDN as the action you have done.

    Anyhow whats on the callstack



  • tonante

    Oh I'm sorry I didn't mention the version. I didn't see any messages that this was only for VS 2005. I had to develop in VC6 because of customers.

    By error-handling do you mean checking the bools returned Doesn't tell me much. And according to documentation there isn't any exception handling either

    I'm pretty new to MFC and shell extensions but I wanted to get a demo up and running as quick as possible. Had no idea it would be this tricky with asserts everywhere.


  • Nate Dogg

    No its not a problem for me. But its complicated to look into VC2005, VC2003, VC2002 and VC6 for a matching line :-)

    Error handling tells you that something was wrong and subsequent calls might fail.
    No there is no excpetion. As documented most of the MFC functions return a BOOL TRUE on success.

    Please trace into the code of CreateStatic. Check the value of GetLastError to see what happens. If the CreateWindow call for the static fails.

    You ASSERT is the follower of an earlier problem.



  • Janus C. H. Knudsen

    Here's the callstack if it helps:

    [code]
    CWnd::AssertValid() line 883 + 67 bytes
    CSplitterWnd::AssertValid() line 2329
    AfxAssertValidObject(const CObject * 0x028451d8 {CSplitterWnd hWnd=0x000607cc}, const char * 0x5f4cd8a0 THIS_FILE, int 244) line 108
    CSplitterWnd::CreateView(int 0, int 0, CRuntimeClass * 0x028200e8 struct CRuntimeClass const CHolderView::classCHolderView, tagSIZE {...}, CCreateContext * 0x01a9e620) line 245
    CIsdShellView::CreateViewWindow(CIsdShellView * const 0x028451a8, IShellView * 0x00137768, const FOLDERSETTINGS * 0x00117ac0, IShellBrowser * 0x00113b58, tagRECT * 0x01a9e7bc {top=82 bottom=553 left=237 right=792}, HWND__ * * 0x01a9e7d0) line 200 + 67 bytes
    SHDOCVW! 7777acd9()
    SHDOCVW! 7777abc6()
    BROWSEUI! 75f88518()
    BROWSEUI! 75fa5fa2()
    SHDOCVW! 7777b056()
    SHDOCVW! 7777aed4()
    SHDOCVW! 7777ae40()
    BROWSEUI! 75f885ef()
    BROWSEUI! 75fa5044()
    SHDOCVW! 7777ab6b()
    SHDOCVW! 7777b1fb()
    BROWSEUI! 75f828c9()
    BROWSEUI! 75fb033d()
    BROWSEUI! 75fadd2e()
    USER32! 77d48734()
    USER32! 77d48816()
    USER32! 77d489cd()
    USER32! 77d48a10()
    BROWSEUI! 75fa6f6d()
    BROWSEUI! 75fae942()
    BROWSEUI! 75faeab5()
    KERNEL32! 7c80b50b()
    [/code]

  • JamesWood

    As you can see in the code I don't have a framewnd. I have the explorer as parent though. maybe there's a framewnd down the line.


  • Marsan001

    the assert_valid crashed on the same spot as createview when I put it after createstatic so something isn't right even though it returns true.


  • Much Less Annoyed

    Sure that OnCreateClient in your FrameWnd is called
    Look at the callstack, what code causes this ASSERT

    A CSplitterWnd can be hosted in any window. No need to be a frame window. The problem are views, views always need a CFrameWnd somewere in the windows tree as parent! (But this is not your problem)



  • RossDonald

    Yeah I can imagine. At least now we're on the same page =)

    Wanna hear something fun CreateStatic doesn't fail. Nor does any other create functions in this function.

    Here's the current version of the CreateViewWindow function.

  • Krystian S.

    Now I see that you are using VC6! You didn't wrote it, and according to the forum topic I thought you are using VS.2005.

    Back to the problem:
    It is as I wrote! Your CSplitterWnd is not created.
    The ASSERT in line 245 of CSplitterWnd says that the object isn't valid. And its not valid because the window m_hWnd is not set.

    You called CreateStatic but you have no error handling. Check out what happens there.

    BTW: Doing this create stuff without error handling is very dangerous.



  • easan

    From my point of view it has nothing to do with CSplitterWnd. The Splitterwnd isnot in the handle map! This will cause the message map translation of the win32 message into the MFC message maps to fail.

    I wonder because the SetStyleEx before the call works. What happens if you call ASSERT_VALID(&m_Splitter) just after creation



  • Creating views for static splitter