Codejock Forums Homepage
Forum Home Forum Home > Codejock Products > Visual C++ MFC > Toolkit Pro
  New Posts New Posts RSS Feed - How to use CXTHeaderCtrl
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

How to use CXTHeaderCtrl

 Post Reply Post Reply
Author
Message
adrien View Drop Down
Senior Member
Senior Member


Joined: 30 April 2007
Location: New Zealand
Status: Offline
Points: 449
Post Options Post Options   Thanks (0) Thanks(0)   Quote adrien Quote  Post ReplyReply Direct Link To This Post Topic: How to use CXTHeaderCtrl
    Posted: 07 October 2007 at 4:51pm

Hi

The documentation on CXTHeaderCtrl isn't clear, and I'm having problems.
 
Documentation doesn't show SetStyle() function, but it exists. 
 
When I create a CXTHeaderCtrl as a member of another class, then I get a blow-up when that object is deleted.
 
The themes is the main problem. 
 
It says I must call a windows API call SubclassWindow.  There is no such API. 
 
* There is a CWnd::SubclassWindow, but this is no use if I already created the control.  Why must I call this anyway? 
* Must I only call this if I derived from CXTHeaderCtrl. 
* Must I derive from CXTHeaderCtrl (and if so why????)
 
Thanks

Adrien
Back to Top
kstowell View Drop Down
Admin Group
Admin Group


Joined: 25 January 2003
Location: MIchigan, USA
Status: Offline
Points: 496
Post Options Post Options   Thanks (0) Thanks(0)   Quote kstowell Quote  Post ReplyReply Direct Link To This Post Posted: 07 October 2007 at 6:00pm

Hi Adrien,

You can subclass the CXTHeaderCtrl by calling the following method:

virtual bool CXTListCtrl::SubclassHeader(bool bBoldFont = false)

Once the header is subclassed, you can then call the following method to access a pointer to the header control:

CXTFlatHeaderCtrl* CXTListCtrl::GetFlatHeaderCtrl() const

NOTE: The CXTFlatHeaderCtrl class is actually obsolete and you should use CXTHeaderCtrl instead. The CXTFlatHeaderCtrl is only provided for backward compatibility with older versions.

The reason why the header control is not automatically instanciated when the CXTListCtrl object is created, is because there may be some cases where a user does not want to use the CXTHeaderCtrl.

Also, it is not necessary to derive a class from CXTHeaderCtrl in order to use it, however you can. You can also instanciate the CXTHeaderCtrl separately from the CXTListCtrl. The "ListCtrl" sample under the "Controls" section demonstrates this. Take a look at the "ListCtrlDlg.cpp" file, you will see the following code:

// Get the windows handle to the header control for the
// list control then subclass the control.
HWND hWndHeader = m_listCtrl.GetDlgItem(0)->GetSafeHwnd();
m_header.SubclassWindow(hWndHeader);
// add bitmap images.
m_header.SetBitmap(0, IDB_COLUMN_0, FALSE, RGB(0,255,0));
m_header.SetBitmap(1, IDB_COLUMN_1, FALSE, RGB(0,255,0));
m_header.SetBitmap(2, IDB_COLUMN_2, FALSE, RGB(0,255,0));
// enable auto sizing.
m_header.EnableAutoSize(TRUE);
m_header.ResizeColumnsToFit();

Hope this helps,

Kirk Stowell, President and CEO
CODEJOCK SOFTWARE SOLUTIONS<
Back to Top
adrien View Drop Down
Senior Member
Senior Member


Joined: 30 April 2007
Location: New Zealand
Status: Offline
Points: 449
Post Options Post Options   Thanks (0) Thanks(0)   Quote adrien Quote  Post ReplyReply Direct Link To This Post Posted: 07 October 2007 at 8:13pm
Thanks for that info.
 
I'm getting a few crashes though.  When the app exits I get an assert
 
 ASSERT(m_factoryList.m_pHead == 0);
in XTThemeManager.cpp(325)
 
and then an access violation exception in
 
AFXTLS.CPP(52) from CSimpleList::Remove() which has come from CXTThemeManagerStyleFactory::~CXTThemeManagerStyleFactory() call to m_hostList.RemoveAll(); 
 
m_hostList.m_pHead are NULL in this case.
 
but in CSimpleList::Remove, m_pHead is 0xfeeefeee (deleted memory) which is being dereferenced (in GetNextPtr)
 
Back to Top
adrien View Drop Down
Senior Member
Senior Member


Joined: 30 April 2007
Location: New Zealand
Status: Offline
Points: 449
Post Options Post Options   Thanks (0) Thanks(0)   Quote adrien Quote  Post ReplyReply Direct Link To This Post Posted: 07 October 2007 at 8:20pm
PS, I'm not using this in a list control.  It's just a header control for a custom control I've written.
 
Code for CXTListBase::SubclassHeader doesn't help either
 
