CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Oct 2011
    Posts
    97

    Subclass HeaderCtrl in ListCtrl

    I made one of these threads a few months ago, but I never solved this problem because I was offered a work-around that was a better choice at the time. But now I'm back to this problem. And although there might be a way to work-around this one, I really don't want. I really want to get this right, because it'll come in so useful. I have a custom CSortListCtrl class that derives from CMFCListCtrl and a custom CSortHeaderCtrl class that derives from CMFCHeaderCtrl. I want to replace the header control in the list control with my custom header control, but can't seem to get it right. So far, this is the code I have in the custom list control.

    Code:
    void CSortListCtrl::PreSubclassWindow()
    {
    	CMFCListCtrl::PreSubclassWindow();
    
    	i_header.SubclassWindow(GetHeaderCtrl().GetSafeHwnd());
    }
    I've also tried having i_header as a pointer and creating it right before subclassing, and that didn't work either. I also tried overriding the GetHeaderCtrl() function to return my header ctrl, but that gives me a runtime exception that causes the program to crash. I've also tried using this line which I found online, but same error.

    Code:
    i_header.SubclassDlgItem(0, this);
    I feel like I've ready every tutorial on the internet and can't get it right. What am I missing?

    EDIT: I should mention that the code I posted compiles, but doesn't actually subclass, as my override functions aren't called.

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Subclass HeaderCtrl in ListCtrl

    Quote Originally Posted by Access_Denied View Post
    ISo far, this is the code I have in the custom list control.
    So, what's wrong with this code?
    Quote Originally Posted by Access_Denied View Post
    I've also tried having i_header as a pointer and creating it right before subclassing, and that didn't work either.
    What do you mean with "didn't work"?
    Quote Originally Posted by Access_Denied View Post
    I also tried overriding the GetHeaderCtrl() function to return my header ctrl, but that gives me a runtime exception that causes the program to crash.
    Where do you get the runtime exception? Did you debug the program?
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Oct 2011
    Posts
    97

    Re: Subclass HeaderCtrl in ListCtrl

    Quote Originally Posted by D_Drmmr View Post
    So, what's wrong with this code?

    What do you mean with "didn't work"?
    I posted that in the edit I made:

    Quote Originally Posted by Access_Denied
    EDIT: I should mention that the code I posted compiles, but doesn't actually subclass, as my override functions aren't called.


    Quote Originally Posted by D_Drmmr View Post
    Where do you get the runtime exception? Did you debug the program?
    It's a debug assertion error. It seems that the header control isn't being created if I override the GetHeaderCtrl function like this:

    Code:
    	virtual CSortHeaderCtrl& GetHeaderCtrl ()
    	{
    		return i_header;
    	}

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Subclass HeaderCtrl in ListCtrl

    Quote Originally Posted by Access_Denied View Post
    EDIT: I should mention that the code I posted compiles, but doesn't actually subclass, as my override functions aren't called.
    From MSDN:
    The window must not already be attached to an MFC object when this function is called.
    Given that you call GetSafeHwnd() to get the window handle, the window is already attached to a CWnd instance. Try detaching the window first in combination with overriding the GetHeaderCtrl function.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: Subclass HeaderCtrl in ListCtrl

    That is the code that works for me for the standard CListCtrl:
    Code:
    void CSubItemCheckListCtrl::PreSubclassWindow() 
    {
    	m_header.SubclassDlgItem(0, this);
    
    	CListCtrl::PreSubclassWindow();
    }
    where m_header is of the type derived from CHeaderCtrl and CSubItemCheckListCtrl is derived from CListCtrl
    Victor Nijegorodov

  6. #6
    Join Date
    Oct 2011
    Posts
    97

    Re: Subclass HeaderCtrl in ListCtrl

    I tried detaching the header control in various ways and that didn't work.

    VictorN, that is the exact code I'm using, but it doesn't seem to work. It runs, but my custom header control functions aren't being called. Maybe it's with my override?

    SortHeaderCtrl.cpp
    Code:
    #include "stdafx.h"
    #include "Scrip Pro.h"
    #include "SortHeaderCtrl.h"
    
    BEGIN_MESSAGE_MAP(CSortHeaderCtrl, CMFCHeaderCtrl)
    END_MESSAGE_MAP()
    
    IMPLEMENT_DYNAMIC(CSortHeaderCtrl, CMFCHeaderCtrl)
    
    /// <summary>
    /// Default constructor.
    /// </summary>
    CSortHeaderCtrl::CSortHeaderCtrl()
    {
    
    }
    
    /// <summary>
    /// Default destructor.
    /// </summary>
    CSortHeaderCtrl::~CSortHeaderCtrl()
    {
    
    }
    
    /// <summary>
    /// Called by the framework to draw the sorting arrow for the column.
    /// </summary>
    /// <param name="pDC">Device context to draw to</param>
    /// <param name="rectArrow">Size of the arrow</param>
    void CSortHeaderCtrl::OnDrawSortArrow( CDC* pDC, CRect rectArrow )
    {
    	pDC->FillSolidRect(rectArrow, RGB(255,255,255));
    }
    SortHeaderCtrl.h
    Code:
    #pragma once
    
    class CSortHeaderCtrl : public CMFCHeaderCtrl
    {
    	DECLARE_DYNAMIC(CSortHeaderCtrl)
    
    public:
    	CSortHeaderCtrl();
    	virtual ~CSortHeaderCtrl();
    
    protected:
    	DECLARE_MESSAGE_MAP()
    
    	virtual void OnDrawSortArrow(CDC* pDC, CRect rectArrow);
    };
    If I set a breakpoint in the OnDrawSortArrow function, it never gets hit. The only thing I'm thinking it could be is that I'm using CMFCListctrl not CListCtrl. But I really need to use CMFCListCtrl. Also, the latter is the parent class of the former, so how could that cause so many issues?

  7. #7
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: Subclass HeaderCtrl in ListCtrl

    i don't know.
    Could you prepare a small test project reproducing such a behavior and post it to Forum?
    Victor Nijegorodov

  8. #8
    Join Date
    Oct 2011
    Posts
    97

    Re: Subclass HeaderCtrl in ListCtrl

    Quote Originally Posted by VictorN View Post
    i don't know.
    Could you prepare a small test project reproducing such a behavior and post it to Forum?
    Yeah, I was actually experimenting with a test project the other day. I added the subclassing (still doesn't work) and uploaded it. There's a lot of files in the project, but the only classes that should be of consideration are CChildFrame, CListCtrlEx and CHeaderCtrlEx.

    I developed this in VS2008 under Windows 7.

    I'm still trying to search on window subclassing, but I'm coming up with nothing. It's quite frustrating. :/

    PS. I know the file is named as a .zip file, but it's actually a .7z file. I had to rename because the forum wouldn't accept .7z files and the actual .zip was too big. So just rename it to .7z.
    Attached Files Attached Files

  9. #9
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,244

    Re: Subclass HeaderCtrl in ListCtrl

    If you want to subclass the header control in your own CMFCHeaderCtrl-derived class (let's say it CMyMFCHeaderCtrl), all you have to do is:
    1. In the class derived from CMFCListCtrl (CMyMFCListCtrl), add a member of type CMyMFCHeaderCtrl, let's say it m_headerCtrl; this will replace CMFCListCtrl::m_wndHeader.
    2. Override CMFCListCtrl::GetHeaderCtrl and return m_headerCtrl.
    3. Override CMFCListCtrl::InitHeader to subclass the header control.

    Example
    Code:
    class CMyMFCListCtrl : public CMFCListCtrl
    {
       CMyMFCHeaderCtrl m_headerCtrl; // replaces CMFCListCtrl::m_wndHeader
    // ...
    public:
       virtual void InitHeader();
       virtual CMFCHeaderCtrl& GetHeaderCtrl() {return m_headerCtrl;}
    // ...
    };
    Code:
    void CMyMFCListCtrl::InitHeader()
    {
       // Initialize header control:
       m_headerCtrl.SubclassDlgItem(0, this);
    }
    That's all and there is nothing more to do in PreSubclassWindow or in other place.
    Last edited by ovidiucucu; May 29th, 2012 at 05:16 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  10. #10
    Join Date
    Oct 2011
    Posts
    97

    Re: Subclass HeaderCtrl in ListCtrl

    My friend, you are a life saver. Worked like a charm. I can't believe that this didn't show up in any of my 100+ searches. :/ Oh well, at least it's now documented for people in the future.

    Thank you to everybody for your help, I appreciate it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured