📄 droptgt.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// Name: src/msw/ole/droptgt.cpp
// Purpose: wxDropTarget implementation
// Author: Vadim Zeitlin
// Modified by:
// Created:
// RCS-ID: $Id: droptgt.cpp,v 1.45 2006/04/26 08:21:09 ABX Exp $
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// Declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#if wxUSE_OLE && wxUSE_DRAG_AND_DROP
#ifndef WX_PRECOMP
#include "wx/log.h"
#endif
#include "wx/msw/private.h"
#ifdef __WXWINCE__
#include <winreg.h>
#include <ole2.h>
#endif
#ifdef __WIN32__
#if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
#if wxCHECK_W32API_VERSION( 1, 0 )
#include "wx/msw/wrapwin.h"
#endif
#include <shlobj.h> // for DROPFILES structure
#endif
#else
#include <shellapi.h>
#endif
#include "wx/dnd.h"
#include "wx/msw/ole/oleutils.h"
// ----------------------------------------------------------------------------
// IDropTarget interface: forward all interesting things to wxDropTarget
// (the name is unfortunate, but wx_I_DropTarget is not at all the same thing
// as wxDropTarget which is 'public' class, while this one is private)
// ----------------------------------------------------------------------------
class wxIDropTarget : public IDropTarget
{
public:
wxIDropTarget(wxDropTarget *p);
virtual ~wxIDropTarget();
// accessors for wxDropTarget
void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
// IDropTarget methods
STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD);
STDMETHODIMP DragLeave();
STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
DECLARE_IUNKNOWN_METHODS;
protected:
IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
wxDropTarget *m_pTarget; // the real target (we're just a proxy)
HWND m_hwnd; // window we're associated with
// get default drop effect for given keyboard flags
static inline DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction);
DECLARE_NO_COPY_CLASS(wxIDropTarget)
};
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
static DWORD ConvertDragResultToEffect(wxDragResult result);
// ============================================================================
// wxIDropTarget implementation
// ============================================================================
// Name : static wxIDropTarget::GetDropEffect
// Purpose : determine the drop operation from keyboard/mouse state.
// Returns : DWORD combined from DROPEFFECT_xxx constants
// Params : [in] DWORD flags kbd & mouse flags as passed to
// IDropTarget methods
// Notes : We do "move" normally and "copy" if <Ctrl> is pressed,
// which is the standard behaviour (currently there is no
// way to redefine it)
DWORD wxIDropTarget::GetDropEffect(DWORD flags, wxDragResult defaultAction)
{
if (defaultAction == wxDragCopy)
return flags & MK_SHIFT ? DROPEFFECT_MOVE : DROPEFFECT_COPY;
return flags & MK_CONTROL ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
}
wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
{
m_pTarget = pTarget;
m_pIDataObject = NULL;
}
wxIDropTarget::~wxIDropTarget()
{
}
BEGIN_IID_TABLE(wxIDropTarget)
ADD_IID(Unknown)
ADD_IID(DropTarget)
END_IID_TABLE;
IMPLEMENT_IUNKNOWN_METHODS(wxIDropTarget)
// Name : wxIDropTarget::DragEnter
// Purpose : Called when the mouse enters the window (dragging something)
// Returns : S_OK
// Params : [in] IDataObject *pIDataSource : source data
// [in] DWORD grfKeyState : kbd & mouse state
// [in] POINTL pt : mouse coordinates
// [out]DWORD *pdwEffect : effect flag
// Notes :
STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
DWORD grfKeyState,
POINTL pt,
DWORD *pdwEffect)
{
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
wxASSERT_MSG( m_pIDataObject == NULL,
_T("drop target must have data object") );
// show the list of formats supported by the source data object for the
// debugging purposes, this is quite useful sometimes - please don't remove
#if 0
IEnumFORMATETC *penumFmt;
if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
{
FORMATETC fmt;
while ( penumFmt->Next(1, &fmt, NULL) == S_OK )
{
wxLogDebug(_T("Drop source supports format %s"),
wxDataObject::GetFormatName(fmt.cfFormat));
}
penumFmt->Release();
}
else
{
wxLogLastError(_T("IDataObject::EnumFormatEtc"));
}
#endif // 0
if ( !m_pTarget->IsAcceptedData(pIDataSource) ) {
// we don't accept this kind of data
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
// get hold of the data object
m_pIDataObject = pIDataSource;
m_pIDataObject->AddRef();
// we need client coordinates to pass to wxWin functions
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
{
wxLogLastError(wxT("ScreenToClient"));
}
// give some visual feedback
*pdwEffect = ConvertDragResultToEffect(
m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult(
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()))
)
);
return S_OK;
}
// Name : wxIDropTarget::DragOver
// Purpose : Indicates that the mouse was moved inside the window represented
// by this drop target.
// Returns : S_OK
// Params : [in] DWORD grfKeyState kbd & mouse state
// [in] POINTL pt mouse coordinates
// [out]LPDWORD pdwEffect effect flag
// Notes : We're called on every WM_MOUSEMOVE, so this function should be
// very efficient.
STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
POINTL pt,
LPDWORD pdwEffect)
{
// there are too many of them... wxLogDebug("IDropTarget::DragOver");
wxDragResult result;
if ( m_pIDataObject ) {
result = ConvertDragEffectToResult(
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()));
}
else {
// can't accept data anyhow normally
result = wxDragNone;
}
// we need client coordinates to pass to wxWin functions
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
{
wxLogLastError(wxT("ScreenToClient"));
}
*pdwEffect = ConvertDragResultToEffect(
m_pTarget->OnDragOver(pt.x, pt.y, result)
);
return S_OK;
}
// Name : wxIDropTarget::DragLeave
// Purpose : Informs the drop target that the operation has left its window.
// Returns : S_OK
// Notes : good place to do any clean-up
STDMETHODIMP wxIDropTarget::DragLeave()
{
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave"));
// remove the UI feedback
m_pTarget->OnLeave();
// release the held object
RELEASE_AND_NULL(m_pIDataObject);
return S_OK;
}
// Name : wxIDropTarget::Drop
// Purpose : Instructs the drop target to paste data that was just now
// dropped on it.
// Returns : S_OK
// Params : [in] IDataObject *pIDataSource the data to paste
// [in] DWORD grfKeyState kbd & mouse state
// [in] POINTL pt where the drop occurred?
// [ouy]DWORD *pdwEffect operation effect
// Notes :
STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
DWORD grfKeyState,
POINTL pt,
DWORD *pdwEffect)
{
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop"));
// TODO I don't know why there is this parameter, but so far I assume
// that it's the same we've already got in DragEnter
wxASSERT( m_pIDataObject == pIDataSource );
// by default, nothing happens
*pdwEffect = DROPEFFECT_NONE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -