|
Please, add the following line to the source code for the correct vertical line painting:
...
CRect rcItem;
m_tree.m_wndHeader.GetItemRect(lpnmhdr->iItem, &rcItem);
rcItem.DeflateRect(m_tree.m_nOffset, 0);
if (phdi != NULL && phdi->mask & HDI_WIDTH)
Oscar L.
|
|
|
|
|
The sort code isn't quite right.
1. The SortItems call in CTLFrame::OnNotify doesn't seem to do anything, since the handle passed in is NULL. The SortTree call immediately following does all the work.
2. It doesn't properly descend the tree. The following code seems to work:
void CTLFrame::SortTree(int nCol, BOOL bAscending, HTREEITEM hParent)
{
if (hParent != NULL) {
HTREEITEM hChild;
m_tree.SortItems(nCol, bAscending, hParent);
if(m_tree.ItemHasChildren(hParent))
{
hChild = m_tree.GetChildItem(hParent);
while(hChild!=NULL)
{
SortTree(nCol, bAscending, hChild);
hChild = m_tree.GetNextSiblingItem(hChild);
}
}
}
}
|
|
|
|
|
Actually, in the initial code, you just have to switch the two lines:
from
m_tree.SortItems(nCol, bAscending, hPa);
SortTree(nCol, bAscending, hChild);
to
SortTree(nCol, bAscending, hChild);
m_tree.SortItems(nCol, bAscending, hPa);
and that works very well. Indeed, you need first to sort the children before the parent, otherwise you can miss some children to be sorted,
Gregoire Gentil
http://www.gentil.com
|
|
|
|
|
I found your control to be spot on, I have been searching for such a solution for a long long long time...
I need such a control to be an OCX file for use in VB 6.0
How would I go about doing this with your code?
Its been a long time since I used VC++ so step by step would be usefull
Thankx in advance
Jerry Gadd
|
|
|
|
|
Just a quickie,
I had an annoying bug where if you call DeleteAllItems on the tree and then insert a single root item it will display the text ok but will miss out the image, if you insert child nodes into the single root item then the expand + will also not be drawn until you blindly click on it..
The solution seems to be in the NewTreeListCtrl.cpp there is a DeleteAllItems, remove both the SetRedraw calls and it should be fine
I have used it like this for a while and ther does not seem to be any repercussions other than it working.
|
|
|
|
|
Yes it works, but....
The SetRedraw(FALSE) avoid the list refresh (during the delete process) , and SetRedraw(TRUE) allows to refresh
If you have many items and you had comment those lines, it will take a long time to fill your list
I got the pb with the image too, and no solution !
Regards
- Don't worry, be happy -
|
|
|
|
|
Is it hard to add multiple row selection to this control? Or is it already there somewhere and I overlooked it?
chris
|
|
|
|
|
|
I added a function to delete headers.
void CNewTreeListCtrl::DeleteHeaders()
{
int nCount = m_wndHeader.GetItemCount();
for (int i=0;i < nCount;i++)
{
m_wndHeader.DeleteItem(0);
}
}
Help yourself and codeproject will help you
|
|
|
|
|
Hi,
I'can't see the last item of the treectrllist.
Is it a scrollbar problem ?
Regards
Oliv'
Help yourself and codeproject will help you
|
|
|
|
|
HI,
Your control is very cool.
I'm working with VC7++, and there is a problem with the notify message.
When I click on an header, the event arrive in CTLFrame::OnNotify, but the test
(pHDN->hdr.code == HDN_ITEMCLICK) doesn't work.
I tried to change the HD_NOTIFY cast in NMHEADER, but nothing to do, it doesn't work.
So, it will be very cool if you can help me !!!!;)
Oliv'
|
|
|
|
|
This is something I found the hard way when first using header controls a few years ago. Even on non-Unicode built apps the messages sent by the headers use the Unicode versions. Therefore the test needs to be:
(pHDN->hdr.code == HDN_ITEMCLICKA || pHDN->hdr.code == HDN_ITEMCLICKW) (I found it using Spy++ : it's always worth using it when the messages don't seem to be behaving themselves.)
I hope this is cool enough for you!
Paul.
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
Hi Paul,
Thanks a lot for your answer and your control.
I beleive the problem has disapeared using VC++7, but I'm not sure.
However another pb appears with VC++, the refresh of the columns displayed some strange squares.
I beleive it was a pb of PAINF message. I corrected something, and that's good now.
I can try to give you more details if you want.
Olivier.
Don't worry, be happy
|
|
|
|
|
Nice control, thanx !! If I have large amounts of data to display, I want to be able to handle the GetDispInfo notification to display items on demand. However, I don't receive the notification at all.
Is it possible to handle the TVN_GETDISPINFO notification with this control ? If so, how ?
Thanks in advance for any help,
Guest
|
|
|
|
|
The version downloadable the 4th of March 2002 is compilable only after:
1) Commenting
lines 366 and 367 in TLView.rc
[
//#include "l.heb\afxres.rc" // Standard components
//#include "l.heb\afxprint.rc" // printing/print preview resources
]
2)
Also it is necessary to create a 'res' subdirectory
and move in there the files:
bmp00001.bmp
bmp00040.bmp
Toolbar.bmp
TLView.ico
TLViewDoc.ico
TLView.rc2
Marcello
|
|
|
|
|
Thanks for documenting this and saving me the time.
--pk
|
|
|
|
|
I would like to do something like the code that follows however it dies with an assertion failure while creating the window. Note that I am not using the control in a dialog box from the resource editor nor in a document/view setup. I am under the impression that the control should work on its own without TLView.
Can anyone help a newbie out?
---------------------------------------------------------------------------------------------
#include "TLFrame.h"
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg int OnCreate(LPCREATESTRUCT);
DECLARE_MESSAGE_MAP()
private:
CTLFrame m_Child;
};
CMyApp myApp;
BOOL CMyApp::InitInstance()
{
CTLFrame::RegisterClass();
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return (TRUE);
}
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
Create(NULL, "Foo");
}
int CMainWindow::OnCreate(LPCREATESTRUCT lpcs)
{
if (CWnd::OnCreate(lpcs) == -1)
return (-1);
CRect rect;
GetClientRect(&rect);
m_Child.Create("LANTIVTREELISTCTRL", "foo", WS_CHILD|WS_VISIBLE, rect, this, 0);
return (0);
}
|
|
|
|
|
The control overrides PreSubclassWindow and performs initialization from there. PreSubclassWindow is called only when the control is subclassed, and not when created. I think you should call CTLFrame::Init after you create the control and it'll work properly.
|
|
|
|
|
Thanks for the reply. The program is actually dying in the call to Create() so it's too late to call Initialize() after that. The stack trace when it dies is below:
CWnd::GetWindowRect(tagRECT * 0x0012f498 {top=-858993460 bottom=-858993460 left=-858993460 right=-858993460}) line 96 + 43 bytes
CTLFrame::OnSize(unsigned int 0, int 1332, int 938) line 413
CWnd::OnWndMsg(unsigned int 5, unsigned int 0, long 61474100, long * 0x0012f5dc) line 1845
CWnd::WindowProc(unsigned int 5, unsigned int 0, long 61474100) line 1585 + 30 bytes
AfxCallWndProc(CWnd * 0x002f2830 {CTLFrame hWnd=0x00070404}, HWND__ * 0x00070404, unsigned int 5, unsigned int 0, long 61474100) line 215 + 26 bytes
AfxWndProc(HWND__ * 0x00070404, unsigned int 5, unsigned int 0, long 61474100) line 368
AfxWndProcBase(HWND__ * 0x00070404, unsigned int 5, unsigned int 0, long 61474100) line 220 + 21 bytes
USER32! 77e11b60()
USER32! 77e12f29()
USER32! 77e12f4f()
NTDLL! 77fa032f()
USER32! 77e17531()
CWnd::CreateEx(unsigned long 0, const char * 0x0041f258 `string', const char * 0x0041f270 `string', unsigned long 1342177280, int 0, int 0, int 1332, int 938, HWND__ * 0x000d0430, HMENU__ * 0x00000000, void * 0x00000000) line 694 + 54 bytes
CWnd::Create(const char * 0x0041f258 `string', const char * 0x0041f270 `string', unsigned long 1342177280, const tagRECT & {top=0 bottom=938 left=0 right=1332}, CWnd * 0x002f2770 {CMainWindow hWnd=0x000d0430}, unsigned int 0, CCreateContext * 0x00000000) line 743
CMainWindow::OnCreate(tagCREATESTRUCTA * 0x0012fbf4) line 48 + 50 bytes
CWnd::OnWndMsg(unsigned int 1, unsigned int 0, long 1244148, long * 0x0012fa7c) line 1811 + 13 bytes
CWnd::WindowProc(unsigned int 1, unsigned int 0, long 1244148) line 1585 + 30 bytes
AfxCallWndProc(CWnd * 0x002f2770 {CMainWindow hWnd=0x000d0430}, HWND__ * 0x000d0430, unsigned int 1, unsigned int 0, long 1244148) line 215 + 26 bytes
AfxWndProc(HWND__ * 0x000d0430, unsigned int 1, unsigned int 0, long 1244148) line 368
AfxWndProcBase(HWND__ * 0x000d0430, unsigned int 1, unsigned int 0, long 1244148) line 220 + 21 bytes
USER32! 77e11b60()
USER32! 77e12f29()
USER32! 77e16169()
NTDLL! 77fa032f()
USER32! 77e17531()
CWnd::CreateEx(unsigned long 0, const char * 0x00000000, const char * 0x0041f124 `string', unsigned long 13565952, int -2147483648, int -2147483648, int -2147483648, int -2147483648, HWND__ * 0x00000000, HMENU__ * 0x00000000, void * 0x00000000) line 694 + 54 bytes
CFrameWnd::Create(const char * 0x00000000, const char * 0x0041f124 `string', unsigned long 13565952, const tagRECT & {top=-2147483648 bottom=0 left=-2147483648 right=0}, CWnd * 0x00000000 {CWnd hWnd=???}, const char * 0x00000000, unsigned long 0, CCreateContext * 0x00000000) line 568 + 79 bytes
CMainWindow::CMainWindow() line 40
CMyApp::InitInstance() line 27 + 34 bytes
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x001330e3, int 1) line 39 + 11 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x001330e3, int 1) line 30
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! 77e8d326()
|
|
|
|
|
I'm having this exact same issue. I used to be using this control from within a view, but the scenerio has changed and I need to create this control "on the fly". I tried creating the control with the name TLFrame instead of LANTIVTREELISTCTRL, and it actually manages to get passed creation...but it isn't really created. Besides that, I get the same results as you.
|
|
|
|
|
ok, here's how I fixed this issue. I went in to the OnSize and MoveWindow code, and added a check GetSafeHwnd() I only check one of the windows, and bail if it fails. The reason this is crashing is because Initialize hasn't been called yet, so those windows haven't been created. (and OnSize gets called when we create the CTLFrame). Anyway, after my Create call, I also call Initialize (made it a public method), this creates the header, tree, etc... I also changed the code in Initialize, where it gets the Parent's Font, changed it to this:
CFont font;
font.Attach(::GetStockObject(DEFAULT_GUI_FONT));
font.GetLogFont(&logfont);
This might not be an issue for you, but it was causing problems for me the way it was. Anyway, hope this helps...
|
|
|
|
|
Anonymous wrote:
PreSubclassWindow is called only when the control is subclassed, and not when created
This is not true. PreSubclassWindow is called from _AfxCbtFilterHook , which is called (indirectly) from CreateWindowEx , which is called to create windows. The call to AfxHookWindowCreate before CreateWindowEx makes sure that the hook function (_AfxCbtFilterHook ) is called. Look in wincore.cpp in the MFC sources.
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
Great control!
One problem though. I can't seem to be able to read the values found in the subitems text using the GetItemText function.
Example:
m_lstBills.m_tree.GetItemText(x, 1);
The value I keep getting returned is the text found in column 0.
Any help will be appreciated!!
Rolando
|
|
|
|
|
I'm having two small but tricky problems.
If I don't put an icon next to an item then I get a strange redrawing problem where scrolling right shows that right side of the control is not being drawn.
The other thing is I've been trying to use CMemDC or some variant thereof to get flicker free drawing. However after numerous tries I don't seem to be getting anywhere. The problem is that I'm not sure whether to call SetViewportOrg() on the buffered DC or on the original DC. Calling it on the original DC seems to have problems and calling it on the buffered DC seems to either cause problems or not do anything. This is different from the usual CMemDC examples because we want to apply horizontal scrolling effect ourselves manually using m_nOffset, and I just can't seem to do it.
Any help would be VERY much appreciated. Thank you!
Kevin
|
|
|
|
|
This flickering problem has nothing to do with the bitmap buffering. It was caused by additional repainting
and erasing of the background of parent classes. So the simplest
solution is to handle WM_PAINT message for CTLFrame class like this
void CTLFrame::OnPaint()
{
CPaintDC dc(this);
// do nothing here
}
And then handle WM_ERASEBKGND message for CTLViewView class like this
BOOL CTLViewView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
And it will remove all annoying background flickering.
If you want to go even further you can use memory double buffering
to avoid even text flickering while resizing, however it is not so
annoying, even standard notepad is doing that.
Igor Novikov
|
|
|
|
|