?? gdkdnd-win32.c
字號:
}static HRESULT STDMETHODCALLTYPEidataobject_dunadvise (LPDATAOBJECT This, DWORD dwConnection){ GDK_NOTE (DND, g_print ("idataobject_dunadvise %p\n", This)); return E_FAIL;}static HRESULT STDMETHODCALLTYPEidataobject_enumdadvise (LPDATAOBJECT This, LPENUMSTATDATA *ppenumAdvise){ GDK_NOTE (DND, g_print ("idataobject_enumdadvise %p\n", This)); return E_FAIL;} static ULONG STDMETHODCALLTYPEienumformatetc_addref (LPENUMFORMATETC This){ enum_formats *en = (enum_formats *) This; int ref_count = ++en->ref_count; GDK_NOTE (DND, g_print ("ienumformatetc_addref %p %d\n", This, ref_count)); return ref_count;}static HRESULT STDMETHODCALLTYPEienumformatetc_queryinterface (LPENUMFORMATETC This, REFIID riid, LPVOID *ppvObject){ GDK_NOTE (DND, g_print ("ienumformatetc_queryinterface %p\n", This)); *ppvObject = NULL; PRINT_GUID (riid); if (IsEqualGUID (riid, &IID_IUnknown)) { g_print ("...IUnknown\n"); ienumformatetc_addref (This); *ppvObject = This; return S_OK; } else if (IsEqualGUID (riid, &IID_IEnumFORMATETC)) { g_print ("...IEnumFORMATETC\n"); ienumformatetc_addref (This); *ppvObject = This; return S_OK; } else { g_print ("...Huh?\n"); return E_NOINTERFACE; }}static ULONG STDMETHODCALLTYPEienumformatetc_release (LPENUMFORMATETC This){ enum_formats *en = (enum_formats *) This; int ref_count = --en->ref_count; GDK_NOTE (DND, g_print ("ienumformatetc_release %p %d\n", This, ref_count)); if (ref_count == 0) g_free (This); return ref_count;}static HRESULT STDMETHODCALLTYPEienumformatetc_next (LPENUMFORMATETC This, ULONG celt, LPFORMATETC elts, ULONG *nelt){ enum_formats *en = (enum_formats *) This; int i, n; GDK_NOTE (DND, g_print ("ienumformatetc_next %p %d %ld\n", This, en->ix, celt)); n = 0; for (i = 0; i < celt; i++) { if (en->ix >= nformats) break; elts[i] = formats[en->ix++]; n++; } if (nelt != NULL) *nelt = n; if (n == celt) return S_OK; else return S_FALSE;}static HRESULT STDMETHODCALLTYPEienumformatetc_skip (LPENUMFORMATETC This, ULONG celt){ enum_formats *en = (enum_formats *) This; GDK_NOTE (DND, g_print ("ienumformatetc_skip %p %d %ld\n", This, en->ix, celt)); en->ix += celt; return S_OK;}static HRESULT STDMETHODCALLTYPEienumformatetc_reset (LPENUMFORMATETC This){ enum_formats *en = (enum_formats *) This; GDK_NOTE (DND, g_print ("ienumformatetc_reset %p\n", This)); en->ix = 0; return S_OK;}static HRESULT STDMETHODCALLTYPEienumformatetc_clone (LPENUMFORMATETC This, LPENUMFORMATETC *ppEnumFormatEtc){ enum_formats *en = (enum_formats *) This; enum_formats *new; GDK_NOTE (DND, g_print ("ienumformatetc_clone %p\n", This)); new = enum_formats_new (); new->ix = en->ix; *ppEnumFormatEtc = &new->ief; return S_OK;}static IDropTargetVtbl idt_vtbl = { idroptarget_queryinterface, idroptarget_addref, idroptarget_release, idroptarget_dragenter, idroptarget_dragover, idroptarget_dragleave, idroptarget_drop};static IDropSourceVtbl ids_vtbl = { idropsource_queryinterface, idropsource_addref, idropsource_release, idropsource_querycontinuedrag, idropsource_givefeedback};static IDataObjectVtbl ido_vtbl = { idataobject_queryinterface, idataobject_addref, idataobject_release, idataobject_getdata, idataobject_getdatahere, idataobject_querygetdata, idataobject_getcanonicalformatetc, idataobject_setdata, idataobject_enumformatetc, idataobject_dadvise, idataobject_dunadvise, idataobject_enumdadvise};static IEnumFORMATETCVtbl ief_vtbl = { ienumformatetc_queryinterface, ienumformatetc_addref, ienumformatetc_release, ienumformatetc_next, ienumformatetc_skip, ienumformatetc_reset, ienumformatetc_clone};static target_drag_context *target_context_new (void){ target_drag_context *result; result = g_new0 (target_drag_context, 1); result->idt.lpVtbl = &idt_vtbl; result->context = gdk_drag_context_new (); result->context->is_source = FALSE; GDK_NOTE (DND, g_print ("target_context_new: %p\n", result)); return result;}static source_drag_context *source_context_new (void){ source_drag_context *result; result = g_new0 (source_drag_context, 1); result->ids.lpVtbl = &ids_vtbl; result->context = gdk_drag_context_new (); result->context->is_source = TRUE; GDK_NOTE (DND, g_print ("source_context_new: %p\n", result)); return result;}static data_object *data_object_new (void){ data_object *result; result = g_new0 (data_object, 1); result->ido.lpVtbl = &ido_vtbl; result->ref_count = 1; GDK_NOTE (DND, g_print ("data_object_new: %p\n", result)); return result;}static enum_formats *enum_formats_new (void){ enum_formats *result; result = g_new0 (enum_formats, 1); result->ief.lpVtbl = &ief_vtbl; result->ref_count = 1; result->ix = 0; GDK_NOTE (DND, g_print ("enum_formats_new: %p\n", result)); return result;}#endif/* From MS Knowledge Base article Q130698 */static HRESULT resolve_link (HWND hWnd, guchar *lpszLinkName, guchar **lpszPath){ HRESULT hres; IShellLinkA *pslA = NULL; IShellLinkW *pslW = NULL; IPersistFile *ppf = NULL; /* Assume failure to start with: */ *lpszPath = 0; /* Call CoCreateInstance to obtain the IShellLink interface * pointer. This call fails if CoInitialize is not called, so it is * assumed that CoInitialize has been called. */ if (G_WIN32_HAVE_WIDECHAR_API ()) hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID *)&pslW); else hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, (LPVOID *)&pslA); if (SUCCEEDED (hres)) { /* The IShellLink interface supports the IPersistFile * interface. Get an interface pointer to it. */ if (G_WIN32_HAVE_WIDECHAR_API ()) hres = pslW->lpVtbl->QueryInterface (pslW, &IID_IPersistFile, (LPVOID *) &ppf); else hres = pslA->lpVtbl->QueryInterface (pslA, &IID_IPersistFile, (LPVOID *) &ppf); } if (SUCCEEDED (hres)) { /* Convert the given link name string to wide character string. */ wchar_t *wsz = g_utf8_to_utf16 (lpszLinkName, -1, NULL, NULL, NULL); /* Load the file. */ hres = ppf->lpVtbl->Load (ppf, wsz, STGM_READ); g_free (wsz); } if (SUCCEEDED (hres)) { /* Resolve the link by calling the Resolve() * interface function. */ if (G_WIN32_HAVE_WIDECHAR_API ()) hres = pslW->lpVtbl->Resolve (pslW, hWnd, SLR_ANY_MATCH | SLR_NO_UI); else hres = pslA->lpVtbl->Resolve (pslA, hWnd, SLR_ANY_MATCH | SLR_NO_UI); } if (SUCCEEDED (hres)) { if (G_WIN32_HAVE_WIDECHAR_API ()) { wchar_t wtarget[MAX_PATH]; hres = pslW->lpVtbl->GetPath (pslW, wtarget, MAX_PATH, NULL, 0); if (SUCCEEDED (hres)) *lpszPath = g_utf16_to_utf8 (wtarget, -1, NULL, NULL, NULL); } else { guchar cptarget[MAX_PATH]; hres = pslA->lpVtbl->GetPath (pslA, cptarget, MAX_PATH, NULL, 0); if (SUCCEEDED (hres)) *lpszPath = g_locale_to_utf8 (cptarget, -1, NULL, NULL, NULL); } } if (ppf) ppf->lpVtbl->Release (ppf); if (pslW) pslW->lpVtbl->Release (pslW); if (pslA) pslA->lpVtbl->Release (pslA); return SUCCEEDED (hres);}static GdkFilterReturngdk_dropfiles_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ GdkDragContext *context; GdkDragContextPrivateWin32 *private; GString *result; MSG *msg = (MSG *) xev; HANDLE hdrop; POINT pt; gint nfiles, i; guchar *fileName, *linkedFile; if (msg->message == WM_DROPFILES) { GDK_NOTE (DND, g_print ("WM_DROPFILES: %p\n", msg->hwnd)); context = gdk_drag_context_new (); private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context); context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES; context->is_source = FALSE; context->source_window = _gdk_parent_root; g_object_ref (context->source_window); context->dest_window = event->any.window; g_object_ref (context->dest_window); /* WM_DROPFILES drops are always file names */ context->targets = g_list_append (NULL, GUINT_TO_POINTER (_text_uri_list)); context->actions = GDK_ACTION_COPY; context->suggested_action = GDK_ACTION_COPY; current_dest_drag = context; event->dnd.type = GDK_DROP_START; event->dnd.context = current_dest_drag; hdrop = (HANDLE) msg->wParam; DragQueryPoint (hdrop, &pt); ClientToScreen (msg->hwnd, &pt); event->dnd.x_root = pt.x + _gdk_offset_x; event->dnd.y_root = pt.y + _gdk_offset_y; event->dnd.time = _gdk_win32_get_next_tick (msg->time); nfiles = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0); result = g_string_new (NULL); for (i = 0; i < nfiles; i++) { gchar *uri; if (G_WIN32_HAVE_WIDECHAR_API ()) { wchar_t wfn[MAX_PATH]; DragQueryFileW (hdrop, i, wfn, MAX_PATH); fileName = g_utf16_to_utf8 (wfn, -1, NULL, NULL, NULL); } else { char cpfn[MAX_PATH]; DragQueryFileA (hdrop, i, cpfn, MAX_PATH); fileName = g_locale_to_utf8 (cpfn, -1, NULL, NULL, NULL); } /* Resolve shortcuts */ if (resolve_link (msg->hwnd, fileName, &linkedFile)) { uri = g_filename_to_uri (linkedFile, NULL, NULL); g_free (linkedFile); if (uri != NULL) { g_string_append (result, uri); GDK_NOTE (DND, g_print ("...%s link to %s: %s\n", fileName, linkedFile, uri)); g_free (uri); } } else { uri = g_filename_to_uri (fileName, NULL, NULL); if (uri != NULL) { g_string_append (result, uri); GDK_NOTE (DND, g_print ("...%s: %s\n", fileName, uri)); g_free (uri); } } g_free (fileName); g_string_append (result, "\015\012"); } _gdk_dropfiles_store (result->str); g_string_free (result, FALSE); DragFinish (hdrop); return GDK_FILTER_TRANSLATE; } else return GDK_FILTER_CONTINUE;}/************************************************************* ************************** Public API *********************** *************************************************************/void_gdk_dnd_init (void){#ifdef OLE2_DND HRESULT hres; hres = OleInitialize (NULL); if (! SUCCEEDED (hres)) g_error ("OleInitialize failed"); nformats = 2; formats = g_new (FORMATETC, nformats); formats[0].cfFormat = CF_TEXT; formats[0].ptd = NULL; formats[0].dwAspect = DVASPECT_CONTENT; formats[0].lindex = -1; formats[0].tymed = TYMED_HGLOBAL; formats[1].cfFormat = CF_GDIOBJFIRST; formats[1].ptd = NULL; formats[1].dwAspect = DVASPECT_CONTENT; formats[1].lindex = -1; formats[1].tymed = TYMED_HGLOBAL;#endif} void_gdk_win32_dnd_exit (void){#ifdef OLE2_DND OleUninitialize ();#endif}/* Source side */static voidlocal_send_leave (GdkDragContext *context, guint32 time){ GdkEvent tmp_event; if ((current_dest_drag != NULL) && (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && (current_dest_drag->source_window == context->source_window)) { tmp_event.dnd.type = GDK_DRAG_LEAVE; tmp_event.dnd.window = context->dest_window; /* Pass ownership of context to the event */ tmp_event.dnd.send_event = FALSE; tmp_event.dnd.context = current_dest_drag; tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ current_dest_drag = NULL; gdk_event_put (&tmp_event); }}static voidlocal_send_enter (GdkDragContext *context, guint32 time){ GdkEvent tmp_event; GdkDragContextPrivateWin32 *private; GdkDragContext *new_context; private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context); if (current_dest_drag != NULL) { gdk_drag_context_unref (current_dest_drag); current_dest_drag = NULL; } new_context = gdk_drag_context_new (); new_context->protocol = GDK_DRAG_PROTO_LOCAL; new_context->is_source = FALSE; new_context->source_window = context->source_window; g_object_ref (new_context->source_window); new_context->dest_window = context->dest_window; g_object_ref (new_context->dest_window); new_context->targets = g_list_copy (context->targets); gdk_window_set_events (new_context->source_window, gdk_window_get_events (new_context->source_window) | GDK_PROPERTY_CHANGE_MASK); new_context->actions = context->actions; tmp_event.dnd.type = GDK_DRAG_ENTER; tmp_event.dnd.window = context->dest_window; tmp_event.dnd.send_event = FALSE; tmp_event.dnd.context = new_context; tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ current_dest_drag = new_context; gdk_event_put (&tmp_event);}static voidlocal_send_motion (GdkDragContext *context, gint x_root, gint y_root, GdkDragAction action, guint32 time){ GdkEvent tmp_event; if ((current_dest_drag != NULL) && (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && (current_dest_drag->source_window == context->source_window)) { tmp_event.dnd.type = GDK_DRAG_MOTION; tmp_event.dnd.window = current_dest_drag->dest_window; tmp_event.dnd.send_event = FALSE; tmp_event.dnd.context = current_dest_drag; tmp_event.dnd.time = time; current_dest_drag->suggested_action = action; current_dest_drag->actions = current_dest_drag->suggested_action; tmp_event.dnd.x_root = x_root;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -