+ workaround: drag n' drop from 32-bit process on Notepad3 x64 window

This commit is contained in:
Rainer Kottenhoff 2017-11-29 00:24:28 +01:00
parent 2eeb276700
commit 720e0c0574
5 changed files with 428 additions and 10 deletions

View File

@ -3580,5 +3580,347 @@ INT UTF8_mbslen(LPCSTR source,INT byte_length)
return wchar_length;
}
///////////////////////////////////////////////////////////////////////////////
//
// Drag N Drop helpers
//
///////////////////////////////////////////////////////////////////////////////
static HANDLE g_hHeap = NULL;
#define NP3DD_HEAP (g_hHeap == NULL ? (g_hHeap = GetProcessHeap()) : g_hHeap)
typedef struct tIDROPTARGET {
IDropTarget idt;
LONG lRefCount;
ULONG lNumFormats;
CLIPFORMAT *pFormat;
HWND hWnd;
BOOL bAllowDrop;
DWORD dwKeyState;
IDataObject *pDataObject;
UINT nMsg;
void *pUserData;
NP3DDCALLBACK pDropProc;
}
NP3IDROPTARGET, *PNP3IDROPTARGET;
typedef struct IDRPTRG_VTBL
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE *QueryInterface)(PNP3IDROPTARGET pThis, REFIID riid, void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(PNP3IDROPTARGET pThis);
ULONG(STDMETHODCALLTYPE *Release)(PNP3IDROPTARGET pThis);
HRESULT(STDMETHODCALLTYPE *DragEnter)(PNP3IDROPTARGET pThis, IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT(STDMETHODCALLTYPE *DragOver)(PNP3IDROPTARGET pThis, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT(STDMETHODCALLTYPE *DragLeave)(PNP3IDROPTARGET pThis);
HRESULT(STDMETHODCALLTYPE *Drop)(PNP3IDROPTARGET pThis, IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
END_INTERFACE
}
IDRPTRG_VTBL, *PIDRPTRG_VTBL;
//=============================================================================
//
// NP3DragnDropInit()
//
void Np3DragnDropInit(HANDLE hHeap)
{
if (g_hHeap == NULL && hHeap == NULL)
g_hHeap = GetProcessHeap();
else if (g_hHeap == NULL)
g_hHeap = hHeap;
OleInitialize(NULL); // just in case
return;
}
//=============================================================================
//
// IDRPTRG_AddRef()
//
static ULONG STDMETHODCALLTYPE IDRPTRG_AddRef(PNP3IDROPTARGET pThis)
{
return InterlockedIncrement(&pThis->lRefCount);
}
//=============================================================================
//
// IDRPTRG_QueryDataObject()
//
static BOOL IDRPTRG_QueryDataObject(PNP3IDROPTARGET pDropTarget, IDataObject *pDataObject)
{
ULONG lFmt;
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
for (lFmt = 0; lFmt < pDropTarget->lNumFormats; lFmt++)
{
fmtetc.cfFormat = pDropTarget->pFormat[lFmt];
if (pDataObject->lpVtbl->QueryGetData(pDataObject, &fmtetc) == S_OK)
return TRUE;
}
return FALSE;
}
//=============================================================================
//
// IDRPTRG_QueryInterface()
//
static HRESULT STDMETHODCALLTYPE IDRPTRG_QueryInterface(PNP3IDROPTARGET pThis, REFIID riid,
LPVOID *ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(riid, &IID_IUnknown))
{
IDRPTRG_AddRef(pThis);
*ppvObject = pThis;
return S_OK;
}
else if (IsEqualGUID(riid, &IID_IDropTarget))
{
IDRPTRG_AddRef(pThis);
*ppvObject = pThis;
return S_OK;
}
return E_NOINTERFACE;
}
//=============================================================================
//
// IDRPTRG_Release()
//
static ULONG STDMETHODCALLTYPE IDRPTRG_Release(PNP3IDROPTARGET pThis)
{
ULONG nCount;
if ((nCount = InterlockedDecrement(&pThis->lRefCount)) == 0)
{
HeapFree(NP3DD_HEAP, 0, pThis);
return 0;
}
return nCount;
}
//=============================================================================
//
// IDRPTRG_DropEffect()
//
static DWORD IDRPTRG_DropEffect(DWORD dwKeyState, POINTL pt, DWORD dwAllowed)
{
DWORD dwEffect = 0;
if (dwKeyState & MK_CONTROL)
dwEffect = dwAllowed & DROPEFFECT_COPY;
else if (dwKeyState & MK_SHIFT)
dwEffect = dwAllowed & DROPEFFECT_MOVE;
if (dwEffect == 0)
{
if (dwAllowed & DROPEFFECT_COPY)
dwEffect = DROPEFFECT_COPY;
if (dwAllowed & DROPEFFECT_MOVE)
dwEffect = DROPEFFECT_MOVE;
}
UNUSED(pt);
return dwEffect;
}
//=============================================================================
//
// IDRPTRG_DragEnter()
//
static HRESULT STDMETHODCALLTYPE IDRPTRG_DragEnter(PNP3IDROPTARGET pThis, IDataObject *pDataObject,
DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
{
pThis->bAllowDrop = IDRPTRG_QueryDataObject(pThis, pDataObject);
if (pThis->bAllowDrop)
{
*pdwEffect = IDRPTRG_DropEffect(dwKeyState, pt, *pdwEffect);
SetFocus(pThis->hWnd);
}
else
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
//=============================================================================
//
// IDRPTRG_DragOver()
//
static HRESULT STDMETHODCALLTYPE IDRPTRG_DragOver(PNP3IDROPTARGET pThis, DWORD dwKeyState, POINTL pt,
DWORD *pdwEffect)
{
if (pThis->bAllowDrop)
{
pThis->dwKeyState = dwKeyState;
*pdwEffect = IDRPTRG_DropEffect(dwKeyState, pt, *pdwEffect);
}
else
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
//=============================================================================
//
// IDRPTRG_DragLeave()
//
static HRESULT STDMETHODCALLTYPE IDRPTRG_DragLeave(PNP3IDROPTARGET pThis)
{
UNUSED(pThis);
return S_OK;
}
//=============================================================================
//
// IDRPTRG_Drop()
//
static HRESULT STDMETHODCALLTYPE IDRPTRG_Drop(PNP3IDROPTARGET pThis, IDataObject *pDataObject,
DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
{
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM medium;
ULONG lFmt;
NP3DROPDATA DropData;
UNUSED(dwKeyState);
UNUSED(pt);
if (pThis->bAllowDrop)
{
for (lFmt = 0; lFmt < pThis->lNumFormats; lFmt++)
{
fmtetc.cfFormat = pThis->pFormat[lFmt];
if (pDataObject->lpVtbl->QueryGetData(pDataObject, &fmtetc) == S_OK)
break;
}
if (lFmt < pThis->lNumFormats)
{
pDataObject->lpVtbl->GetData(pDataObject, &fmtetc, &medium);
*pdwEffect = DROPEFFECT_NONE;
if (pThis->pDropProc != NULL)
*pdwEffect = (*pThis->pDropProc)(pThis->pFormat[lFmt], medium.hGlobal, pThis->hWnd, pThis->dwKeyState,
pt, pThis->pUserData);
else if (pThis->nMsg != WM_NULL)
{
DropData.cf = pThis->pFormat[lFmt];
DropData.dwKeyState = pThis->dwKeyState;
DropData.hData = medium.hGlobal;
DropData.pt = pt;
*pdwEffect = (DWORD)SendMessage(pThis->hWnd, pThis->nMsg, (WPARAM)&DropData,
(LPARAM)pThis->pUserData);
}
if (*pdwEffect != DROPEFFECT_NONE)
ReleaseStgMedium(&medium);
}
}
else
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
//=============================================================================
//
// Np3CreateDropTarget()
//
IDropTarget* Np3CreateDropTarget(CLIPFORMAT *pFormat, ULONG lFmt, HWND hWnd, UINT nMsg,
DWORD(*pDropProc)(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData),
void *pUserData)
{
PNP3IDROPTARGET pRet;
static IDRPTRG_VTBL idt_vtbl = {
IDRPTRG_QueryInterface,
IDRPTRG_AddRef,
IDRPTRG_Release,
IDRPTRG_DragEnter,
IDRPTRG_DragOver,
IDRPTRG_DragLeave,
IDRPTRG_Drop };
if ((pRet = HeapAlloc(NP3DD_HEAP, 0, sizeof(NP3IDROPTARGET) + lFmt * sizeof(CLIPFORMAT))) == NULL)
return NULL;
pRet->pFormat = (CLIPFORMAT *)(((char *)pRet) + sizeof(NP3IDROPTARGET));
pRet->idt.lpVtbl = (IDropTargetVtbl*)&idt_vtbl;
pRet->lRefCount = 1;
pRet->hWnd = hWnd;
pRet->nMsg = nMsg;
pRet->bAllowDrop = FALSE;
pRet->dwKeyState = 0;
pRet->lNumFormats = lFmt;
pRet->pDropProc = pDropProc;
pRet->pUserData = pUserData;
for (lFmt = 0; lFmt < pRet->lNumFormats; lFmt++)
pRet->pFormat[lFmt] = pFormat[lFmt];
return (IDropTarget *)pRet;
}
//=============================================================================
//
// Np3RegisterDragnDrop()
//
PNP3DROPTARGET Np3RegisterDragnDrop(HWND hWnd, CLIPFORMAT *pFormat, ULONG lFmt, UINT nMsg, NP3DDCALLBACK pDropProc, void *pUserData)
{
IDropTarget *pTarget;
if ((pTarget = Np3CreateDropTarget(pFormat, lFmt, hWnd, nMsg, pDropProc, pUserData)) == NULL)
return NULL;
if (RegisterDragDrop(hWnd, pTarget) != S_OK)
{
HeapFree(NP3DD_HEAP, 0, pTarget);
return NULL;
}
return (PNP3DROPTARGET)pTarget;
}
//=============================================================================
//
// Np3RevokeDragnDrop()
//
PNP3DROPTARGET Np3RevokeDragnDrop(PNP3DROPTARGET pTarget)
{
if (pTarget == NULL)
return NULL;
if (((PNP3IDROPTARGET)pTarget)->hWnd != NULL)
{
if (GetWindowLongPtr(((PNP3IDROPTARGET)pTarget)->hWnd, GWLP_WNDPROC) != 0)
RevokeDragDrop(((PNP3IDROPTARGET)pTarget)->hWnd);
}
((IDropTarget *)pTarget)->lpVtbl->Release((IDropTarget *)pTarget);
return NULL;
}
/// End of Helpers.c \\\

View File

@ -436,6 +436,25 @@ inline HRESULT PathCchRenameExtension(PWSTR p,size_t l,PCWSTR a) { UNUSED(l); re
inline HRESULT PathCchRemoveFileSpec(PWSTR p,size_t l) { UNUSED(l); return (PathRemoveFileSpec(p) ? S_OK : E_FAIL); }
// special Drag and Drop Handling
typedef struct tNP3DROPDATA
{
CLIPFORMAT cf;
POINTL pt;
DWORD dwKeyState;
HGLOBAL hData;
}
NP3DROPDATA, *PNP3DROPDATA;
typedef struct tNP3DROPTARGET *PNP3DROPTARGET;
typedef DWORD(*NP3DDCALLBACK)(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData);
void Np3DragnDropInit(HANDLE hHeap);
PNP3DROPTARGET Np3RegisterDragnDrop(HWND hWnd, CLIPFORMAT *pFormat, ULONG lFmt, UINT nMsg, NP3DDCALLBACK, void *pUserData);
PNP3DROPTARGET Np3RevokeDragnDrop(PNP3DROPTARGET pTarget);
#endif //_NP3_HELPERS_H_
/// End of Helpers.h \\\

View File

@ -310,6 +310,13 @@ WCHAR g_wchWorkingDirectory[MAX_PATH+2] = { L'\0' };
static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), NULL, NULL, NULL };
static UT_array* UndoRedoSelectionUTArray = NULL;
static CLIPFORMAT cfDrpF = CF_HDROP;
static POINTL ptDummy = { 0, 0 };
static PNP3DROPTARGET pDropTarget = NULL;
static DWORD DropFilesProc(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData);
//=============================================================================
//
// Flags
@ -644,6 +651,9 @@ int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpCmdLine,int n
if (!hwnd)
return FALSE;
// init DragnDrop handler
Np3DragnDropInit(NULL);
if (IsVista()) {
if (iSciDirectWriteTech >= 0)
SciCall_SetTechnology(DirectWriteTechnology[iSciDirectWriteTech]);
@ -1168,7 +1178,6 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
MsgDropFiles(hwnd, wParam, lParam);
break;
case WM_COPYDATA:
return MsgCopyData(hwnd, wParam, lParam);
@ -1225,13 +1234,6 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
case WM_TRAYMESSAGE:
return MsgTrayMessage(hwnd, wParam, lParam);
case WM_MOUSEWHEEL:
case WM_MBUTTONDOWN:
if (wParam & MK_MBUTTON) {
PostMessage(hwnd, WM_COMMAND, MAKELONG(BME_EDIT_BOOKMARKTOGGLE, 1), 0);
}
return DefWindowProc(hwnd, umsg, wParam, lParam);
default:
if (umsg == msgTaskbarCreated) {
if (!IsWindowVisible(hwnd))
@ -1412,6 +1414,7 @@ LRESULT MsgCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
// Drag & Drop
DragAcceptFiles(hwnd,TRUE);
pDropTarget = Np3RegisterDragnDrop(hwnd, &cfDrpF, 1, WM_NULL, DropFilesProc, (void*)hwndEdit);
// File MRU
pFileMRU = MRU_Create(L"Recent Files",MRU_NOCASE,32);
@ -1634,6 +1637,7 @@ void MsgEndSession(HWND hwnd, UINT umsg)
wininfo = GetMyWindowPlacement(hwnd, NULL);
DragAcceptFiles(hwnd, FALSE);
Np3RevokeDragnDrop(pDropTarget);
// Terminate clipboard watching
if (flagPasteBoard) {
@ -1855,9 +1859,10 @@ void MsgDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
if (OpenFileDlg(hwndMain, tchFile, COUNTOF(tchFile), szBuf))
FileLoad(FALSE, FALSE, FALSE, FALSE, tchFile);
}
else
else if (PathFileExists(szBuf))
FileLoad(FALSE, FALSE, FALSE, FALSE, szBuf);
else
MsgBox(MBWARN, IDS_DROP_NO_FILE);
if (DragQueryFile(hDrop, (UINT)(-1), NULL, 0) > 1)
MsgBox(MBWARN, IDS_ERR_DROP);
@ -1868,6 +1873,57 @@ void MsgDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
}
//=============================================================================
//
// DropFilesProc() - Handles DROPFILES
//
//
static DWORD DropFilesProc(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData)
{
UNUSED(dwKeyState);
UNUSED(pt);
DWORD dwEffect = DROPEFFECT_NONE;
//HWND hEditWnd = (HWND)pUserData;
UNUSED(pUserData);
if (cf == CF_HDROP)
{
WCHAR szBuf[MAX_PATH + 40];
HDROP hDrop = (HDROP)hData;
// Reset Change Notify
//bPendingChangeNotify = FALSE;
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
//SetForegroundWindow(hwnd);
DragQueryFile(hDrop, 0, szBuf, COUNTOF(szBuf));
if (PathIsDirectory(szBuf)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(hWnd, tchFile, COUNTOF(tchFile), szBuf))
FileLoad(FALSE, FALSE, FALSE, FALSE, tchFile);
}
else
FileLoad(FALSE, FALSE, FALSE, FALSE, szBuf);
if (DragQueryFile(hDrop, (UINT)(-1), NULL, 0) > 1)
MsgBox(MBWARN, IDS_ERR_DROP);
dwEffect = DROPEFFECT_COPY;
}
return dwEffect;
} /* End of MyDropProc(). */
//=============================================================================
//
// MsgCopyData() - Handles WM_COPYDATA

Binary file not shown.

View File

@ -460,6 +460,7 @@
#define IDS_ERR_ACCESSDENIED 50041
#define IDS_WARN_UNKNOWN_EXT 50042
#define IDS_REGEX_INVALID 50043
#define IDS_DROP_NO_FILE 50044
#define IDS_CMDLINEHELP 60000
#define IDM_EDIT_INSERT_GUID 60001
#define IDC_STATIC -1