Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
ddproxy.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 10k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "ctlspriv.h"
- #include "olestuff.h"
- //------------------------------------------------------------------------------
- STDAPI GetItemObject(CONTROLINFO *pci, UINT uMsg, const IID *piid, LPNMOBJECTNOTIFY pnon)
- {
- pnon->piid = piid;
- pnon->pObject = NULL;
- pnon->hResult = E_NOINTERFACE;
- CCSendNotify(pci, uMsg, &pnon->hdr);
- ASSERT(SUCCEEDED(pnon->hResult) ? (pnon->pObject != NULL) : (pnon->pObject == NULL));
- return pnon->hResult;
- }
- //------------------------------------------------------------------------------
- class CDragProxy : public IDropTarget
- {
- public:
- // IUnknown
- STDMETHODIMP QueryInterface(REFIID, void **);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- // IDropTarget
- STDMETHODIMP DragEnter(IDataObject *, DWORD, POINTL, DWORD *);
- STDMETHODIMP DragOver(DWORD, POINTL, DWORD *);
- STDMETHODIMP DragLeave();
- STDMETHODIMP Drop(IDataObject *, DWORD, POINTL, DWORD *);
- CDragProxy(HWND hwnd, PFNDRAGCB pfn);
- BOOL Register();
- void RevokeAndFreeCB();
- private:
- ~CDragProxy();
- int _cRef; // object reference count
- HWND _hwnd; // window that owns us
- PFNDRAGCB _pfnCallback; // callback for that window
- IDataObject *_pdtobj; // data object being dragged
- IDropTarget *_pdtgtItem; // drop target of item under mouse
- int _idItem; // id of item under mouse
- DWORD _dwFlags;
- int _idDefault; // id to use when outside a drag etc
- DWORD _dwEffectItem; // DROPEFFECT returned for item under mouse
- DWORD _fKeysLast; // key flags from last DragOver
- POINTL _ptLast; // location of last DragOver
- DWORD _dwEffectLast; // effect available from last DragOver
- HMODULE _hmodOLE; // OLE32 ref, also indicates we did a Register()
- void SetTargetItem(int id, DWORD dwFlags);
- void SetDropTarget(IDropTarget *pdt);
- void UpdateSelection(DWORD dwEffect);
- LRESULT CallCB(UINT code, WPARAM wp, LPARAM lp);
- };
- //------------------------------------------------------------------------------
- STDAPI_(HDRAGPROXY) CreateDragProxy(HWND hwnd, PFNDRAGCB pfn, BOOL bRegister)
- {
- CDragProxy *pdp = new CDragProxy(hwnd, pfn);
- //
- // register as needed
- //
- if (pdp && bRegister && !pdp->Register())
- {
- pdp->Release();
- pdp = NULL;
- }
- return (HDRAGPROXY)pdp;
- }
- STDAPI_(void) DestroyDragProxy(HDRAGPROXY hdp)
- {
- if (hdp)
- {
- ((CDragProxy *)hdp)->RevokeAndFreeCB();
- ((CDragProxy *)hdp)->Release();
- }
- }
- STDAPI GetDragProxyTarget(HDRAGPROXY hdp, IDropTarget **ppdtgt)
- {
- if (hdp)
- {
- *ppdtgt = SAFECAST((CDragProxy *)hdp, IDropTarget *);
- ((CDragProxy *)hdp)->AddRef();
- return NOERROR;
- }
- *ppdtgt = NULL;
- return E_FAIL;
- }
- //------------------------------------------------------------------------------
- CDragProxy::CDragProxy(HWND hwnd, PFNDRAGCB pfn)
- : _hwnd(hwnd), _pfnCallback(pfn),
- _cRef(1),
- _hmodOLE(NULL),
- _pdtobj(NULL),
- _pdtgtItem(NULL),
- _dwEffectItem(DROPEFFECT_NONE)
- {
- _idDefault = _idItem = (int)CallCB(DPX_DRAGHIT, 0, 0);
- }
- CDragProxy::~CDragProxy()
- {
- DragLeave();
- }
- HRESULT CDragProxy::QueryInterface(REFIID iid, void **ppv)
- {
- if (IsEqualIID(iid, IID_IDropTarget) || IsEqualIID(iid, IID_IUnknown))
- {
- *ppv = SAFECAST(this, IDropTarget *);
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
- _cRef++;
- return NOERROR;
- }
- ULONG CDragProxy::AddRef()
- {
- return ++_cRef;
- }
- ULONG CDragProxy::Release()
- {
- if (--_cRef)
- return _cRef;
- delete this;
- return 0;
- }
- HRESULT CDragProxy::DragEnter(IDataObject *pdo, DWORD fKeys, POINTL pt, DWORD *pdwEffect)
- {
- //
- // some sanity
- //
- ASSERT(!_pdtgtItem);
- ASSERT(!_pdtobj);
- if (!pdo)
- {
- ASSERT(FALSE);
- return E_INVALIDARG;
- }
- //
- // make sure our callback will allow us to do d/d now
- //
- if (!CallCB(DPX_ENTER, 0, 0))
- return E_FAIL;
- //
- // save away the data object
- //
- pdo->AddRef();
- _pdtobj = pdo;
- //
- // and process this like a DragOver
- //
- DragOver(fKeys, pt, pdwEffect);
- //
- // always succeed DragEnter
- //
- return NOERROR;
- }
- HRESULT CDragProxy::DragLeave()
- {
- //
- // release any drop target that we are holding
- //
- SetDropTarget(NULL);
- _idItem = _idDefault;
- //
- // if we had a data object then we were actually dragging
- //
- if (_pdtobj)
- {
- CallCB(DPX_LEAVE, 0, 0);
- IDataObject* p = _pdtobj;
- _pdtobj = NULL;
- p->Release();
- }
- //
- // all done
- //
- return NOERROR;
- }
- HRESULT CDragProxy::DragOver(DWORD fKeys, POINTL pt, DWORD *pdwEffect)
- {
- DWORD dwFlags = 0;
- HRESULT hres;
- int id;
- ASSERT(_pdtobj);
- //
- // save the current drag state
- //
- _fKeysLast = fKeys;
- _ptLast = pt;
- _dwEffectLast = *pdwEffect;
- //
- // make sure we have the correct drop target for this location
- //
- id = (int)CallCB(DPX_DRAGHIT, (WPARAM)&dwFlags, (LPARAM)&pt);
- SetTargetItem(id, dwFlags);
- //
- // do we have a target to drop on?
- //
- if (_pdtgtItem)
- {
- //
- // forward the DragOver along to the item's drop target (if any)
- //
- hres = _pdtgtItem->DragOver(fKeys, pt, pdwEffect);
- }
- else
- {
- //
- // can't drop here
- //
- *pdwEffect = DROPEFFECT_NONE;
- hres = NOERROR;
- }
- //
- // and update our selection state accordingly
- //
- UpdateSelection(*pdwEffect);
- return hres;
- }
- HRESULT CDragProxy::Drop(IDataObject *pdo, DWORD fKeys, POINTL pt, DWORD *pdwEffect)
- {
- HRESULT hres;
- AddRef();
- //
- // do we have a target to drop on?
- //
- if (_pdtgtItem)
- {
- // From a comment in browseui, there's apparently a chance to put up UI
- // which could cause us to get re-entered. Hard to believe, but see if
- // this fixes the fault:
- //
- IDropTarget * pdtCur = _pdtgtItem;
- _pdtgtItem = NULL;
- //
- // do the drop
- //
- hres = pdtCur->Drop(pdo, fKeys, pt, pdwEffect);
- //
- // we call our DragLeave below but we don't want the item's to be
- // called (since it already saw the Drop) so we release right away
- //
- pdtCur->Release();
- }
- else
- {
- //
- // can't drop here
- //
- *pdwEffect = DROPEFFECT_NONE;
- hres = NOERROR;
- }
- //
- // now clean up
- //
- DragLeave();
- Release();
- return hres;
- }
- void CDragProxy::SetTargetItem(int id, DWORD dwFlags)
- {
- //
- // anything to do?
- //
- if (id == _idItem && dwFlags == _dwFlags)
- return;
- //
- // deselect the old item (if any)
- //
- // the GETOBJECT below could take a long time and we don't want a
- // lingering highlight on the object we are leaving
- //
- UpdateSelection(DROPEFFECT_NONE);
- //
- // get a drop target for the new item
- //
- _idItem = id;
- _dwFlags = dwFlags;
- NMOBJECTNOTIFY non;
- non.iItem = id;
- non.dwFlags = dwFlags;
- if (!_pdtobj || FAILED((HRESULT)CallCB(DPX_GETOBJECT, 0, (LPARAM)&non)))
- non.pObject = NULL;
- //
- // use this drop target (if any)
- //
- SetDropTarget((IDropTarget*)non.pObject);
- //
- // release our ref from the GETOBJECT above
- //
- if (non.pObject)
- ((IDropTarget*)non.pObject)->Release();
- }
- void CDragProxy::SetDropTarget(IDropTarget *pdt)
- {
- //
- // NOTE: we intentionally skip the test for drop-target equality here
- // this allows controls owners to share a target among multiple items
- // while retaining the proper leave/enter sequence...
- //
- // BOGUS: we should actually compare here when the Internet Toolbar gets
- // fixed (see comment in CDragProxy::SetTargetItem). anybody who wants
- // to share a target like this should just do the right hit-testing in
- // their DragOver implementation
- //
- //
- // make sure nothing is selected
- //
- UpdateSelection(DROPEFFECT_NONE);
- //
- // leave/release the old item
- //
- if (_pdtgtItem)
- {
- _pdtgtItem->DragLeave();
- _pdtgtItem->Release();
- }
- //
- // store the new item
- //
- _pdtgtItem = pdt;
- //
- // addref/enter the new item
- //
- if (_pdtgtItem)
- {
- ASSERT(_pdtobj); // must have a data object by now
- _pdtgtItem->AddRef();
- DWORD dwEffect = _dwEffectLast;
- if (FAILED(_pdtgtItem->DragEnter(_pdtobj, _fKeysLast, _ptLast, &dwEffect)))
- dwEffect = DROPEFFECT_NONE;
- //
- // update the selection
- //
- UpdateSelection(dwEffect);
- }
- }
- void CDragProxy::UpdateSelection(DWORD dwEffect)
- {
- //
- // anything to do?
- //
- if (dwEffect == _dwEffectItem)
- return;
- //
- // update the flags and tell the callback they changed
- //
- _dwEffectItem = dwEffect;
- CallCB(DPX_SELECT, (WPARAM)_idItem, (LPARAM)dwEffect);
- }
- LRESULT CDragProxy::CallCB(UINT code, WPARAM wp, LPARAM lp)
- {
- return _pfnCallback ? _pfnCallback(_hwnd, code, wp, lp) : (LRESULT)-1;
- }
- BOOL CDragProxy::Register()
- {
- _hmodOLE = PrivLoadOleLibrary();
- if (_hmodOLE)
- {
- if (SUCCEEDED(PrivCoInitialize(_hmodOLE)))
- {
- if (SUCCEEDED(PrivRegisterDragDrop(_hmodOLE, _hwnd, this)))
- return TRUE;
- PrivCoUninitialize(_hmodOLE);
- }
- PrivFreeOleLibrary(_hmodOLE);
- _hmodOLE = NULL;
- }
- return FALSE;
- }
- void CDragProxy::RevokeAndFreeCB()
- {
- if (_hmodOLE)
- {
- PrivRevokeDragDrop(_hmodOLE, _hwnd);
- PrivCoUninitialize(_hmodOLE);
- PrivFreeOleLibrary(_hmodOLE);
- }
- _pfnCallback = NULL;
- }