dポイントプレゼントキャンペーン実施中!

Visual Sutdio 2010 , VC++ , MFC でファイルリスト一覧作成ソフトを作っている者です。

CSting 型の _T("~\0~\0\0") を TCHAR [] に変換したいです。
CSting 型の変数名は、DeleteFilePathです。

'\0' を他の文字に置換して確認した所、正しく入っています。

現在は、4096文字の文字列配列に入れています。
ゴミ箱に移動できる時とできない時があります。

_______________________________________________________________________________
■現在のコード

 index = -1;
 while ((index = CFileListCreatorDlg::m_xcList.GetNextItem
 (index, LVNI_ALL | LVNI_SELECTED)) != -1)
 {

  CString FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);

  if (FullPathString.Right(1) != _T("\\")){
    ::SetFocus(::GetDlgItem(m_hWnd,IDC_LIST));

   FullPathString.Replace(_T ("\\"),_T("\\\\"));

   DeleteFilePath = DeleteFilePath + FullPathString + _T('\0');

   CFileListCreatorDlg::m_xcList.DeleteItem(index);
  }
  index--;
 }

 DeleteFilePath = DeleteFilePath + _T('\0');


 _TCHAR cszPath[4096];   // TCHAR型
 _tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型


 SHFILEOPSTRUCT sfs;

 memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );
 sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合 FOF_ALLOWUNDO をつける;
 sfs.wFunc = FO_DELETE;
 sfs.pFrom = cszPath;

 if ( 0 != SHFileOperation ( &sfs ) )
 {
  MessageBox(_T("ゴミ箱に移動できませんでした"),_T("SHFileOperation 失敗"),MB_OK);
  return 0;
 }
_________________________________________________________________________________________________________________________________________________


5回に1回成功するので、不思議です。

ファイルのパスは、リストコントロールのアイテムに格納されていて、
削除したいアイテムを選択肢、Shift + Delete で、ゴミ箱に削除する ユーザー関数が呼び出されます。(ゴミ箱に移動するだけで、確認メッセージは出なくていいです。)


今まで、具体的した事を記すと以下のようになります。

cszPath = const_cast<LPTSTR>(static_cast<LPCTSTR>DeleteFilePath;  //ビルドエラー
としたり、

_TCHAR cszPath[DeleteFilePath.GetLength()];  // TCHAR型

としたり、

TCHAR cszPath[256];  // TCHAR型

_tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型

・・・とやってみましたが、出来ません。


http://www.usefullcode.net/2006/12/post_13.html
http://www5d.biglobe.ne.jp/~noocyte/Programming/ …

とかが参考になりそうです。

先程も書きましたが const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" ); の代入がうまく行きません。
____________________________________________________________________________________________________________________________________

http://sysneitf.ifdef.jp/shell_filestotrash.html

以下、参考にした部分


// 複数ある場合は、パスを'\0'で区切る。終端は、'\0''\0'である必要がある
 const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" );

// "c:\\a.txt"と"C:\\b.txt" をゴミ箱へファイルを移動するサンプル (シェルエミュレート)
 SHFILEOPSTRUCT sfs;

 memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );
 sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合  FOF_ALLOWUNDO をつける;
 sfs.wFunc = FO_DELETE;
 sfs.pFrom = cszPath;

 if ( 0 != SHFileOperation ( &sfs ) )
 {
  MessageBox ( NULL,
  _TEXT ( "SHFileOperation 失敗" ),
  _TEXT ( "エラー" ),
  MB_OK | MB_ICONSTOP );
 }


どなたか、お教え下さると嬉しいですm(_ _)m

A 回答 (4件)

// resultを動的に確保してない点が気になりますが



では std::basic_string で。

#define _UNICODE
#define UNICODE
#define _AFXDLL

#include <afx.h>
#include <tchar.h>
#include <string>

#include <iostream>

typedef std::basic_string<TCHAR> tstring;

int main() {
const wchar_t nc = L'\0';
CString input = L"";
input += L"abc";
input += nc;
input += L"def";
input += nc;
input += L"ghi";
input += nc;
input += nc;

tstring buffer(static_cast<const _TCHAR*>(input), input.GetLength());
const _TCHAR* result = buffer.data();
for ( int i = 0; i < buffer.size(); ++i ) {
if ( result[i] == L'\0' )
std::wcout << "'\\0'" << std::endl;
else
std::wcout << result[i] << std::endl;
}
}
    • good
    • 0
この回答へのお礼

ご親切にどうも有難うございました!自分では到底たどりつかないレベルでビックリしてます。
他にも応用が効きそうです。



▼要らなくなる部分▼
const _TCHAR* cszPath = static_cast<const _TCHAR*>( DeleteFilePath );

// DeleteFilePathの先頭から長さ分をresultにコピー
std::copy(cszPath, cszPath+DeleteFilePath.GetLength(), result);
▲要らなくなる部分▲

//この部分が要らなくなるのですね。最初分かりませんでした。

そして、教わった部分・・・

tstring buffer(static_cast<const _TCHAR*>( DeleteFilePath ), DeleteFilePath.GetLength());
const _TCHAR* cszPath = buffer.data();

・・・を書いて、変数名を cszPath にそろえました。

お礼日時:2014/06/28 23:52

_tcscpyはナル文字を見つけた時点でコピーをやめちゃいますよ。



/*
* std::copyを使った例
* cl -EHsc -MD trial.cpp
*/
#define _UNICODE
#define UNICODE
#define _AFXDLL

