CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップする方法

このQ&Aのポイント
  • CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップする方法について教えてください。
  • VC++ 6.0の環境でCListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップするソースコードが不足しており、方法がわからない状況です。どのようにすれば実現できるでしょうか?
  • ダイアログベースのVC++ 6.0プロジェクトでCListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップする方法のソースコードが一部不足しており、複数ファイルをドラッグ&ドロップするための手順や正しく動作するための修正方法を教えてください。
回答を見る
  • ベストアンサー

CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップするには

CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップするソースに手間取っていますのでご教授をお願いします。 (VC++ 6.0のサンプルコードがあまりなくて) なんとか、1つのファイルはできるようになったのですが複数にするやり方がわかりません。 どのようにすればよいでしょうか? また、おかしい箇所などありましたら合わせてお願いします。 ※単純の繋げるだけじゃないんですよね?※ CString fname = "C:\\aaa.txt"; fname += "C:\\bbb.txt"; -環境- ・VC++ 6.0 ・MFC ・ダイアログベース -ソース- void aaaDlg::OnBegindragListView(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください if(pNMListView->iItem != -1) { CString fname = "C:\\aaa.txt"; // 動作確認のため固定 HDROP hptr = DragCreateFiles(fname); if (hptr == NULL) { *pResult = 0; return; } m_DropData.CacheGlobalData(CF_HDROP, hptr); CRect rect(0,0,0,0); DROPEFFECT effect = m_DropData.DoDragDrop(DROPEFFECT_COPY, rect); } *pResult = 0; } static HDROP DragCreateFiles (LPCSTR fname) { HDROP hDrop; LPDROPFILES lpDropFileStruct; // Allocate dynamic memory for the DROPFILESTRUCT data // structure and for the extra zero-character identifying // that there are no pathnames in the block yet. int flen = lstrlen(fname); hDrop = (HDROP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(DROPFILES) + flen + 2); // If unsuccessful, return NULL if (hDrop == NULL) return(hDrop); // Lock block and initialize the data members lpDropFileStruct = (LPDROPFILES) GlobalLock(hDrop); memset(lpDropFileStruct,0,sizeof(DROPFILES) + flen + 2); lpDropFileStruct->pFiles = sizeof(DROPFILES); lpDropFileStruct->pt.x = 0; lpDropFileStruct->pt.y = 0; lpDropFileStruct->fNC = FALSE; lpDropFileStruct->fWide = FALSE; char* szPathA = (char*) (&lpDropFileStruct[1]); lstrcpy(szPathA,fname); // Unlock the block and return its handle. GlobalUnlock(hDrop); return(hDrop); }

  • nagare
  • お礼率65% (125/191)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんばんは。  複数の場合はNULL文字で区切ってファイル名を並べ、最後にもう1つNULL文字を置くので、例えば  2個ならば、  C:\\aaa.txt\0C:\\bbb.txt\0\0  sizeof(DROPFILES) + 23文字  3個ならば、  C:\\aaa.txt\0C:\\bbb.txt\0C:\\ccc.txt\0\0  sizeof(DROPFILES) + 34文字  となるのではないでしょうか。  以下、送信と受信をまとめて実装して、同じアプリを2つ立ち上げて試していますが、ドロップされた側に複数のファイル名が入ってきています。  実験的なコードなのですが、参考程度に。 static HDROP DragCreateFiles(const CStringArray& fileList) { //最後にもう1つNULLを含めておく int len = 1; for(int i = 0; i < fileList.GetSize(); ++i) { len += fileList[i].GetLength() + 1; } HDROP hDrop = (HDROP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(DROPFILES) + len); if(hDrop == NULL) return(hDrop); LPDROPFILES lpDropFileStruct = (LPDROPFILES)GlobalLock(hDrop); memset(lpDropFileStruct,0,sizeof(DROPFILES) + len); lpDropFileStruct->pFiles = sizeof(DROPFILES); lpDropFileStruct->pt.x = 0; lpDropFileStruct->pt.y = 0; lpDropFileStruct->fNC = FALSE; lpDropFileStruct->fWide = FALSE; char* szPathA = (char*)(&lpDropFileStruct[1]); //文字列を書き込む for(int i = 0; i < fileList.GetSize(); ++i) { lstrcpy(szPathA, fileList[i].GetString()); szPathA += fileList[i].GetLength() + 1; } GlobalUnlock(hDrop); return(hDrop); } void CTestDlg::OnLvnBegindragList1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 if(pNMLV->iItem != -1) { //3つ分送る CStringArray fileList; fileList.Add("C:\\aaa.txt"); fileList.Add("C:\\bbb.txt"); fileList.Add("C:\\ccc.txt"); HDROP hDrop = DragCreateFiles(fileList); if (hDrop == NULL) { *pResult = 0; return; } COleDataSource OleDataSrc; OleDataSrc.CacheGlobalData(CF_HDROP, hDrop); DROPEFFECT DropEffect = OleDataSrc.DoDragDrop(DROPEFFECT_COPY); *pResult = 0; } } //受け取りテスト void CTestDlg::OnDropFiles(HDROP hDropInfo) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 CDialog::OnDropFiles(hDropInfo); CHAR sz[MAX_PATH + 1]; const int fileCount = DragQueryFile(hDropInfo, -1, NULL, 0); for(int i = 0; i < fileCount; ++i) { DragQueryFile(hDropInfo, i, sz, MAX_PATH); } DragFinish(hDropInfo); }

nagare
質問者

お礼

ありがとうございます 合計ファイルパス長 = (ファイルパス長 + 1(\0)) * ファイル数 で解決しました

関連するQ&A

  • VC++でドラッグドロップ

    いつもお世話になっております。 今回はドラッグ&ドロップについてお聞きしたいです。 リストボックスにフォルダをドラッグしてそのフォルダの中身を リストに表示するというものを作りたく、ネットでいろいろ調べた所 以下のように作りました。 ResourceViewでドロップドラッグを許可にチェックを入れる case WM_CREATE:   DragAcceptFiles(::GetDlgItem(hWnd, IDC_LIST1), TRUE);   return TRUE; case WM_DROPFILES:   { // ドロップされた内容を取得   hdrop = (HDROP)wParam;   DWORD dwSize;   CHAR szPath[MAX_PATH+1];   ZeroMemory(szPath, sizeof(szPath));   int num = ::DragQueryFile(hdrop, -1, NULL, 0);   for (int i = 0; i < num; i++);{     dwSize = ::DragQueryFile(hdrop , i, szPath, MAX_PATH+1);     if (dwSize <= 0) //取得失敗     {       return FALSE;     }     else{ //以下にszPathから中身を表示させる処理 ・・・} 以上のようにするとドラッグしたファイルの数は 正しく取得しているのですがファイル名を得る関数部分で 1.i=0としているのに、最初からi=numの数になってしまう 2.二つ目のDragQueryFileのiを1にしても戻値(ファイル名のサイズ)は 0となって取得していない となってしまいます。 なぜこのようになってしまうのか、ご教授願います。 環境はVisual C++6.0 OSは windowsXP SP2です

  • ファイルサイズを変更したい

    visualstudio2010を使用しています。 c言語で書いているのですが、 test.txt ←abcdefg ファイルサイズ1KB Wtest.txt←書き込み用ファイル 上記のようなファイルがあり、バイナリでtest.txtを読み込みWtest.txtに書き込みたいと思っています。 その際に、1KBのtest.txtを5KBになるまでバイナリで「abcdefg」の後に0を代入したいのですがどう書けば良いのかわかりません。 FILE *fp, *fpw; char *fname = "test.txt"; char *fname_w = "Wtest.txt"; unsigned char buf[10000]; int size; fp = fopen( fname, "rb" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } fpw = fopen(fname_w, "wb"); if(fpw == NULL){ printf( "%sファイルが開けません\n", fname_w ); return -1; } size = fread( buf, sizeof( unsigned char ), sizeof (fp), fp ); /*ここに処理を追加したい*/ fwrite( buf, sizeof( unsigned char ), size, fpw);

  • アドレス

    利用環境はMFCのVC++6.0です。 void CTestDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) { CString str; int num=m_list.GetSelectionMark(); str=m_list.GetItemText(num,0); if(Tstr!=NULL){ *Tstr=str; } CTest2 dlg2; dlg2.DoModal(); ・ ・ ・ } ヘッダ:CString *Tstr; とすると*Tstr=str;がおかしいらしく、アドレスがきちんと渡っていないようです。Tstr!=NULLの所ではアドレスは0xcccccc"???"となっていて if文は意味をなしません。 値を受け取るダイアログでは CTest Tdlg; CString aa; Tdlg.Tstr=&aa; MessageBox(aa); としています。 TestDlgのリストビューの内容をうけとりそれを新しくダイアログを作って そちらに移すプログラムです。

  • C言語 複数ファイル操作について

    Cプログラミング初心者です。 論文などの何行も文章があるようなテキストファイル(ここでは1.txtとします)と、他に予め単語をいくつか登録しているテキストファイル(2.txt)を開き、1.txtを最初の行から一行ごとに読み込み、2.txtの中にある単語が1つでもその一行の文章中に含まれていたらその一行の文章を出力し、また次の行においても2.txtの中にある単語のいずれかが含まれているかどうかを調べて含まれている場合は出力…含まれていない場合は出力せずに次の行へ…といったようにこれを1.txt内の最後の行まで繰り返し行うプログラムを作りたいのですが、自分が作ったプログラムでは含む・含まない関係なく1.txt内の文章全てが出力されてしまいます。おそらく最初のwhile文あたりがおかしいのだろうという予想はつくのですがどのように直せばよいのかわからず悩んでいます。どなたか教えていただければ嬉しいです(;_:) #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1056 void delkaigyo(char *s1,char *s2){ char *p = s1; p=strstr(s1,s2); if(p!=NULL){ strcpy(p,p+strlen(s2)); delkaigyo(p+1,s2); } } int main(void){ FILE *fp; char *filename = "2.txt"; char str1[N]; char str2[N]; char kaigyo[] = "\n"; int i; int a=0; char fname[64]; printf("file:"); scanf("%s", fname);   ←ここで1.txtを入力するとします fp = fopen(fname, "r"); while(fgets(str1, N, fp) != NULL){ delkaigyo(str1, kaigyo); memset(str1, 0, N); fread(str1, 1, N-1, fp); if((fp = fopen(filename, "r")) == NULL){ fprintf(stderr, "%serror.\n", filename); exit(EXIT_FAILURE); } while(fgets(str2, N, fp) != NULL){ delkaigyo(str2,kaigyo); if(strstr(str1,str2)!=NULL){ a = 1; printf("%s\n", str1); break; } } if(a==0){ return 0; } fclose(fp); } return EXIT_SUCCESS; }

  • VC#でドラッグアンドドロップ時のカーソルの制御

    プログラミング初心者です。 ファイル管理ソフトを作りたいなと、種々の言語を比較した結果VC#が一番やりやすいかなと思い、基礎知識もなくvisual studioをインストールしてあれこれ試行錯誤しながら、メニューやボタンやリストビューを作るところまでは行きました。ドラッグアンドドロップ機能を付けたいと思い、色々と検索してドラッグアンドドロップでlistView1に特定の拡張子のファイルを入れる下記のコードは見つかりました。さらに、特定の拡張子(ここでは.txt)以外のファイルをドラッグしてlistView1の領域に入った時、カーソルを禁止のマークに変えたいのですがそのコードがわかりません。ご教授いただければと存じます。 // もちろん基礎知識も平行して勉強しているところです。 // 下記のlistView1_DragEnterイベントハンドラ内に // if(ドラッグしたファイルの拡張子が.txt以外だったら){Cursor.Current = Cursors.No;} // とすると思い色々試したのですがうまくいきませんでした。(素人の試行錯誤なので提示できません) private void listView1_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Link; } } private void listView1_DragDrop(object sender, DragEventArgs e) { string[] handles = (string[])e.Data.GetData(DataFormats.FileDrop, false); foreach (string s in handles) { if (File.Exists(s)) { if (string.Compare(Path.GetExtension(s), ".txt", true) == 0) { AddFileToListview(s); } } else if (Directory.Exists(s)) { DirectoryInfo di = new DirectoryInfo(s); FileInfo[] files = di.GetFiles("*.txt"); foreach (FileInfo file in files) AddFileToListview(file.FullName); } } } private void AddFileToListview(string fullFilePath) { if (!File.Exists(fullFilePath)) return; string fileName = Path.GetFileNameWithoutExtension(fullFilePath); string dirName = Path.GetDirectoryName(fullFilePath); if (dirName.EndsWith(Convert.ToString(Path.DirectorySeparatorChar))) dirName = dirName.Substring(0, dirName.Length - 1); //hack off the trailing \ ListViewItem itm = listView1.Items.Add(fileName); itm.SubItems.Add(dirName); //second column = path }

  • CTreeCtrlでアイコンが変化しない

    環境は、MSVC++6.0&MFCです。 やりたいことは、ツリーコントロールのアイコンをエクスプローラのフォルダのように、 開いたときと閉じたときとで、アイコンを変化させたいのです。 以下は、ソースです。 CTreeCtrlからMyTreeCtrlを派生しています。 テスト用に開いたときは、文字列を"開いた"、閉じたときは、"閉じた"のように変化させるようにしています。 void MyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if(pNMTreeView->action == TVE_EXPAND){ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(0) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "開いた"); }else{ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(1) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "閉じた"); } *pResult = 0; } 実行すると、文字は、開いたときは、"開いた"、閉じたときは、"閉じた"とちゃんと表示されますが、 アイコンが変化しません。 お分かりの方、いらっしゃいましたら、教えてください。

  • C++6.0における動画再生プログラムについて

    動画再生プログラムを作成したのですが、実行するとファイルから選択して動画を再生という形になっています。 ここでやりたいこととしては、実行するとプログラム内で指定したファイルがすぐ再生できるようなプログラムに改良したいと思っています。 どこを改良したらよいかわからないので、どなたか教えていただけませんでしょうか?以下が作成したプログラムです。 #include <windows.h> #include <string.h> #include <dshow.h> //DirectShowのさまざまな準備 #include <conio.h> //getch()用 #include <stdio.h>//インターフェース用のポインタ IGraphBuilder * pigb = NULL; IMediaControl * pimc = NULL; void main (){ OPENFILENAME fname; static char fn [256]; memset ( &fname, 0, sizeof (OPENFILENAME) ) ; fname.lStructSize = sizeof (OPENFILENAME) ; fname.lpstrFile = fn; fname.nMaxFile = sizeof (fn) ; fname.Flags= OFN_FILEMUSTEXIST |OFN_HIDEREADONLY; if ( !GetOpenFileName ( &fname ) ) return ; WCHAR filename [MAX_PATH] ; HRESULT hr; CoInitialize (NULL) ;//ファイル名の変換 MultiByteToWideChar ( CP_ACP, 0, fn, -1, filename, MAX_PATH ) ; //FilterGraphの初期化,GraphBuilderインターフェースを得る hr = CoCreateInstance ( CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**) &pigb) ; if (SUCCEEDED (hr) ){//MediaControlインターフェースを得る pigb -> QueryInterface ( IID_IMediaControl, (void**) &pimc ) ; //再生するファイルを指定 hr = pigb -> RenderFile ( filename, NULL ) ; if (SUCCEEDED ( hr ) ){//再生 pimc -> Run () ; printf ("\n 再生中です、再生終了後どれかキーを押してください.") ; getch() ; } } //FilterGraphの開放 if ( pigb )pigb -> Release () ; if ( pimc )pimc -> Release () ; CoUninitialize () ; return ; }

  • SHGetFileInfoでアイコンが取得できない場合がある

    VC++にてエクスプローラもどきを作成しています。 ListViewへファイルアイコンを表示するために、 SHGetFileInfoを使用し、 // 大きいアイコンのハンドル取得 // fnameは拡張子だけの文字列です SHGetFileInfo( fname, NULL, &shfInfo, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES ); licon = shfInfo.hIcon; 上記のようにしてファイルアイコンを取得し、 CImageListへ追加した上で、描画しています。 そして、ダイアログのサイズが変更された際に、 OnSize関数にて、ListView内のアイコンを再度取得し、 再描画しているのですが、 何度もOnSizeで再描画を行っているうちに、 SHGetFileInfoにて取得したshfInfo.hIconが NULLになってしまいます。 一度、shfInfo.hIconがNULLになると、 何度、SHGetFileInfoを呼んでも、返ってくるhIconは 毎回NULLになってしまい、ListView内に アイコンが表示されません。 SHGetFileInfo関数を呼ぶ際の制約等があるのでしょうか?

  • BCCのコンソールアプリからウィンドウ表示

    BCCのコンソールアプリからウィンドウを表示したいのですが、うまくいきません。 なにが悪いのでしょうか・・・ どなたかお教えいただけると助かります。 よろしくお願いいたします。 コンパイラ: Borland C++ 5.5.1 bcc32 コンパイル方法: bcc32 -WC WindowTest.cpp (コンソールアプリにしているのは、標準入力を受け標準出力に出すフィルタ機能も持たせようと思っているからです。) *** ソース (WindowTest.cpp) *** #include <windows.h> LRESULT CALLBACK WndProc ( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ){ // とりあえず空 (void)hWnd; (void)msg; (void)wp; (void)lp; return 0; } int main (int argc, char**argv){ HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); WNDCLASSEX wc; char className[] = "hoge"; memset( &wc, 0, sizeof( wc )); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = className; wc.hIconSm = NULL; if(! RegisterClassEx( &wc )) return 1; HWND hWnd = CreateWindow(className, "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL); // ← ここで失敗し、ウィンドウが表示されない if (!hWnd) return 2; ShowWindow(hWnd, NULL); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } (void)argc; (void)argv; return 0; }

  • ファイルをドロップするとfopenからファイルが作成できません

    C言語でコンソールアプリケーションを作っています。 ファイルをexeにドロップして実行し、別のファイルに結果を出力させたいのですが、出力ファイルが作成されません。 どのようにすればよろしいのでしょうか。 コンソールから渡すときはファイルが作成されます。 コンパイラはBorland C++ Compiler 5.5を使用しています。 以下にコードの一部を掲載します。 int main(int argc, char *argv[]) {  char filename[256];  FILE *inputFile;  FILE *outputFile;  int i;  for(i=1; i<argc; i++)  {   if((inputFile=fopen(filename,"r")) == NULL)   {/*エラー処理*/}   sprintf(filename,"result%d.txt",i); // 出力ファイル名   if((outputFile=fopen(filename,"w")) == NULL)   {/*エラー処理*/}   for(;;)   {    char ss[1024];    if(fgets(ss,1024,inputFile) ==NULL) break;    fputs(ss,outputFile);   }   fclose(inputFile);   fclose(outputFile);  }  return 0; }

専門家に質問してみよう