Dec 082017
Hierarchical List Box for the Microsoft Foundation Classes (MFC) 2.0. | |||
---|---|---|---|
File Name | File Size | Zip Size | Zip Type |
CLOSELEV.CPP | 1084 | 467 | deflated |
CLOSELEV.H | 677 | 362 | deflated |
CTL3D.DLL | 20272 | 9507 | deflated |
CTL3D.H | 1386 | 528 | deflated |
CTL3D.LIB | 2560 | 531 | deflated |
DRAGDROP.CPP | 634 | 323 | deflated |
DRAGDROP.H | 719 | 367 | deflated |
HIERLB.CPP | 13607 | 4021 | deflated |
HIERLB.H | 2810 | 1129 | deflated |
HIERLDOC.CPP | 1759 | 606 | deflated |
HIERLDOC.H | 949 | 452 | deflated |
HIERLIST.APS | 19335 | 6045 | deflated |
HIERLIST.CLW | 3327 | 988 | deflated |
HIERLIST.CPP | 4537 | 1684 | deflated |
HIERLIST.DEF | 356 | 242 | deflated |
HIERLIST.H | 857 | 433 | deflated |
HIERLIST.MAK | 6134 | 1459 | deflated |
HIERLIST.RC | 10878 | 2546 | deflated |
HIERLIST.VCW | 312 | 182 | deflated |
HIERLIST.WSP | 356 | 144 | deflated |
HIERLVW.CPP | 4601 | 1594 | deflated |
HIERLVW.H | 1549 | 660 | deflated |
LSTBOXEX.CPP | 14398 | 4354 | deflated |
LSTBOXEX.H | 4575 | 1432 | deflated |
MAINFRM.CPP | 2640 | 947 | deflated |
MAINFRM.H | 932 | 458 | deflated |
README.TXT | 6434 | 2621 | deflated |
RES | 0 | 0 | stored |
RESOURCE.H | 1578 | 455 | deflated |
COPYSING.CUR | 326 | 194 | deflated |
CUR914.CUR | 326 | 131 | deflated |
DRAG_MUL.CUR | 326 | 154 | deflated |
HIERICON.BMP | 1126 | 293 | deflated |
HIERLDOC.ICO | 768 | 183 | deflated |
HIERLIST.ICO | 768 | 205 | deflated |
HIERLIST.RC2 | 1553 | 658 | deflated |
MOVE.CUR | 326 | 177 | deflated |
MOVEMULT.CUR | 326 | 137 | deflated |
MOVESING.CUR | 326 | 115 | deflated |
NODROP.CUR | 326 | 93 | deflated |
TOOLBAR.BMP | 1200 | 355 | deflated |
SPLASH.CPP | 1188 | 496 | deflated |
SPLASH.H | 778 | 420 | deflated |
STDAFX.CPP | 204 | 128 | deflated |
STDAFX.H | 283 | 176 | deflated |
TESTHIER.CPP | 4125 | 1646 | deflated |
TESTHIER.H | 1311 | 551 | deflated |
TESTLIST.CPP | 2959 | 1248 | deflated |
TESTLIST.H | 1308 | 576 | deflated |
Download File HIERLIST.ZIP Here
Contents of the README.TXT file
This is my second attempt at the following enhancements to list boxes in MFC2.0
The interface has changed since my first attempt - but not that much.
As before we have:-
1) Owner draw list box items using transparent bitmaps
2) Drag and drop - not necessarily between listboxes.
3) Hierarchical listboxes with lines.
There are three main classes
1) CListBoxExResources
This class encapsulates the resources required for a CListBoxEx and prepares
a transparent bitmap into a memory device context for use in drawing the
list box items. (A bug has been fixed in this class. I was storing a temporary
pointer and the passing it to SelectObject on destruction of the object. )
See lstboxex.h for the definition.
The constructor takes resource ids for one bitmap and five cursors, a WORD value
which can be used to indicate the width of individual bitmaps within the larger
bitmap and two COLORREF items which describe the background colours of the bitmap.
The bitmap must be a two high bitmap as shown below:-
Single large bitmap made up of two identical rows of bitmaps which you are going to use
in your listboxes.
+---+---+---+---+---+
| | | | | | Background of this row is blue = RGB(0,0,255)
| | | | | |
+---+---+---+---+---+
| | | | | | Background of this row is magenta = RGB(255,0,255)
| | | | | |
+---+---+---+---+---+
CListBoxExResources copies this bitmap into a memory DC and transforms it
so that the bottom row has
the background colour COLOR_WINDOW and the top row colour COLOR_HIGHLIGHT.
A CListBoxExResources object should be declared in say your CMainFrame object
and passed to any CListBoxEx objects you declare.
The OnSysColorChange handler should be added to CMainFrame and
m_Resources.SysColorChanged() called from there.
This regenerates the bitmap with the correct background colours.
2) CListBoxEx
Create a CListBoxEx with LBS_OWNERDRAWVARIABLE.
This is an abstract base class - you must derive from it and override the virtual function
void CListBoxEx::DrawItemEx( const CListBoxExDrawStruct& )
where the class CListBoxExDrawStruct is as follows.
class CListBoxExDrawStruct
{
public:
const CListBoxExResources* m_pResources;
CDC* m_pDC;
CRect m_Rect;
BOOL m_Sel;
DWORD m_ItemData;
};
Use this to draw your list box item or override DrawItem(DRAWITEMSTRUCT) and do it all
yourself.
The function CListBox::DrawItem( DRAWITEMSTRUCT ) has been overridden and calls
DrawItemEx after preparing various things.
These functions can be overridden to provide drag and drop functionality
virtual void DroppedItemsOnWindowAt( CWnd*, const CPoint&, BOOL bCopy=FALSE ){}
virtual BOOL CanDrop( CWnd*, const CPoint&, BOOL bCopy=FALSE ) { return FALSE; }
This function has been added since version 1.
I have added it in case a derived class wishes to customize the
cursors used during drag/drop operations for each individual listbox.
If the function returns NULL (as the default case does) then the cursors
from the attached CListBoxExResource object are used.
virtual HCURSOR GetCursor( eLbExCursor ) const { return HCURSOR(NULL); }
If you call CListBoxEx::EnableDragDrop(TRUE) then you can drag items from the CListBoxEx
object. As the mouse moves the function CanDrop is called with a pointer to the
targer CWnd, the mouse point in client co-ords and the drag operation copy or move.
When the mouse is release over a drag client then the function DroppedItemsOnWindowAt is
called with the same pararameters. It is up to the user to provide these functions. See
CTestListEx for an example.
Items are added to a CListBoxEx using AddString( (LPCSTR)item ) etc.
3) CHierListBox
This is derived from CListBoxEx and inherits all of it's functionality. It adds
the ability to display items hierarchically like file mananger.
This interface to this class has changed substantially.
This is an abstract base class - derive and override these functions
void CListBoxEx::DrawItemEx( CListBoxExDrawStruct& ds );
The ds.m_Rect has been adjusted for indentation so just BitBlt a bitmap and
draw some text.
This is now const ---------------------+
BOOL CHierListBox::OpenNode( const CHierListNode*, int& nodeIndex )
This is called when the used double clicks on a closed node.
The derived class should open the node if possible by inserting
new items using InsertNode( DWORD item, const CHierListNode* parentNode, int index )
and on return indicate TRUE/FALSE for ability to open node.
If items have been inserted then the return value of InsertNode for the last child item should be
returned in nodeIndex.
These are used to request the opening or closing of particular nodes.
BOOL CloseToLevel(unsigned int=0);
BOOL CloseAll();
BOOL CloseNode(int);
BOOL DeleteNode(int);
BOOL OpenNode(int);
OpenNode(int) will in turn call OpenNode( const HeirListNode*, int& ) but will ensure
that the lines are drawn correctly.
This can be used to insert indivual items. This still needs some work.
int InsertNode(DWORD, const CHierListNode*, int index=-1);
Use these to enable disable the lines
void EnableLines(BOOL);
BOOL LinesEnabled() const { return m_bLines; }
It is possible that CHierListBox could support sorting of items but this is more
difficult than usual so it's up to you if you want this feature.
If you override CHierListBox::DeleteItem for CHierListBox then make sure you delete
your data first and then call the parent class version.
Test app
--------
The test application demonstrates all of the capabilities of the list boxes.
Try dragging from the right list box to the left. You might get assert failures
but these can be ignored for demonstration purposes.
The about box demonstrates subclassing the listboxes. Items can be dragged
from the about box to another instance of the app.
Outstanding problems
--------------------
If items are dragged from the right hand listbox in the about box to the
right hand listbox of another instance of the app then an AfxMessageBox appears.
I call ReleaseCapture before sending the WM_DROP message but the mouse cursor is
lost - hitting Escape sorts things out. Any help with this would be appreciated.
CHierListBox::InsertNode needs more work .
Comments to:-
Philip Lee 100065,3244
The interface has changed since my first attempt - but not that much.
As before we have:-
1) Owner draw list box items using transparent bitmaps
2) Drag and drop - not necessarily between listboxes.
3) Hierarchical listboxes with lines.
There are three main classes
1) CListBoxExResources
This class encapsulates the resources required for a CListBoxEx and prepares
a transparent bitmap into a memory device context for use in drawing the
list box items. (A bug has been fixed in this class. I was storing a temporary
pointer and the passing it to SelectObject on destruction of the object. )
See lstboxex.h for the definition.
The constructor takes resource ids for one bitmap and five cursors, a WORD value
which can be used to indicate the width of individual bitmaps within the larger
bitmap and two COLORREF items which describe the background colours of the bitmap.
The bitmap must be a two high bitmap as shown below:-
Single large bitmap made up of two identical rows of bitmaps which you are going to use
in your listboxes.
+---+---+---+---+---+
| | | | | | Background of this row is blue = RGB(0,0,255)
| | | | | |
+---+---+---+---+---+
| | | | | | Background of this row is magenta = RGB(255,0,255)
| | | | | |
+---+---+---+---+---+
CListBoxExResources copies this bitmap into a memory DC and transforms it
so that the bottom row has
the background colour COLOR_WINDOW and the top row colour COLOR_HIGHLIGHT.
A CListBoxExResources object should be declared in say your CMainFrame object
and passed to any CListBoxEx objects you declare.
The OnSysColorChange handler should be added to CMainFrame and
m_Resources.SysColorChanged() called from there.
This regenerates the bitmap with the correct background colours.
2) CListBoxEx
Create a CListBoxEx with LBS_OWNERDRAWVARIABLE.
This is an abstract base class - you must derive from it and override the virtual function
void CListBoxEx::DrawItemEx( const CListBoxExDrawStruct& )
where the class CListBoxExDrawStruct is as follows.
class CListBoxExDrawStruct
{
public:
const CListBoxExResources* m_pResources;
CDC* m_pDC;
CRect m_Rect;
BOOL m_Sel;
DWORD m_ItemData;
};
Use this to draw your list box item or override DrawItem(DRAWITEMSTRUCT) and do it all
yourself.
The function CListBox::DrawItem( DRAWITEMSTRUCT ) has been overridden and calls
DrawItemEx after preparing various things.
These functions can be overridden to provide drag and drop functionality
virtual void DroppedItemsOnWindowAt( CWnd*, const CPoint&, BOOL bCopy=FALSE ){}
virtual BOOL CanDrop( CWnd*, const CPoint&, BOOL bCopy=FALSE ) { return FALSE; }
This function has been added since version 1.
I have added it in case a derived class wishes to customize the
cursors used during drag/drop operations for each individual listbox.
If the function returns NULL (as the default case does) then the cursors
from the attached CListBoxExResource object are used.
virtual HCURSOR GetCursor( eLbExCursor ) const { return HCURSOR(NULL); }
If you call CListBoxEx::EnableDragDrop(TRUE) then you can drag items from the CListBoxEx
object. As the mouse moves the function CanDrop is called with a pointer to the
targer CWnd, the mouse point in client co-ords and the drag operation copy or move.
When the mouse is release over a drag client then the function DroppedItemsOnWindowAt is
called with the same pararameters. It is up to the user to provide these functions. See
CTestListEx for an example.
Items are added to a CListBoxEx using AddString( (LPCSTR)item ) etc.
3) CHierListBox
This is derived from CListBoxEx and inherits all of it's functionality. It adds
the ability to display items hierarchically like file mananger.
This interface to this class has changed substantially.
This is an abstract base class - derive and override these functions
void CListBoxEx::DrawItemEx( CListBoxExDrawStruct& ds );
The ds.m_Rect has been adjusted for indentation so just BitBlt a bitmap and
draw some text.
This is now const ---------------------+
BOOL CHierListBox::OpenNode( const CHierListNode*, int& nodeIndex )
This is called when the used double clicks on a closed node.
The derived class should open the node if possible by inserting
new items using InsertNode( DWORD item, const CHierListNode* parentNode, int index )
and on return indicate TRUE/FALSE for ability to open node.
If items have been inserted then the return value of InsertNode for the last child item should be
returned in nodeIndex.
These are used to request the opening or closing of particular nodes.
BOOL CloseToLevel(unsigned int=0);
BOOL CloseAll();
BOOL CloseNode(int);
BOOL DeleteNode(int);
BOOL OpenNode(int);
OpenNode(int) will in turn call OpenNode( const HeirListNode*, int& ) but will ensure
that the lines are drawn correctly.
This can be used to insert indivual items. This still needs some work.
int InsertNode(DWORD, const CHierListNode*, int index=-1);
Use these to enable disable the lines
void EnableLines(BOOL);
BOOL LinesEnabled() const { return m_bLines; }
It is possible that CHierListBox could support sorting of items but this is more
difficult than usual so it's up to you if you want this feature.
If you override CHierListBox::DeleteItem for CHierListBox then make sure you delete
your data first and then call the parent class version.
Test app
--------
The test application demonstrates all of the capabilities of the list boxes.
Try dragging from the right list box to the left. You might get assert failures
but these can be ignored for demonstration purposes.
The about box demonstrates subclassing the listboxes. Items can be dragged
from the about box to another instance of the app.
Outstanding problems
--------------------
If items are dragged from the right hand listbox in the about box to the
right hand listbox of another instance of the app then an AfxMessageBox appears.
I call ReleaseCapture before sending the WM_DROP message but the mouse cursor is
lost - hitting Escape sorts things out. Any help with this would be appreciated.
CHierListBox::InsertNode needs more work .
Comments to:-
Philip Lee 100065,3244
December 8, 2017
Add comments