OSDN Git Service

Modify documents.
[ffftp/ffftp.git] / OleDragDrop.c
1 /**************************************************************************\r
2 \r
3         OleDragDrop.c\r
4 \r
5         (C) Copyright 1996-2002 By Tomoaki Nakashima. All right reserved.       \r
6                 http://www.nakka.com/\r
7                 nakka@nakka.com\r
8 \r
9 **************************************************************************/\r
10 \r
11 /**************************************************************************\r
12         Include Files\r
13 **************************************************************************/\r
14 \r
15 // UTF-8対応\r
16 #include <winsock2.h>\r
17 \r
18 #define _INC_OLE\r
19 #include <windows.h>\r
20 #undef  _INC_OLE\r
21 \r
22 #include <oleidl.h>\r
23 #include <objidl.h>\r
24 \r
25 // UTF-8対応\r
26 #include "common.h"\r
27 \r
28 #include "OleDragDrop.h"\r
29 \r
30 \r
31 /* Clipboard format から Type of storage medium を取得 */\r
32 static DWORD FormatToTymed(const UINT cfFormat)\r
33 {\r
34         switch(cfFormat)\r
35         {\r
36         case CF_BITMAP:\r
37                 return TYMED_GDI;\r
38 \r
39         case CF_METAFILEPICT:\r
40                 return TYMED_MFPICT;\r
41 \r
42         case CF_ENHMETAFILE:\r
43                 return TYMED_ENHMF;\r
44         }\r
45         return TYMED_HGLOBAL;\r
46 }\r
47 \r
48 \r
49 /******************************************************************************\r
50 \r
51         IDropTarget\r
52 \r
53 ******************************************************************************/\r
54 \r
55 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_QueryInterface(LPDROPTARGET pThis, REFIID riid, LPVOID *ppvObject);\r
56 static ULONG STDMETHODCALLTYPE OLE_IDropTarget_AddRef(LPDROPTARGET pThis);\r
57 static ULONG STDMETHODCALLTYPE OLE_IDropTarget_Release(LPDROPTARGET pThis);\r
58 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragEnter(LPDROPTARGET pThis, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);\r
59 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragOver(LPDROPTARGET pThis, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);\r
60 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragLeave(LPDROPTARGET pThis);\r
61 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_Drop(LPDROPTARGET pThis, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);\r
62 static HRESULT APIPRIVATE OLE_IDropTarget_Internal_SendMessage(LPDROPTARGET pThis, UINT uNotify, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL *ppt, LPDWORD pdwEffect);\r
63 static HRESULT APIPRIVATE DropTarget_GetData(LPDATAOBJECT pdo, UINT cfFormat, LPSTGMEDIUM psm);\r
64 static HRESULT APIPRIVATE DropTarget_QueryGetData(LPDATAOBJECT pdo, UINT cfFormat);\r
65 \r
66 /* IDropTarget Virtual Table */\r
67 static IDropTargetVtbl dtv = {\r
68         OLE_IDropTarget_QueryInterface,\r
69         OLE_IDropTarget_AddRef,\r
70         OLE_IDropTarget_Release,\r
71         OLE_IDropTarget_DragEnter,\r
72         OLE_IDropTarget_DragOver,\r
73         OLE_IDropTarget_DragLeave,\r
74         OLE_IDropTarget_Drop\r
75 };\r
76 \r
77 typedef struct _IDROPTARGET_INTERNAL{\r
78         LPVOID lpVtbl;\r
79         ULONG m_refCnt;\r
80         HWND hWnd;\r
81         UINT uCallbackMessage;\r
82         UINT *cFormat;\r
83         int cfcnt;\r
84         IDROPTARGET_NOTIFY dtn;\r
85 }IDROPTARGET_INTERNAL , *LPIDROPTARGET_INTERNAL;\r
86 \r
87 /* OLEのドロップターゲットとして登録する */\r
88 BOOL APIPRIVATE OLE_IDropTarget_RegisterDragDrop(HWND hWnd, UINT uCallbackMessage, UINT *cFormat, int cfcnt)\r
89 {\r
90         static IDROPTARGET_INTERNAL *pdti;\r
91 \r
92         pdti = GlobalAlloc(GPTR, sizeof(IDROPTARGET_INTERNAL));\r
93         if(pdti == NULL){\r
94                 return FALSE;\r
95         }\r
96         pdti->lpVtbl = (LPVOID)&dtv;\r
97         pdti->m_refCnt = 0;\r
98         pdti->hWnd = hWnd;                                                                                                      /* メッセージを受け取るウィンドウ */\r
99         pdti->uCallbackMessage = uCallbackMessage;                                                      /* メッセージ */\r
100         pdti->cFormat = (UINT *)GlobalAlloc(GPTR, sizeof(UINT) * cfcnt);                /* 対応しているクリップボードフォーマット */\r
101         if(pdti->cFormat == NULL){\r
102                 GlobalFree(pdti);\r
103                 return FALSE;\r
104         }\r
105         CopyMemory(pdti->cFormat, cFormat, sizeof(UINT) * cfcnt);\r
106         pdti->cfcnt = cfcnt;                                                                                            /* クリップボードフォーマットの数 */\r
107         return (S_OK == RegisterDragDrop(hWnd, (LPDROPTARGET)pdti));\r
108 }\r
109 \r
110 /* OLEのドロップターゲットを解除する */\r
111 void APIPRIVATE OLE_IDropTarget_RevokeDragDrop(HWND hWnd)\r
112 {\r
113         RevokeDragDrop(hWnd);\r
114 }\r
115 \r
116 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_QueryInterface(LPDROPTARGET pThis, REFIID riid, PVOID *ppvObject)\r
117 {\r
118         //要求されたIIDと同じ場合はオブジェクトを返す\r
119         if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDropTarget)){\r
120                 *ppvObject = (LPVOID)pThis;\r
121                 ((LPUNKNOWN)*ppvObject)->lpVtbl->AddRef((LPUNKNOWN)*ppvObject);\r
122                 return S_OK;\r
123         }\r
124         *ppvObject = NULL;\r
125         return ResultFromScode(E_NOINTERFACE);\r
126 }\r
127 \r
128 static ULONG STDMETHODCALLTYPE OLE_IDropTarget_AddRef(LPDROPTARGET pThis)\r
129 {\r
130         CONST LPIDROPTARGET_INTERNAL pdti = (LPIDROPTARGET_INTERNAL)pThis;\r
131 \r
132         /* reference countをインクリメントする */\r
133         pdti->m_refCnt++;\r
134         return pdti->m_refCnt;\r
135 }\r
136 \r
137 static ULONG STDMETHODCALLTYPE OLE_IDropTarget_Release(LPDROPTARGET pThis)\r
138 {\r
139         CONST LPIDROPTARGET_INTERNAL pdti = (LPIDROPTARGET_INTERNAL)pThis;\r
140 \r
141         /* reference countをデクリメントする */\r
142         pdti->m_refCnt--;\r
143 \r
144         /* reference countが 0 になった場合はオブジェクトの解放を行う */\r
145         if(pdti->m_refCnt == 0L){\r
146                 if(pdti->cFormat != NULL){\r
147                         GlobalFree(pdti->cFormat);\r
148                 }\r
149                 GlobalFree(pdti);\r
150                 return 0L;\r
151         }\r
152         return pdti->m_refCnt;\r
153 }\r
154 \r
155 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragEnter(LPDROPTARGET pThis, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)\r
156 {\r
157         return OLE_IDropTarget_Internal_SendMessage(pThis, IDROPTARGET_NOTIFY_DRAGENTER, pdo, grfKeyState, &pt, pdwEffect);\r
158 }\r
159 \r
160 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragOver(LPDROPTARGET pThis, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)\r
161 {\r
162         return OLE_IDropTarget_Internal_SendMessage(pThis, IDROPTARGET_NOTIFY_DRAGOVER, NULL, grfKeyState, &pt, pdwEffect);\r
163 }\r
164 \r
165 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_DragLeave(LPDROPTARGET pThis)\r
166 {\r
167         return OLE_IDropTarget_Internal_SendMessage(pThis, IDROPTARGET_NOTIFY_DRAGLEAVE, NULL, 0, NULL, NULL);\r
168 }\r
169 \r
170 static HRESULT STDMETHODCALLTYPE OLE_IDropTarget_Drop(LPDROPTARGET pThis, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)\r
171 {\r
172         return OLE_IDropTarget_Internal_SendMessage(pThis, IDROPTARGET_NOTIFY_DROP, pdo, grfKeyState, &pt, pdwEffect);\r
173 }\r
174 \r
175 static HRESULT APIPRIVATE OLE_IDropTarget_Internal_SendMessage(LPDROPTARGET pThis, UINT uNotify, LPDATAOBJECT pdo, DWORD grfKeyState, POINTL *ppt, LPDWORD pdwEffect)\r
176 {\r
177         CONST LPIDROPTARGET_INTERNAL pdti = (LPIDROPTARGET_INTERNAL)pThis;\r
178         CONST LPIDROPTARGET_NOTIFY pdtn = &(pdti->dtn);\r
179         STGMEDIUM sm;\r
180         UINT cfFormat = 0;\r
181         int i;\r
182 \r
183         if(pdo){\r
184                 /* 対応しているクリップボードフォーマットがあるか調べる */\r
185                 for(i = 0;i < pdti->cfcnt;i++){\r
186                         if(DropTarget_QueryGetData(pdo, pdti->cFormat[i]) == S_OK){\r
187                                 cfFormat = pdti->cFormat[i];\r
188                                 break;\r
189                         }\r
190                 }\r
191                 /* クリップボードフォーマットからデータを取得する */\r
192                 if(cfFormat != 0){\r
193                         if (DropTarget_GetData(pdo, cfFormat, &sm) != S_OK){\r
194                                 cfFormat = 0;\r
195                         }\r
196                 }\r
197         }\r
198         pdtn->ppt = ppt;                                        /* マウスポインタの位置 */\r
199         pdtn->grfKeyState = grfKeyState;        /* キー、マウスボタンの状態 */\r
200         pdtn->cfFormat = cfFormat;                      /* クリップボードフォーマット */\r
201         pdtn->hMem = sm.hGlobal;                        /* 実データ */\r
202         pdtn->pdo = pdo;                                        /* IDataObject */\r
203 \r
204         /* ウィンドウにイベントを通知する */\r
205         SendMessage(pdti->hWnd, pdti->uCallbackMessage, (WPARAM)uNotify, (LPARAM)pdtn);\r
206 \r
207         /* クリップボード形式のデータの解放 */\r
208         if(cfFormat){\r
209                 ReleaseStgMedium(&sm);\r
210         }\r
211 \r
212         /* 効果の設定 */\r
213         if(pdwEffect){\r
214                 *pdwEffect &= pdtn->dwEffect;\r
215 \r
216                 if((*pdwEffect & DROPEFFECT_MOVE) && (*pdwEffect & DROPEFFECT_COPY)){\r
217                         *pdwEffect ^= DROPEFFECT_COPY;\r
218                         pdtn->dwEffect ^= DROPEFFECT_COPY;\r
219                 }\r
220         }\r
221         return S_OK;\r
222 }\r
223 \r
224 static HRESULT APIPRIVATE DropTarget_GetData(LPDATAOBJECT pdo, UINT cfFormat, LPSTGMEDIUM psm)\r
225 {\r
226         FORMATETC fmt;\r
227 \r
228         /* IDataObjectにクリップボード形式のデータを要求する */\r
229         fmt.cfFormat = cfFormat;\r
230         fmt.ptd = NULL;\r
231         fmt.dwAspect = DVASPECT_CONTENT;\r
232         fmt.lindex = -1;\r
233         fmt.tymed = FormatToTymed(cfFormat);\r
234         return pdo->lpVtbl->GetData(pdo, &fmt, psm);\r
235 }\r
236 \r
237 static HRESULT APIPRIVATE DropTarget_QueryGetData(LPDATAOBJECT pdo, UINT cfFormat)\r
238 {\r
239         FORMATETC fmt;\r
240 \r
241         /* IDataObjectに指定のクリップボードフォーマットが存在するか問い合わせる */\r
242         fmt.cfFormat = cfFormat;\r
243         fmt.ptd = NULL;\r
244         fmt.dwAspect = DVASPECT_CONTENT;\r
245         fmt.lindex = -1;\r
246         fmt.tymed = FormatToTymed(cfFormat);\r
247         return pdo->lpVtbl->QueryGetData(pdo, &fmt);\r
248 }\r
249 \r
250 \r
251 /******************************************************************************\r
252 \r
253         IEnumFORMATETC\r
254 \r
255 ******************************************************************************/\r
256 \r
257 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* lplpvObj);\r
258 static ULONG STDMETHODCALLTYPE OLE_IEnumFORMATETC_AddRef(LPENUMFORMATETC lpThis);\r
259 static ULONG STDMETHODCALLTYPE OLE_IEnumFORMATETC_Release(LPENUMFORMATETC lpThis);\r
260 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Next(LPENUMFORMATETC lpThis, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);\r
261 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Skip(LPENUMFORMATETC lpThis, ULONG celt);\r
262 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Reset(LPENUMFORMATETC lpThis);\r
263 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Clone(LPENUMFORMATETC lpThis, IEnumFORMATETC **ppenum);\r
264 \r
265 /* IEnumFORMATETC Virtual Table */\r
266 static IEnumFORMATETCVtbl efv = {\r
267         OLE_IEnumFORMATETC_QueryInterface,\r
268         OLE_IEnumFORMATETC_AddRef,\r
269         OLE_IEnumFORMATETC_Release,\r
270         OLE_IEnumFORMATETC_Next,\r
271         OLE_IEnumFORMATETC_Skip,\r
272         OLE_IEnumFORMATETC_Reset,\r
273         OLE_IEnumFORMATETC_Clone\r
274 };\r
275 \r
276 typedef struct _IENUMFORMATETC_INTERNAL{\r
277         LPVOID lpVtbl;\r
278         ULONG m_refCnt;\r
279         LPUNKNOWN m_pUnknownObj;\r
280         ULONG m_currElement;\r
281         ULONG m_numFormats;\r
282         LPFORMATETC m_formatList;\r
283 }IENUMFORMATETC_INTERNAL , *LPIENUMFORMATETC_INTERNAL;\r
284 \r
285 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* lplpvObj)\r
286 {\r
287         //要求されたIIDと同じ場合はオブジェクトを返す\r
288         if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumFORMATETC)){\r
289                 *lplpvObj = (LPVOID) lpThis;\r
290                  ((LPUNKNOWN)*lplpvObj)->lpVtbl->AddRef(((LPUNKNOWN)*lplpvObj));\r
291                 return S_OK;\r
292         }\r
293         *lplpvObj = NULL;\r
294         return ResultFromScode(E_NOINTERFACE);\r
295 }\r
296 \r
297 static ULONG STDMETHODCALLTYPE OLE_IEnumFORMATETC_AddRef(LPENUMFORMATETC lpThis)\r
298 {\r
299         CONST LPIENUMFORMATETC_INTERNAL pefi = (LPIENUMFORMATETC_INTERNAL)lpThis;\r
300 \r
301         /* reference countをインクリメントする */\r
302         pefi->m_refCnt++;\r
303         /* 親オブジェクトのreference countを加える */\r
304         pefi->m_pUnknownObj->lpVtbl->AddRef(pefi->m_pUnknownObj);\r
305         return pefi->m_refCnt;\r
306 }\r
307 \r
308 static ULONG STDMETHODCALLTYPE OLE_IEnumFORMATETC_Release(LPENUMFORMATETC lpThis)\r
309 {\r
310         CONST LPIENUMFORMATETC_INTERNAL pefi = (LPIENUMFORMATETC_INTERNAL)lpThis;\r
311 \r
312         /* reference countをデクリメントする */\r
313         pefi->m_refCnt--;\r
314         /* 親オブジェクトのreference countを減らす */\r
315         pefi->m_pUnknownObj->lpVtbl->Release(pefi->m_pUnknownObj);\r
316 \r
317         /* reference countが 0 になった場合はオブジェクトの解放を行う */\r
318         if(pefi->m_refCnt == 0L){\r
319                 if(pefi->m_formatList != NULL){\r
320                         GlobalFree(pefi->m_formatList);\r
321                 }\r
322                 GlobalFree(pefi);\r
323                 return 0L;\r
324         }\r
325         return pefi->m_refCnt;\r
326 }\r
327 \r
328 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Next(LPENUMFORMATETC lpThis, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched)\r
329 {\r
330         ULONG i;\r
331         ULONG cReturn=0L;\r
332         LPIENUMFORMATETC_INTERNAL lpefi = ((LPIENUMFORMATETC_INTERNAL)lpThis);\r
333 \r
334         if(pceltFetched){\r
335                 *pceltFetched = 0L;\r
336         }\r
337         if(lpefi->m_formatList == NULL){\r
338                 return ResultFromScode(S_FALSE);\r
339         }\r
340 \r
341         if(rgelt == NULL){\r
342                 if(celt == 1){\r
343                         return ResultFromScode(S_FALSE);\r
344                 }else{\r
345                         return ResultFromScode(E_POINTER);\r
346                 }\r
347         }\r
348 \r
349         if(lpefi->m_currElement >= lpefi->m_numFormats){\r
350                 return ResultFromScode(S_FALSE);\r
351         }\r
352 \r
353         for(i = 0;i < celt && lpefi->m_currElement < lpefi->m_numFormats;i++, lpefi->m_currElement++){\r
354                 *rgelt = lpefi->m_formatList[lpefi->m_currElement];\r
355                 rgelt++;\r
356         }\r
357 \r
358         if(pceltFetched != NULL){\r
359                 *pceltFetched = i;\r
360         }\r
361         return S_OK;\r
362 \r
363 }\r
364 \r
365 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Skip(LPENUMFORMATETC lpThis, ULONG celt)\r
366 {\r
367         LPIENUMFORMATETC_INTERNAL lpefi = ((LPIENUMFORMATETC_INTERNAL)lpThis);\r
368 \r
369         lpefi->m_currElement += celt;\r
370 \r
371         if(lpefi->m_currElement > lpefi->m_numFormats){\r
372                 lpefi->m_currElement = lpefi->m_numFormats;\r
373                 return ResultFromScode(S_FALSE);\r
374         }\r
375         return S_OK;\r
376 }\r
377 \r
378 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Reset(LPENUMFORMATETC lpThis)\r
379 {\r
380         LPIENUMFORMATETC_INTERNAL lpefi = ((LPIENUMFORMATETC_INTERNAL)lpThis);\r
381 \r
382         lpefi->m_currElement = 0L;\r
383         return S_OK;\r
384 }\r
385 \r
386 static HRESULT STDMETHODCALLTYPE OLE_IEnumFORMATETC_Clone(LPENUMFORMATETC lpThis, IEnumFORMATETC **ppenum)\r
387 {\r
388         LPIENUMFORMATETC_INTERNAL pNew;\r
389         LPIENUMFORMATETC_INTERNAL lpefi = ((LPIENUMFORMATETC_INTERNAL)lpThis);\r
390         UINT i;\r
391 \r
392         /* IEnumFORMATETCを作成する */\r
393         pNew = GlobalAlloc(GPTR, sizeof(IENUMFORMATETC_INTERNAL));\r
394         if(pNew == NULL){\r
395                 return ResultFromScode(E_OUTOFMEMORY);\r
396         }\r
397         pNew->lpVtbl = (LPVOID)&efv;\r
398         pNew->m_refCnt = 0;\r
399         pNew->m_currElement = 0;\r
400 \r
401         pNew->m_pUnknownObj = lpefi->m_pUnknownObj;\r
402         pNew->m_numFormats = lpefi->m_numFormats;\r
403 \r
404         /* クリップボードフォーマットのリストをコピーする */\r
405         pNew->m_formatList = GlobalAlloc(GPTR, sizeof(FORMATETC) * pNew->m_numFormats);\r
406         if(pNew->m_formatList != NULL){\r
407                 for(i = 0;i < pNew->m_numFormats;i++){\r
408                           pNew->m_formatList[i] = lpefi->m_formatList[i];\r
409                 }\r
410         }\r
411 \r
412         *ppenum = (struct IEnumFORMATETC *)pNew;\r
413         if(pNew == NULL){\r
414                 return ResultFromScode(E_OUTOFMEMORY);\r
415         }\r
416         ((LPENUMFORMATETC)pNew)->lpVtbl->AddRef(((LPENUMFORMATETC)pNew));\r
417         pNew->m_currElement = lpefi->m_currElement;\r
418         return S_OK;\r
419 }\r
420 \r
421 \r
422 /******************************************************************************\r
423 \r
424         IDataObject\r
425 \r
426 ******************************************************************************/\r
427 \r
428 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_QueryInterface(LPDATAOBJECT lpThis, REFIID riid, LPVOID FAR *lplpvObj);\r
429 static ULONG STDMETHODCALLTYPE OLE_IDataObject_AddRef(LPDATAOBJECT lpThis);\r
430 static ULONG STDMETHODCALLTYPE OLE_IDataObject_Release(LPDATAOBJECT lpThis);\r
431 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium);\r
432 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetDataHere(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium);\r
433 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_QueryGetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc);\r
434 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT lpThis, FORMATETC *pFormatetcIn, FORMATETC *pFormatetcOut);\r
435 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_SetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium, BOOL fRelease);\r
436 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_EnumFormatEtc(LPDATAOBJECT lpThis, DWORD dwDirection, IEnumFORMATETC **ppenumFormatetc);\r
437 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_DAdvise(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);\r
438 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection);\r
439 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_EnumDAdvise(LPDATAOBJECT lpThis, IEnumSTATDATA **ppenumAdvise);\r
440 \r
441 /* IDataObject Virtual Table */\r
442 static IDataObjectVtbl dov = {\r
443         OLE_IDataObject_QueryInterface,\r
444         OLE_IDataObject_AddRef,\r
445         OLE_IDataObject_Release,\r
446         OLE_IDataObject_GetData,\r
447         OLE_IDataObject_GetDataHere,\r
448         OLE_IDataObject_QueryGetData,\r
449         OLE_IDataObject_GetCanonicalFormatEtc,\r
450         OLE_IDataObject_SetData,\r
451         OLE_IDataObject_EnumFormatEtc,\r
452         OLE_IDataObject_DAdvise,\r
453         OLE_IDataObject_DUnadvise,\r
454         OLE_IDataObject_EnumDAdvise\r
455 };\r
456 \r
457 typedef struct _IDATAOBJECT_INTERNAL{\r
458         LPVOID lpVtbl;\r
459         ULONG m_refCnt;\r
460         UINT m_numTypes;\r
461         UINT m_maxTypes;\r
462         FORMATETC *m_typeList;\r
463         HWND hWnd;\r
464         UINT uCallbackMessage;\r
465 }IDATAOBJECT_INTERNAL , *LPIDATAOBJECT_INTERNAL;\r
466 \r
467 \r
468 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_QueryInterface(LPDATAOBJECT lpThis, REFIID riid, LPVOID FAR *lplpvObj)\r
469 {\r
470         //要求されたIIDと同じ場合はオブジェクトを返す\r
471         if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDataObject)){\r
472                 *lplpvObj = lpThis;\r
473                  ((LPUNKNOWN)*lplpvObj)->lpVtbl->AddRef(((LPUNKNOWN)*lplpvObj));\r
474                 return S_OK;\r
475         }\r
476         *lplpvObj = NULL;\r
477         return ResultFromScode(E_NOINTERFACE);\r
478 }\r
479 \r
480 static ULONG STDMETHODCALLTYPE OLE_IDataObject_AddRef(LPDATAOBJECT lpThis)\r
481 {\r
482         CONST LPIDATAOBJECT_INTERNAL pdoi = (LPIDATAOBJECT_INTERNAL)lpThis;\r
483 \r
484         /* reference countをインクリメントする */\r
485         pdoi->m_refCnt++;\r
486         return pdoi->m_refCnt;\r
487 }\r
488 \r
489 static ULONG STDMETHODCALLTYPE OLE_IDataObject_Release(LPDATAOBJECT lpThis)\r
490 {\r
491         CONST LPIDATAOBJECT_INTERNAL pdoi = (LPIDATAOBJECT_INTERNAL)lpThis;\r
492 \r
493         /* reference countをデクリメントする */\r
494         pdoi->m_refCnt--;\r
495 \r
496         /* reference countが 0 になった場合はオブジェクトの解放を行う */\r
497         if(pdoi->m_refCnt == 0L){\r
498                 if(pdoi->m_typeList != NULL){\r
499                         GlobalFree(pdoi->m_typeList);\r
500                 }\r
501                 GlobalFree(pdoi);\r
502                 return 0L;\r
503         }\r
504         return pdoi->m_refCnt;\r
505 }\r
506 \r
507 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium)\r
508 {\r
509         CONST LPIDATAOBJECT_INTERNAL pdoi = (LPIDATAOBJECT_INTERNAL)lpThis;\r
510         HGLOBAL hMem;\r
511         UINT i;\r
512 \r
513         /* 要求されたクリップボードフォーマットが存在するか調べる */\r
514         for(i = 0;i < pdoi->m_numTypes;i++){\r
515                 if(pdoi->m_typeList[i].cfFormat == pFormatetc->cfFormat){\r
516                         break;\r
517                 }\r
518         }\r
519         if(i == pdoi->m_numTypes){\r
520                 /* 要求されたクリップボードフォーマットをサポートしてない場合 */\r
521                 return ResultFromScode(DV_E_FORMATETC);\r
522         }\r
523 \r
524         // マウスのドラッグ中は WM_GETDATA を送らないようにする。(2007.9.3 yutaka)\r
525         if (GetAsyncKeyState(VK_LBUTTON) & 0x8000 ||\r
526                 GetAsyncKeyState(VK_RBUTTON) & 0x8000) {\r
527                 return ResultFromScode(DV_E_FORMATETC);\r
528         }\r
529 \r
530         /* ウィンドウにデータの要求を行う */\r
531         SendMessage(pdoi->hWnd, pdoi->uCallbackMessage, (WPARAM)pdoi->m_typeList[i].cfFormat, (LPARAM)&hMem);\r
532         if(hMem == NULL){\r
533                 return ResultFromScode(STG_E_MEDIUMFULL);\r
534         }\r
535         pmedium->hGlobal = hMem;\r
536         pmedium->tymed = FormatToTymed(pFormatetc->cfFormat);\r
537         pmedium->pUnkForRelease = NULL;\r
538         return S_OK;\r
539 }\r
540 \r
541 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetDataHere(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium)\r
542 {\r
543         return ResultFromScode(E_NOTIMPL);\r
544 }\r
545 \r
546 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_QueryGetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc)\r
547 {\r
548         CONST LPIDATAOBJECT_INTERNAL pdoi = (LPIDATAOBJECT_INTERNAL)lpThis;\r
549         UINT i;\r
550 \r
551         /* 要求されたクリップボードフォーマットが存在するか調べる */\r
552         for(i = 0;i < pdoi->m_numTypes;i++){\r
553                 if(pdoi->m_typeList[i].cfFormat == pFormatetc->cfFormat){\r
554                         return S_OK;\r
555                 }\r
556         }\r
557         return ResultFromScode(DV_E_FORMATETC);\r
558 }\r
559 \r
560 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT lpThis, FORMATETC *pFormatetcIn, FORMATETC *pFormatetcOut)\r
561 {\r
562         return ResultFromScode(E_NOTIMPL);\r
563 }\r
564 \r
565 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_SetData(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, STGMEDIUM *pmedium, BOOL fRelease)\r
566 {\r
567         return ResultFromScode(E_NOTIMPL);\r
568 }\r
569 \r
570 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_EnumFormatEtc(LPDATAOBJECT lpThis, DWORD dwDirection, IEnumFORMATETC **ppenumFormatetc)\r
571 {\r
572         CONST LPIDATAOBJECT_INTERNAL pdoi = (LPIDATAOBJECT_INTERNAL)lpThis;\r
573         static IENUMFORMATETC_INTERNAL *pefi;\r
574         UINT i;\r
575 \r
576         if(ppenumFormatetc == NULL){\r
577                 return ResultFromScode(E_INVALIDARG);\r
578         }\r
579 \r
580         if(dwDirection != DATADIR_GET){\r
581                 *ppenumFormatetc = NULL;\r
582                 return ResultFromScode(E_NOTIMPL);\r
583         }\r
584 \r
585         /* IEnumFORMATETCを作成する */\r
586         pefi = GlobalAlloc(GPTR, sizeof(IENUMFORMATETC_INTERNAL));\r
587         if(pefi == NULL){\r
588                 return E_OUTOFMEMORY;\r
589         }\r
590         pefi->lpVtbl = (LPVOID)&efv;\r
591         pefi->m_refCnt = 0;\r
592         pefi->m_currElement = 0;\r
593         pefi->m_pUnknownObj = (struct IUnknown *)lpThis;\r
594         pefi->m_numFormats = pdoi->m_numTypes;\r
595 \r
596         /* クリップボードフォーマットのリストをコピーする */\r
597         pefi->m_formatList = GlobalAlloc(GPTR, sizeof(FORMATETC) * pefi->m_numFormats);\r
598         if(pefi->m_formatList != NULL){\r
599                 for(i = 0;i < pefi->m_numFormats;i++){\r
600                           pefi->m_formatList[i] = pdoi->m_typeList[i];\r
601                 }\r
602         }\r
603 \r
604         ((LPENUMFORMATETC)pefi)->lpVtbl->AddRef(((LPENUMFORMATETC)pefi));\r
605 \r
606         *ppenumFormatetc = (struct IEnumFORMATETC *)pefi;\r
607         if(*ppenumFormatetc == NULL){\r
608                 return E_OUTOFMEMORY;\r
609         }\r
610         return S_OK;\r
611 }\r
612 \r
613 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_DAdvise(LPDATAOBJECT lpThis, FORMATETC *pFormatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)\r
614 {\r
615         return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);\r
616 }\r
617 \r
618 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection)\r
619 {\r
620         return ResultFromScode(OLE_E_NOCONNECTION);\r
621 }\r
622 \r
623 static HRESULT STDMETHODCALLTYPE OLE_IDataObject_EnumDAdvise(LPDATAOBJECT lpThis, IEnumSTATDATA **ppenumAdvise)\r
624 {\r
625         return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);\r
626 }\r
627 \r
628 \r
629 /******************************************************************************\r
630 \r
631         IDropSource\r
632 \r
633 ******************************************************************************/\r
634 \r
635 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_QueryInterface(LPDROPSOURCE lpThis, REFIID riid, LPVOID FAR* lplpvObj);\r
636 static ULONG STDMETHODCALLTYPE OLE_IDropSource_AddRef(LPDROPSOURCE lpThis);\r
637 static ULONG STDMETHODCALLTYPE OLE_IDropSource_Release(LPDROPSOURCE lpThis);\r
638 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_QueryContinueDrag(LPDROPSOURCE lpThis, BOOL fEscapePressed, DWORD grfKeyState);\r
639 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_GiveFeedback(LPDROPSOURCE lpThis, DWORD dwEffect);\r
640 \r
641 /* IDropSource Virtual Table */\r
642 static IDropSourceVtbl dsv = {\r
643         OLE_IDropSource_QueryInterface,\r
644         OLE_IDropSource_AddRef,\r
645         OLE_IDropSource_Release,\r
646         OLE_IDropSource_QueryContinueDrag,\r
647         OLE_IDropSource_GiveFeedback,\r
648 };\r
649 \r
650 typedef struct _IDROPSOURCE_INTERNAL{\r
651         LPVOID lpVtbl;\r
652         ULONG m_refCnt;\r
653         DWORD m_keyState;\r
654         DWORD m_button;\r
655         HWND m_hWnd;\r
656         UINT m_uCallbackDragOverMessage;\r
657 }IDROPSOURCE_INTERNAL , *LPIDROPSOURCE_INTERNAL;\r
658 \r
659 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_QueryInterface(LPDROPSOURCE lpThis, REFIID riid, LPVOID FAR *lplpvObj)\r
660 {\r
661         //要求されたIIDと同じ場合はオブジェクトを返す\r
662         if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDropSource)){\r
663                 *lplpvObj = (LPVOID) lpThis;\r
664                 ((LPUNKNOWN)*lplpvObj)->lpVtbl->AddRef(((LPUNKNOWN)*lplpvObj));\r
665                 return S_OK;\r
666         }\r
667         *lplpvObj = NULL;\r
668         return ResultFromScode(E_NOINTERFACE);\r
669 \r
670 }\r
671 \r
672 static ULONG STDMETHODCALLTYPE OLE_IDropSource_AddRef(LPDROPSOURCE lpThis)\r
673 {\r
674         CONST LPIDROPSOURCE_INTERNAL pdsi = (LPIDROPSOURCE_INTERNAL)lpThis;\r
675 \r
676         /* reference countをインクリメントする */\r
677         pdsi->m_refCnt++;\r
678         return pdsi->m_refCnt;\r
679 }\r
680 \r
681 static ULONG STDMETHODCALLTYPE OLE_IDropSource_Release(LPDROPSOURCE lpThis)\r
682 {\r
683         CONST LPIDROPSOURCE_INTERNAL pdsi = (LPIDROPSOURCE_INTERNAL)lpThis;\r
684 \r
685         /* reference countをデクリメントする */\r
686         pdsi->m_refCnt--;\r
687 \r
688         /* reference countが 0 になった場合はオブジェクトの解放を行う */\r
689         if(pdsi->m_refCnt == 0L){\r
690                 GlobalFree(pdsi);\r
691                 return 0L;\r
692         }\r
693         return pdsi->m_refCnt;\r
694 }\r
695 \r
696 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_QueryContinueDrag(LPDROPSOURCE lpThis, BOOL fEscapePressed, DWORD grfKeyState)\r
697 {\r
698         CONST LPIDROPSOURCE_INTERNAL pdsi = (LPIDROPSOURCE_INTERNAL)lpThis;\r
699 \r
700         if(fEscapePressed){\r
701                 /* エスケープが押された場合はキャンセルにする */\r
702                 return ResultFromScode(DRAGDROP_S_CANCEL);\r
703         }\r
704 \r
705         // Mouse overの通知 (yutaka)\r
706         SendMessage(pdsi->m_hWnd, pdsi->m_uCallbackDragOverMessage, 0, 0);\r
707 \r
708         /* 指定のキーやマウスが離された場合はドロップにする */\r
709         if(pdsi->m_button == 0){\r
710                 if(grfKeyState != pdsi->m_keyState){\r
711                         return ResultFromScode(DRAGDROP_S_DROP);\r
712                 }\r
713         }else{\r
714                 if(!(grfKeyState & pdsi->m_button)){\r
715                         return ResultFromScode(DRAGDROP_S_DROP);\r
716                 }\r
717         }\r
718         return S_OK;\r
719 }\r
720 \r
721 static HRESULT STDMETHODCALLTYPE OLE_IDropSource_GiveFeedback(LPDROPSOURCE lpThis, DWORD dwEffect)\r
722 {\r
723         return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);\r
724 }\r
725 \r
726 /* ドラッグ&ドロップの開始 */\r
727 int APIPRIVATE OLE_IDropSource_Start(HWND hWnd, UINT uCallbackMessage, UINT uCallbackDragOverMessage, UINT *ClipFormtList, int cfcnt, int Effect)\r
728 {\r
729         static IDATAOBJECT_INTERNAL *pdoi;\r
730         static IDROPSOURCE_INTERNAL *pdsi;\r
731         DWORD lpdwEffect;\r
732         DWORD keyState;\r
733         int i;\r
734         int ret;\r
735 \r
736         /* IDataObjectの作成 */\r
737         pdoi = GlobalAlloc(GPTR, sizeof(IDATAOBJECT_INTERNAL));\r
738         if(pdoi == NULL){\r
739                 return -1;\r
740         }\r
741         pdoi->lpVtbl = (LPVOID)&dov;\r
742         pdoi->m_refCnt = 0;\r
743         pdoi->m_numTypes = cfcnt;\r
744         pdoi->m_maxTypes = cfcnt;\r
745         /* 有効なクリップボードフォーマットを設定する */\r
746         pdoi->m_typeList = GlobalAlloc(GPTR, sizeof(FORMATETC) * cfcnt);\r
747         if(pdoi->m_typeList == NULL){\r
748                 GlobalFree(pdoi);\r
749                 return -1;\r
750         }\r
751         for(i = 0;i < cfcnt;i++){\r
752                 pdoi->m_typeList[i].cfFormat = ClipFormtList[i];\r
753                 pdoi->m_typeList[i].ptd = NULL;\r
754                 pdoi->m_typeList[i].dwAspect = DVASPECT_CONTENT;\r
755                 pdoi->m_typeList[i].lindex = -1;\r
756                 pdoi->m_typeList[i].tymed = FormatToTymed(ClipFormtList[i]);\r
757         }\r
758         pdoi->hWnd = hWnd;\r
759         pdoi->uCallbackMessage = uCallbackMessage;\r
760         ((LPDATAOBJECT)pdoi)->lpVtbl->AddRef((LPDATAOBJECT)pdoi);\r
761 \r
762         /* IDropSourceの作成 */\r
763         pdsi = GlobalAlloc(GPTR, sizeof(IDROPSOURCE_INTERNAL));\r
764         if(pdsi == NULL){\r
765                 /* IDataObjectを解放する */\r
766                 ((LPDATAOBJECT)pdoi)->lpVtbl->Release((LPDATAOBJECT)pdoi);\r
767                 return -1;\r
768         }\r
769         pdsi->lpVtbl = (LPVOID)&dsv;\r
770         pdsi->m_refCnt = 0;\r
771         pdsi->m_hWnd = hWnd; // yutaka\r
772         pdsi->m_uCallbackDragOverMessage = uCallbackDragOverMessage;\r
773 \r
774         /* 有効なキーとマウスの状態 */\r
775         if(GetKeyState(VK_RBUTTON) & 0x8000){\r
776                 pdsi->m_button = MK_RBUTTON;\r
777         }else{\r
778                 pdsi->m_button = MK_LBUTTON;\r
779         }\r
780 \r
781         /* 現在のキーとマウスの状態 */\r
782         keyState = 0;\r
783         if(GetKeyState(VK_SHIFT) & 0x8000){\r
784                 keyState |= MK_SHIFT;\r
785         }\r
786         if(GetKeyState(VK_CONTROL) & 0x8000){\r
787                 keyState |= MK_CONTROL;\r
788         }\r
789         if(GetKeyState(VK_MENU) & 0x8000){\r
790                 keyState |= MK_ALT;\r
791         }\r
792         if(GetKeyState(VK_LBUTTON) & 0x8000){\r
793                 keyState |= MK_LBUTTON;\r
794         }\r
795         if(GetKeyState(VK_MBUTTON) & 0x8000){\r
796                 keyState |= MK_MBUTTON;\r
797         }\r
798         if(GetKeyState(VK_RBUTTON) & 0x8000){\r
799                 keyState |= MK_RBUTTON;\r
800         }\r
801         pdsi->m_keyState = keyState;\r
802         ((LPDROPSOURCE)pdsi)->lpVtbl->AddRef((LPDROPSOURCE)pdsi);\r
803 \r
804         lpdwEffect = 0;\r
805 \r
806         /* ドラッグ&ドロップの開始 */\r
807         ret = DoDragDrop((LPDATAOBJECT)pdoi, (LPDROPSOURCE)pdsi, Effect, &lpdwEffect);\r
808 \r
809         /* IDataObjectを解放する */\r
810         ((LPDATAOBJECT)pdoi)->lpVtbl->Release((LPDATAOBJECT)pdoi);\r
811         /* IDropSourceを解放する */\r
812         ((LPDROPSOURCE)pdsi)->lpVtbl->Release((LPDROPSOURCE)pdsi);\r
813 \r
814         if(ret == DRAGDROP_S_DROP){\r
815                 /* ドロップ先のアプリケーションが設定した効果を返す */\r
816                 return lpdwEffect;\r
817         }\r
818         return -1;\r
819 }\r
820 /* End of source */\r