[python-win32] Drag and drop of files (CF_HDROP)
mir amicitas
amicitas at gmail.com
Wed Sep 24 09:46:19 CEST 2008
>The last arg is output, and will be returned from the function.
>
In that case I am confused about the output coming out of DoDragDrop().
The output that I get for different cases:
drag canceled: 0
copy succeed: 1
move succeed: 0
I expect that move succeed would give me a value of 2
(shellcon.DROPEFFEC_MOVE).
With the output above I cannot tell weather a move succeded or the drop got
canceled.
This is not critical functionality for me (I don't need to know the end
result). At this point I am just curious.
Below I am including the dragging code that I put together, just in case it
is useful to anyone. (if anyone happens to notice something horribly wrong
with it let me know though.)
- Novi
-------------------------------------------
import pythoncom
import win32con
import winerror
import win32clipboard
from win32com.server.util import NewEnum, wrap
from win32com.server.exception import COMException
from win32com.shell import shellcon
num_do_objects = 0
def WrapCOMObject(ob, iid=None):
return wrap(ob, iid=iid, useDispatcher = 0)
def PackDROPFILESStructure(file_name_array):
import struct
"""
typedef struct _DROPFILES {
DWORD pFiles;
POINT pt;
BOOL fNC;
BOOL fWide; } DROPFILES, *LPDROPFILES;
"""
file_name_buffer='\0'.join(file_name_array)+'\0\0'
fmt="lllll%ss" %len(file_name_buffer)
dropfiles=struct.pack(fmt, 20, 0, 0, 0, 0, file_name_buffer)
return dropfiles
def RegisterClipboardFormats(qmimedata):
"""
Here we extract all of the formats from the qmimedata object and
register them. This will give us an ID for each type.
This will return a dictionary with the ID's and descriptions for
each mime type.
"""
mime_formats = qmimedata.formats()
format_dictionary = dict()
for format in mime_formats:
id = win32clipboard.RegisterClipboardFormat(str(format))
format_dictionary[id] = format
return format_dictionary
def GetClipboardFormats(qmimedata):
"""
What I want to do here is to check if any of the mime data
in the QMimeData object can/should be converted into a standard
windows clipboard format.
If it can I will extract the data here.
This essentially does what QWindowsMime probably does, but
since QWindowsMime is not in PyQt4 I have to do this myself.
"""
format_dictionary = dict()
if qmimedata.hasText():
id = win32con.CF_TEXT
data = str(qmimedata.text())
format_dictionary[id] = data
id = win32con.CF_UNICODETEXT
data = unicode(qmimedata.text())
format_dictionary[id] = data
if qmimedata.hasUrls():
files = []
for url in qmimedata.urls():
file_name = url.toLocalFile()
if file_name:
files.append(str(file_name))
if files:
id = win32con.CF_HDROP
format_dictionary[id] = files
return format_dictionary
class IDropSource:
_com_interfaces_ = [pythoncom.IID_IDropSource]
_public_methods_ = ["QueryContinueDrag", "GiveFeedback"]
def __init__(self):
pass
def __del__(self):
pass
def QueryContinueDrag(self, is_escape_pressed, modifier_key_state):
if is_escape_pressed == True:
return winerror.DRAGDROP_S_CANCEL
if (modifier_key_state & win32con.MK_LBUTTON) == False and \
(modifier_key_state & win32con.MK_RBUTTON) == False:
return winerror.DRAGDROP_S_DROP
return winerror.S_OK
def GiveFeedback(self, effect):
return winerror.DRAGDROP_S_USEDEFAULTCURSORS
class IDataObject:
_com_interfaces_ = [pythoncom.IID_IDataObject]
_public_methods_ = ["GetData", "GetDataHere", "QueryGetData" \
,"GetCanonicalFormatEtc", "SetData",
"EnumFormatEtc" \
,"DAdvise", "DUnadvise", "EnumDAdvise"]
def __init__(self, qmimedata):
global num_do_objects
num_do_objects += 1
self.qmimedata = qmimedata
self.mime_formats = RegisterClipboardFormats(qmimedata)
self.clipboard_formats = GetClipboardFormats(qmimedata)
self.supported_formatetc = []
for format in self.mime_formats:
formatetc = format, None, pythoncom.DVASPECT_CONTENT, -1,
pythoncom.TYMED_HGLOBAL
self.supported_formatetc.append(formatetc)
for format in self.clipboard_formats:
formatetc = format, None, pythoncom.DVASPECT_CONTENT, -1,
pythoncom.TYMED_HGLOBAL
self.supported_formatetc.append(formatetc)
def __del__(self):
global num_do_objects
num_do_objects -= 1
def _query_interface_(self, iid):
if iid==pythoncom.IID_IEnumFORMATETC:
return NewEnum(self.supported_formatetc, iid=iid)
def GetData(self, formatetc_in):
#print 'GetData'
ret_stg = None
cf_in, target_in, aspect_in, index_in, tymed_in = formatetc_in
# Loop through the supported formats.
# We do this as opposed to directly searching mime_formats &
clipboard_formats
# mostly just to make sure the order is consistant.
for formatetc in self.supported_formatetc:
cf, target, aspect, index, tymed = formatetc
if (aspect_in == aspect) and \
(tymed_in & tymed) and \
(cf_in == cf):
ret_stg = pythoncom.STGMEDIUM()
if self.mime_formats.has_key(cf):
data = self.qmimedata.data(self.mime_formats[cf])
ret_stg.set(tymed, data)
elif self.clipboard_formats.has_key(cf):
data = self.clipboard_formats[cf]
if cf == win32con.CF_TEXT or cf_in ==
win32con.CF_UNICODETEXT:
ret_stg.set(tymed, data)
elif cf == win32con.CF_HDROP:
dropfiles = PackDROPFILESStructure(data)
ret_stg.set(tymed, dropfiles)
else:
print "hystrixNtDrag.IDataObject.GetData:"
print " Programming Error: id should be supported
but isn't"
if ret_stg is None:
raise COMException(hresult=winerror.E_NOTIMPL)
return ret_stg
def GetDataHere(self, formatetc):
#print 'GetDataHere'
raise COMException(hresult=winerror.E_NOTIMPL)
def QueryGetData(self, formatetc_in):
#print 'QueryGetData'
cf_in, target_in, aspect_in, index_in, tymed_in = formatetc_in
for formatetc in self.supported_formatetc:
cf, target, aspect, index, tymed = formatetc
if (aspect_in & aspect) and \
(tymed_in & tymed) and \
(cf_in == cf):
return winerror.S_OK
raise COMException(hresult=winerror.DV_E_FORMATETC)
return winerror.DV_E_FORMATETC
def GetCanonicalFormatEtc(self, formatetc):
#print 'GetCanonicalFormatEtc'
RaiseCOMException(winerror.DATA_S_SAMEFORMATETC)
# return fe
def SetData(self, formatetc, medium, fRelease):
#print 'SetData'
raise COMException(hresult=winerror.E_NOTIMPL)
def EnumFormatEtc(self, direction):
#print 'EnumFormatEtc'
if direction != pythoncom.DATADIR_GET:
raise COMException(hresult=winerror.E_NOTIMPL)
return NewEnum(self.supported_formatetc,
iid=pythoncom.IID_IEnumFORMATETC)
def DAdvise(self, formatetc, flags, sink):
#print 'DAdvise'
raise COMException(hresult=winerror.E_NOTIMPL)
def DUnadvise(self, connection):
#print 'DUnadvise'
raise COMException(hresult=winerror.E_NOTIMPL)
def EnumDAdvise(self):
#print 'EnumDAdvise'
raise COMException(hresult=winerror.E_NOTIMPL)
def DoDragDrop(qmimedata, allow_copy=True, allow_move=False):
source = IDropSource()
source = WrapCOMObject(source, iid=pythoncom.IID_IDropSource)
data_object = IDataObject(qmimedata)
data_object = WrapCOMObject(data_object, iid=pythoncom.IID_IDataObject)
effect_mask = 0
if allow_copy:
effect_mask += shellcon.DROPEFFECT_COPY
if allow_move:
effect_mask += shellcon.DROPEFFECT_MOVE
value = pythoncom.DoDragDrop(data_object, source, effect_mask)
print value
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-win32/attachments/20080924/7cdd9535/attachment-0001.htm>
More information about the python-win32
mailing list