#include <afx.h>
#include <tchar.h>

#include <iostream>
#include <algorithm> // 必須!

int main() {
const wchar_t nc = L'\0';
CString input = L"";
input += L"abc";
input += nc;
input += L"def";
input += nc;
input += L"ghi";
input += nc;
input += nc;

_TCHAR result[16];
const _TCHAR* p = static_cast<const _TCHAR*>(input);
// inputの先頭から長さ分をresultにコピー
std::copy(p, p+input.GetLength(), result);

for ( int i = 0; i < 16; ++i ) {
if ( result[i] == L'\0' )
std::wcout << "'\\0'" << std::endl;
else
std::wcout << result[i] << std::endl;
}
}

この回答への補足

できました!ありがとうございます!
一応、ソースを・・・

CString DeleteFilePath = _T("");

myResult = MessageBox(_T("現在選択されているデータ(本体)を削除しますか?") ,_T("Deletion range confirmation"),MB_YESNOCANCEL);
if(myResult == IDYES){
 index = -1;
 while ((index = CFileListCreatorDlg::m_xcList.GetNextItem
  (index, LVNI_ALL | LVNI_SELECTED)) != -1)
 {

  CString FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);
  FullPathString.Replace(_T ("\\"),_T("\\\\"));

  if ( FullPathString != "" ){
   if ( PathFileExists(FullPathString) && FullPathString.Right(1) != _T("\\")) { //条件追加
    DeleteFilePath = DeleteFilePath + FullPathString + _T('\0');
    CFileListCreatorDlg::m_xcList.DeleteItem(index);
   }else{
    m_xcList.GetNextItem(index++, LVNI_ALL | LVNI_SELECTED);
   }
  }
  index--;
 }

 DeleteFilePath = DeleteFilePath + _T('\0');

 if ( DeleteFilePath == "" || DeleteFilePath == "\0\0" ) return -1;

 const wchar_t nc = L'\0';
 _TCHAR result[256*1000];

 if ( DeleteFilePath.GetLength() >= sizeof result /sizeof result[0]) return -1;

 const _TCHAR* cszPath = static_cast<const _TCHAR*>(DeleteFilePath);

 // DeleteFilePathの先頭から長さ分をresultにコピー
 std::copy(cszPath, cszPath+DeleteFilePath.GetLength(), result);

 SHFILEOPSTRUCT sfs;

 memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );
 sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
 // ゴミ箱へ移動するが確認はしない FOF_ALLOWUNDO | FOF_NOCONFIRMATION; をつける
 
 sfs.wFunc = FO_DELETE;
 sfs.pFrom = cszPath;

 if ( 0 != SHFileOperation ( &sfs ) )
 {
  //free( cszPath );

  MessageBox(_T("ゴミ箱に移動できませんでした"),_T("SHFileOperation 失敗"),MB_OK);
  return -1;
 }
 return 0;
}


// resultを動的に確保してない点が気になりますが、問題なければ もうすぐ締め切りますm(_ _)m

補足日時:2014/06/28 18:12
    • good
    • 0

>_tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型


strcpy系は終端文字の検索を行うので、複数のパスがセットされてると上手くコピーされないのでは。
    • good
    • 0
この回答へのお礼

ご指摘の通りでした。回答ありがとうございました!

お礼日時:2014/06/29 04:09

>ブレークポイントおいてメモリダンプ見たらすぐわかんじゃねかな


https://twitter.com/miyabi_inoue/status/48230339 …
だそうです(・∀・)

この回答への補足

回答ありがとうございます。ブレイクポイントと設定するまでは分かるのですが、
メモリダンプの見方が分かりませんでした。マウスを変数の上に持って行って、値を
見る事はできますが。

_TCHAR cszPath[4096];   // TCHAR型
_tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型

↑の部分を(1)(2)のように書き換えてみましたが、上手くいきません。

(1)
int len = DeleteFilePath.GetLength();
_TCHAR *cszPath = (TCHAR*)malloc( sizeof( TCHAR ) * len ;)

(2)
size_t len = _tcsclen(DeleteFilePath);
_TCHAR *cszPath = (TCHAR*)malloc( sizeof( TCHAR ) * len ;)

~ゴミ箱に移動する処理~
 // "c:\\a.txt"と"C:\\b.txt" をゴミ箱へファイルを移動するサンプル (シェルエミュレート)
 SHFILEOPSTRUCT sfs;

 memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );
 sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合 FOF_ALLOWUNDO をつける;
 sfs.wFunc = FO_DELETE;
 sfs.pFrom = cszPath; //←ここがうまく行ってないんだと思います。
~ゴミ箱に移動する処理~

free( cszPath );

(3)
念のため、トリムしてみましたが、意味がありませんでした。
CString FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2).Trim();

___________________________________________________________________________________

いずれも・・・

if ( 0 != SHFileOperation ( &sfs ) )
{
 MessageBox(_T("ゴミ箱に移動できませんでした"),_T("SHFileOperation 失敗"),MB_OK);
 return 0;
}

・・・"ゴミ箱に移動できませんでした"と画面にでます。


ただ、リストにフルパスを格納しているので、まずは一つのファイルを捨てる事から試して
います。とりあえず「複数のパスがセットされてると上手くコピーされないのでは。」これは
置いておきたいです。

もう少し試行錯誤してみます。

補足日時:2014/06/28 11:43
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!