bool CXTListBase::SubclassHeader(bool bBoldFont/*= false*/)
{
 // if we are not in report mode return false.
 if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  return false;
 // header was already subclassed!
 if (::IsWindow(m_flatHeader.GetSafeHwnd()))
  return false;
 // Get the windows handle to the header control for the
 // list control then subclass the control.
 HWND hWndHeader = _xtGetHeaderCtrl()->GetSafeHwnd();
 if (!m_flatHeader.SubclassWindow (hWndHeader))
  return false;
 // finish header initialization.
 m_flatHeader.InitializeHeader(bBoldFont);
 return true;
}
All it's doing is calling CWnd::SubclassHeader, but only if the control already hasn't been created.  So how do we just use a CXTHeaderCtrl?  It seems what you need to do is.
 
1. Create some other control (not CXTHeaderCtrl).
2. Subclass it to be a CXTHeaderCtrl by having another object of type CXTHeaderCtrl say m_Header, and calling m_Header.SubclassWindow(hWndOfOtherCtrl)
 
my code is:
 
 m_Header.Create(HDS_HOTTRACK | HDS_HORZ | CCS_TOP | WS_CHILD | WS_VISIBLE, CRect(0,0,0,0), this, 1);
 m_Header.InitializeHeader(FALSE);
 m_Header.SetTheme(new CXTHeaderCtrlThemeOffice2003());
 
 HDITEM item;
...
 m_Header.InsertItem(0, &item);
 
 
 
Back to Top
kstowell View Drop Down
Admin Group
Admin Group


Joined: 25 January 2003
Location: MIchigan, USA
Status: Offline
Points: 496
Post Options Post Options   Thanks (0) Thanks(0)   Quote kstowell Quote  Post ReplyReply Direct Link To This Post Posted: 08 October 2007 at 10:52am
Originally posted by adrien adrien wrote:

PS, I'm not using this in a list control.  It's just a header control for a custom control I've written.
 
This is could be the problem. The CXTHeaderCtrl was created as a companion to CXTListCtrl and CXTListView class, and most likely will not work when subclassed for other controls.
 
Instead of subclassing the header by calling CWnd::SubclassWindow(HWND) have you tried to create the header and position it manually? You may have better results.
 
if (!m_header.Create([args]))
    return FALSE;
 
then:
 
m_header.SetWindowPos([args]);
 
Regards,
Kirk Stowell, President and CEO
CODEJOCK SOFTWARE SOLUTIONS<
Back to Top
adrien View Drop Down
Senior Member
Senior Member


Joined: 30 April 2007
Location: New Zealand
Status: Offline
Points: 449
Post Options Post Options   Thanks (0) Thanks(0)   Quote adrien Quote  Post ReplyReply Direct Link To This Post Posted: 08 October 2007 at 3:10pm
Hi
 
yes,that's what I ended up doing.
 
It's just that the code blows up when the app exits.  I think there's a bug somewhere in the CJ framework which isn't removing style factories when things using them are destroyed.
 
At the moment to stop it crashing (it still asserts though, which is really annoying) I had to new the instance of the CXTHeaderCtrl and not delete it (so leak).
 
Since it derives from CHeaderCtrl, it should be usable like CHeaderCtrl, which works fine in this case (just no styles).
Back to Top
kstowell View Drop Down
Admin Group
Admin Group


Joined: 25 January 2003
Location: MIchigan, USA
Status: Offline
Points: 496
Post Options Post Options   Thanks (0) Thanks(0)   Quote kstowell Quote  Post ReplyReply Direct Link To This Post Posted: 08 October 2007 at 3:52pm
If you can send me a sample app, I can debug it and try to provide a more stable solution for you. You can send it to support@codejock.com if you like, just put it to my attention.
 
Cheers,
Kirk Stowell, President and CEO
CODEJOCK SOFTWARE SOLUTIONS<
Back to Top
Algae View Drop Down
Senior Member
Senior Member
Avatar

Joined: 08 January 2007
Location: United States
Status: Offline
Points: 217
Post Options Post Options   Thanks (0) Thanks(0)   Quote Algae Quote  Post ReplyReply Direct Link To This Post Posted: 14 March 2008 at 1:48pm
I've subclassed the CXTListHeader before and haven't had trouble with it.

However, if you are getting the dreaded CXTThemeManager assert:

ASSERT(m_factoryList.m_pHead == 0);

the manager is only trying to tell you that things are not cleaning up.  It's just a little obscure is all.

Usually this problem has happened to me when I created a modeless dialog and forgot to add the cleanup to it. For example we can create a dialog (assume it is themed):

void CMainFrame::OnMyModelessDlg()
{
    CMyModelessDlg*dlg = new CMyModelessDlg(AfxGetMainWnd());
    dlg->Create(CMyModelessDlg::IDD);
    dlg->ShowWindow(SW_SHOW);
}

Now, if you exit the program it will assert in CXTThemeManager! Unless we add this to the CMyModelessDlg class:

void CMyModelessDlg::PostNcDestroy()
{   
    CXTPDialog::PostNcDestroy();
    delete this;
}

That will clean things up and the assert no longer happens.



Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 12.04
Copyright ©2001-2021 Web Wiz Ltd.

This page was generated in 0.188 seconds.