|
|
//
// ITBDROP.CPP
// routines for implementing OLE drop target capability
// within the internet toolbar control
//
// History:
// 07/13/96 t-mkim Created
// 10/13/96 chrisg massive cleanup
//
#include "priv.h"
#include "itbdrop.h"
#include "sccls.h"
#include "resource.h"
#include "mluisupp.h"
#ifdef UNIX
#ifdef SIZEOF
#undef SIZEOF
#endif
#define SIZEOF(x) sizeof(x) // has been checked for UNICODE correctness
#endif
#define MAX_NAME_QUICKLINK 40
// Data type of the incoming data object.
#define CITBDTYPE_NONE 0
#define CITBDTYPE_HDROP 1
#define CITBDTYPE_URL 2
#define CITBDTYPE_TEXT 3
// get an IDropTarget for shell special folders
//
HRESULT _GetSpecialDropTarget(UINT csidl, IDropTarget **ppdtgt) { IShellFolder *psfDesktop;
*ppdtgt = NULL;
HRESULT hres = SHGetDesktopFolder(&psfDesktop); if (SUCCEEDED(hres)) { LPITEMIDLIST pidl; hres = SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (SUCCEEDED(hres)) { IShellFolder *psf; hres = psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (void **)&psf); if (SUCCEEDED(hres)) { hres = psf->CreateViewObject(NULL, IID_IDropTarget, (void **)ppdtgt); psf->Release(); }
ILFree(pidl); } psfDesktop->Release(); } return hres; }
// Takes a variety of inputs and returns a string for drop targets.
// szUrl: the URL
// szName: the name (for quicklinks and the confo dialog boxes)
// returns: NOERROR if succeeded
//
HRESULT _GetURLData(IDataObject *pdtobj, int iDropType, TCHAR *pszUrl, DWORD cchUrl, TCHAR *pszName) { HRESULT hRes = NOERROR; STGMEDIUM stgmedium; UINT cfFormat;
*pszName = 0; *pszUrl = 0;
switch (iDropType) { case CITBDTYPE_HDROP: cfFormat = CF_HDROP; break;
case CITBDTYPE_URL: InitClipboardFormats(); cfFormat = g_cfURL; break;
case CITBDTYPE_TEXT: cfFormat = CF_TEXT; break;
default: return E_UNEXPECTED; }
// Get the parse string
LPCSTR pszURL = (LPCSTR)DataObj_GetDataOfType(pdtobj, cfFormat, &stgmedium); if (pszURL) { if (iDropType == CITBDTYPE_HDROP) { ASSERT(stgmedium.tymed == TYMED_HGLOBAL);
TCHAR szPath[MAX_PATH]; DragQueryFile((HDROP)stgmedium.hGlobal, 0, szPath, ARRAYSIZE(szPath));
// defaults...
lstrcpyn(pszUrl, szPath, MAX_URL_STRING); lstrcpyn(pszName, szPath, MAX_NAME_QUICKLINK);
SHFILEINFO sfi; DWORD_PTR bGotInfo = SHGetFileInfo(szPath, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_ATTRIBUTES); if (bGotInfo) lstrcpyn(pszName, sfi.szDisplayName, MAX_NAME_QUICKLINK);
if (bGotInfo && (sfi.dwAttributes & SFGAO_LINK)) { LPITEMIDLIST pidl; if (SUCCEEDED(GetLinkTargetIDList(szPath, pszUrl, cchUrl, &pidl))) { // we only care about the name... thanks anyway.
ILFree(pidl); } } } else { #ifdef UNICODE
WCHAR wszURL[MAX_URL_STRING]; SHAnsiToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL)); LPTSTR pszURLData = wszURL; #else
LPTSTR pszURLData = pszURL; #endif
if (iDropType == CITBDTYPE_URL) { // defaults
lstrcpyn(pszUrl, pszURLData, MAX_URL_STRING); lstrcpyn(pszName, pszURLData, MAX_NAME_QUICKLINK);
WCHAR szPath[MAX_PATH];
if (SUCCEEDED(DataObj_GetNameFromFileDescriptor(pdtobj, szPath, ARRAYSIZE(szPath)))) PathToDisplayNameW(szPath, pszName, MAX_NAME_QUICKLINK); } else // if (iDropType == CITBDTYPE_TEXT)
{ ASSERT(iDropType == CITBDTYPE_TEXT);
lstrcpyn(pszUrl, pszURLData, MAX_URL_STRING); lstrcpyn(pszName, pszURLData, MAX_NAME_QUICKLINK); } } ReleaseStgMediumHGLOBAL(NULL, &stgmedium); } else { hRes = E_FAIL; }
return hRes; }
// Displays a dialog asking for confirmation of drop-set operations.
// Returns: User's response to the dialog box: YES = TRUE, NO = FALSE
//
BOOL _ConfirmChangeQuickLink(HWND hwndParent, TCHAR *pszName, int iTarget) { MSGBOXPARAMS mbp; TCHAR szHeader[64]; TCHAR szBuffer [MAX_NAME_QUICKLINK + 64]; TCHAR szCaption [MAX_NAME_QUICKLINK + 64]; UINT titleID, textID, iconID;
switch (iTarget) { case TBIDM_HOME: titleID = IDS_SETHOME_TITLE; textID = IDS_SETHOME_TEXT; iconID = IDI_HOMEPAGE; break; #if 0
case TBIDM_SEARCH: titleID = IDS_SETSEARCH_TITLE; textID = IDS_SETSEARCH_TEXT; iconID = IDI_FRAME; // Warning if you unif0 this: IDI_FRAME is not in this dll
break; #endif
default: return FALSE; // We should never get here!
} mbp.cbSize = sizeof (MSGBOXPARAMS); mbp.hwndOwner = hwndParent; mbp.hInstance = HinstShdocvw(); mbp.dwStyle = MB_YESNO | MB_USERICON; MLLoadString(titleID, szCaption, ARRAYSIZE (szCaption)); mbp.lpszCaption = szCaption; mbp.lpszIcon = MAKEINTRESOURCE (iconID); mbp.dwContextHelpId = 0; mbp.lpfnMsgBoxCallback = NULL; mbp.dwLanguageId = LANGIDFROMLCID (g_lcidLocale);
MLLoadString(textID, szHeader, ARRAYSIZE (szHeader)); wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szHeader, pszName); mbp.lpszText = szBuffer;
return MessageBoxIndirect(&mbp) == IDYES; }
// Creates an instance of CITBarDropTarget. ptr is a pointer to the parent
// CInternetToolbar.
//
CITBarDropTarget::CITBarDropTarget(HWND hwnd, int iTarget) : _cRef(1), _iDropType(CITBDTYPE_NONE), _hwndParent(hwnd), _iTarget(iTarget) { }
STDMETHODIMP CITBarDropTarget::QueryInterface(REFIID iid, void **ppvObj) { if (IsEqualIID (iid, IID_IUnknown) || IsEqualIID (iid, IID_IDropTarget)) { *ppvObj = SAFECAST(this, IDropTarget*); AddRef(); return NOERROR; }
*ppvObj = NULL; return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CITBarDropTarget::AddRef() { _cRef++; return _cRef; }
STDMETHODIMP_(ULONG) CITBarDropTarget::Release() { _cRef--;
if (_cRef > 0) return _cRef;
delete this; return 0; }
typedef struct { int iTarget; int iDropType; HWND hwnd; TCHAR szUrl [MAX_URL_STRING]; TCHAR szName [MAX_NAME_QUICKLINK]; } DROPDATA;
DWORD CALLBACK ITBarDropThreadProc(void *pv) { DROPDATA *pdd = (DROPDATA *)pv;
switch (pdd->iTarget) { case TBIDM_HOME:
if (pdd->iDropType != CITBDTYPE_TEXT) { if (_ConfirmChangeQuickLink(pdd->hwnd, pdd->szName, pdd->iTarget)) { ASSERT(pdd->iTarget == TBIDM_HOME); // currently don't support pdd->itarget == TBIDM_SEARCH
//(pdd->iTarget == TBIDM_HOME) ? DVIDM_GOHOME : DVIDM_GOSEARCH);
_SetStdLocation(pdd->szUrl, DVIDM_GOHOME); } } break;
case TBIDM_SEARCH: ASSERT(0); break; }
LocalFree(pdd);
return 0; }
STDMETHODIMP CITBarDropTarget::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) { ASSERT(pdtobj); _DragEnter(_hwndParent, ptl, pdtobj); if (_iTarget == TBIDM_FAVORITES) { if (SUCCEEDED(_GetSpecialDropTarget(CSIDL_FAVORITES, &_pdrop))) _pdrop->DragEnter(pdtobj, grfKeyState, ptl, pdwEffect); else *pdwEffect = DROPEFFECT_NONE; return NOERROR; } else if (_iTarget == TBIDM_HOME) { HKEY hkeyRest = 0; DWORD dwValue = 0; DWORD dwLen = sizeof(DWORD);
// Check if setting home page is restricted
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_SET_HOMEPAGE_RESTRICTION, 0, KEY_READ, &hkeyRest) == ERROR_SUCCESS) { if (RegQueryValueEx(hkeyRest, REGVAL_HOMEPAGE_RESTRICTION, NULL, NULL, (LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS && dwValue) { return E_ACCESSDENIED; } RegCloseKey(hkeyRest); } }
InitClipboardFormats();
// Find the drop object's data format.
FORMATETC fe = {g_cfURL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; if (NOERROR == pdtobj->QueryGetData (&fe)) { _iDropType = CITBDTYPE_URL; } else if (fe.cfFormat = CF_HDROP, NOERROR == pdtobj->QueryGetData (&fe)) { _iDropType = CITBDTYPE_HDROP; } else if (fe.cfFormat = CF_TEXT, NOERROR == pdtobj->QueryGetData (&fe)) { _iDropType = CITBDTYPE_TEXT; // We want to eventually pick through the text for an
// URL, but right now we just leave it unmolested.
} DragOver (grfKeyState, ptl, pdwEffect); return NOERROR; }
STDMETHODIMP CITBarDropTarget::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) { DWORD dwEffectAvail; _DragMove(_hwndParent, ptl); if (_iTarget == TBIDM_FAVORITES) { if (_pdrop) return _pdrop->DragOver(grfKeyState, ptl, pdwEffect);
*pdwEffect = DROPEFFECT_NONE; return NOERROR; } ASSERT(!_pdrop);
if (_iDropType == CITBDTYPE_NONE) { *pdwEffect = DROPEFFECT_NONE; return NOERROR; }
dwEffectAvail = DROPEFFECT_NONE; switch (_iTarget) { case TBIDM_HOME: case TBIDM_SEARCH: if (_iDropType == CITBDTYPE_TEXT) { // CF_TEXT doesn't do link.
} else dwEffectAvail = DROPEFFECT_LINK; break; } *pdwEffect &= dwEffectAvail; return NOERROR; }
STDMETHODIMP CITBarDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { BOOL fSafe = TRUE; LPITEMIDLIST pidl;
if (_pdrop) { ASSERT(_iTarget == TBIDM_FAVORITES);
//
// Force a linking since we are passing straight through to the folder.
// This avoids confusion when dragging to the toolbar button.
//
// FEATURE: this should really go through the "Add to Favorites" UI
//
// When forcing a link, make sure that you can move it. If you cannot move it,
// then we rely on the prefered effect of the data object. Why? Well, the history
// folder only allows a copy. If you just whack this to LINK, the shell folder hoses
// the drag images (Does a DAD_SetDragImage(NULL), blowing away the information about
// the last locked window, without unlocking it.). So, if you can move the item,
// you can link to it (I guess), but if you cannot move it, do whatever.
// - (lamadio) 1.3.99
if (*pdwEffect & DROPEFFECT_MOVE) *pdwEffect = DROPEFFECT_LINK;
if (TBIDM_FAVORITES == _iTarget && SUCCEEDED(SHPidlFromDataObject(pdtobj, &pidl, NULL, 0))) { fSafe = IEIsLinkSafe(_hwndParent, pidl, ILS_ADDTOFAV); ILFree(pidl); }
if (fSafe) { _pdrop->Drop(pdtobj, grfKeyState, pt, pdwEffect); } else { pdtobj->Release(); // Match Release called in _pdrop->Drop.
} DAD_DragLeave();
_pdrop->Release(); _pdrop = NULL; } else { if (TBIDM_HOME == _iTarget && SUCCEEDED(SHPidlFromDataObject(pdtobj, &pidl, NULL, 0))) { fSafe = IEIsLinkSafe(_hwndParent, pidl, ILS_HOME); ILFree(pidl); }
if (fSafe) { DROPDATA *pdd = (DROPDATA *)LocalAlloc (LPTR, sizeof(DROPDATA)); if (pdd) { pdd->iTarget = _iTarget; pdd->iDropType = _iDropType; pdd->hwnd = _hwndParent;
// do this async so we don't block the source of the drag durring our UI
if (FAILED(_GetURLData(pdtobj, _iDropType, pdd->szUrl, ARRAYSIZE(pdd->szUrl), pdd->szName)) || !SHCreateThread(ITBarDropThreadProc, pdd, 0, NULL)) LocalFree(pdd); } } DragLeave(); } return NOERROR; }
STDMETHODIMP CITBarDropTarget::DragLeave(void) { DAD_DragLeave(); // Check if we should to pass to the favorites dt.
if (_pdrop) { ASSERT(_iTarget == TBIDM_FAVORITES); _pdrop->DragLeave(); _pdrop->Release(); _pdrop = NULL; } _iDropType = CITBDTYPE_NONE;
return NOERROR; }
|