Windows drag & drop with win32com and IDropTarget

Greg K ranger2086 at gmail.com
Fri Jan 15 08:20:32 CET 2010


I'm trying to create a program that will process files dragged into
its window, however I can't seem to get the cursor to change correctly
when something is dragged over the window. I've created an object that
implements the IDropTarget interface, but it seems the value returned
by its DragEnter method is ignored by Windows. No matter what value it
returns, I always get a "create shortcut" cursor when something is
dragged over the window. I'm thinking maybe the value returned by the
Python object isn't getting mapped to the "ByRef" parameter correctly,
but I can't figure out how to fix it. Can anyone see what I'm doing
wrong? This is the code:

---
import winerror
import win32gui
import win32con
import pythoncom
from win32com.shell import shellcon
from win32com.server.policy import DesignatedWrapPolicy

def main():
    pythoncom.OleInitialize()
    hWnd = CreateWindow()
    pythoncom.RegisterDragDrop(
        hWnd,
        pythoncom.WrapObject(
            DropTarget( hWnd ),
            pythoncom.IID_IDropTarget,
            pythoncom.IID_IDropTarget
            )
        )
    win32gui.PumpMessages()

class DropTarget( DesignatedWrapPolicy ):
    _reg_clsid_ = "{8BFD2A1E-5F4B-4B0A-9246-52C5FDBB3B50}"
    _reg_progid_ = "Blah.Blah"
    _reg_desc_ = "Test"
    _public_methods_ = [ 'DragEnter', 'DragOver', 'DragLeave',
'Drop' ]
    _com_interfaces_ = [ pythoncom.IID_IDropTarget ]

    def __init__( self, hWnd ):
        self._wrap_( self )
        self.hWnd = hWnd

    def DragEnter( self, dataObject, keyState, point, effect ):
        return winerror.S_OK, shellcon.DROPEFFECT_COPY
        # return shellcon.DROPEFFECT_COPY # also doesn't work
    def DragOver( self, keyState, point, effect ):
        pass
    def DragLeave( self ):
        pass
    def Drop( self, dataObject, keyState, point, effect ):
        pass

def CreateWindow():

    def OnDestroy( hwnd, msg, wparam, lparam ):
        win32gui.PostQuitMessage( 0 )

    wc = win32gui.WNDCLASS()
    hinst = win32gui.GetModuleHandle( None )
    wc.lpszClassName = "BlahBlah"
    wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW
    wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW )
    wc.hbrBackground = win32con.COLOR_WINDOW
    wc.lpfnWndProc = {
        win32con.WM_DESTROY : OnDestroy
        }
    classAtom = win32gui.RegisterClass( wc )

    return win32gui.CreateWindow(
        classAtom,
        "Title",
        win32con.WS_VISIBLE | win32con.WS_OVERLAPPED |
win32con.WS_SYSMENU,
        200, 200, 200, 200,
        0, 0, hinst, None
        )

if __name__ == '__main__':
    main()
---

The DragEnter method is documented on MSDN as:

HRESULT DragEnter(
  [in]       IDataObject *pDataObj,
  [in]       DWORD grfKeyState,
  [in]       POINTL pt,
  [in, out]  DWORD *pdwEffect
);

The out value of pdwEffect should determine the cursor appearance.

Thanks,
Greg.



More information about the Python-list mailing list