Home | History | Annotate | Download | only in dragdrop
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/base/dragdrop/drop_target_win.h"
      6 
      7 #include <shlobj.h>
      8 
      9 #include "base/logging.h"
     10 
     11 namespace ui {
     12 
     13 IDropTargetHelper* DropTargetWin::cached_drop_target_helper_ = NULL;
     14 
     15 DropTargetWin::DropTargetWin(HWND hwnd)
     16     : hwnd_(hwnd),
     17       ref_count_(0) {
     18   DCHECK(hwnd);
     19   HRESULT result = RegisterDragDrop(hwnd, this);
     20   DCHECK(SUCCEEDED(result));
     21 }
     22 
     23 DropTargetWin::~DropTargetWin() {
     24 }
     25 
     26 // static
     27 IDropTargetHelper* DropTargetWin::DropHelper() {
     28   if (!cached_drop_target_helper_) {
     29     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
     30                      IID_IDropTargetHelper,
     31                      reinterpret_cast<void**>(&cached_drop_target_helper_));
     32   }
     33   return cached_drop_target_helper_;
     34 }
     35 
     36 ///////////////////////////////////////////////////////////////////////////////
     37 // DropTargetWin, IDropTarget implementation:
     38 
     39 HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
     40                                  DWORD key_state,
     41                                  POINTL cursor_position,
     42                                  DWORD* effect) {
     43   // Tell the helper that we entered so it can update the drag image.
     44   IDropTargetHelper* drop_helper = DropHelper();
     45   if (drop_helper) {
     46     drop_helper->DragEnter(GetHWND(), data_object,
     47                            reinterpret_cast<POINT*>(&cursor_position), *effect);
     48   }
     49 
     50   current_data_object_ = data_object;
     51   POINT screen_pt = { cursor_position.x, cursor_position.y };
     52   *effect = OnDragEnter(current_data_object_, key_state, screen_pt, *effect);
     53   return S_OK;
     54 }
     55 
     56 HRESULT DropTargetWin::DragOver(DWORD key_state,
     57                                 POINTL cursor_position,
     58                                 DWORD* effect) {
     59   // Tell the helper that we moved over it so it can update the drag image.
     60   IDropTargetHelper* drop_helper = DropHelper();
     61   if (drop_helper)
     62     drop_helper->DragOver(reinterpret_cast<POINT*>(&cursor_position), *effect);
     63 
     64   POINT screen_pt = { cursor_position.x, cursor_position.y };
     65   *effect = OnDragOver(current_data_object_, key_state, screen_pt, *effect);
     66   return S_OK;
     67 }
     68 
     69 HRESULT DropTargetWin::DragLeave() {
     70   // Tell the helper that we moved out of it so it can update the drag image.
     71   IDropTargetHelper* drop_helper = DropHelper();
     72   if (drop_helper)
     73     drop_helper->DragLeave();
     74 
     75   OnDragLeave(current_data_object_);
     76 
     77   current_data_object_ = NULL;
     78   return S_OK;
     79 }
     80 
     81 HRESULT DropTargetWin::Drop(IDataObject* data_object,
     82                             DWORD key_state,
     83                             POINTL cursor_position,
     84                             DWORD* effect) {
     85   // Tell the helper that we dropped onto it so it can update the drag image.
     86   IDropTargetHelper* drop_helper = DropHelper();
     87   if (drop_helper) {
     88     drop_helper->Drop(current_data_object_,
     89                       reinterpret_cast<POINT*>(&cursor_position), *effect);
     90   }
     91 
     92   POINT screen_pt = { cursor_position.x, cursor_position.y };
     93   *effect = OnDrop(current_data_object_, key_state, screen_pt, *effect);
     94   return S_OK;
     95 }
     96 
     97 ///////////////////////////////////////////////////////////////////////////////
     98 // DropTargetWin, IUnknown implementation:
     99 
    100 HRESULT DropTargetWin::QueryInterface(const IID& iid, void** object) {
    101   *object = NULL;
    102   if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDropTarget)) {
    103     *object = this;
    104   } else {
    105     return E_NOINTERFACE;
    106   }
    107   AddRef();
    108   return S_OK;
    109 }
    110 
    111 ULONG DropTargetWin::AddRef() {
    112   return ++ref_count_;
    113 }
    114 
    115 ULONG DropTargetWin::Release() {
    116   if (--ref_count_ == 0) {
    117     delete this;
    118     return 0U;
    119   }
    120   return ref_count_;
    121 }
    122 
    123 DWORD DropTargetWin::OnDragEnter(IDataObject* data_object,
    124                                  DWORD key_state,
    125                                  POINT cursor_position,
    126                                  DWORD effect) {
    127   return DROPEFFECT_NONE;
    128 }
    129 
    130 DWORD DropTargetWin::OnDragOver(IDataObject* data_object,
    131                                 DWORD key_state,
    132                                 POINT cursor_position,
    133                                 DWORD effect) {
    134   return DROPEFFECT_NONE;
    135 }
    136 
    137 void DropTargetWin::OnDragLeave(IDataObject* data_object) {
    138 }
    139 
    140 DWORD DropTargetWin::OnDrop(IDataObject* data_object,
    141                             DWORD key_state,
    142                             POINT cursor_position,
    143                             DWORD effect) {
    144   return DROPEFFECT_NONE;
    145 }
    146 
    147 }  // namespace ui
    148