ListViewコントロールについて

解決


みけにゃん  URL  2007-03-03 08:38:33  No: 64571

数年前から悩んでいたメールデータをローカルにファイル化して
格納するというところは解決したのですが、それから先のところで
つまづいてしまっています。

それはファイル化したメールデータのヘッダ情報(件名、差出人、
受信日時、メールのファイルサイズ、ファイル名(メールデータ
ファイルを開くためのものなので非表示))をListViewに追加するという
コードを猫でも分かるやいろいろなページを見て作ったのですが
件名だけが1件目以降ずれて追加され、データのない行に1行
件名だけ追加されている項目が出来てしまっています。
http://angelteatime.punyu.net/mview_list.png

これはどうして出来てしまったものなのでしょうか?
教えていただけないでしょうか・・・。

該当するコードの部分を載せておきます。
// ローカルに保存されているメールを取得する
void SetLocalMail(HWND hListL)
{
  WIN32_FIND_DATA wfd;
  HANDLE hFind;
  HANDLE hFile;              // ファイルハンドル
  HGLOBAL hMem;              // グローバルハンドル
  DWORD dwFSizeHigh, dwFSize, dwAccBytes;  // バイト数
  char szfname[MAX_PATH + 5];        // ファイル名
  char *lpszBuf;              // ファイルバッファ
  int ret;                // 戻り値
  int iListNo;

  // 添付メール展開用変数
  char subject[TEMP_MAX], date[TEMP_MAX], from[TEMP_MAX], header[TEMP_MAX], body[TEMP_MAX];
  char FileName[TEMP_MAX], Temp[NMAIL_ATTACHMENT_TEMP_SIZE], szSize[TEMP_MAX];
  
  // リストの初期化
  ListView_DeleteAllItems(hListL);
  GetCurrentDirectory(MAX_PATH, szfname);
  iListNo = 0;
  
  // メールファイルを探す
  hFind = FindFirstFile("*.dat", &wfd);
  
  // 検索が失敗した場合(ファイルがない場合)
  if(hFind == INVALID_HANDLE_VALUE){
    //MessageBox(NULL, "エラーです", "Error", MB_OK | MB_ICONSTOP);
    FindClose(hFind);
    return;
  }
  else{
    // ファイル名をリストに追加
    strcpy(szfname, wfd.cFileName);

    // ファイルを開く
    hFile = CreateFile(szfname, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if(hFile == INVALID_HANDLE_VALUE){
      MessageBox(NULL, "ファイルをオープンできません", "Error", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // ファイルサイズを調べる
    dwFSize = GetFileSize(hFile, &dwFSizeHigh);
    
    if(dwFSizeHigh != 0){
      MessageBox(NULL, "ファイルが大きすぎます", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // ファイルを読み込むためのメモリ領域を確保
    hMem = GlobalAlloc(GHND, dwFSize + 1);
    
    if(hMem == NULL){
      MessageBox(NULL, "メモリを確保できません", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // メモリ領域をロックしてファイルを読み込む
    lpszBuf = (char *)GlobalLock(hMem);
    ReadFile(hFile, lpszBuf, dwFSize, &dwAccBytes, NULL);
    lpszBuf[dwFSize] = '\0';
    
    // szAtFileDataのメモリ領域を確保する
    szAtFileData = (char *)malloc(sizeof(char) * dwFSize);
    
    if(szAtFileData == NULL){
      MessageBox(NULL, "メモリ確保に失敗しました", "メモリ確保失敗", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // メールファイルの中身をコピーする
    strcpy((char *)szAtFileData, lpszBuf);
    
    // ファイルを閉じる
    CloseHandle(hFile);
    GlobalUnlock(hMem);
    GlobalFree(hMem);
    
    // 添付ファイルの展開(実際はメール本文とヘッダの分割のみ)
    ret = NMailAttachmentFileFirst(Temp, subject, date, from, header, body, NULL, FileName, szAtFileData, NULL);
    
    if(ret == NMAIL_SUCCESS){
      //NMailAttachmentFileClose(Temp);
    }

    // メールサイズを変換する
    wsprintf(szSize, "%d", dwFSize);
    
    if(strlen(subject) > 0){
      InsertItem(hListL, iListNo, 0, subject);
    }
    else{
      InsertItem(hListL, iListNo, 0, "(件名なし)");
    }
    InsertItem(hListL, iListNo, 1, from);
    InsertItem(hListL, iListNo, 2, date);
    InsertItem(hListL, iListNo, 3, szSize);
    InsertItem(hListL, iListNo, 4, szfname);

    iListNo++;
  }
  
  // ファイルがなくなるまでリストに追加
  do{
    strcpy(szfname, wfd.cFileName);

    // ファイルを開く
    hFile = CreateFile(szfname, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if(hFile == INVALID_HANDLE_VALUE){
      MessageBox(NULL, "ファイルをオープンできません", "Error", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // ファイルサイズを調べる
    dwFSize = GetFileSize(hFile, &dwFSizeHigh);
    
    if(dwFSizeHigh != 0){
      MessageBox(NULL, "ファイルが大きすぎます", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // ファイルを読み込むためのメモリ領域を確保
    hMem = GlobalAlloc(GHND, dwFSize + 1);
    
    if(hMem == NULL){
      MessageBox(NULL, "メモリを確保できません", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // メモリ領域をロックしてファイルを読み込む
    lpszBuf = (char *)GlobalLock(hMem);
    ReadFile(hFile, lpszBuf, dwFSize, &dwAccBytes, NULL);
    lpszBuf[dwFSize] = '\0';
    
    // szAtFileDataのメモリ領域を確保する
    szAtFileData = (char *)malloc(sizeof(char) * dwFSize);
    
    if(szAtFileData == NULL){
      MessageBox(NULL, "メモリ確保に失敗しました", "メモリ確保失敗", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // メールファイルの中身をコピーする
    strcpy((char *)szAtFileData, lpszBuf);
    
    // ファイルを閉じる
    CloseHandle(hFile);
    GlobalUnlock(hMem);
    GlobalFree(hMem);
    
    // 添付ファイルの展開(実際はメール本文とヘッダの分割のみ)
    ret = NMailAttachmentFileFirst(Temp, subject, date, from, header, body, NULL, FileName, szAtFileData, NULL);
    
    if(ret == NMAIL_SUCCESS){
      //NMailAttachmentFileClose(Temp);
    }

    // メールサイズを変換する
    wsprintf(szSize, "%d", dwFSize);

    if(strlen(subject) > 0){
      InsertItem(hListL, iListNo, 0, subject);
    }
    else{
      InsertItem(hListL, iListNo, 0, "(件名なし)");
    }
    InsertItem(hListL, iListNo, 1, from);
    InsertItem(hListL, iListNo, 2, date);
    InsertItem(hListL, iListNo, 3, szSize);
    InsertItem(hListL, iListNo, 4, szfname);

    iListNo++;

  }while(FindNextFile(hFind, &wfd) == TRUE);

  FindClose(hFind);

  return;

}


瀬戸っぷ  2007-03-03 10:14:37  No: 64572

InsertItem()は自作関数でしょうか?
Listiew()の場合、最初にInsertItem()の後はSetItem()のようですが。
http://wisdom.sakura.ne.jp/system/winapi/common/common15.html

nMail.DLLも一応バージョンアップしているようですが、そちらも上げていますか?
ソースが全体を見れるわけではないので、想定でレスするしかないところですけど。

あとは……バッファオーバーフローの可能性でしょうかね。
長い件名を付けられた…など。


みけにゃん  URL  2007-03-03 17:56:32  No: 64573

InsertItemは自作関数(猫でもの238章のものを流用)です。
http://www.kumei.jp/c_lang/sdk3/sdk_238.htm

全体コードをあとで私のホームページからダウンロードできるようにします。
ちなみにPOP3からのメール受信時のInsertItem関数は正しく動いています。


瀬戸っぷ  2007-03-03 19:46:47  No: 64574

>ちなみにPOP3からのメール受信時のInsertItem関数は正しく動いています。

そうなると、受信時と読み込み時での差を調べることになるかと思います。
OutputDebugString()を使うか、ブレークポイントを置いてステップ実行していくことになるかと。
地道に調べるしかありません。
(InsertItem()の中にブレークポイント置けば、受信時/読み込み時問わずに止められるかと)


みけにゃん  URL  2007-03-03 22:33:03  No: 64575

プログラムの本体とソースコードをダウンロードできるようにしました。
http://angelteatime.punyu.net/mview006p.lzh


みけにゃん  URL  2007-03-04 06:19:53  No: 64576

InsertItem関数の中でデバッグ(MessageBoxで値を表示)をしてみると
多く追加していることに気づいて、原因である最初に上げた関数を
以下のように修正することで無事にやりたいことが出来ました。(>_<)
瀬戸っぷさんありがとうございます。

// ローカルに保存されているメールを取得する
void SetLocalMail(HWND hListL)
{
  WIN32_FIND_DATA wfd;
  HANDLE hFind;
  HANDLE hFile;              // ファイルハンドル
  HGLOBAL hMem;              // グローバルハンドル
  DWORD dwFSizeHigh, dwFSize, dwAccBytes;  // バイト数
  char szfname[MAX_PATH + 5];        // ファイル名
  char *lpszBuf;              // ファイルバッファ
  int ret;                // 戻り値
  int iListNo;

  // 添付メール展開用変数
  char subject[TEMP_MAX], date[TEMP_MAX], from[TEMP_MAX], header[TEMP_MAX], body[TEMP_MAX];
  char FileName[TEMP_MAX], Temp[NMAIL_ATTACHMENT_TEMP_SIZE], szSize[TEMP_MAX];
  
  // リストの初期化
  ListView_DeleteAllItems(hListL);
  GetCurrentDirectory(MAX_PATH, szfname);
  iListNo = 0;
  
  // メールファイルを探す
  hFind = FindFirstFile("*.dat", &wfd);
  
  // 検索が失敗した場合(ファイルがない場合)
  if(hFind == INVALID_HANDLE_VALUE){
    //MessageBox(NULL, "エラーです", "Error", MB_OK | MB_ICONSTOP);
    FindClose(hFind);
    return;
  }
  
  // ファイルがなくなるまでリストに追加
  do{
    strcpy(szfname, wfd.cFileName);

    // ファイルを開く
    hFile = CreateFile(szfname, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if(hFile == INVALID_HANDLE_VALUE){
      MessageBox(NULL, "ファイルをオープンできません", "Error", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // ファイルサイズを調べる
    dwFSize = GetFileSize(hFile, &dwFSizeHigh);
    
    if(dwFSizeHigh != 0){
      MessageBox(NULL, "ファイルが大きすぎます", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // ファイルを読み込むためのメモリ領域を確保
    hMem = GlobalAlloc(GHND, dwFSize + 1);
    
    if(hMem == NULL){
      MessageBox(NULL, "メモリを確保できません", "Error", MB_OK | MB_ICONSTOP);
      CloseHandle(hFile);
      return;
    }
    
    // メモリ領域をロックしてファイルを読み込む
    lpszBuf = (char *)GlobalLock(hMem);
    ReadFile(hFile, lpszBuf, dwFSize, &dwAccBytes, NULL);
    lpszBuf[dwFSize] = '\0';
    
    // szAtFileDataのメモリ領域を確保する
    szAtFileData = (char *)malloc(sizeof(char) * dwFSize);
    
    if(szAtFileData == NULL){
      MessageBox(NULL, "メモリ確保に失敗しました", "メモリ確保失敗", MB_OK | MB_ICONSTOP);
      return;
    }
    
    // メールファイルの中身をコピーする
    strcpy((char *)szAtFileData, lpszBuf);
    
    // ファイルを閉じる
    CloseHandle(hFile);
    GlobalUnlock(hMem);
    GlobalFree(hMem);
    
    // 添付ファイルの展開(実際はメール本文とヘッダの分割のみ)
    ret = NMailAttachmentFileFirst(Temp, subject, date, from, header, body, NULL, FileName, szAtFileData, NULL);
    
    if(ret == NMAIL_SUCCESS){
      //NMailAttachmentFileClose(Temp);
    }

    // メールサイズを変換する
    wsprintf(szSize, "%d", dwFSize);

    if(strlen(subject) > 0){
      InsertItem(hListL, iListNo, 0, subject);
    }
    else{
      InsertItem(hListL, iListNo, 0, "(件名なし)");
    }
    InsertItem(hListL, iListNo + 1, 1, from);
    InsertItem(hListL, iListNo + 1, 2, date);
    InsertItem(hListL, iListNo + 1, 3, szSize);
    InsertItem(hListL, iListNo + 1, 4, szfname);

    iListNo++;

  }while(FindNextFile(hFind, &wfd) == TRUE);

  FindClose(hFind);

  return;

}


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加