C++ Explorer不';进行拖放操作时,不要释放IDataObject
我正在我的应用程序中实现拖放。Windows资源管理器在拖放操作后未释放IDataObject时出现问题。为了解决这个问题,我实现了一个非常简单的拖放源代码,它应该在大多数Win32编译器中编译。数据对象不包含任何数据;正如你所见,一切都很简单。数据对象包含可使用DebugView查看的跟踪,以指示创建和销毁数据对象的时间 复制:C++ Explorer不';进行拖放操作时,不要释放IDataObject,c++,windows,winapi,com,drag-and-drop,C++,Windows,Winapi,Com,Drag And Drop,我正在我的应用程序中实现拖放。Windows资源管理器在拖放操作后未释放IDataObject时出现问题。为了解决这个问题,我实现了一个非常简单的拖放源代码,它应该在大多数Win32编译器中编译。数据对象不包含任何数据;正如你所见,一切都很简单。数据对象包含可使用DebugView查看的跟踪,以指示创建和销毁数据对象的时间 复制: 按住鼠标按钮开始拖动 将对象拖放到打开的Windows资源管理器窗口中 在调试视图中观察输出;样本输出: [4964] gdo ctor [4964] gds cto
[4964] gdo ctor
[4964] gds ctor
[4964] gds dtor
此输出表示数据源已被破坏,但仍有人持有对我的IDataObject的引用gdo dtor
,这表明对IDataObject的最终引用已发布class GenericDataObject : public IDataObject
{
public:
// basic IUnknown implementation
ULONG __stdcall AddRef() { return InterlockedIncrement(&refcount); }
ULONG __stdcall Release() {
ULONG nRefCount = InterlockedDecrement(&refcount);
if (nRefCount == 0) delete this;
return nRefCount;
}
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) {
if (!ppvObject) return E_POINTER;
if (riid == IID_IUnknown) {
*ppvObject = static_cast<IUnknown*>(this);
AddRef();
return S_OK;
} else if (riid == IID_IDataObject) {
*ppvObject = static_cast<IDataObject*>(this);
AddRef();
return S_OK;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
}
// IDataObject members
STDMETHODIMP GetData (FORMATETC *pformatetcIn, STGMEDIUM *pmedium) { return DV_E_FORMATETC; }
STDMETHODIMP GetDataHere (FORMATETC *pformatetc, STGMEDIUM *pmedium) { return E_NOTIMPL; }
STDMETHODIMP QueryGetData (FORMATETC *pformatetc) { return DV_E_FORMATETC; }
STDMETHODIMP GetCanonicalFormatEtc (FORMATETC *pformatectIn, FORMATETC *pformatetcOut) { return DV_E_FORMATETC; }
STDMETHODIMP SetData (FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease) { return E_NOTIMPL; }
STDMETHODIMP EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) { return E_NOTIMPL; }
STDMETHODIMP DAdvise (FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) { return OLE_E_ADVISENOTSUPPORTED; }
STDMETHODIMP DUnadvise (DWORD dwConnection) { return OLE_E_ADVISENOTSUPPORTED; }
STDMETHODIMP EnumDAdvise (IEnumSTATDATA **ppenumAdvise) { return OLE_E_ADVISENOTSUPPORTED; }
public:
GenericDataObject() : refcount(1) {OutputDebugString("gdo ctor");}
~GenericDataObject() {OutputDebugString("gdo dtor");}
private:
LONG refcount;
};
class GenericDropSource : public IDropSource
{
public:
// basic IUnknown implementation
ULONG __stdcall AddRef() { return InterlockedIncrement(&refcount); }
ULONG __stdcall Release() {
ULONG nRefCount = InterlockedDecrement(&refcount);
if (nRefCount == 0) delete this;
return nRefCount;
}
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) {
if (!ppvObject) return E_POINTER;
if (riid == IID_IUnknown) {
*ppvObject = static_cast<IUnknown*>(this);
AddRef();
return S_OK;
} else if (riid == IID_IDropSource) {
*ppvObject = static_cast<IDropSource*>(this);
AddRef();
return S_OK;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
}
// IDropSource members
STDMETHODIMP QueryContinueDrag (BOOL fEscapePressed, DWORD grfKeyState) {
if (fEscapePressed) {
return DRAGDROP_S_CANCEL;
}
if (!(grfKeyState & (MK_LBUTTON | MK_RBUTTON))) {
return DRAGDROP_S_DROP;
}
return S_OK;
}
STDMETHODIMP GiveFeedback (DWORD dwEffect) { return DRAGDROP_S_USEDEFAULTCURSORS; }
public:
GenericDropSource() : refcount(1) {OutputDebugString("gds ctor");}
~GenericDropSource() {OutputDebugString("gds dtor");}
private:
LONG refcount;
};
// This is the C++ Builder-specific part; all I did was add a label to the default form
// and tie this event to it.
void __fastcall TForm1::Label1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
OleInitialize(NULL);
GenericDataObject *o = new GenericDataObject;
GenericDropSource *s = new GenericDropSource;
DWORD effect = 0;
DoDragDrop(o, s, DROPEFFECT_COPY, &effect);
o->Release();
s->Release();
}
class GenericDataObject:公共IDataObject
{
公众:
//基本IUnknown实现
ULONG u stdcall AddRef(){return InterlockedIncrement(&refcount);}
ULONG uu stdcall发布(){
ULONG nRefCount=联锁减量(&refcount);
如果(nRefCount==0)删除此项;
返回nRefCount;
}
STDMETHODIMP查询接口(refid-riid,void**ppvObject){
如果(!ppvObject)返回E_指针;
如果(riid==IID_IUnknown){
*ppvObject=静态投影(此);
AddRef();
返回S_OK;
}else if(riid==IID_IDataObject){
*ppvObject=静态投影(此);
AddRef();
返回S_OK;
}否则{
*ppvObject=NULL;
返回E_NOINTERFACE;
}
}
//IDataObject成员
STDMETHODIMP GetData(FORMATETC*pformatetcIn,STGMEDIUM*pmedium){return DV_E_FORMATETC;}
STDMETHODIMP GetDataHere(FORMATETC*pformatetc,STGMEDIUM*pmedium){返回E_NOTIMPL;}
STDMETHODIMP QueryGetData(FORMATETC*pformatetc){return DV_E_FORMATETC;}
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC*pformatectIn,FORMATETC*pformatetcOut){return DV_E_FORMATETC;}
STDMETHODIMP SetData(FORMATETC*pformatetc、STGMEDIUM*pmedium、BOOL fRelease){return E_NOTIMPL;}
STDMETHODIMP EnumFormatEtc(DWORD dwDirection、IEnumFORMATETC**ppenumFormatEtc){return E_NOTIMPL;}
STDMETHODIMP-DAdvise(FORMATETC*pformatetc、DWORD advf、IAdviseSink*pAdvSink、DWORD*pdwConnection){返回OLE_E_advisionnotsupported;}
STDMETHODIMP DUnadvise(DWORD dwConnection){return OLE_E_advisionnotsupported;}
STDMETHODIMP enumdavise(IEnumSTATDATA**ppenumAdvise){返回OLE_E_advisionnotsupported;}
公众:
GenericDataObject():refcount(1){OutputDebugString(“gdo ctor”);}
~GenericDataObject(){OutputDebugString(“gdo dtor”);}
私人:
长参考计数;
};
类GenericDropSource:公共IDropSource
{
公众:
//基本IUnknown实现
ULONG u stdcall AddRef(){return InterlockedIncrement(&refcount);}
ULONG uu stdcall发布(){
ULONG nRefCount=联锁减量(&refcount);
如果(nRefCount==0)删除此项;
返回nRefCount;
}
STDMETHODIMP查询接口(refid-riid,void**ppvObject){
如果(!ppvObject)返回E_指针;
如果(riid==IID_IUnknown){
*ppvObject=静态投影(此);
AddRef();
返回S_OK;
}else if(riid==IID_IDropSource){
*ppvObject=静态投影(此);
AddRef();
返回S_OK;
}否则{
*ppvObject=NULL;
返回E_NOINTERFACE;
}
}
//IDropSource成员
标准方法