home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (c) 1993 by Barking Spider Software Inc. All rights reserved
-
- Filename...: treedem3.c
-
- Version,,,,: 1.0
-
- Language...: Microsoft C/C++ 7.0
-
- Model......: Small
-
- Environment: Microsoft Windows 3.1
-
- Description: Sample MDI code that demonstrates the functionality of the
- tree control. The window procedures TreeCtrlFrameWndProc
- and ListCtrlFrameWndProc are the center of attention. They
- are the window procedures of the MDI child windows. When
- these procedures receive their WM_CREATE message, the
- handlers each create a BSS Tree Control.
-
- After the tree controls are created, they are populated with
- a root and the first level tree nodes. The
- TreeCtrlFrameWndProc populates it's tree control with the
- database stored in the user-defined resource TREEDB RCDATA
- which is located in the file TREEDB.DAT. This database
- describes the tree control exported API. The
- ListCtrlFrameWndProc populates it's tree control with the
- database stored in the user-defined resource LISTDB RCDATA
- which is located in the file TREEDB.DAT. This database
- describes the list control exported API.
-
- When a user double clicks on any of these tree nodes, the MDI
- child window will receive a notification. This
- notification describes the node that was selected by the
- double click. The MDI child window will respond by taking
- the key index of the tree node that was selected, use it to
- access the database, and retrieve the list of children for
- that node. The BSS Tree Control is sent this list via the
- exported API, BST_AddChildrenToParent, and SLAM! The list
- of children for the selected node is displayed in the tree.
-
- The MDI child window procedure also demonstrates the passing
- of the WM_SYSCOLORCHANGE notification to the BSS Tree Control
- for system color changes.
-
- REMEMBER:
-
- The static databases that are used in this example are just
- one type of storage system. The database could be a file
- system, a finite state machine, a relational database
- browser, a network map, etc.
-
- Notes......:
-
- History....:
-
- Author.....: Peter J. Kaufman
- */
-
- #include <windows.h>
- #include <stdlib.h>
- #include "treedem3.h"
- #include "..\bscore.h" // Contains tree control structures, notification
- // messages, error codes, etc.
- #include "..\bstree.h" // Contains exported tree control API prototypes.
-
- #include <string.h>
- #include <malloc.h>
-
- // Database that describes the tree control exported API.
- #define TREE_SIZE 908
- TREE_DATABASE TreeDatabase [TREE_SIZE];
-
- // Database that describes the list control exported API.
- #define LIST_SIZE 719
- TREE_DATABASE ListDatabase [LIST_SIZE];
-
- char szFrameClass [] = "Frame" ;
- char szTreeCtrlFrameClass [] = "TreeCtrlFrame";
- char szListCtrlFrameClass [] = "ListCtrlFrame";
-
- HANDLE hInst ;
- HMENU hMenuInit, hMenuTreeCtrl , hMenuListCtrl;
- HMENU hMenuInitWindow, hMenuTreeCtrlWindow, hMenuListCtrlWindow;
-
- // Bitmaps used in the tree control.
- HBITMAP hbmClosedActive;
- HBITMAP hbmClosed;
- HBITMAP hbmOpenActive;
- HBITMAP hbmOpen;
- HBITMAP hbmSheetActive;
- HBITMAP hbmSheet;
- HBITMAP hbm[MAX_BITMAP_ID];
-
- /*****************************************************************************
- int PASCAL WinMain ( HANDLE hInstance,
- HANDLE hPrevInstance,
- LPSTR lpszCmdLine,
- int nCmdShow);
-
- The following code registers the MDI Frame window and the MDI child window
- classes. It then sets up the menus, creates the Frame window and then
- processes the messages in the main message loop.
- *****************************************************************************/
-
- int PASCAL WinMain ( HANDLE hInstance,
- HANDLE hPrevInstance,
- LPSTR lpszCmdLine,
- int nCmdShow)
- {
- HWND hwndFrame, hwndClient ;
- MSG msg ;
- WNDCLASS wndclass ;
-
- hInst = hInstance ;
-
- if (!hPrevInstance)
- {
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = FrameWndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (hInst,
- MAKEINTRESOURCE(IDR_TREEDEMO_ICON)) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = COLOR_APPWORKSPACE + 1 ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szFrameClass ;
-
- RegisterClass (&wndclass) ;
-
- // Register the MDI child that will create the tree control describing
- // the tree control exported APIs.
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = TreeCtrlFrameWndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = TREECTRL_WND_EXTRA;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szTreeCtrlFrameClass ;
-
- RegisterClass (&wndclass) ;
-
- // Register the MDI child that will create the tree control describing
- // the list control exported APIs.
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = ListCtrlFrameWndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = LISTCTRL_WND_EXTRA;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szListCtrlFrameClass ;
-
- RegisterClass (&wndclass) ;
- }
-
- // Convert the RCDATA of both the tree control exported API and
- // the list control exported API.
- if(ReadInDatabases () == 0)
- {
- hMenuInit = LoadMenu(hInst, "InitialMenu") ;
- hMenuTreeCtrl = LoadMenu (hInst, "TreeCtrlMenu") ;
- hMenuListCtrl = LoadMenu (hInst, "ListCtrlMenu") ;
-
- hMenuInitWindow = GetSubMenu (hMenuInit, INIT_MENU_POS) ;
- hMenuTreeCtrlWindow = GetSubMenu (hMenuTreeCtrl, TREECTRL_MENU_POS) ;
- hMenuListCtrlWindow = GetSubMenu (hMenuListCtrl, LISTCTRL_MENU_POS) ;
-
- hwndFrame = CreateWindow ( szFrameClass,
- "Barking Spider Software, Inc. Tree Demo 3 - MDI",
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- hMenuInit,
- hInstance,
- NULL) ;
-
- hwndClient = GetWindow (hwndFrame, GW_CHILD) ;
-
- ShowWindow (hwndFrame, nCmdShow) ;
- UpdateWindow (hwndFrame) ;
-
- SendMessage (hwndFrame, WM_COMMAND, IDM_NEW_TREECTRL, 0L);
- SendMessage (hwndFrame, WM_COMMAND, IDM_NEW_LISTCTRL, 0L);
- SendMessage (hwndFrame, WM_COMMAND, IDM_CASCADE, 0L);
-
- while (GetMessage (&msg, NULL, 0, 0))
- {
- if (! TranslateMDISysAccel (hwndClient, &msg))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- }
- DestroyMenu (hMenuTreeCtrl) ;
- DestroyMenu (hMenuListCtrl);
- }
- return msg.wParam ;
- }
-
-
- /*****************************************************************************
- long FAR PASCAL _export FrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam);
-
- This is the window procedure for the MDI Frame window created above.
- It mainly processes the menu messages. The two most important menu messages
- are the WM_COMMAND message with wParam set to IDM_NEW_TREECTRL and the
- the WM_COMMAND message with wParam set to IDM_NEW_LISTCTRL.
- When FrameWndProc receives these messages, it means that the user has
- selected the "New Tree" or the "New List" menu item under File. The code
- that handles these messages creates the appropriate MDI child window which
- in turn creates a single tree control.
-
- Another important message is the WM_SYSCOLORCHANGE message which is sent to
- all top level windows when a system color changes. For example, if a user
- opens the Color Dialog and changes the background window color,
- Windows will send the WM_SYSCOLORCHANGE notification to this window procedure
- but not to any of the MDI children. So... since the tree controls are
- children of the MDI child window, the tree controls will not receive the
- WM_SYSCOLORCHANGE notification. The tree control handles the
- WM_SYSCOLORCHANGE notification if it is sent. When FrameWndProc,
- the window procedure below, receives a WM_SYSCOLORCHANGE notification,
- it enumerates all of the MDI children, getting each of the window handles,
- so to send the notification onto them. In turn the MDI children window
- procedures send the WM_SYSCOLORCHANGE notification to the tree controls.
- The tree controls then handles the color change and repaints the trees.
-
- Notice that all of the bitmaps are loaded here. These are global to all
- MDI child windows.
-
- *****************************************************************************/
-
- long FAR PASCAL _export FrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam)
- {
- static HWND hwndClient ;
- CLIENTCREATESTRUCT clientcreate ;
- FARPROC lpfnEnum ;
- HWND hwndChild ;
- MDICREATESTRUCT mdicreate ;
- WORD i;
-
- switch (message)
- {
- case WM_CREATE:
- hbm[0] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_API));
- hbm[1] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_ARG));
- hbm[2] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_TXT));
- hbm[3] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_RET));
- hbm[4] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_DSC));
- hbm[5] = LoadBitmap (hInst, MAKEINTRESOURCE(IDR_COM));
-
- // CreateBackgroundMatchedBitmap creates the folders used in
- // the BSS Tree Control. CreateBackgroundMatchedBitmap does what
- // it says. It loads the initial folder bitmap from the resource,
- // and converts the bitmap's background color to match the system
- // window color. This is done for the closed, open. and sheet
- // folder bitmaps. The bitmaps above are rectangular and need no
- // background masking.
-
- // Notice that this procedure is also done for the COLOR_HIGHLIGHT
- // color. COLOR_HIGHLIGHT is the color used to show the current
- // selection (active node).
-
- hbmClosed = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_WINDOW),
- IDR_CLOSED_FOLDER);
-
- hbmClosedActive = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_HIGHLIGHT),
- IDR_CLOSED_FOLDER);
-
- hbmOpen = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_WINDOW),
- IDR_OPEN_FOLDER);
-
- hbmOpenActive = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_HIGHLIGHT),
- IDR_OPEN_FOLDER);
-
- hbmSheet = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_WINDOW),
- IDR_SHEET);
-
- hbmSheetActive = CreateBackgroundMatchedBitmap (
- GetSysColor (COLOR_HIGHLIGHT),
- IDR_SHEET);
-
- clientcreate.hWindowMenu = hMenuInitWindow ;
- clientcreate.idFirstChild = IDM_FIRSTCHILD ;
-
- hwndClient = CreateWindow ("MDICLIENT",
- NULL,
- WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
- 0,
- 0,
- 0,
- 0,
- hwnd,
- 1,
- hInst,
- (LPSTR) &clientcreate) ;
-
- ShowWindow (hwndClient,SW_SHOW);
- return 0 ;
-
- case WM_COMMAND:
- switch (wParam)
- {
- // Creates the MDI child that will in turn create the tree control
- // which will display the database in TREEDB.DAT. TREEDB.DAT
- // describes the tree control exported APIs.
- case IDM_NEW_TREECTRL:
-
- mdicreate.szClass = szTreeCtrlFrameClass ;
- mdicreate.szTitle = "BSS Tree Control" ;
- mdicreate.hOwner = hInst ;
- mdicreate.x = CW_USEDEFAULT ;
- mdicreate.y = CW_USEDEFAULT ;
- mdicreate.cx = CW_USEDEFAULT ;
- mdicreate.cy = CW_USEDEFAULT ;
- mdicreate.style = 0 ;
- mdicreate.lParam = NULL ;
-
- hwndChild = (HWND) SendMessage ( hwndClient,
- WM_MDICREATE,
- 0,
- (long) (LPMDICREATESTRUCT) &mdicreate) ;
- return 0 ;
-
-
- // Creates the MDI child that will in turn create the tree control
- // which will display the database in LISTDB.DAT. LISTDB.DAT
- // describes the list control exported APIs.
-
- case IDM_NEW_LISTCTRL:
-
- mdicreate.szClass = szListCtrlFrameClass ;
- mdicreate.szTitle = "BSS List Control" ;
- mdicreate.hOwner = hInst ;
- mdicreate.x = CW_USEDEFAULT ;
- mdicreate.y = CW_USEDEFAULT ;
- mdicreate.cx = CW_USEDEFAULT ;
- mdicreate.cy = CW_USEDEFAULT ;
- mdicreate.style = 0 ;
- mdicreate.lParam = NULL ;
-
- hwndChild = (HWND) SendMessage ( hwndClient,
- WM_MDICREATE,
- 0,
- (long) (LPMDICREATESTRUCT) &mdicreate) ;
- return 0 ;
-
- case IDM_CLOSE:
-
- hwndChild = LOWORD (SendMessage (hwndClient,
- WM_MDIGETACTIVE,
- 0,
- 0L)) ;
-
- if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0L))
- SendMessage ( hwndClient, WM_MDIDESTROY, hwndChild, 0L) ;
- return 0 ;
-
- case IDM_EXIT:
- SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
- return 0 ;
-
- case IDM_TILE:
- SendMessage (hwndClient, WM_MDITILE, 0, 0L) ;
- return 0 ;
-
- case IDM_CASCADE:
- SendMessage (hwndClient, WM_MDICASCADE, 0, 0L) ;
- return 0 ;
-
- case IDM_ARRANGE:
- SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0L) ;
- return 0 ;
-
- case IDM_CLOSEALL:
- lpfnEnum = MakeProcInstance ((FARPROC) CloseEnumProc,
- hInst) ;
- EnumChildWindows (hwndClient, lpfnEnum, 0L) ;
- FreeProcInstance (lpfnEnum) ;
- return 0 ;
-
- default:
- hwndChild = LOWORD (SendMessage (hwndClient,
- WM_MDIGETACTIVE, 0, 0L)) ;
-
- if (IsWindow (hwndChild))
- SendMessage (hwndChild, WM_COMMAND, wParam, lParam) ;
- break;
- }
- break ;
-
- case WM_QUERYENDSESSION:
- case WM_CLOSE:
- SendMessage (hwnd, WM_COMMAND, IDM_CLOSEALL, 0L) ;
-
- if (NULL != GetWindow (hwndClient, GW_CHILD))
- return 0 ;
- break ;
-
- /*
- Passed on all MDI children so that they may pass it onto their
- BSS Tree Control child.
- */
- case WM_SYSCOLORCHANGE:
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_WINDOW),
- hbmClosed,
- IDR_CLOSED_FOLDER);
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_WINDOW),
- hbmOpen,
- IDR_OPEN_FOLDER);
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_HIGHLIGHT),
- hbmClosedActive,
- IDR_CLOSED_FOLDER);
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_HIGHLIGHT),
- hbmOpenActive,
- IDR_OPEN_FOLDER);
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_WINDOW),
- hbmSheet,
- IDR_SHEET);
- ChangeBitmapToMatchBackground ( GetSysColor (COLOR_HIGHLIGHT),
- hbmSheetActive,
- IDR_SHEET);
- lpfnEnum = MakeProcInstance ((FARPROC) SysColorChangeEnumProc, hInst) ;
- EnumChildWindows (hwndClient, lpfnEnum, 0L) ;
- FreeProcInstance (lpfnEnum) ;
- return 0 ;
-
- case WM_DESTROY :
- // Destroy the bitmaps used in the tree.
- DeleteObject(hbmClosed);
- DeleteObject(hbmClosedActive);
- DeleteObject(hbmOpen);
- DeleteObject(hbmOpenActive);
- DeleteObject(hbmSheet);
- DeleteObject(hbmSheetActive);
-
- for (i = 0; i < MAX_BITMAP_ID; i++)
- DeleteObject(hbm[i]);
-
- for( i = 0; i < TREE_SIZE; i++)
- _ffree(TreeDatabase[i].lpszNodeText);
-
- for( i = 0; i < LIST_SIZE; i++)
- _ffree(ListDatabase[i].lpszNodeText);
-
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;
- }
-
-
-
- /*****************************************************************************
- BOOL FAR PASCAL _export SysColorChangeEnumProc ( HWND hwnd,
- LONG lParam)
-
- All this callback does, is send a WM_SYSCOLORCHANGE notification to the
- window identified by hwnd. This routine gets called as a result of the
- Frame window enumerating all of its children when it receives a
- WM_SYSCOLORCHANGE notification. Windows sends this notification when any
- of the system colors change. Since only top level windows receive
- this notification, the Frame window must pass it to it's children so that
- it's children can pass it onto their controls namely the BSS Tree Control.
- The BSS Tree Control handles this notification nicely.
- *****************************************************************************/
-
- BOOL FAR PASCAL _export SysColorChangeEnumProc ( HWND hwnd,
- LONG lParam)
- {
- SendMessage (hwnd, WM_SYSCOLORCHANGE, 0, 0L);
- return TRUE;
- }
-
- /*****************************************************************************
- BOOL FAR PASCAL _export CloseEnumProc (HWND hwnd, LONG lParam)
-
- Callback in which Windows calls for each child MDI window when the Frame
- window to be destroyed.
- ******************************************************************************/
-
- BOOL FAR PASCAL _export CloseEnumProc (HWND hwnd, LONG lParam)
- {
- if (GetWindow (hwnd, GW_OWNER))
- return TRUE;
-
- SendMessage (GetParent (hwnd), WM_MDIRESTORE, hwnd, 0L) ;
-
- if (!SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0L))
- return TRUE;
-
- SendMessage (GetParent (hwnd), WM_MDIDESTROY, hwnd, 0L) ;
- return TRUE;
- }
-
-
-
-
- /*****************************************************************************
- long FAR PASCAL _export TreeCtrlFrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam)
-
-
- This is the window procedure of the MDI child window. When this procedure
- receives it's WM_CREATE message, a BSS Tree Control is created as a child
- window (control).
-
- After this tree is created, it is populated with the root node and the first
- level nodes taken from the database described in the file TREEDB.DAT which
- is in RCDATA format.
-
- When a user double clicks on any of these nodes, the MDI child window (which
- is the parent of the BSS Tree Control) will receive a notification.
- This notification describes the node that was selected by the
- double click. The MDI child window will respond by taking the key index of
- the node that was clicked on, use it to access the database, and retrieve the
- list of children for that node. The BSS Tree Control is sent this list via
- the exported API, BST_AddChildrenToParent, and SLAM! The list of children
- for the selected node is displayed.
-
- This MDI child window procedure also demonstrates the passing of the
- WM_SYSCOLORCHANGE notification to the BSS Tree Control for system color
- changes.
-
- REMEMBER:
-
- The database that is used in this example is just one storage system.
- The database could be a file system, a finite state machine, a relational
- database browser, a network map, etc.
- ******************************************************************************/
-
-
- #define SPACE_BEFORE_TEXT 4
-
- long FAR PASCAL _export TreeCtrlFrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam)
- {
- static HWND hwndClient;
- static HWND hwndFrame ;
- // The following are important pointers in the process of building the
- // tree. The structure definition that these pointers point to are defined
- // in bstree.h
- LP_TREE_NODE lpParentTreeNode; // Points to a tree node
- LP_TREE_NODE_DEF lpTreeNodeDef; // Points to an array of 1 or more
- // tree node definitions that are
- // defined by the application.
- LP_TREE_NODE_DEF lpTreeNodeDef2; // Runner used to traverse the list
- // tree node definitions pointed to
- // by the pointer above.
- LP_SELECT_NOTIF lpSelectNotif; // Pointer to the tree control owned
- // notification structure used to
- // pass information about a tree node
- // to the application.
- WORD i;
- WORD j;
- HWND hwndTree;
- WORD wNumberOfChildren;
- WORD wIndexOfChildren;
- LOCALHANDLE hTreeData ;
- NP_TREE_DATA npTreeData ;
- short cx, cy;
- WORD wErrCode;
- LONG lResult;
-
- switch (message)
- {
- case WM_CREATE:
- hwndClient = GetParent (hwnd) ;
-
- hwndFrame = GetParent (hwndClient) ;
-
- lResult = 0xFFFFFFFF;
-
- // Allocate the instance data for this MDI child window. This data
- // structure will hold the window handle of the tree control and the
- // handles of the bitmaps to be displayed in the tree nodes. The
- // BSS Tree Control window handle is used in almost all the APIs
- // to the tree control.
-
- hTreeData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
- sizeof (TREE_DATA)) ;
- if(hTreeData != NULL)
- {
- // Save the above memory handle in the extra window memory reserved
- // during the registration of the "TreeCtrlFrame" class (MDI child
- // window).
-
- SetWindowWord (hwnd, WND_EXTRA_TREE_DATA, hTreeData) ;
-
- // Lock down the memory to get the pointer to the instance data
- // structure. We will be assigning the newly created BSS Tree
- // Control window handle to the hwndTree member of TREE_DATA.
- // The bitmap handles will also be assigned to members in TREE_DATA
- // to be referenced later.
-
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData) ;
-
- // Not necessary since the structure allocated above was zero
- // initialized but the below statement will remain only as a
- // reminder that messages may come into this window procedure
- // during the call to create a tree. And if the tree control
- // handle is referenced before the return from the call
- // BST_CreateTree, the tree control handle will be invalid.
- // This is the case with WM_SYSCOLORCHANGE. For unregistered
- // copies of the BSS Tree Control, a modal dialog box is
- // created during the WM_CREATE message of the Tree Control.
- // While this message is up, a user can open the Color Dialog and
- // change a color causing a WM_SYSCOLORCHANGE to be sent to all
- // the top level windows. Since execution has not returned from
- // the call to BST_CreateTree but yet the message
- // WM_SYSCOLORCHANGE is sent to this procedure by its parent, the
- // reference to npTreeData->hwndTree will be invalid and a GP
- // will occur. Trust me. This happened.
-
- npTreeData->hwndTree = NULL;
-
- // BST_CreateTree creates a BSS Tree Control. The parameters are
- // similar to the Windows API CreateWindowEx. Why have the call
- // anyway? The API guarantees that the Window style will include
- // the scroll bars, clipping, and helps the programmer use the
- // right class. Notice I added a border to the style. Looks
- // great! Notice that the starting x, y, width, and height are
- // 0? This works because the WM_SIZE message handler of this
- // window procedure does a MoveWindow to the BSS Tree Control to
- // keep the tree control sized to the MDI child window.
-
- hwndTree = BST_CreateTree (hInst,hwnd,0, 0, 0,0,WS_BORDER, 0);
-
- if(hwndTree != NULL)
- {
- // Now the assignment of instance data.
-
- npTreeData->hwndTree = hwndTree;
-
-
- // This is a commented out example to setting the font in the
- // BSS Tree Control using the BST_SetFont API. The font could
- // be a result of the font common dialog.
-
- // BST_SetFont( hwndTree,GetStockObject(ANSI_VAR_FONT));
-
- // Bitmaps spaces are locations bitmaps are placed in a tree
- // node. The bitmap spaces are placed left of the text.
- // Below, two bitmap spaces are defined. The max width
- // and height are defined. The first argument is the BSS
- // Tree Control handle, the second is the bitmap space
- // identifier (which bitmap space is being defined). The
- // third and fourth arguments are the width and height
- // respectively. The last argument signals the BSS Tree
- // Control whether to center or left justify the currently
- // assigned bitmap in this bitmap space. TRUE means center,
- // FALSE means left justify.
-
- // This defines the bitmap spaces globally for every tree node.
- // This keeps column alignment of bitmaps on the same level.
-
- BST_SetBitmapSpace( hwndTree, 0, 22, 17, TRUE);
-
- BST_SetBitmapSpace( hwndTree, 1, 42, 20, TRUE);
-
- // Tells the BSS Tree Control to place so many pixels after the
- // last bitmap (if any) and before the first character of the
- // text string.
-
- BST_SetXSpaceBeforeText( hwndTree, SPACE_BEFORE_TEXT);
-
- // By default this is TRUE, but for purpose of demonstration...
-
- // BST_ShowLines( hwndTree, TRUE);
-
- // Now, the fun part... Defining tree nodes.
-
- // First... define the root!
-
- // Allocate a tree node definition for the root. It
- // is best if this memory is initialize to zero. The tree node
- // definition structure is the vehicle that the application uses
- // to define tree nodes to the BSS Tree Control. This memory is
- // the property of the application. Its contents are copied to
- // the a newly created tree node in the tree control. Once the
- // node is defined, this memory can be freed.
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP( GlobalAlloc (GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)*1,0)),0);
-
- if(lpTreeNodeDef)
- {
- // Assign the text that will be displayed for the tree node.
-
- lpTreeNodeDef->lpszText= TreeDatabase[0].lpszNodeText;
-
- // Length of the above text.
-
- lpTreeNodeDef->wTextLength = lstrlen(lpTreeNodeDef->lpszText);
-
- // Since the string for this node is in a static database
- // and will never be deleted or modified by the application,
- // there is no need for the tree control to allocated
- // memory to store it. Setting the high bit
- // (0x8000) of the wTextLength member tells the tree control
- // to use the given pointer directly. The tree control will
- // not try to free this memory when the tree node is
- // deleted. The tree control simply copies the given
- // string pointer into the TREE_NODE and uses the pointer
- // to access the string.
-
- lpTreeNodeDef->wTextLength |= 0x8000;
-
- // Setup the lpUserData member. This member can be used
- // to store a pointer to application defined memory that
- // takes advantage of the tree control's structure. If
- // this is used for application defined memory, then it
- // is the responsibility of the application to maintain
- // it.
- // To aid in this adventure, the BSS Tree Control exported
- // API provides a way for the application to define a
- // callback that will be called everytime a node is deleted.
-
- // In the below case, the lpUserData is used as a DWORD
- // storage instead of a pointer for two values that
- // describe the children of the parent. The low word is
- // the offset into the database where the children definition
- // starts and the high word is the number of children of the
- // parent.
-
- wNumberOfChildren = TreeDatabase[0].wNumberOfChildren;
-
-
- lpTreeNodeDef->lpUserData = MAKEP(wNumberOfChildren,
- TreeDatabase[0].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the tree control
- lpTreeNodeDef->wUserDataSize = 0;
-
- // Assign bitmaps created earlier to the first bitmap space
- // which were also defined earlier. PS. The active bitmap
- // is the bitmap that is displayed when the tree node is
- // highlighted. Currently, there are two bitmap spaces
- // defined per node. If more is needed, then the source
- // can be purchased and the number of bitmap spaces can
- // be increased. In most case only two bitmaps are good
- // enough. If any of the bitmap spaces are not used, then
- // make sure that a NULL handle is assigned to the bitmap
- // space.
-
- lpTreeNodeDef->hBitmap[0] = hbmClosed;
-
- lpTreeNodeDef->hActiveBitmap[0] = hbmClosedActive;
-
- if(TreeDatabase[0].wBitmapIndex != 0)
- lpTreeNodeDef->hBitmap[1] =
- hbm[TreeDatabase[0].wBitmapIndex - 1];
- else
- lpTreeNodeDef->hBitmap[1] = NULL;
-
-
- lpTreeNodeDef->hActiveBitmap[1] = NULL;
- lpTreeNodeDef->hBitmap[2] = NULL;
-
-
- // Since the tree node definition structure is defined then
- // call the BST_AddChildrenToParent API. Notice the 0L value.
- // This is the indicator that this node is the root. The
- // tree can only have one root. If the root is NOT defined
- // then calling any other API will cause havoc.
-
- wErrCode =
- BST_AddChildrenToParent(hwndTree, 0L, 1,lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- // The lpTreeNode member is an important animal. When
- // BST_AddChildrenToParent is called with the tree
- // node definitions, the tree control internally allocates
- // the tree node memory in which it stores the tree node
- // definition information.
- // The tree control then assigns this new tree node
- // pointer to the tree node definition member 'lpTreeNode'.
- // Remember, the tree node definition structure is
- // shared memory between the application and the tree
- // control. The application could use the 'lpTreeNode'
- // value for future references to the new node such as
- // adding nodes as children.
-
- // Below, the 'lpTreeNode' member of the tree node
- // definition is saved. It will be used as a reference
- // to add children. This pointer points to the root tree
- // node in the tree control.
-
- lpParentTreeNode = lpTreeNodeDef->lpTreeNode;
-
- FREEP(lpTreeNodeDef);
-
- // Next... define the children of the root.
- // Allocate the memory (application grown and owned).
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP(GlobalAlloc(GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)
- * wNumberOfChildren ,0)),0);
-
- if(lpTreeNodeDef)
- {
- // Traverse the memory, initializing text, text
- // length, user data, bitmaps, etc.
-
- lpTreeNodeDef2 = lpTreeNodeDef;
-
- for (i = 0, j = TreeDatabase[0].wIndexOfChildren;
- i < wNumberOfChildren;
- i++, lpTreeNodeDef2++, j++)
- {
- lpTreeNodeDef2->lpszText
- = TreeDatabase[j].lpszNodeText;
-
- lpTreeNodeDef2->lpUserData
- = MAKEP(TreeDatabase[j].wNumberOfChildren,
- TreeDatabase[j].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the
- // tree control
- lpTreeNodeDef2->wUserDataSize = 0;
-
- if(TreeDatabase[j].wNumberOfChildren == 0)
- {
- lpTreeNodeDef2->hBitmap[0] = hbmSheet;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmSheetActive;
- }
- else
- {
- lpTreeNodeDef2->hBitmap[0] = hbmClosed;
- lpTreeNodeDef2->hActiveBitmap[0]
- = hbmClosedActive;
- }
- if(TreeDatabase[j].wBitmapIndex != 0)
- lpTreeNodeDef2->hBitmap[1] =
- hbm[TreeDatabase[j].wBitmapIndex - 1];
- else
- lpTreeNodeDef2->hBitmap[1] = NULL;
- lpTreeNodeDef2->hActiveBitmap[1] = NULL;
- lpTreeNodeDef2->hBitmap[2] = NULL;
-
- lpTreeNodeDef2->wTextLength =
- lstrlen(lpTreeNodeDef2->lpszText);
-
- // Since the string for this node is in a static
- // database and will never be deleted or
- // modified by the application, there is no need
- // for the tree control to allocated memory to
- // store it. Setting the high bit (0x8000) of the
- // wTextLength member tells the tree control to use
- // the given pointer directly. The tree control
- // will not try to free this memory when the tree
- // node is deleted. The tree control simply
- // copies the given string pointer into the
- // TREE_NODE and uses the pointer to access the
- // string.
-
- lpTreeNodeDef2->wTextLength |= 0x8000;
-
- }
-
- // Add the children to the parent 'lpTreeNode'.
- // We do not need to store the tree node pointer that
- // was created as a result of the below call because
- // we will rely on the notification message that will
- // be generated when the user clicks or double
- // clicks on any of these nodes.
-
- wErrCode = BST_AddChildrenToParent( hwndTree,
- lpParentTreeNode, // Parent which is the root
- wNumberOfChildren,
- lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- FREEP(lpTreeNodeDef);
- lpTreeNodeDef = NULL;
- // Open the folder
-
- BST_SetBitmapAndActiveBitmap( hwndTree,
- 0,
- lpParentTreeNode,
- hbmOpen,
- hbmOpenActive);
-
- SetFocus (hwndTree);
-
- ShowWindow (hwndTree, SW_SHOW);
-
- lResult = 0L;
- }
- }
- else
- lResult = 1L;
- }
- }
- else
- lResult = 1L;
- }
- LocalUnlock (hTreeData) ;
-
- if(hwndTree == NULL)
- {
- MessageBox ( hwnd,
- "Problem creating tree control.",
- "WM_CREATE",
- MB_OK);
-
- SetWindowWord (hwnd, WND_EXTRA_TREE_DATA, NULL) ;
- LocalFree (hTreeData);
- }
- else if (lResult != 0L)
- {
- if(lResult == 1L)
- MessageBox (hwnd, "Out of memory.", "WM_CREATE", MB_OK);
- if(lpTreeNodeDef != NULL)
- FREEP(lpTreeNodeDef);
- BST_EraseTree( hwndTree);
- LocalFree (hTreeData);
- SetWindowWord (hwnd, WND_EXTRA_TREE_DATA, NULL) ;
- lResult = 0xFFFFFFFF;
- }
- }
- return lResult ;
-
-
- case WM_BST_SELECT_NOTIF_DBLCLK:
-
- // WM_BST_SELECT_NOTIF_DBLCLK is a notification message sent to
- // the application when the user double clicks on a tree node.
- // lParam is a pointer to a notification structure that is owned by
- // the tree control. DO NOT FREE THIS MEMORY OR ALL HELL WILL
- // BREAK LOOSE. The members of the SELECT_NOTIF structure consist
- // of the pointer to the tree node that was selected and a flags
- // member that describes what region of the tree node that was
- // clicked on and if the tree node had children or not (OPEN or
- // CLOSED).
-
- lpSelectNotif = (LP_SELECT_NOTIF) lParam;
- lpParentTreeNode = lpSelectNotif->lpTreeNode;
-
-
- hTreeData = GetWindowWord (hwnd, WND_EXTRA_TREE_DATA) ;
-
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData) ;
-
- // Is the tree node that was selected, OPENED or CLOSED?
-
- if(lpSelectNotif->wFlags & NODE_OPENED)
- {
- // Yes... then delete the children
-
- BST_DeleteChildrenOfParent( (HWND)wParam, lpParentTreeNode);
-
- // Close the folder
- BST_SetBitmapAndActiveBitmap( wParam,
- 0,
- lpParentTreeNode,
- hbmClosed,
- hbmClosedActive);
- }
- else
- {
- // No... then open it and add children if this tree node gots them.
-
-
- // Notice the use of the lpUserData member of the tree node.
- // Creativity is a desire not a disease.
-
- wIndexOfChildren = LOWORD (lpParentTreeNode->lpUserData);
-
- wNumberOfChildren = HIWORD (lpParentTreeNode->lpUserData);
-
- if(wNumberOfChildren > 0)
- {
- // Define the children as in WM_CREATE: but use the
- // tree node pointer defined in the SELECT_NOTIF structure
- // (lParam) as the parent.
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP(GlobalAlloc(GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)* wNumberOfChildren ,0)),0);
-
- if(lpTreeNodeDef)
- {
- lpTreeNodeDef2 = lpTreeNodeDef;
-
- for (i = 0, j = wIndexOfChildren;
- i < wNumberOfChildren;
- i++, lpTreeNodeDef2++, j++)
- {
- lpTreeNodeDef2->lpszText = TreeDatabase[j].lpszNodeText;
- lpTreeNodeDef2->wTextLength =
- lstrlen(lpTreeNodeDef2->lpszText);
-
- // Since the string for this node is in a static
- // database and will never be deleted or
- // modified by the application, there is no need
- // for the tree control to allocated memory to
- // store it. Setting the high bit (0x8000) of the
- // wTextLength member tells the tree control to use
- // the given pointer directly. The tree control
- // will not try to free this memory when the tree
- // node is deleted. The tree control simply
- // copies the given string pointer into the
- // TREE_NODE and uses the pointer to access the
- // string.
-
- lpTreeNodeDef2->wTextLength |= 0x8000;
-
- lpTreeNodeDef2->lpUserData =
- MAKEP(TreeDatabase[j].wNumberOfChildren,
- TreeDatabase[j].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the
- // tree control
- lpTreeNodeDef2->wUserDataSize = 0;
-
- if(TreeDatabase[j].wNumberOfChildren == 0)
- {
- lpTreeNodeDef2->hBitmap[0] = hbmSheet;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmSheetActive;
- }
- else
- {
- lpTreeNodeDef2->hBitmap[0] = hbmClosed;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmClosedActive;
- }
-
- if(TreeDatabase[j].wBitmapIndex != 0)
- lpTreeNodeDef2->hBitmap[1] =
- hbm[TreeDatabase[j].wBitmapIndex - 1];
- else
- lpTreeNodeDef2->hBitmap[1] = NULL;
- lpTreeNodeDef2->hActiveBitmap[1] = NULL;
- lpTreeNodeDef2->hBitmap[2] = NULL;
- }
- // Add 'em ...
-
- wErrCode = BST_AddChildrenToParent( wParam,
- lpParentTreeNode,
- wNumberOfChildren,
- lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- // Open the folder of the parent
-
- BST_SetBitmapAndActiveBitmap( wParam,
- 0,
- lpParentTreeNode,
- hbmOpen,
- hbmOpenActive);
- }
- FREEP(lpTreeNodeDef);
- }
- else
- {
- MessageBox ( hwnd,
- "Out of memory.",
- "WM_BST_SELECT_NOTIF_DBLCLK",
- MB_OK);
- }
- }
- }
- LocalUnlock (hTreeData) ;
- return 0;
-
-
- case WM_SYSCOLORCHANGE:
-
- // Sad but true... The WM_SYSCOLORCHANGE notification has be sent
- // to the tree control since only top level windows get this
- // notification. Since the colors are going to change in the
- // tree control, better make sure that the background color of
- // the bitmaps is correct.
-
- hTreeData = GetWindowWord (hwnd, WND_EXTRA_TREE_DATA) ;
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData);
- if(npTreeData->hwndTree)
- SendMessage (npTreeData->hwndTree, message, wParam, lParam);
- LocalUnlock (hTreeData) ;
- return 0;
-
-
- case WM_SETFOCUS:
-
- // Keep the focus on the tree control.
-
- hTreeData = GetWindowWord (hwnd, WND_EXTRA_TREE_DATA) ;
- if(hTreeData)
- {
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData) ;
- SetFocus(npTreeData->hwndTree);
- LocalUnlock (hTreeData) ;
- }
- break;
-
- case WM_SIZE:
- // Keep the tree control in the client area of the
- // MDI child window.
-
- hTreeData = GetWindowWord (hwnd, WND_EXTRA_TREE_DATA) ;
- if(hTreeData)
- {
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData) ;
- cx = GetSystemMetrics ( SM_CXVSCROLL) / 2;
- cy = GetSystemMetrics ( SM_CYHSCROLL) / 2;
- MoveWindow ( npTreeData->hwndTree,
- cx,
- cy,
- max(LOWORD(lParam) - 2 * cx, 0),
- max(HIWORD(lParam) - 2 * cy, 0),
- TRUE);
-
- LocalUnlock (hTreeData) ;
- }
- break;
-
- case WM_MDIACTIVATE:
-
- if (wParam == TRUE)
- SendMessage ( hwndClient,
- WM_MDISETMENU,
- 0,
- MAKELONG (hMenuTreeCtrl, hMenuTreeCtrlWindow)) ;
-
- if (wParam == FALSE)
- SendMessage ( hwndClient,
- WM_MDISETMENU,
- 0,
- MAKELONG (hMenuInit, hMenuInitWindow)) ;
-
- DrawMenuBar (hwndFrame) ;
- return 0 ;
-
- case WM_DESTROY:
-
- // Clean up time. The tree control will receive a WM_DESTROY
- // therefore it will automatically free all memory it owns.
- // But the bitmaps are the property of the application so it must
- // free these objects.
-
- hTreeData = GetWindowWord (hwnd, WND_EXTRA_TREE_DATA) ;
- if(hTreeData)
- {
- npTreeData = (NP_TREE_DATA) LocalLock (hTreeData) ;
- BST_EraseTree( npTreeData->hwndTree); // Do a erase tree first before
- // freeing bitmaps since the
- // tree may need these objects
- LocalUnlock (hTreeData) ;
- LocalFree(hTreeData);
- }
- return 0 ;
- }
- return DefMDIChildProc (hwnd, message, wParam, lParam) ;
- }
-
-
-
-
-
- /*****************************************************************************
- long FAR PASCAL _export ListCtrlFrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam)
-
-
- This is the window procedure of the MDI child window. When this procedure
- receives it's WM_CREATE message, a BSS Tree Control is created as a child
- window (control).
-
- After this tree is created, it is populated with the root node and the first
- level nodes taken from the database described in the file which
- is in RCDATA format.
-
- When a user double clicks on any of these nodes, the MDI child window (which
- is the parent of the BSS Tree Control) will receive a notification.
- This notification describes the node that was selected by the
- double click. The MDI child window will respond by taking the key index of
- the node that was clicked on, use it to access the database, and retrieve the
- list of children for that node. The BSS Tree Control is sent this list via
- the exported API, BST_AddChildrenToParent, and SLAM! The list of children
- for the selected node is displayed.
-
- This MDI child window procedure also demonstrates the passing of the
- WM_SYSCOLORCHANGE notification to the BSS Tree Control for system color
- changes.
-
- REMEMBER:
-
- The database that is used in this example is just one storage system.
- The database could be a file system, a finite state machine, a relational
- database browser, a network map, etc.
-
- ******************************************************************************/
-
- long FAR PASCAL _export ListCtrlFrameWndProc ( HWND hwnd,
- UINT message,
- UINT wParam,
- LONG lParam)
- {
- static HWND hwndClient;
- static HWND hwndFrame ;
- // The following are important pointers in the process of building the
- // tree. The structure definition that these pointers point to are defined
- // in bstree.h
- LP_TREE_NODE lpParentTreeNode; // Points to a tree node
- LP_TREE_NODE_DEF lpTreeNodeDef; // Points to an array of 1 or more
- // tree node definitions that are
- // defined by the application.
- LP_TREE_NODE_DEF lpTreeNodeDef2; // Runner used to traverse the list
- // tree node definitions pointed to
- // by the pointer above.
- LP_SELECT_NOTIF lpSelectNotif; // Pointer to the tree control owned
- // notification structure used to
- // pass information about a tree node
- // to the application.
- WORD i;
- WORD j;
- HWND hwndTree;
- WORD wNumberOfChildren;
- WORD wIndexOfChildren;
- LOCALHANDLE hListData ;
- NP_LIST_DATA npListData ;
- short cx, cy;
- WORD wErrCode;
- LONG lResult;
-
- switch (message)
- {
- case WM_CREATE:
- hwndClient = GetParent (hwnd) ;
-
- hwndFrame = GetParent (hwndClient) ;
-
- lResult = 0xFFFFFFFF;
-
- // Allocate the instance data for this MDI child window. This data
- // structure will hold the window handle of the tree control and the
- // handles of the bitmaps to be displayed in the tree nodes. The
- // BSS Tree Control window handle is used in almost all the APIs
- // to the tree control.
-
- hListData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
- sizeof (LIST_DATA)) ;
- if(hListData != NULL)
- {
- // Save the above memory handle in the extra window memory reserved
- // during the registration of the "ListCtrlFrame" class (MDI child
- // window).
-
- SetWindowWord (hwnd, WND_EXTRA_LIST_DATA, hListData) ;
-
- // Lock down the memory to get the pointer to the instance data
- // structure. We will be assigning the newly created BSS Tree
- // Control window handle to the hwndTree member of LIST_DATA.
- // The bitmap handles will also be assigned to members in
- // LIST_DATA to be referenced later.
-
- npListData = (NP_LIST_DATA) LocalLock (hListData) ;
-
- // Not necessary since the structure allocated above was zero
- // initialized but the below statement will remain only as a
- // reminder that messages may come into this window procedure
- // during the call to create a tree. And if the tree control
- // handle is referenced before the return from the call
- // BST_CreateTree, the tree control handle will be invalid.
- // This is the case with WM_SYSCOLORCHANGE. For unregistered
- // copies of the BSS Tree Control, a modal dialog box is
- // created during the WM_CREATE message of the Tree Control.
- // While this message is up, a user can open the Color Dialog and
- // change a color causing a WM_SYSCOLORCHANGE to be sent to all
- // the top level windows. Since execution has not returned from
- // the call to BST_CreateTree but yet the message
- // WM_SYSCOLORCHANGE is sent to this procedure by its parent, the
- // reference to npListData->hwndTree will be invalid and a GP
- // will occur. Trust me. This happened.
-
- npListData->hwndTree = NULL;
-
- // BST_CreateTree creates a BSS Tree Control. The parameters are
- // similar to the Windows API CreateWindowEx. Why have the call
- // anyway? The API guarantees that the Window style will include
- // the scroll bars, clipping, and helps the programmer use the
- // right class. Notice I added a border to the style. Looks
- // great! Notice that the starting x, y, width, and height are
- // 0? This works because the WM_SIZE message handler of this
- // window procedure does a MoveWindow to the BSS Tree Control to
- // keep the tree control sized to the MDI child window.
-
- hwndTree = BST_CreateTree (hInst,hwnd,0, 0, 0,0,WS_BORDER, 0);
-
- if(hwndTree != NULL)
- {
- // Now the assignment of instance data.
-
- npListData->hwndTree = hwndTree;
-
-
- // This is a commented out example to setting the font in the
- // BSS Tree Control using the BST_SetFont API. The font could
- // be a result of the font common dialog.
-
- // BST_SetFont( hwndTree,GetStockObject(ANSI_VAR_FONT));
-
- // Bitmaps spaces are locations bitmaps are placed in a tree
- // node. The bitmap spaces are placed left of the text.
- // Below, two bitmap spaces are defined. The max width
- // and height are defined. The first argument is the BSS
- // Tree Control handle, the second is the bitmap space
- // identifier (which bitmap space is being defined). The
- // third and fourth arguments are the width and height
- // respectively. The last argument signals the BSS Tree
- // Control whether to center or left justify the currently
- // assigned bitmap in this bitmap space. TRUE means center,
- // FALSE means left justify.
-
- // This defines the bitmap spaces globally for every tree node.
- // This keeps column alignment of bitmaps on the same level.
-
- BST_SetBitmapSpace( hwndTree, 0, 22, 17, TRUE);
-
- BST_SetBitmapSpace( hwndTree, 1, 42, 20, TRUE);
-
- // Tells the BSS Tree Control to place so many pixels after the
- // last bitmap (if any) and before the first character of the
- // text string.
-
- BST_SetXSpaceBeforeText( hwndTree, SPACE_BEFORE_TEXT);
-
- // By default this is TRUE, but for purpose of demonstration...
-
- // BST_ShowLines( hwndTree, TRUE);
-
- // Now, the fun part... Defining tree nodes.
-
- // First... define the root!
-
- // Allocate a tree node definition for the root. It
- // is best if this memory is initialize to zero. The tree node
- // definition structure is the vehicle that the application uses
- // to define tree nodes to the BSS Tree Control. This memory is
- // the property of the application. Its contents are copied to
- // the a newly created tree node in the tree control. Once the
- // node is defined, this memory can be freed.
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP( GlobalAlloc (GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)*1,0)),0);
-
- if(lpTreeNodeDef)
- {
- // Assign the text that will be displayed for the tree node.
-
- lpTreeNodeDef->lpszText = ListDatabase[0].lpszNodeText;
-
- // Length of the above text.
-
- lpTreeNodeDef->wTextLength = lstrlen(lpTreeNodeDef->lpszText);
-
- // Since the string for this node is in a static database
- // and will never be deleted or modified by the application,
- // there is no need for the tree control to allocated
- // memory to store it. Setting the high bit
- // (0x8000) of the wTextLength member tells the tree control
- // to use the given pointer directly. The tree control will
- // not try to free this memory when the tree node is
- // deleted. The tree control simply copies the given
- // string pointer into the TREE_NODE and uses the pointer
- // to access the string.
-
- lpTreeNodeDef->wTextLength |= 0x8000;
-
- // Setup the lpUserData member. This member can be used
- // to store a pointer to application defined memory that
- // takes advantage of the tree control's structure. If
- // this is used for application defined memory, then it
- // is the responsibility of the application to maintain
- // it.
- // To aid in this adventure, the BSS Tree Control exported
- // API provides a way for the application to define a
- // callback that will be called everytime a node is deleted.
-
- // In the below case, the lpUserData is used as a DWORD
- // storage instead of a pointer for two values that
- // describe the children of the parent. The low word is
- // the offset into the database where the children definition
- // starts and the high word is the number of children of the
- // parent.
-
- wNumberOfChildren = ListDatabase[0].wNumberOfChildren;
-
-
- lpTreeNodeDef->lpUserData = MAKEP(wNumberOfChildren,
- ListDatabase[0].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the tree control
- lpTreeNodeDef->wUserDataSize = 0;
-
- // Assign bitmaps created earlier to the first bitmap space
- // which were also defined earlier. PS. The active bitmap
- // is the bitmap that is displayed when the tree node is
- // highlighted. Currently, there are two bitmap spaces
- // defined per node. If more is needed, then the source
- // can be purchased and the number of bitmap spaces can
- // be increased. In most case only two bitmaps are good
- // enough. If any of the bitmap spaces are not used, then
- // make sure that a NULL handle is assigned to the bitmap
- // space.
-
- lpTreeNodeDef->hBitmap[0] = hbmClosed;
-
- lpTreeNodeDef->hActiveBitmap[0] = hbmClosedActive;
-
- if(ListDatabase[0].wBitmapIndex != 0)
- lpTreeNodeDef->hBitmap[1] =
- hbm[ListDatabase[0].wBitmapIndex - 1];
- else
- lpTreeNodeDef->hBitmap[1] = NULL;
-
-
- lpTreeNodeDef->hActiveBitmap[1] = NULL;
- lpTreeNodeDef->hBitmap[2] = NULL;
-
-
- // Since the tree node definition structure is defined then
- // call the BST_AddChildrenToParent API. Notice the 0L value.
- // This is the indicator that this node is the root. The
- // tree can only have one root. If the root is NOT defined
- // then calling any other API will cause havoc.
-
- wErrCode =
- BST_AddChildrenToParent(hwndTree, 0L, 1,lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- // The lpTreeNode member is an important animal. When
- // BST_AddChildrenToParent is called with the tree
- // node definitions, the tree control internally allocates
- // the tree node memory in which it stores the tree node
- // definition information.
- // The tree control then assigns this new tree node
- // pointer to the tree node definition member 'lpTreeNode'.
- // Remember, the tree node definition structure is
- // shared memory between the application and the tree
- // control. The application could use the 'lpTreeNode'
- // value for future references to the new node such as
- // adding nodes as children.
-
- // Below, the 'lpTreeNode' member of the tree node
- // definition is saved. It will be used as a reference
- // to add children. This pointer points to the root tree
- // node in the tree control.
-
- lpParentTreeNode = lpTreeNodeDef->lpTreeNode;
-
- FREEP(lpTreeNodeDef);
-
- // Next... define the children of the root.
- // Allocate the memory (application grown and owned).
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP(GlobalAlloc(GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)
- * wNumberOfChildren ,0)),0);
-
- if(lpTreeNodeDef)
- {
- // Traverse the memory, initializing text, text
- // length, user data, bitmaps, etc.
-
- lpTreeNodeDef2 = lpTreeNodeDef;
-
- for (i = 0, j = ListDatabase[0].wIndexOfChildren;
- i < wNumberOfChildren;
- i++, lpTreeNodeDef2++, j++)
- {
- lpTreeNodeDef2->lpszText
- = ListDatabase[j].lpszNodeText;
-
- lpTreeNodeDef2->lpUserData
- = MAKEP(ListDatabase[j].wNumberOfChildren,
- ListDatabase[j].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the
- // tree control
- lpTreeNodeDef2->wUserDataSize = 0;
-
- if(ListDatabase[j].wNumberOfChildren == 0)
- {
- lpTreeNodeDef2->hBitmap[0] = hbmSheet;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmSheetActive;
- }
- else
- {
- lpTreeNodeDef2->hBitmap[0] = hbmClosed;
- lpTreeNodeDef2->hActiveBitmap[0]
- = hbmClosedActive;
- }
- if(ListDatabase[j].wBitmapIndex != 0)
- lpTreeNodeDef2->hBitmap[1] =
- hbm[ListDatabase[j].wBitmapIndex - 1];
- else
- lpTreeNodeDef2->hBitmap[1] = NULL;
- lpTreeNodeDef2->hActiveBitmap[1] = NULL;
- lpTreeNodeDef2->hBitmap[2] = NULL;
-
- lpTreeNodeDef2->wTextLength =
- lstrlen(lpTreeNodeDef2->lpszText);
-
- // Since the string for this node is in a static
- // database and will never be deleted or
- // modified by the application, there is no need
- // for the tree control to allocated memory to
- // store it. Setting the high bit (0x8000) of the
- // wTextLength member tells the tree control to use
- // the given pointer directly. The tree control
- // will not try to free this memory when the tree
- // node is deleted. The tree control simply
- // copies the given string pointer into the
- // TREE_NODE and uses the pointer to access the
- // string.
-
- lpTreeNodeDef2->wTextLength |= 0x8000;
-
- }
-
- // Add the children to the parent 'lpTreeNode'.
- // We do not need to store the tree node pointer that
- // was created as a result of the below call because
- // we will rely on the notification message that will
- // be generated when the user clicks or double
- // clicks on any of these nodes.
-
- wErrCode = BST_AddChildrenToParent( hwndTree,
- lpParentTreeNode, // Parent which is the root
- wNumberOfChildren,
- lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- FREEP(lpTreeNodeDef);
- lpTreeNodeDef = NULL;
- // Open the folder
-
- BST_SetBitmapAndActiveBitmap( hwndTree,
- 0,
- lpParentTreeNode,
- hbmOpen,
- hbmOpenActive);
-
- SetFocus (hwndTree);
-
- ShowWindow (hwndTree, SW_SHOW);
-
- lResult = 0L;
- }
- }
- else
- lResult = 1L;
- }
- }
- else
- lResult = 1L;
- }
- LocalUnlock (hListData) ;
-
- if(hwndTree == NULL)
- {
- MessageBox ( hwnd,
- "Problem creating tree control.",
- "WM_CREATE",
- MB_OK);
-
- SetWindowWord (hwnd, WND_EXTRA_LIST_DATA, NULL) ;
- LocalFree (hListData);
- }
- else if (lResult != 0L)
- {
- if(lResult == 1L)
- MessageBox (hwnd, "Out of memory.", "WM_CREATE", MB_OK);
- if(lpTreeNodeDef != NULL)
- FREEP(lpTreeNodeDef);
- BST_EraseTree( hwndTree);
- LocalFree (hListData);
- SetWindowWord (hwnd, WND_EXTRA_LIST_DATA, NULL) ;
- lResult = 0xFFFFFFFF;
- }
- }
- return lResult ;
-
-
- case WM_BST_SELECT_NOTIF_DBLCLK:
-
- // WM_BST_SELECT_NOTIF_DBLCLK is a notification message sent to
- // the application when the user double clicks on a tree node.
- // lParam is a pointer to a notification structure that is owned by
- // the tree control. DO NOT FREE THIS MEMORY OR ALL HELL WILL
- // BREAK LOOSE. The members of the SELECT_NOTIF structure consist
- // of the pointer to the tree node that was selected and a flags
- // member that describes what region of the tree node that was
- // clicked on and if the tree node had children or not (OPEN or
- // CLOSED).
-
- lpSelectNotif = (LP_SELECT_NOTIF) lParam;
- lpParentTreeNode = lpSelectNotif->lpTreeNode;
-
-
- hListData = GetWindowWord (hwnd, WND_EXTRA_LIST_DATA) ;
-
- npListData = (NP_LIST_DATA) LocalLock (hListData) ;
-
- // Is the tree node that was selected, OPENED or CLOSED?
-
- if(lpSelectNotif->wFlags & NODE_OPENED)
- {
- // Yes... then delete the children
-
- BST_DeleteChildrenOfParent( (HWND)wParam, lpParentTreeNode);
-
- // Close the folder
- BST_SetBitmapAndActiveBitmap( wParam,
- 0,
- lpParentTreeNode,
- hbmClosed,
- hbmClosedActive);
- }
- else
- {
- // No... then open it and add children if this tree node gots them.
-
-
- // Notice the use of the lpUserData member of the tree node.
- // Creativity is a desire not a disease.
-
- wIndexOfChildren = LOWORD (lpParentTreeNode->lpUserData);
-
- wNumberOfChildren = HIWORD (lpParentTreeNode->lpUserData);
-
- if(wNumberOfChildren > 0)
- {
- // Define the children as in WM_CREATE: but use the
- // tree node pointer defined in the SELECT_NOTIF structure
- // (lParam) as the parent.
-
- lpTreeNodeDef = (LP_TREE_NODE_DEF)
- MAKEP(GlobalAlloc(GPTR|GMEM_SHARE,
- MAKELONG(sizeof(TREE_NODE_DEF)* wNumberOfChildren ,0)),0);
-
- if(lpTreeNodeDef)
- {
- lpTreeNodeDef2 = lpTreeNodeDef;
-
- for (i = 0, j = wIndexOfChildren;
- i < wNumberOfChildren;
- i++, lpTreeNodeDef2++, j++)
- {
- lpTreeNodeDef2->lpszText = ListDatabase[j].lpszNodeText;
- lpTreeNodeDef2->wTextLength =
- lstrlen(lpTreeNodeDef2->lpszText);
-
- // Since the string for this node is in a static
- // database and will never be deleted or
- // modified by the application, there is no need
- // for the tree control to allocated memory to
- // store it. Setting the high bit (0x8000) of the
- // wTextLength member tells the tree control to use
- // the given pointer directly. The tree control
- // will not try to free this memory when the tree
- // node is deleted. The tree control simply
- // copies the given string pointer into the
- // TREE_NODE and uses the pointer to access the
- // string.
-
- lpTreeNodeDef2->wTextLength |= 0x8000;
-
- lpTreeNodeDef2->lpUserData =
- MAKEP(ListDatabase[j].wNumberOfChildren,
- ListDatabase[j].wIndexOfChildren);
-
- // No dynamically allocated memory needed from the
- // tree control
- lpTreeNodeDef2->wUserDataSize = 0;
-
- if(ListDatabase[j].wNumberOfChildren == 0)
- {
- lpTreeNodeDef2->hBitmap[0] = hbmSheet;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmSheetActive;
- }
- else
- {
- lpTreeNodeDef2->hBitmap[0] = hbmClosed;
- lpTreeNodeDef2->hActiveBitmap[0] = hbmClosedActive;
- }
-
- if(ListDatabase[j].wBitmapIndex != 0)
- lpTreeNodeDef2->hBitmap[1] =
- hbm[ListDatabase[j].wBitmapIndex - 1];
- else
- lpTreeNodeDef2->hBitmap[1] = NULL;
- lpTreeNodeDef2->hActiveBitmap[1] = NULL;
- lpTreeNodeDef2->hBitmap[2] = NULL;
- }
- // Add 'em ...
-
- wErrCode = BST_AddChildrenToParent( wParam,
- lpParentTreeNode,
- wNumberOfChildren,
- lpTreeNodeDef);
-
- if(HandleAddChildrenError( hwnd, wErrCode) == 0)
- {
- // Open the folder of the parent
-
- BST_SetBitmapAndActiveBitmap( wParam,
- 0,
- lpParentTreeNode,
- hbmOpen,
- hbmOpenActive);
- }
- FREEP(lpTreeNodeDef);
- }
- else
- {
- MessageBox ( hwnd,
- "Out of memory.",
- "WM_BST_SELECT_NOTIF_DBLCLK",
- MB_OK);
- }
- }
- }
- LocalUnlock (hListData) ;
- return 0;
-
-
- case WM_SYSCOLORCHANGE:
-
- // Sad but true... The WM_SYSCOLORCHANGE notification has be sent
- // to the tree control since only top level windows get this
- // notification. Since the colors are going to change in the
- // tree control, better make sure that the background color of
- // the bitmaps is correct.
-
- hListData = GetWindowWord (hwnd, WND_EXTRA_LIST_DATA) ;
- npListData = (NP_LIST_DATA) LocalLock (hListData);
- if(npListData->hwndTree)
- SendMessage (npListData->hwndTree, message, wParam, lParam);
- LocalUnlock (hListData) ;
- return 0;
-
-
- case WM_SETFOCUS:
-
- // Keep the focus on the tree control.
-
- hListData = GetWindowWord (hwnd, WND_EXTRA_LIST_DATA) ;
- if(hListData)
- {
- npListData = (NP_LIST_DATA) LocalLock (hListData) ;
- SetFocus(npListData->hwndTree);
- LocalUnlock (hListData) ;
- }
- break;
-
- case WM_SIZE:
- // Keep the tree control in the client area of the
- // MDI child window.
-
- hListData = GetWindowWord (hwnd, WND_EXTRA_LIST_DATA) ;
- if(hListData)
- {
- npListData = (NP_LIST_DATA) LocalLock (hListData) ;
- cx = GetSystemMetrics ( SM_CXVSCROLL) / 2;
- cy = GetSystemMetrics ( SM_CYHSCROLL) / 2;
- MoveWindow ( npListData->hwndTree,
- cx,
- cy,
- max(LOWORD(lParam) - 2 * cx, 0),
- max(HIWORD(lParam) - 2 * cy, 0),
- TRUE);
-
- LocalUnlock (hListData) ;
- }
- break;
-
- case WM_MDIACTIVATE:
-
- if (wParam == TRUE)
- SendMessage ( hwndClient,
- WM_MDISETMENU,
- 0,
- MAKELONG (hMenuTreeCtrl, hMenuTreeCtrlWindow)) ;
-
- if (wParam == FALSE)
- SendMessage ( hwndClient,
- WM_MDISETMENU,
- 0,
- MAKELONG (hMenuInit, hMenuInitWindow)) ;
-
- DrawMenuBar (hwndFrame) ;
- return 0 ;
-
- case WM_DESTROY:
-
- // Clean up time. The tree control will receive a WM_DESTROY
- // therefore it will automatically free all memory it owns.
- // But the bitmaps are the property of the application so it must
- // free these objects.
-
- hListData = GetWindowWord (hwnd, WND_EXTRA_LIST_DATA) ;
- if(hListData)
- {
- npListData = (NP_LIST_DATA) LocalLock (hListData) ;
- BST_EraseTree( npListData->hwndTree); // Do a erase tree first before
- // freeing bitmaps since the
- // tree may need these objects
- LocalUnlock (hListData) ;
- LocalFree(hListData);
- }
- return 0 ;
- }
- return DefMDIChildProc (hwnd, message, wParam, lParam) ;
- }
-
-
-
-
-
-
-
- char * npszAddChildrenErrors [] =
- {
- "Memory allocation failure.",
- "Level limit exceeded.",
- "The number of nodes supported has been exeeded.",
- "Only on root per tree.",
- "Given parent node is invalid.",
- "Invalid error code."
- };
-
- WORD HandleAddChildrenError( HWND hwnd, WORD wErrCode)
- {
- WORD i;
-
- switch (wErrCode)
- {
- case BST_NO_ERROR:
- i = 0;
- break;
-
- case BST_ERR_MEMORY_ALLOC_FAILED:
- i = 1;
- break;
-
- case BST_ERR_LEVEL_LIMIT_EXCEEDED:
- i = 2;
- break;
-
- case BST_ERR_TOO_MANY_NODES:
- i = 3;
- break;
-
- case BST_ERR_ONLY_ONE_ROOT_ALLOWED:
- i = 4;
- break;
-
- case BST_ERR_INVALID_PARENT_FOR_INSERTION:
- i = 5;
- break;
-
- default:
- i = 6;
- break;
- }
- if ( i != 0)
- {
- MessageBox ( hwnd,
- npszAddChildrenErrors[i-1],
- "BST_AddChildrenToParent",
- MB_OK);
- }
- return i;
- }
-
-
-
-
-
- /**************************************************************************/
- /* Below are support routines for the 16 color bitmaps used in the tree */
- // Enjoy!
-
- HBITMAP CreateBackgroundMatchedBitmap (DWORD dwrgbBackground, int nBitmapResouce)
- {
- HANDLE hBitmap;
- HANDLE hRes;
- HANDLE hResMem;
- LPBITMAPINFOHEADER lpbi;
- DWORD FAR * lpColorTable;
- LPSTR lpBits;
- int bc;
- HDC hdc;
-
- hRes = FindResource ( hInst,
- MAKEINTRESOURCE (nBitmapResouce),
- RT_BITMAP);
-
- hResMem = LoadResource (hInst, hRes);
- lpbi = (LPBITMAPINFOHEADER) LockResource (hResMem);
-
- lpColorTable = (DWORD FAR *)(lpbi + 1);
- lpBits = (LPSTR) (lpColorTable + 16);
-
- bc = (lpBits[0] & 0xF0) >> 4;
-
- lpColorTable [bc] = RGB( GetBValue (dwrgbBackground),
- GetGValue (dwrgbBackground),
- GetRValue (dwrgbBackground));
- hdc = GetDC(NULL);
- hBitmap = CreateDIBitmap ( hdc,
- lpbi,
- (DWORD) CBM_INIT,
- lpBits,
- (LPBITMAPINFO) lpbi,
- DIB_RGB_COLORS);
- ReleaseDC(NULL, hdc);
- UnlockResource (hResMem);
- FreeResource(hResMem);
- return hBitmap;
- }
-
-
- char rgchBits [2048];
-
- short ChangeBitmapToMatchBackground ( DWORD dwrgbBackground,
- HANDLE hBitmap,
- int nBitmapResouce)
- {
- int bc;
- HDC hdc;
- LPBITMAPINFO lpbi;
- HANDLE hRes;
- HANDLE hResMem;
-
- hRes = FindResource ( hInst,
- MAKEINTRESOURCE (nBitmapResouce),
- RT_BITMAP);
-
- hResMem = LoadResource (hInst, hRes);
- lpbi = ( LPBITMAPINFO ) LockResource (hResMem);
-
- hdc = GetDC (NULL);
-
- GetDIBits ( hdc,
- hBitmap,
- 0,
- LOWORD(lpbi->bmiHeader.biHeight),
- rgchBits,
- lpbi,
- DIB_RGB_COLORS);
-
- bc = (rgchBits[0] & 0xF0) >> 4;
-
- lpbi->bmiColors[bc].rgbBlue = GetBValue (dwrgbBackground);
- lpbi->bmiColors[bc].rgbGreen = GetGValue (dwrgbBackground);
- lpbi->bmiColors[bc].rgbRed = GetRValue (dwrgbBackground);
- lpbi->bmiColors[bc].rgbReserved = 0;
-
- SetDIBits(hdc,
- hBitmap,
- 0,
- LOWORD(lpbi->bmiHeader.biHeight),
- rgchBits,
- lpbi,
- DIB_RGB_COLORS);
-
- ReleaseDC(NULL, hdc );
- UnlockResource (hResMem);
- FreeResource(hResMem);
- return 0;
- }
-
-
-
- short ReadInDatabases ( void )
- {
- HANDLE hResource;
- LP_TREE_DATABASE lpTreeDB;
- LPSTR lpsz;
- short i;
-
- hResource = LoadResource (hInst,
- FindResource (hInst, "TREEDB", RT_RCDATA));
- lpTreeDB = (LP_TREE_DATABASE) LockResource (hResource);
- if(lpTreeDB == NULL)
- {
- MessageBox (NULL, "Resource lock down error.", "Tree Demo 3", MB_OK);
- return 1;
- }
- lpsz = (LPSTR) lpTreeDB;
-
- for( i = 0; i < TREE_SIZE; i++)
- {
- TreeDatabase[i].wIndexOfThisNode = lpTreeDB->wIndexOfThisNode;
- TreeDatabase[i].wBitmapIndex = lpTreeDB->wBitmapIndex;
- TreeDatabase[i].wNumberOfChildren = lpTreeDB->wNumberOfChildren;
- TreeDatabase[i].wIndexOfChildren = lpTreeDB->wIndexOfChildren;
- TreeDatabase[i].lpszNodeText = (char _far *) _fmalloc(160);
- if(TreeDatabase[i].lpszNodeText == NULL)
- {
- MessageBox (NULL, "Database memory allocation error.", "Tree Demo 3", MB_OK);
- return 1;
- }
- lpsz += (sizeof (TREE_DATABASE) - sizeof(LPSTR));
- lstrcpy (TreeDatabase[i].lpszNodeText, lpsz);
- lpsz += lstrlen ( (LPSTR) lpsz) + 1;
- lpTreeDB = (LP_TREE_DATABASE) lpsz;
- }
- UnlockResource (hResource);
- FreeResource (hResource);
-
- hResource = LoadResource (hInst,
- FindResource (hInst, "LISTDB", RT_RCDATA));
- lpTreeDB = (LP_TREE_DATABASE) LockResource (hResource);
- if(lpTreeDB == NULL)
- {
- MessageBox (NULL, "Resource lock down error.", "Tree Demo 3", MB_OK);
- return 1;
-
- }
- lpsz = (LPSTR) lpTreeDB;
-
- for( i = 0; i < LIST_SIZE; i++)
- {
- ListDatabase[i].wIndexOfThisNode = lpTreeDB->wIndexOfThisNode;
- ListDatabase[i].wBitmapIndex = lpTreeDB->wBitmapIndex;
- ListDatabase[i].wNumberOfChildren = lpTreeDB->wNumberOfChildren;
- ListDatabase[i].wIndexOfChildren = lpTreeDB->wIndexOfChildren;
- ListDatabase[i].lpszNodeText = (char _far *) _fmalloc(160);
- if(TreeDatabase[i].lpszNodeText == NULL)
- {
- MessageBox (NULL, "Database memory allocation error.", "Tree Demo 3", MB_OK);
- return 1;
- }
- lpsz += (sizeof (TREE_DATABASE) - sizeof(LPSTR));
- lstrcpy (ListDatabase[i].lpszNodeText, lpsz);
- lpsz += lstrlen ( (LPSTR) lpsz) + 1;
- lpTreeDB = (LP_TREE_DATABASE) lpsz;
- }
- UnlockResource (hResource);
- FreeResource (hResource);
- return 0;
- }
-
- /*--------------------------------- EOF -----------------------------------*/
-