Using Win32 functions in Visual FoxPro Image Gallery
Code examples:
The SQLGetProp() creates a bridge between Visual FoxPro and the ODBC API
Windows Shell Icons displayed and exported to ICO files (Vista)
Creating the Save dialog box to specify the drive, directory, and name of a file to save
How to find the application associated with a file name
Programmatically removing submenus from VFP main menu
Retrieving the name of the network resource associated with a local device
Reading header information from AVI file
Enumerating ports that are available for printing on a specified server
Enumerating print processors and supporting data types installed on the specified server
Initiating Inet connection using a modem
Monitoring changes occurring within a directory
Retrieving the interface–to–IP address mapping table
Smart Card Database Query Functions
Displaying dimmed window behind VFP top-level form
Enumerating printer drivers installed
How to copy the image of a form to the Clipboard using Bitmap API functions
How to enumerate, add and delete shares on the local computer (WinNT/XP)
Quering a waveform-audio input device
Converting characters in a URL into corresponding escape sequences and backwards
CryptoAPI: Collection of Providers class
GDI+: Drawing a Pie Chart
How to register custom Event Log source
How to retrieve adapter information for the local computer (including MAC address)
Semi-transparent Form
Displaying Windows shell folders in TreeView control with Visual FoxPro FLL

User rating: 0/10 (0 votes)
Rate this code sample:
  • ~
More code examples    Listed functions    Add comment     W32 Constants      Translate this page Printer friendly version of this code sample
Before you begin:
TreeViewExtender.FLL is a dynamic-link library compiled in Visual FoxPro FLL format.

Combined with this library, a regular TreeView ActiveX control displays shell folders in attractive and convenient way. It can also automatically reflect folder changes happening on the host computer (VFP9).

