7.3 Creating a Drop Handler

only for RuBoard - do not distribute or recompile

7.3 Creating a Drop Handler

We need to add a new class to the RadEx project that will implement IPersistFile and IDropTarget . Call the file clsDropHandler.cls . Its declarations section begins as follows :

 'clsDropHandler.cls Implements IDropTarget Implements IPersistFile 

7.3.1 Implementing IPersistFile

The only method that we need to implement on this interface is Load . The code is the same as the code we used to create the icon handler back in Chapter 5. Example 7.1 contains the implementation.

Example 7.1. IPersistFile::Load Implementation
 'clsDropHandler.cls Private m_sTargetFile As String Private Sub IPersistFile_Load(     ByVal pszFileName As VBShellLib.LPCOLESTR, _      ByVal dwMode As VBShellLib.DWORD)     m_sTargetFile = Space(255)     CopyMemory ByVal StrPtr(m_sTargetFile), _                 ByVal pszFileName, _                 Len(m_sTargetFile)      End Sub 

7.3.2 Implementing IDropTarget

The most interesting aspect of implementing the IDropTarget interface (and, in particular, its DragEnter method) concerns the POINTL parameter to the DragEnter method. Notice from our earlier presentation of the method's syntax that it is an [in] parameter; therefore, it is not a pointer. We have a slight problem here, because Visual Basic does not allow UDTs to be passed ByVal , which is what is going on here. POINTL is a structure that contains the location of the mouse in the drop area. It is defined like this:

 typedef struct _POINTL {      LONG x;      LONG y;  } POINTL; 

Fortunately, we do not need this point information, so there is a simple workaround. Instead of passing a point, we can use two Longs, which will occupy the same space on the stack as a POINTL structure. The final definition for DragEnter looks like this:

 HRESULT DragEnter (     [in] IDataObject *pDataObj,     [in] KEYSTATES grfKeyState,     [in] long x,     [in] long y,     [in, out] DROPEFFECT *pdwEffect ); 

DragOver and Drop will also use two Long values in place of POINTL .

7.3.2.1 DragEnter

With that said, let's get on to the actual implementation of IDropTarget . We only need to implement two methods ( DragEnter and Drop ) to satisfy our needs. Let's look at the DragEnter implementation, which is shown in Example 7.2, and then we'll discuss how it works.

Example 7.2. DragEnter Implementation
 Private m_dwDropKey As KEYSTATES Private m_dwMouseKey As KEYSTATES Private Sub IDropTarget_DragEnter(     ByVal pDataObj As VBShellLib.IDataObject, _      ByVal grfKeyState As VBShellLib.KEYSTATES, _      ByVal x As Long, _      ByVal y As Long, _      pdwEffect As VBShellLib.DROPEFFECT)          pdwEffect = DROPEFFECT_COPY          'Get keyboard state     'Does NOT take into account multiple keys being held down     If grfKeyState And MK_CONTROL Then         m_dwDropKey = MK_CONTROL     ElseIf grfKeyState And MK_SHIFT Then         m_dwDropKey = MK_SHIFT     ElseIf grfKeyState And MK_ALT Then         m_dwDropKey = MK_ALT     Else         m_dwDropKey = 0     End If          'Get mouse state     If grfKeyState And MK_LBUTTON Then         m_dwMouseKey = MK_LBUTTON     ElseIf grfKeyState And MK_RBUTTON Then         m_dwMouseKey = MK_RBUTTON     End If      End Sub 

The first parameter given to us by the shell is an IDataObject reference. Remember clsDropFiles? This is the class we used in Chapter 6, to implement IShellExtInit::Initialize . We could pass this IDataObject reference to an instance of clsDropFiles to get a list of all the source filenames for our Drop implementation. But we won't, because in this instance it would be a little slow. It would be called every time we enter the drop target, which is way too often. Instead, we'll wait until Drop is actually called to get a list of the source filenames. So, for now, we can ignore the pDataObj parameter. The parameters we are really interested in are pdwEffect and grfKeyState .

The pdwEffect parameter is set to one of the DROPEFFECT enumeration values and is used to visually indicate what the result of a drop operation would be. The shell conveys this by changing the cursor to one of the shapes shown in Figure 7.1. As the cursor moves over a drop target, the shell changes the cursor to visually show what type of drop operation is occurring. To cancel a drop operation, pdwEffect is set to DROPEFFECT_NONE .

Figure 7.1. DROPEFFECT operations
figs/vshl.0701.gif

The grfKeyState parameter contains keyboard- and mouse-state information.

Our implementation sets pdwEffect to DROPEFFECT_COPY regardless of the keys pressed. This will cause the cursor to change (as shown in Figure 7.1), giving us a visual cue that the files can be dropped. Keyboard and mouse states are stored in two separate private data members . These values will be used when we implement Drop .

7.3.2.2 Drop

Drop is where all the action takes place. This is the method that is called when a file is dropped on a drop target. Our implementation, which is shown in Example 7.3, is fairly straightforward. Let's take a look.

Example 7.3. Drop Implementation
 Private Sub IDropTarget_Drop(     ByVal pDataObj As VBShellLib.IDataObject, _      ByVal grfKeyState As VBShellLib.KEYSTATES, _      ByVal x As Long, _     ByVal y As Long, _      pdwEffect As VBShellLib.DROPEFFECT)          Dim i As Integer     Dim sMsg As String  Set m_clsDropFiles = New clsDropFiles     m_clsDropFiles.GetDropFiles pDataObj, ".rad"          If (m_clsDropFiles.Count = 0) Then         MsgBox "Only RAD files can be dropped here!", _              vbOKOnly, _              "RAD Drop Handler"         Exit Sub     End If  If m_dwMouseKey = MK_LBUTTON Then         sMsg = "MK_LBUTTON" & vbCrLf     End If          If m_dwMouseKey = MK_RBUTTON Then         sMsg = "MK_RBUTTON" & vbCrLf     End If          Select Case m_dwDropKey         Case MK_CONTROL             sMsg = sMsg & "Drop + CTRL"         Case MK_SHIFT             sMsg = sMsg & "Drop + SHIFT"         Case MK_ALT             sMsg = sMsg & "Drop + ALT"         Case Else             sMsg = sMsg & "Normal Drop"     End Select          sMsg = sMsg & vbCrLf & vbCrLf     sMsg = sMsg & "Drop File(s):" & vbCrLf          For i = 0 To m_clsDropFiles.Count - 1         sMsg = sMsg & m_clsDropFiles.Files(i) & vbCrLf     Next i          sMsg = sMsg & vbCrLf     sMsg = sMsg & "Target File: " & m_sTargetFile          MsgBox sMsg, vbOKOnly, "RAD Drop Handler"      End Sub 

The shell passes in a reference to IDataObject , which we in turn pass on to an instance of clsDropFiles (see Chapter 5). If our file count is at this point, we know that the files dropped were not .rad files, and we can display an error message. Otherwise, a list of the target files, the name of the drop file, and the keyboard and mouse states are displayed in a message box like the one shown in Figure 7.2.

Figure 7.2. Drop handler info
figs/vshl.0702.gif
only for RuBoard - do not distribute or recompile


Visual Basic Shell Programming
Visual Basic Shell Programming
ISBN: B00007FY99
EAN: N/A
Year: 2000
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net