数年前から悩んでいたメールデータをローカルにファイル化して
格納するというところは解決したのですが、それから先のところで
つまづいてしまっています。
それはファイル化したメールデータのヘッダ情報(件名、差出人、
受信日時、メールのファイルサイズ、ファイル名(メールデータ
ファイルを開くためのものなので非表示))を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;
}
InsertItem()は自作関数でしょうか?
Listiew()の場合、最初にInsertItem()の後はSetItem()のようですが。
http://wisdom.sakura.ne.jp/system/winapi/common/common15.html
nMail.DLLも一応バージョンアップしているようですが、そちらも上げていますか?
ソースが全体を見れるわけではないので、想定でレスするしかないところですけど。
あとは……バッファオーバーフローの可能性でしょうかね。
長い件名を付けられた…など。
InsertItemは自作関数(猫でもの238章のものを流用)です。
http://www.kumei.jp/c_lang/sdk3/sdk_238.htm
全体コードをあとで私のホームページからダウンロードできるようにします。
ちなみにPOP3からのメール受信時のInsertItem関数は正しく動いています。
>ちなみにPOP3からのメール受信時のInsertItem関数は正しく動いています。
そうなると、受信時と読み込み時での差を調べることになるかと思います。
OutputDebugString()を使うか、ブレークポイントを置いてステップ実行していくことになるかと。
地道に調べるしかありません。
(InsertItem()の中にブレークポイント置けば、受信時/読み込み時問わずに止められるかと)
プログラムの本体とソースコードをダウンロードできるようにしました。
http://angelteatime.punyu.net/mview006p.lzh
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;
}