How to Drag and Drop onto a Directory List Box
PSS ID Number: Q114772
Article last modified on 05-15-1994

2.00 3.00

WINDOWS


---------------------------------------------------------------------
The information in this article applies to:

- Standard and Professional Editions of Microsoft Visual Basic for
  Windows, versions 2.0 and 3.0
---------------------------------------------------------------------

SUMMARY
=======

You can drag an item and drop it into a specific location on a directory
list box by using the SendMessage() function to calculate where to drop
the item.

Working with directory list boxes is different from working with standard
list boxes because directory list boxes contain pictures. For additional
information on how to drag and drop onto a list box, please see the
following article in the Microsoft Knowledge Base:

ARTICLE-ID: Q80187
TITLE     : How to Drop Item into Specified Location in VB List Box

MORE INFORMATION
================

There is no standard way to determine the exact position where you are
dropping an item onto a Visual Basic directory list box when you perform a
drag and drop operation. You must calculate the position by using the
SendMessage() function with the constants LB_GETITEMHEIGHT and
LB_GETTOPINDEX.

Use LB_GETITEMHEIGHT to determine the height of each row of a list box.
Then divide this by the Y value that is passed as an argument in the
File_DragDrop event procedure. In this way, you can determine the position
of the Drag.Icon relative to the list box -- that is, the number of lines
from the top of the list box.

Use LB_GETTOPINDEX to get the index of the first visible item in the list
box. Add these two numbers to get the index location for the insertion
point. This is the spot where you want to insert the item in the list box.

A directory list box adds another element to this equation because of its
hierarchical nature. Because of this, the first element in the list does
not have a ListIndex of 0. A ListIndex of 0 is the subdirectory the file
list box is displaying. The parent directories have negative ListIndex
values. Therefore, you need to keep track of how many subdirectories deep
you are nested, and then subtract this value from the sum of the topindex
and linecount calculation.

Step-by-Step Example
--------------------

1. Start a new project in Visual Basic. Form1 is created by default.

2. Add following declarations and subroutine to the general declarations
   section of the form:

   ' Enter the following Declare statement as one, single line:
   Declare Function SendMessage Lib "User" (ByVal hWnd%, ByVal wMsg%,
      ByVal wParam%, lParam As Any) As Long
   Const WM_USER = &H400
   Const LB_GETITEMHEIGHT = (WM_USER + 34) ' Used by SendMessage()
   Const LB_GETTOPINDEX = (WM_USER + 15)

   Dim DirectoryItemHeight As Long  ' To hold height of directory item
   Dim SubDirDeep As Integer        ' To hold number of subdirectories deep

   Sub CalcSubDir ()
      ' Look at each backslash in the Path property to decide how deep you
      ' are in the subdirectory structure.

      Dim i As Integer
      Dim position As Integer
      Dim found As Integer

      found = True
      position = 0
      SubDirDeep = 0

      Do
         position = InStr(position + 1, Dir2.Path, "\")     'Find backslash
         If position = Len(Dir2.Path) Or position = 0 Then  'At end?
            found = False
         End If
         SubDirDeep = SubDirDeep + 1       'Keep track of them
      Loop Until (found = False)

   End Sub

3. Add two frame controls (Frame1 and Frame2) to the form.

4. Draw a directory list box (Dir1 and Dir2) inside each frame.

5. Draw a file list box (File1) inside the first frame. Frame1 should now
   contain the directory list box Dir1 and the file list box File1, while
   the second frame, Frame2, contains just a directory list box Dir2.

6. Place the following code in the Load event of Form1:

   Sub Form_Load ()
      ' Set captions
      Me.Caption = "File Copy"
      Frame1.Caption = "Source"
      Frame2.Caption = "Destination"

      ' Use Windows API SendMessage function to get the height of an item
      ' in the directory listbox. There's no way to do this with Visual
      ' Basic code.
      DirectoryItemHeight=SendMessage(Dir2.hWnd, LB_GETITEMHEIGHT, 0&, 0&)
      DirectoryItemHeight=DirectoryItemHeight * screen.TwipsPerPixelY

      ' Find the nesting level of the subdirectories for default directory:
      Call CalcSubDir

      ' Load drag icon for the file list box. You may need to change the
      ' path if you installed Visual Basic in a different directory.
      Dir1.DragIcon = LoadPicture("C:\VB3\ICONS\DRAGDROP\DRAG1PG.ICO")

   End Sub

7. Add the following code to the MouseDown event for the file list box
   File1:

   Sub File1_MouseDown ()

      ' Begin dragging the control
      ' Dragging will terminate automatically.
      File1.Drag 1

   End Sub

8. Add the following code to the Change event for the source directory list
   box (Dir1):

   Sub Dir1_Change ()

      ' Update the file list box when you change directories in the source
      ' directory list box.
      File1.Path = Dir1.Path

   End Sub

9. Add the following code to the following event procedures for the
   destination directory list box (Dir2):

   Sub Dir2_Change ()
      Call CalcSubDir    'find how deep we are in subdirectories
   End Sub

   Sub Dir2_DragDrop ()
      Dim Sc$
      Dim dest$
      Dim msg as String
      Dim answer As Integer
      Dim IDYES As Integer

      IDYES = 6     ' ID for click of Yes in messagebox

      Sc$ = Source.Path & "\" & Source.FileName
      dest$ = Dir2.List(Dir2.ListIndex)

      msg = "Are you sure you want to copy: "
      msg = msg & Sc$ & Chr(13) & Chr(10) & Chr(13) & Chr(10)
      msg = msg & "To:" & Chr(9) & dest$

      answer = MsgBox(msg, 36)
      If answer = IDYES Then
         FileCopy Sc$, dest$
         MsgBox "Copied '" & Sc$ & "' to '" & dest$ & "'"
      End If
   End Sub

   Sub Dir2_DragOver ()
      Dim TopIndex As Long     ' Index value of first visible item in list.
      Dim Selection As Integer ' Hold destination dir selected by user.

      ' Determine which item I have dragged onto:
      TopIndex = SendMessage(Dir2.hWnd, LB_GETTOPINDEX, 0, ByVal 0&)
      Selection = Y \ DirectoryItemHeight

      Selection = Selection - SubDirDeep + TopIndex

      If Selection <= (Dir2.ListCount - 1) Then
         ' Highlight Selection:
         Dir2.ListIndex = Selection
      End If
   End Sub

9. Press the F5 key to run the program. When you drag a file from the
   source file list box over to the destination directory list box, the
   destination directory will be highlighted to tell you where you are
   copying the file.

Additional reference words: 2.00 3.00
KBCategory:
KBSubcategory: APrgWindow

=============================================================================

Copyright Microsoft Corporation 1994.
