this wasn't working in CmdViewAll()        
        // collapse the TreeView
        fExpandEnabled = TRUE;
        TreeView_Expand(hwndTreeView, htiCurrentRoot, TVE_COLLAPSE);
        fExpandEnabled = FALSE;

        // display first destination line expanded
        ExpandBranch(htiCurrentRoot);

BOOL InitMixer(HWND hwnd)
{           
    MMRESULT result;
    char achMsg[80];   
   
    // query for the number of mixer devices in the system
    uNumMixers = mixerGetNumDevs();    
    if (!uNumMixers)
    {
        MessageBox(hwnd, 
            "No mixer devices are present - MixTree will close", 
            "MixTree", 
            MB_ICONHAND);         
        return (FALSE);
    }
        
// note - this code just deals with a single mixer device!
    // it just picks mixer device id 0 regardless of how many
    // mixers are actually present
    uMixerID = 0;
    result = mixerOpen(&hMixer, uMixerID, 0, 0, 0);
    
    // could do it like this to get callback - but probably don't need to
    // result = mixerOpen(&hMixer, uMixerID, hWnd, 0, CALLBACK_WINDOW);

    if (result)
    {               
        wsprintf((LPSTR)achMsg, (LPSTR)"Error #%d opening mixer device", result);
        MessageBox(hwnd, achMsg, "MixTree Error", MB_ICONHAND);
        return (FALSE);
    }
   
    // query the mixer's capabilities
    result = mixerGetDevCaps(uMixerID, &MixerCaps, sizeof(MIXERCAPS));  
    if (result)
    {               
        wsprintf((LPSTR)achMsg, (LPSTR)"Error #%d getting mixer capabilities", result);
        MessageBox(hwnd, achMsg, "MixTree Error", MB_ICONHAND);
        return (FALSE);
    }
                   
    return (TRUE);
}

 

LRESULT MsgDeviceChange(HWND, UINT, WPARAM, LPARAM);

       {WM_DEVICECHANGE, MsgDeviceChange},

//    MsgDeviceChange - Handles WM_DEVICECHANGE messages for main window.
  
//
//  FUNCTION: MsgDeviceChange(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Handles WM_DEVICECHANGE message.  Since a mixer device may have
//           been added or removed, this function enumerates the mixer devices
//           and checks to see if the one in use is still valid.
//
//  PARAMETERS:
//
//    hwnd      - Window handle  (Unused)
//    uMessage  - Message number (Unused)
//    wparam    - Event type.
//    lparam    - Address of a structure that contains event-specific data. (Unused)
//
//  RETURN VALUE:
//
//    Always returns 0 - Message handled
//
//  COMMENTS:
//
//

LRESULT MsgDeviceChange(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
{	
    MMRESULT result;
    UINT uNewNumMixers, uNewMixerID;
    char achMsg[80];    

    switch (wparam)
    {
#if 0
// note: this code was not finalized

        case DBT_DEVICEARRIVAL:
            // A device has been inserted and is now available. 
            // MixTree needs to respond to this.            
            break;

        case DBT_DEVICEQUERYREMOVE:
            // Permission to remove a device is requested. 
            // Any application can deny this request and cancel the removal.
            // MixTree only needs to allow the device to be removed.
            return TRUE;            

        case DBT_DEVICEQUERYREMOVEFAILED:
            // Request to remove a device has been canceled.
            // MixTree doesn't mind.
            return TRUE;

        case DBT_DEVICEREMOVEPENDING:
            // Device is about to be removed. Can not be denied.
            // MixTree won't act until the device is removed.
            return TRUE;

        case DBT_DEVICEREMOVECOMPLETE:
            // Device has been removed.
            // MixTree will handle this.
            break;

        case DBT_DEVICETYPESPECIFIC:
            // Device-specific event.
            // Nothing to do.
            return TRUE;

        case DBT_CONFIGCHANGED:
            // Current configuration has changed.
            // Nothing to do.
            return TRUE;

        case DBT_DEVNODES_CHANGED:
            // Device node has changed.
            // Nothing to do.
            return TRUE;
#endif

        default:
            break;
    }
 
    // check to see if number of mixer devices in system changed
    uNewNumMixers = mixerGetNumDevs();
    if (!uNewNumMixers)
    {       
        MessageBox(hwnd, 
            "No mixer devices are present - MixTree will close", 
            "MixTree", 
            MB_ICONHAND);        

        PostMessage(hwnd, WM_CLOSE, 0L, 0L);        
    }
    else if (uNewNumMixers != uNumMixers)  
    {
        // there was a change to mixer devices and at least one is present
// rebuild menu    
        // check to see if the current mixer's ID changed    
        result = mixerGetID(hMixer, &uNewMixerID, MIXER_OBJECTF_HMIXER);
        if (result)
        {                                
// should check the error code, but probably it's an invalid hmixer
// if it were, we'd remove the existing treeview and autoselect mixer id 0, 
// and rebuild the treeview
// for now, just do this...      
            wsprintf((LPSTR)achMsg, (LPSTR)"Error #%d calling mixerGetID", result);
            MessageBox(hwnd, achMsg, "MixTree Error", MB_ICONHAND);  
        
             
        }
        else
            // just update the variable whether the ID changed or not
            uMixerID = uNewMixerID;      
    }
    // else no change to mixer devices, nothing to do
                 
    return TRUE;
}

#if 0
    // get the item number stored in the root item's lparam member
    _fmemset((LPBYTE)&tvi, 0, sizeof(TV_ITEM));
    tvi.hItem = htiCurrentRoot;
    tvi.mask = TVIF_PARAM;
    TreeView_GetItem(hwndTreeView, &tvi);

    // set the current item
    lCurrentItem = tvi.lParam;

    // select current item in the TreeView control with highlight
    TreeView_SelectDropTarget(hwndTreeView, htiCurrentRoot);

    // display the current item's info
    hdc = GetDC(hwnd);
    DisplayItemInfo(hwnd, hdc);
    ReleaseDC(hwnd, hdc);
#endif
  
