Using Win32 functions in Visual FoxPro Image Gallery
Code examples:
WAV file player
Retrieving size of a remote file
Using WM_COPYDATA for interprocess communication (VFP9)
Setting the mouse capture to the specified window
Using MessageBeep
GDI+: sending image of FoxPro form to printer
How to display the port-configuration dialog box for a port on the specified server
How to upload a local file to FTP server using FtpPutFile
Locking the workstation
Quering a waveform-audio input device
Retrieving list of all active RAS connections
Retrieving Printer Device Context using PrintDlg function
Setting the volume label
Using the SystemParametersInfo function
HOWTO: Use the Win32 API to Access File Dates and Times
Semi-transparent Form
Enumerating Volumes and Volume Mounting Points (NTFS)
The original LoadPicture() function in VFP returns valid handles to bitmaps, icons, cursors, and metafiles
Converting an HTTP time/date string to a SYSTEMTIME structure
How to create transparent areas inside a form -- punching holes in the form
Setting the date and time that a file was created
Displaying OS Memory Status
GDI+: saving image of FoxPro form to graphics file (BMP, GIF, JPG, PNG, TIF)
How to browse and connect to printers on a network (WinNT)
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: 72  
    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 (54.224.79.93)
    4 sec.Function: 'WTSRegisterSessionNotification'
    1 day(s)Function: 'CreateFont'
     Function: 'GetThreadDesktop'
    Function group: 'Window Station and Desktop'
     Function: 'CoCreateGuid'
     Example: 'How to block the PrintScreen key'
     Example: 'Reading the structure of VFP main menu'
     Function: 'SHRegEnumUSKey'
     Function: 'InternetCloseHandle'
    Function group: 'Internet Functions (WinInet)'
    2 day(s)Function: 'waveOutGetVolume'
     Function: 'AVIStreamGetFrameClose'
    Google
    Advertise here!