Skip to content

Commit ade099f

Browse files
author
Adam Gates
committed
Added DragDrop
1 parent e257334 commit ade099f

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

DragDrop.cpp

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// See http://blogs.msdn.com/b/oldnewthing/archive/tags/what+a+drag/
2+
3+
#include <windows.h>
4+
#include <stdio.h>
5+
#include <tchar.h>
6+
#include <vector>
7+
#include <string>
8+
#include <Shlobj.h>
9+
#include <Shlwapi.h>
10+
11+
// From http://blogs.msdn.com/b/oldnewthing/archive/2004/09/20/231739.aspx
12+
13+
HRESULT GetUIObjectOfFile(HWND hwnd, LPCWSTR pszPath, REFIID riid, void **ppv)
14+
{
15+
*ppv = NULL;
16+
HRESULT hr;
17+
LPITEMIDLIST pidl;
18+
SFGAOF sfgao;
19+
if (SUCCEEDED(hr = SHParseDisplayName(pszPath, NULL, &pidl, 0, &sfgao))) {
20+
IShellFolder *psf;
21+
LPCITEMIDLIST pidlChild;
22+
if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder,
23+
(void**)&psf, &pidlChild))) {
24+
hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv);
25+
psf->Release();
26+
}
27+
CoTaskMemFree(pidl);
28+
}
29+
return hr;
30+
}
31+
32+
// ====
33+
34+
struct sFindWindowWildcard
35+
{
36+
const _TCHAR* lpClassName;
37+
const _TCHAR* lpWindowName;
38+
HWND hwnd;
39+
};
40+
41+
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
42+
{
43+
if (hwnd != GetConsoleWindow())
44+
{
45+
sFindWindowWildcard* fww = (sFindWindowWildcard*) lParam;
46+
47+
TCHAR name[1024];
48+
TCHAR wndclass[1024];
49+
GetWindowText(hwnd, name, 1024);
50+
GetClassName(hwnd, wndclass, 1024);
51+
52+
if ((fww->lpClassName == NULL || PathMatchSpec(wndclass, fww->lpClassName))
53+
&& (fww->lpWindowName == NULL || PathMatchSpec(name, fww->lpWindowName)))
54+
{
55+
fww->hwnd = hwnd;
56+
return FALSE;
57+
}
58+
else
59+
return TRUE;
60+
}
61+
else
62+
return TRUE;
63+
}
64+
65+
HWND FindWindowWildcard(const _TCHAR* lpClassName, const _TCHAR* lpWindowName)
66+
{
67+
//return FindWindow(lpClassName, lpWindowName);
68+
69+
sFindWindowWildcard fww;
70+
fww.lpClassName = lpClassName;
71+
fww.lpWindowName = lpWindowName;
72+
fww.hwnd = NULL;
73+
74+
if (lpClassName != NULL || lpWindowName != NULL)
75+
EnumWindows(EnumWindowsProc, (LPARAM) &fww);
76+
77+
return fww.hwnd;
78+
}
79+
80+
void DoDragDrop(IDropTarget *pdt, const std::vector<std::wstring>& files)
81+
{
82+
IDataObject *pdtobj = NULL;
83+
for (std::vector<std::wstring>::const_iterator it = files.begin(); it != files.end(); ++it)
84+
{
85+
// TODO Dropping one at a time. Should lookup how drop all as one.
86+
if (SUCCEEDED(GetUIObjectOfFile(NULL, it->c_str(), IID_IDataObject, (void**)&pdtobj))) {
87+
POINTL pt = { 0, 0 };
88+
DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_LINK;
89+
90+
if (SUCCEEDED(pdt->DragEnter(pdtobj, MK_LBUTTON, pt, &dwEffect))) {
91+
dwEffect &= DROPEFFECT_COPY | DROPEFFECT_LINK;
92+
if (dwEffect) {
93+
pdt->Drop(pdtobj, MK_LBUTTON, pt, &dwEffect);
94+
} else {
95+
pdt->DragLeave();
96+
}
97+
}
98+
pdtobj->Release();
99+
}
100+
}
101+
}
102+
103+
void DoDragDrop(HWND hWndDest, const std::vector<std::wstring>& files)
104+
{
105+
size_t size = sizeof(DROPFILES) + sizeof(_TCHAR);
106+
for (std::vector<std::wstring>::const_iterator it = files.begin(); it != files.end(); ++it)
107+
{
108+
size += (it->length() + 1) * sizeof(_TCHAR);
109+
}
110+
111+
HGLOBAL hGlobal = GlobalAlloc(GHND, size);
112+
DROPFILES * df = static_cast<DROPFILES *>(GlobalLock(hGlobal));
113+
df->pFiles = sizeof(DROPFILES);
114+
_TCHAR* f = reinterpret_cast<_TCHAR *>(df + 1);
115+
size -= sizeof(DROPFILES) + sizeof(_TCHAR);
116+
for (std::vector<std::wstring>::const_iterator it = files.begin(); it != files.end(); ++it)
117+
{
118+
_tcscpy_s(f, it->length() + 1, it->c_str());
119+
size -= (it->length() + 1) * sizeof(_TCHAR);
120+
f += it->length() + 1;
121+
}
122+
df->fNC = TRUE;
123+
df->fWide = TRUE;
124+
GlobalUnlock(hGlobal);
125+
126+
PostMessage(hWndDest, WM_DROPFILES, (WPARAM) hGlobal, 0);
127+
GlobalFree(hGlobal);
128+
}
129+
130+
int _tmain(int argc, _TCHAR* argv[])
131+
{
132+
/*HRESULT hr =*/ CoInitialize(0);
133+
134+
const _TCHAR* lpClassName = NULL;
135+
const _TCHAR* lpWindowName = NULL;
136+
std::vector<std::wstring> files;
137+
138+
//lpClassName = _T("ATL:006AD5B8");
139+
//files.push_back(_T("C:\\Windows\\ODBC.INI"));
140+
for (int i = 1; i < argc; ++i)
141+
{
142+
const TCHAR* arg = argv[i];
143+
144+
if (_tcsncmp(arg, _T("/class:"), 7) == 0)
145+
{
146+
lpClassName = arg + 7;
147+
}
148+
else if (_tcsncmp(arg, _T("/window:"), 8) == 0)
149+
{
150+
lpWindowName = arg + 8;
151+
}
152+
else
153+
{
154+
WIN32_FIND_DATA FindFileData;
155+
HANDLE hFind = FindFirstFile(arg, &FindFileData);
156+
if (hFind != INVALID_HANDLE_VALUE)
157+
{
158+
do
159+
{
160+
TCHAR buffer[4096];
161+
if (GetFullPathName(FindFileData.cFileName, 4096, buffer, NULL) != 0)
162+
{
163+
files.push_back(buffer);
164+
}
165+
} while (FindNextFile(hFind, &FindFileData));
166+
FindClose(hFind);
167+
}
168+
}
169+
}
170+
171+
if (files.empty())
172+
{
173+
_tprintf(_T("Usage:\n"));
174+
_tprintf(_T("\tDragDrop [/class:<class name>] [/window:<window name>] <files>\n"));
175+
}
176+
else
177+
{
178+
HWND hWndDest = FindWindowWildcard(lpClassName, lpWindowName);
179+
180+
if (hWndDest != NULL)
181+
{
182+
LONG ExStyle = GetWindowLong(hWndDest, GWL_EXSTYLE);
183+
184+
IDropTarget *pdt = (IDropTarget *) GetProp(hWndDest, _T("OleDropTargetInterface"));
185+
//if (SUCCEEDED(GetUIObjectOfFile(hwnd, _T("C:\\Windows\\notepad.exe"), IID_IDropTarget, (void**)&pdt))) {
186+
187+
if (pdt != NULL)
188+
{
189+
DoDragDrop(pdt, files);
190+
}
191+
else if ((ExStyle & WS_EX_ACCEPTFILES) == WS_EX_ACCEPTFILES)
192+
{
193+
DoDragDrop(hWndDest, files);
194+
}
195+
else
196+
{
197+
_tprintf(_T("Window 0x%x doesnt support drag and drop.\n"), HandleToUlong(hWndDest));
198+
}
199+
}
200+
else
201+
{
202+
_tprintf(_T("Could not find window with class %s and name %s.\n"), lpClassName, lpWindowName);
203+
}
204+
}
205+
206+
CoUninitialize();
207+
208+
return 0;
209+
}

DragDrop.props

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+
<PropertyGroup>
3+
<CharacterSet>Unicode</CharacterSet>
4+
</PropertyGroup>
5+
<ItemDefinitionGroup>
6+
<Link>
7+
<AdditionalDependencies>user32.lib;ole32.lib;shell32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
8+
</Link>
9+
</ItemDefinitionGroup>
10+
</Project>

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,6 @@ Copies stdin to stdout prepending each line with a timestamp.
4242

4343
## [whoami](whoami.c)
4444
Outputs the name of the current user
45+
46+
## [DragDrop](DragDrop.cpp)
47+
Simulates drag and dropping a file onto a window

0 commit comments

Comments
 (0)