ホームに戻る
 ブラウザからURLをドラッグアンドドロップ

#include <windows.h>
#include <windowsx.h>

#define ID_EDIT 1000

// ウィンドウプロシージャの宣言(ウィンドウの動作を規定)
LRESULT CALLBACK WndProc(
  HWND hwnd,    //ウィンドウハンドル(void型ポインタ)
  UINT message,    //メッセージ識別番号(unsigned int)
  WPARAM wParam,    //(32ビットlong)
  LPARAM lParam);    //(32ビットlong)

//エディット用の文字列追加関数
void Edit_AddString(HWND hwnd, char *string);

//エディットを1個宣言
HWND hEdit;

//文字列の保管用
static char txt[57];

//メイン関数
int APIENTRY WinMain(
  HINSTANCE hInstance,  //インスタンスのハンドル
  HINSTANCE hPreInstance, //以前のインスタンスハンドル
  LPSTR cmdLine,  //コマンド行の文字列
  int cmdShow)    //ウィンドウの表示状態
{
  //ウィンドウクラスの宣言
  WNDCLASS wd;

  //ウィンドウクラス名
  char *wdName = "window00";

  //ウィンドウ登録のためのループ
  if (!hPreInstance) {
    //ウィンドウスタイル
    wd.style = CS_HREDRAW | CS_VREDRAW;  //幅、高さの変化に対し再描画する
    //ウィンドウプロシージャ
    wd.lpfnWndProc = (WNDPROC)WndProc;
    //クラスの予備のメモリ領域
    wd.cbClsExtra = 0;
    //ウィンドウの予備のメモリ領域
    wd.cbWndExtra = 0;
    //プログラムのインスタンスハンドル
    wd.hInstance = hInstance;
    //アイコンのハンドル
    wd.hIcon = NULL;
    //カーソルのハンドル
    wd.hCursor = LoadCursor(NULL, IDC_ARROW);
    //バックグラウンドのブラシのハンドル
    wd.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    //メニュー名
    wd.lpszMenuName = NULL;
    //クラス名
    wd.lpszClassName = wdName;

    //ウィンドウの登録(成功 非0、失敗 0)
    if (!RegisterClass(&wd))
      return FALSE;
  }

  //ウィンドウの生成(ハンドルを form00 とする)
  HWND form00 = CreateWindowEx(
    NULL,      //拡張スタイル(なし)
    wdName,      //ウィンドウクラス名
    "window",    //ウィンドウの名前
    WS_OVERLAPPEDWINDOW,  //ウィンドウスタイル(オーバーラップ型)
    CW_USEDEFAULT,    //ウィンドウのX座標(ディフォルト)
    CW_USEDEFAULT,    //ウィンドウのY座標(ディフォルト)
    200,      //ウィンドウの幅(80に設定)
    100,      //ウィンドウの高さ(50に設定)
    NULL,      //親ウィンドウ(この場合自身が親)
    NULL,      //メニュー(なし)
    hInstance,    //プログラムのハンドル
    NULL);      //予備パラメータ

  //ウィンドウの表示
  ShowWindow(form00, cmdShow);

  //ウィンドウの更新
  UpdateWindow(form00);

  //イベントのループ
  MSG msg;
  while (GetMessage(&msg, NULL, NULL, NULL))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// ドラッグ・アンド・ドロップを登録するためのクラス
// 注:必ず new で作成すること
class CDropTarget : public IDropTarget
{
public:
  CDropTarget():URLDrop(NULL),_RefCount(1),_DataObject(NULL),pData(NULL){};
  ~CDropTarget(){};

  virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
  virtual ULONG __stdcall AddRef();
  virtual ULONG __stdcall Release();
  virtual HRESULT __stdcall DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect  );
  virtual HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect);
  virtual HRESULT __stdcall DragLeave();
  virtual HRESULT __stdcall Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect);

  // コールバック関数
  void __fastcall (*URLDrop)(char* url_name);

  // URL名を得る
  char *getName(){return (char *)pData;}
private:
  LONG _RefCount;
  IDataObject *_DataObject;
  void *pData;
};

HRESULT __stdcall CDropTarget::QueryInterface(const IID& iid, void** ppv)
{
  HRESULT hr;

  if(iid == IID_IDropTarget || iid == IID_IUnknown){
    hr = S_OK;
    *ppv = (void*)this;
    AddRef();
  }
  else{
    hr = E_NOINTERFACE;
    *ppv = 0;
  }

  return hr;
}

