プログラミングメモ →目次

ファイルの双方向ドラッグアンドドロップ(VC++)

DragAcceptFiles()などのAPIで、エクスプローラなどからファイルを降ろすことができますが、自分のアプリケーションからファイルを他のアプリケーションへのドラッグアンドドロップを実現するために、クリップボード上で、ファイル名をデータとして入れる処理が必要です。ファイルのドラッグアンドドロップの為に、クリップボードに入れるデータ形式のIDは、CF_HDROP (#define CF_HDROP 15)として登録済みです。一般的なドラッグアンドドロップのやり方は、 http://www.softist.com/programming/dandd/dandd.htmに記述されていますが、ここで、ファイルのデータ形式のドラッグアンドドロップにあたって、データ処理方法についてのやり方だけを記述します。
1.ファイルパスネームをクリップボードに入れる方法。例:自分のアプリケーションから二つのファイルをドラッグする処理です。

void DoBegindrag()
{
    char name1[] = "d:\\file1.txt";
    char name2[] = "d:\\file2.txt";
    HDROP hDrop;
    LPDROPFILES lpDropFile;
    int iByteCount = strlen(name1) + 1 + strlen(name2) + 1; 

    hDrop = (HDROP)::GlobalAlloc(GHND, sizeof(DROPFILES) + iByteCount + 1);
    if (hDrop == NULL)
        return;

    lpDropFile = (LPDROPFILES)::GlobalLock(hDrop);
    lpDropFile->pFiles = sizeof(DROPFILES);    
    lpDropFile->pt.x = 0;
    lpDropFile->pt.y = 0;
    lpDropFile->fNC = FALSE;
    lpDropFile->fWide = FALSE;

    char* lpNams = (char *)(lpDropFile);
    lpNams += lpDropFile->pFiles;
    strcpy(lpNams, name1);
    lpNams += strlen(name1) + 1;
    strcpy(lpNams, name2);
    lpNams += strlen(name2) + 1;
    *lpNams = '\0';
    ::GlobalUnlock(hDrop);

    COleDataSource OleDataSrc;
    OleDataSrc.CacheGlobalData(CF_HDROP, hDrop);
    DROPEFFECT DropEffect = OleDataSrc.DoDragDrop(DROPEFFECT_COPY);
}

2.クリップボードからファイルパスネームを取得する方法。例:エクスプローラなどからファイルを降ろして、ファイルのパスネームをトレースします。

BOOL CTestView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
{
    if (pDataObject->IsDataAvailable((CLIPFORMAT)CF_HDROP))
    {
        STGMEDIUM    medium;
        char name[MAX_PATH];
        memset(name, 0, MAX_PATH);
        if (pDataObject->GetData(CF_HDROP, &medium))
        {
            UINT iFile = DragQueryFile((HDROP)medium.hGlobal,0xFFFFFFFF, NULL, NULL);
            for (UINT i = 0; i < iFile; i ++)
            {
                UINT uiBytes = DragQueryFile((HDROP)medium.hGlobal, i, name, sizeof(name));
                TRACE([%s]\r\n", name);
            }
            ReleaseStgMedium(&medium);
        }
        return TRUE;
    }
    return FALSE;
}