Features:

  • a regular TreeView control is used (MSComctlLib.TreeCtrl)
  • FLL can monitor folder changes in multiple roots
  • VFP9 forms can receive folder change notifications via window messages (VFP9)
  • older VFP versions can poll recent folder changes using Timer control
  • folders are depicted using appropriate system images (no extra graphics required)
  • the tree displays compressed (zipped) folders (Vista)
  • no API declarations in VFP code, the complexity moved inside the FLL
  • the FLL has small footprint -- about 40 KB
  • Minimal client: Windows XP, VFP8 (7?)

  •  
    PUBLIC oForm As Explorer
    oForm = CREATEOBJECT("Explorer")
    oForm.Visible=.T.
    * end of main
     
    DEFINE CLASS Explorer As Form
        Width=480
        Height=500
        AutoCenter=.T.
        Caption="Folders"
        Backcolor=RGB(255,255,255)
        ShowWindow=2
     
        ADD OBJECT tree As ExplorerTree WITH;
        Left=20, Top=10, Width=440, Height=440,;
        StartPath="c:\"
     
    ENDDEFINE
     
    DEFINE CLASS ExplorerTree As OleControl
        OleClass="MSComctlLib.TreeCtrl"
     
        oRoot=NULL && root node
        StartPath=""
        hWindow=0
     
        DirectoryWatch_Msg=0
        DirectoryWatch_Id=0
     
        * only top level of subfolders to be scanned
        FolderEnum_MaxEnumLevel=0
     
        * the FLL populates all following properties
        * for each subfolder found
        FolderEnum_StartPath=""
        FolderEnum_Status=0
        FolderList_Status=0
        FolderEnum_FolderCount=0
        FolderEnum_PathValid=.F.
     
        FolderList_FolderIndex=0
        FolderList_Foldername=""
        FolderList_HasSubfolders=.F.
        FolderList_FolderPath=""
        FolderList_ParentPath=""
        FolderList_FolderLevel=0
        FolderList_FolderSFGAOAttributes=0
        FolderList_FolderAttributes=0
        FolderList_TypeName=""
     
    PROCEDURE Init
        SET LIBRARY TO TreeViewExtender.fll ADDITIVE
     
        WITH THIS
            .HideSelection=.F.
            .PathSeparator="\"
            .Style=3
            .LineStyle=1
            .LabelEdit=1
            .Indentation=16
            .BorderStyle=0
            .Appearance=0
            .Sorted=.T.
     
            .hWindow = ThisForm.HWnd
     
            * Windows Message ID to be sent to
            * the window defined by THIS.hWindow
            .DirectoryWatch_Msg =;
                TVX_GetNotificationMessageId()
     
            IF VERSION(5) >= 900  && VFP9+
                .Anchor=15
     
                BINDEVENT( .hWindow, .DirectoryWatch_Msg,;
                    THIS, "WinProc" )
            ENDIF
     
            * links TreeView control 
            * to the system image list
            TVX_SetImageList( .hwnd )
     
            .RefreshTree
        ENDWITH
     
    PROCEDURE Destroy
        WITH THIS
            TVX_UnregisterDirectoryWatch(;
                .hWindow, .DirectoryWatch_Id )
        ENDWITH
     
    PROCEDURE RefreshTree
        IF NOT EMPTY( THIS.StartPath )
            THIS.StartPath = THIS.StartPath
        ENDIF
     
    PROCEDURE StartPath_ASSIGN( cPath As String )
        WITH THIS
            .StartPath = m.cPath
     
            .Nodes.Clear
            .oRoot = .Nodes.Add(,,;
                UPPER(ALLTRIM(.StartPath)),;
                "Scanning "+.StartPath+"..." )
     
            nResult = TVX_ListFolders( .StartPath, THIS )
     
            .oRoot.Key = UPPER(ALLTRIM(.FolderEnum_StartPath))
            .oRoot.Text = .FolderEnum_StartPath
            .oRoot.Sorted = .T.
            .oRoot.Selected = .T.
     
            .RegisterDirectoryWatch
        ENDWITH
     
    PROCEDURE RegisterDirectoryWatch
        WITH THIS
            TVX_UnregisterDirectoryWatch(;
                .hWindow, .DirectoryWatch_Id )
     
            IF .FolderEnum_PathValid
     
            .DirectoryWatch_Id =;
                    TVX_RegisterDirectoryWatch(;
                    .FolderEnum_StartPath, .hWindow )
            ENDIF
        ENDWITH
     
    PROCEDURE WinProc(hWindow as Integer, nMsgID as Integer,;
        wParam as Integer, lParam as Integer)
    * ignored for VFP versions before VFP9
     
        * this message notifies about changes in folders
        IF nMsgID = THIS.DirectoryWatch_Msg;
            AND m.wParam = THIS.DirectoryWatch_Id
     
            THIS.GetDirectoryChanges
        ENDIF
    RETURN 0
     
    PROCEDURE GetDirectoryChanges
        LOCAL cBuffer
     
        IF NOT USED("csChanges")
        * the cursor is for demo purpose only
            CREATE CURSOR csChanges ( dirchangedata M )
        ENDIF
     
        DO WHILE .T.
        * pulling latest changes while supply lasts
            cBuffer = TVX_GetDirectoryChanges(;
                THIS.hWindow, THIS.DirectoryWatch_Id )
     
            IF EMPTY(m.cBuffer)
                EXIT
            ELSE
                INSERT INTO csChanges (dirchangedata);
                VALUES (m.cBuffer )
     
                THIS.RescanTree( m.cBuffer )
            ENDIF
        ENDDO
     
    PROCEDURE RescanTree( cBuffer )
     
        LOCAL nActionCount, nActionIndex, cAction,;
            cPath, cParentPath, cNewPath, oNode
     
        cNewPath=""
        nActionCount = ALINES( arrActions,;
            m.cBuffer, CHR(13)+CHR(10) )
     
        * scans changes from newest to oldest
        FOR nActionIndex=nActionCount TO 1 STEP -1
            cAction = SUBSTR(arrActions[nActionIndex], 1, 1)
     
            cPath = SUBSTR(arrActions[nActionIndex], 2)
            cPath = STRTRAN(m.cPath, "\\", "\") && a bug to be pinned
            cParentPath = JUSTPATH( m.cPath )
     
            DO CASE
            CASE INLIST( m.cAction, "1", "3" )
            * new folder detected
            * rescanning the parent path
                oNode = THIS.GetNodeByKey( m.cParentPath )
     
                IF NOT ISNULL(m.oNode)
                    TVX_ListFolders( m.cParentPath, THIS )
                ENDIF
     
            CASE m.cAction="2"
            * a folder has been deleted
            * deleting existing node
                oNode = THIS.GetNodeByKey( m.cPath )
                IF NOT ISNULL(m.oNode)
                    THIS.Nodes.Remove( oNode.Key )
                ENDIF
     
            CASE m.cAction="4"
            * a folder has been renamed - storing old name
            * changing Name and Key of existing node
                oNode = THIS.GetNodeByKey( m.cPath )
                IF NOT ISNULL(m.oNode)
                    oNode.Text = JUSTFNAME(m.cNewPath)
                    oNode.Key = UPPER(ALLTRIM(m.cNewPath))
                    THIS.RemoveChildren( oNode )                
                    TVX_ListFolders( m.cNewPath, THIS )
                ENDIF
                cNewPath=""
     
            CASE m.cAction="5"
            * a folder has been renamed - storing new name
                cNewPath = m.cPath
     
            ENDCASE
        NEXT
     
    PROCEDURE Expand( oNode )
        IF NOT oNode.Checked
            RETURN
        ENDIF
        THIS.RescanNode( m.oNode )
     
    PROCEDURE RescanNode( oNode )
        THIS.RemovePlaceholderNode( oNode )
     
        TVX_ListFolders( oNode.Key, THIS )
     
        IF NOT THIS.FolderEnum_PathValid
            THIS.Nodes.Remove( m.oNode.Key )
        ELSE
            oNode.Selected=.T.
        ENDIF
     
    PROCEDURE FolderEnum_Status_ASSIGN( nNewStatus As Number )
        WITH THIS
            .FolderEnum_Status = m.nNewStatus
            DO CASE
            CASE .FolderEnum_Status = 1
            * FLL begins enumerating folder.
            * Do not clear TreeView nodes here, because 
            * an enumeration may start on expanding a node,
            * not just on populating the whole tree
            CASE .FolderEnum_Status = 2
            * FLL has finished enumerating folders
            CASE .FolderEnum_Status = 5
            * FLL begins sending folderes data to the control
            CASE .FolderEnum_Status = 6
            * FLL has finished sending floders data to the control
            ENDCASE
        ENDWITH
     
    PROCEDURE FolderList_Status_ASSIGN( nNewStatus As Number )
        WITH THIS
            .FolderList_Status = m.nNewStatus
            DO CASE
            CASE .FolderList_Status = 1
            * FLL begins sending data for next folder
            CASE .FolderList_Status = 2
            * FLL has finished sending data for a folder
                .AddFolder
            ENDCASE
        ENDWITH
     
    PROCEDURE RemoveChildren( oNode )
        DO WHILE oNode.Children > 0
            THIS.Nodes.Remove( oNode.Child.Key )
        ENDDO
     
    FUNCTION GetNodeByKey( cKey As String )
        LOCAL oNode
        TRY
            oNode = THIS.Nodes( UPPER(ALLTRIM(m.cKey)) )
        CATCH
            oNode=NULL
        ENDTRY
    RETURN m.oNode
     
    FUNCTION NodeExists( cKey As String )
    RETURN VARTYPE( THIS.GetNodeByKey(m.cKey) ) = "O"
     
    PROCEDURE GetParentNode( cKey As String )
        LOCAL oNode
     
        IF EMPTY(m.cKey)
            oNode = NULL
        ELSE
            TRY
                oNode=THIS.Nodes( UPPER(ALLTRIM(m.cKey)) )
            CATCH
                oNode=NULL
            ENDTRY
        ENDIF
    RETURN m.oNode
     
    PROCEDURE AddPlaceholderNode( oNode )
        LOCAL cKey, oPlaceholder
        cKey = oNode.Key + "\.."
        IF NOT THIS.NodeExists(m.cKey)
            oPlaceholder = .Nodes.Add( oNode, 4, m.cKey, ".." )
            DOEVENTS
        ENDIF
        oNode.Checked=.T.
     
    PROCEDURE RemovePlaceholderNode( oNode )
        LOCAL cKey
        cKey = oNode.Key + "\.."
        IF THIS.NodeExists(m.cKey)
            THIS.Nodes.Remove( m.cKey )
        ENDIF
        oNode.Checked=.F.
     
    PROCEDURE AddFolder
        LOCAL oParentNode, oNode, ex As Exception
     
        WITH THIS
            oNode = .GetNodeByKey( .FolderList_FolderPath )
            IF VARTYPE(m.oNode)="O"
                oNode.Text = .FolderList_Foldername
                RETURN
            ENDIF
     
            oParentNode = .GetParentNode( .FolderList_ParentPath )
            IF ISNULL(oParentNode)
                oParentNode = THIS.oRoot
            ELSE
            .RemovePlaceholderNode( oParentNode )
            ENDIF
     
            TRY
                oNode = .Nodes.Add( oParentNode, 4,;
                    UPPER(ALLTRIM(.FolderList_FolderPath)),;
                    .FolderList_Foldername )
     
                IF .FolderList_HasSubfolders
                    .AddPlaceholderNode( oNode )
                ENDIF
     
                oNode.Sorted=.T.
                oNode.Selected=.T.
     
            CATCH TO ex
            * subfolders in ZIP files
            * the routine is to be completed
                ACTIVATE SCREEN
                ? ex.Message
                ? THIS.FolderList_FolderPath
            ENDTRY
        ENDWITH
     
    ENDDEFINE
     

    User rating: 0/10 (0 votes)
    Rate this code sample:
    • ~
    7905 bytes  
    Created: 2011-01-26 17:41:47  
    Modified: 2011-01-31 23:45:11  
    Visits in 7 days: 100  
    Listed functions:
    Printer friendly API declarations
    My comment:
    Note: this is an alpha version of the library. More testing and cleaning to be done. The interface may eventually change.


    Library functions:

    FUNCTION TVX_ListFolders ( cStartPath As String,
                    oVFPObject As Object ) As Number


    For a given path, enumerates subfolders and sends the data to a TreeView control (2nd parameter). The target control should have a configured set of properties.

    For each subfolder found within the start path, the FLL populates certain properties of TreeView control. VFP application uses these properties when adds tree nodes.


    FUNCTION TVX_GetNotificationMessageId () As Number

    Returns window message Id assigned to notify VFP application about folder changes. Do not replace the call with a constant value. This message id can vary through different computers (see RegisterWindowMessage API).


    FUNCTION TVX_RegisterDirectoryWatch ( cStartPath As String,
                    nHWnd As Number ) As Number


    The nHWnd must belong to a VFP form. The function returns the MonitorId to be used in subsequent calls to other library functions.

    Upon this call, the FLL starts monitoring specified path, subfolders included, for any folder-related changes. Notifications of such changes are periodically sent to the form through a window message. In VFP9 the messages can be picked up with BINDEVENT() function. The WParam contains MonitorId value. The LParam contains the number of folder change records waiting.

    This function can be called multiple times for the same nHWnd, each time with different start path; as well as multiple times for the same start path, each time with different HWnd.


    FUNCTION TVX_GetDirectoryChanges ( nHWnd As Number,
                    MonitorId As Number ) As String


    For given HWnd and MonitorId, returns a text buffer containing formatted list of recent folder changes happened within the monitored path. This function should be called in a cycle, until it returns an empty string. VFP application should interpret the folder changes: add, delete and modify TreeView nodes accordingly.

    In VFP9 application, this function should be called upon receiving the notification message. While VFP8 application cannot capture window messages natively, it still can obtain folder changes through calling the TVX_GetDirectoryChanges() periodically.


    PROCEDURE TVX_UnregisterDirectoryWatch ( nHWnd As Number,
                    nDirectoryWatchId As Number )


    For given HWnd and MonitorId, closes folder changes monitor.


    PROCEDURE TVX_SetImageList ( nHWnd As Number )

    Links TreeView ActiveX control, specified by its HWnd, to the system image list, enabling system images in tree nodes.
    Word Index links for this example:
    Translate this page:
      Spanish    Portuguese    German    French    Italian  
    FreeTranslation.com offers instant, free translations of text or web pages.
    User Contributed Notes:
    There are no notes on this subject.


    Copyright © 2001-2013 News2News, Inc. Before reproducing or distributing any data from this site please ask for an approval from its owner. Unless otherwise specified, this page is for your personal and non-commercial use. The information on this page is presented AS IS, meaning that you may use it at your own risk. Microsoft Visual FoxPro and Windows are trade marks of Microsoft Corp. All other trademarks are the property of their respective owners. 

    Privacy policy
    Credits: PHP (4.4.9), an HTML-embedded scripting language, MySQL (5.1.55-log), the Open Source standard SQL database, AceHTML Freeware Version 4, freeware HTML Editor of choice.   Hosted by Korax Online Inc.
    Last Topics Visited (23.22.76.170)
    4 sec.Example: 'Uploading file to the FTP server using InternetWriteFile'
    5.44 hrs.Example: 'How to empty the Recycle Bin'
     Example: 'Quering waveform-audio output devices'
    9.94 hrs.Example: 'Saving available locale records into a cursor'
    9.95 hrs.Example: 'Enumerating network resources'
    10.87 hrs.Function: 'GetAncestor'
    Function group: 'Window'
    10.88 hrs.Function: 'WTSEnumerateServers'
    11.45 hrs.Example: 'Accessing Adobe Reader 7.0 main menu from VFP application'
    13.98 hrs.Example: 'How to make a VFP form fading out when released (GDI+ version)'
    22.43 hrs.Function: 'UnregisterHotKey'
    Function group: 'Keyboard Input'
    Google
    Advertise here!