ULONG __stdcall CDropTarget::AddRef()
{
  InterlockedIncrement(&_RefCount);
  return (ULONG)_RefCount;
}

ULONG __stdcall CDropTarget::Release()
{
  ULONG ret = (ULONG)InterlockedDecrement(&_RefCount);
  if(ret == 0){
    delete this;
  }
  return (ULONG)_RefCount;
}

HRESULT __stdcall CDropTarget::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
  _DataObject = pDataObject;
  return DragOver(grfKeyState, ptl, pdwEffect);
}

HRESULT __stdcall CDropTarget::DragOver(DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
  *pdwEffect = DROPEFFECT_LINK;
  return S_OK;
}

HRESULT __stdcall CDropTarget::DragLeave()
{
  _DataObject = NULL;
  return S_OK;
}

HRESULT __stdcall CDropTarget::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
  FORMATETC sFormatEtc;
  STGMEDIUM sStgMedium;

  if(_DataObject == NULL){
    return 0;
  }
  
  ::ZeroMemory(&sFormatEtc,sizeof(FORMATETC));
  sFormatEtc.cfFormat = CF_TEXT;
  sFormatEtc.dwAspect = DVASPECT_CONTENT;
  sFormatEtc.lindex   = -1;
  sFormatEtc.tymed    = TYMED_HGLOBAL;

  _DataObject->GetData(&sFormatEtc,&sStgMedium);

  pData = GlobalLock(sStgMedium.hGlobal);

  if(URLDrop != NULL){  
    URLDrop((char *)pData);
  }

  ::GlobalUnlock(sStgMedium.hGlobal);
  ::ReleaseStgMedium(&sStgMedium);

  return S_OK;
}

// ドラッグ・アンド・ドロップ時に呼ばれる
void __fastcall URLDrop(char* url_name){
  Edit_AddString(hEdit, (LPTSTR)url_name);
  Edit_AddString(hEdit, (LPTSTR)"\r\n");
}

// ウィンドウプロシージャ(ウィンドウの動作を規定)
LRESULT CALLBACK WndProc(
  HWND hwnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam)
{
  //インスタンスハンドルを得る
  HINSTANCE hInst;
  hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

  //ウィンドウのサイズ取得用
  RECT r;

  static CDropTarget *DTarget;

  switch (message) {
  //ウィンドウを表示するとき処理
    case WM_CREATE:
      // ドラッグ・アンド・ドロップを登録
      OleInitialize(NULL);
      DTarget = new CDropTarget();
      DTarget->URLDrop = URLDrop;
      RegisterDragDrop(hwnd, (IDropTarget*)DTarget);  
      //エディットの表示
      GetClientRect(hwnd, &r);
      hEdit = CreateWindow(
          "EDIT",
          NULL,
          WS_CHILD | WS_VISIBLE | 
          ES_WANTRETURN | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL |
          ES_AUTOHSCROLL | WS_HSCROLL,
          0, 0,
          r.right, r.bottom,
          hwnd,
          (HMENU)ID_EDIT,
          hInst,
          NULL);
      SendMessage(hEdit, EM_SETLIMITTEXT, (WPARAM)1024*64, 0);
      break;
  //ウィンドウサイズ変更に対する処理
    case WM_SIZE:
      GetClientRect(hwnd, &r);
      MoveWindow(hEdit
        ,r.left
        ,r.top
        ,r.right
        ,r.bottom
        ,TRUE); //再描画のフラグ
      break;
  //ウィンドウを破壊する時の処理
    case WM_DESTROY:
      delete(DTarget);
      //メイン関数のループを終了
      PostQuitMessage(0);
      break;
  //デフォルトの処理に対してデフォルトの処理を返す
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
  return NULL;
}

//エディット用の文字列追加関数
// Edit_ のために windowsx.h が必要
void Edit_AddString(HWND hwnd, char *string)
{
  //エディタ中の文字列の長さを得る
  int length = Edit_GetTextLength(hwnd);

  //エディタの文字列の末尾に移動
  Edit_SetSel(hwnd, length, length);

  //文字列を追加
  Edit_ReplaceSel(hwnd, string);
} 

inserted by FC2 system