Stack Overflowをなくすには?

解決


みけにゃん  URL  2007-03-20 06:31:08  No: 64727

かなり変な所ではまってしまってしまいました・・・。
以前のプログラムでは問題なく開いていたダイアログを
開こうとすると不正な処理で落ちてしまい、デバックを
してみるとStack Overflowで落ちていることが分かったのですが

過去に作っていたプログラムと問題の部分を照らし合わせても
何も変わりがないのでどうしてなのかなぁ・・・と
詰まってしまっているところです・・・。

以前のプログラムのソースコード
http://angelteatime.punyu.net/knot/file/mview005.lzh

現在の最新ソースコード
http://angelteatime.punyu.net/knot/file/mview006.lzh

問題なのはWndProcのWM_COMMANDで呼び出している
IDM_OPEN:で開くダイアログ(添付ファイルを開く)を
開こうとするとStack Overflowで落ちます。

たぶん開放していない変数はないと思うのですが・・・・。
原因を教えていただけないでしょうか?


wclrp ( 'o')  2007-03-20 07:32:14  No: 64728

ローカル変数のメモリ使用量が多すぎるからでしょ。


みけにゃん  URL  2007-03-20 07:33:46  No: 64729

環境はVC++6.0、WindowsXP Home SP2です。

ちなみに他のダイアログの表示(新規メール作成、メールの設定、
バージョン表示など)では落ちずに表示できるという変な状態です。

あとその中で使用しているCenterWindow(自作関数)関数の中で
戻り値で使用しているSetWindowPosの実行でStack Overflowが
起きていて、その関数をコメント化するとダイアログは表示
されるけれど閉じるボタン(ただEndDialogを呼んでいるだけ)を
押すとStack Overflowになるというという変な状態です。

部分的にコードを載せておきます。

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  int iClickNo, Ret;
  static int iStatusWy;
  unsigned long datasz, Result, datatype;  // レジストリ用の変数
  static HWND hEdit, hList;        // コントロールハンドル

  RECT rc;          // RECT構造体
  POINT pt;          // POINT構造体
  DWORD dwStyle;        // ウィンドウスタイル
  LPNMHDR lpnmhdr;      // ヘッダハンドラ
  LPNMLISTVIEW lpnmlv;    // リストビューハンドラ
  HKEY hRegKey;        // レジストリハンドラ
  HMENU hMenu, hPMenu;    // メニューハンドル
  INITCOMMONCONTROLSEX ic;  // コモンコントロール
  char szFileName[TEMP_MAX], szSubject[TEMP_MAX];

  switch(msg){
    case WM_CREATE:
      NMailSetParameter(0, TEMP_MAX, 0);
      NMailInitializeWinSock();
      ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
      ic.dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES;
      InitCommonControlsEx(&ic);
            hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 0, 0, 0, 0, hWnd, (HMENU)ID_EDIT, hInst, NULL);
      SendMessage(hEdit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
      hList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "", WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT, 0, 0, 0, 0, hWnd, (HMENU)ID_LISTVIEW, hInst, NULL);
      dwStyle = ListView_GetExtendedListViewStyle(hList);
      dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP;
      ListView_SetExtendedListViewStyle(hList, dwStyle);
      InsertColumn(hList);
      hStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, ID_STATUS);
      GetWindowRect(hStatus, &rc);
      iStatusWy = rc.bottom - rc.top;

      RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Angelic Software\\MailViewer", 0, "MailViewer", 0, KEY_ALL_ACCESS, NULL, &hRegKey, &Result);

      if(Result == REG_CREATED_NEW_KEY){
        // レジストリへの新規作成処理
        RegSetValueEx(hRegKey, "Smtp Address", 0, REG_SZ, (LPBYTE)szSmtpServer, strlen(szSmtpServer)+1);
        RegSetValueEx(hRegKey, "Pop3 Address", 0, REG_SZ, (LPBYTE)szPopServer, strlen(szPopServer)+1);
        RegSetValueEx(hRegKey, "Mail Address", 0, REG_SZ, (LPBYTE)szMailAddr, strlen(szMailAddr)+1);
        RegSetValueEx(hRegKey, "User Name", 0, REG_SZ, (LPBYTE)szUserName, strlen(szUserName)+1);
        RegSetValueEx(hRegKey, "From Name", 0, REG_SZ, (LPBYTE)szName, strlen(szName)+1);
        RegSetValueEx(hRegKey, "Password", 0, REG_SZ, (LPBYTE)szPass, strlen(szPass)+1);
        RegSetValueEx(hRegKey, "APop", 0, REG_DWORD, (LPBYTE)&bApop, sizeof(DWORD));
        RegSetValueEx(hRegKey, "Pop Before SMTP", 0, REG_DWORD, (LPBYTE)&bPSmtp, sizeof(DWORD));
        RegSetValueEx(hRegKey, "Server Mail Del", 0, REG_DWORD, (LPBYTE)&bSMailDel, sizeof(DWORD));
      }
      else{
        // レジストリからの読出し処理
        datasz = 256;
        RegQueryValueEx(hRegKey, "Smtp Address",NULL,&datatype,(LPBYTE)szSmtpServer,&datasz);
        datasz = 256;
        RegQueryValueEx(hRegKey, "Mail Address",NULL,&datatype,(LPBYTE)szMailAddr,&datasz);
        datasz = 256;
        RegQueryValueEx(hRegKey, "Pop3 Address",NULL,&datatype,(LPBYTE)szPopServer,&datasz);
        datasz = 256;
        RegQueryValueEx(hRegKey, "User Name",NULL,&datatype,(LPBYTE)szUserName,&datasz);
        datasz = 256;
        RegQueryValueEx(hRegKey, "Password",NULL,&datatype,(LPBYTE)szPass,&datasz);
        datasz = 256;
        RegQueryValueEx(hRegKey, "From Name",NULL,&datatype,(LPBYTE)szName,&datasz);
        datasz = sizeof(DWORD);
        RegQueryValueEx(hRegKey, "APop",NULL,&datatype,(LPBYTE)&bApop,&datasz);
        datasz = sizeof(DWORD);
        RegQueryValueEx(hRegKey, "Pop Before SMTP",NULL,&datatype,(LPBYTE)&bPSmtp,&datasz);
        datasz = sizeof(DWORD);
        RegQueryValueEx(hRegKey, "Server Mail Del",NULL,&datatype,(LPBYTE)&bSMailDel,&datasz);
      }
      RegCloseKey(hRegKey);

      // 起動時のバグを回避
      No = -1;

      // ローカルに保存しているメール一覧を表示
      SetLocalMail(hList);
      break;
    case WM_SIZE:
      MoveWindow(hList, 0, 0, LOWORD(lParam), (HIWORD(lParam) - iStatusWy) / 2, TRUE);
      MoveWindow(hEdit, 0, (HIWORD(lParam) - iStatusWy) / 2, LOWORD(lParam), (HIWORD(lParam) - iStatusWy) / 2, TRUE);
      sb_size = LOWORD(lParam) - 120;
      SendMessage(hStatus, WM_SIZE, wParam, lParam);
      break;
    case WM_NOTIFY:
      lpnmhdr = (LPNMHDR)lParam;

      // 新しいコード
      if(lpnmhdr->hwndFrom == hList){
        switch(lpnmhdr->code){
          // シングルクリックの時
          case NM_CLICK:
            lpnmlv = (LPNMLISTVIEW)lParam;
            No = iClickNo = lpnmlv->iItem;
            
            // クリックした番号が-1の時はメールを表示しない
            if(iClickNo == -1){
              break;
            }
            
            // メールデータファイル名を取得する
            ListView_GetItemText(hList, iClickNo, 4, szFileName, sizeof(szFileName));

            // メールファイルを開く
            Read_MailData(szFileName, hEdit);
          break;
          case NM_RCLICK:
            lpnmlv = (LPNMLISTVIEW)lParam;
            iClickNo = lpnmlv->iItem;// + 1;
            
            // クリックした番号が-1の時はメニューを表示しない
            if(iClickNo == -1){
              break;
            }

            // 右クリックメニューを開く
            GetCursorPos(&pt);
            CreatePopupMenu();
            hPMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU2));
            hMenu = GetSubMenu(hPMenu, 0);
            TrackPopupMenu(hMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,hWnd,NULL);
            DestroyMenu(hMenu);
          break;
        }
      }
            break;
    // メニューを選択した時の説明表示(ステータスバー)
    case WM_MENUSELECT:
      switch (LOWORD(wParam)){
        case IDM_OPEN:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[0]);
          break;
        case IDM_SAVE:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[1]);
          break;
        case IDM_PAGEINF:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[2]);
          break;
        case IDM_PRINT:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[3]);
          break;
        case IDM_EXIT:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[4]);
          break;
        case IDM_NEW:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[5]);
          break;
        case IDM_RCVMAIL:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[6]);
          break;
        case IDM_REPLY:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[7]);
          break;
        case IDM_DELETE:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[8]);
          break;
        case IDM_HEADER:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[9]);
          break;
        case IDM_SET:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[10]);
          break;
        case IDM_HELP:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[11]);
          break;
        case IDM_ABOUT:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)szTipText[12]);
          break;
        default:
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)"");
          break;
      }
      break;
    // メニューを抜けた時の処理
    case WM_EXITMENULOOP:
      SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)"");
      break;
    case WM_COMMAND:
      switch(LOWORD(wParam)){
        case IDM_NEW:
          // 新規
          DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG4), hWnd, (DLGPROC)NewMailProc);
          break;
        case IDM_OPEN:
          // 開く
          DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG5), hWnd, (DLGPROC)AttachFileProc);
          break;
        case IDM_SAVE:
          // 保存
          //if(No > 0){
          if(No >= 0){
            WriteMailFile(hWnd);
          }
          break;
        case IDM_PRINT:
          // 印刷
          //if(No > 0){
          if(No >= 0){
            // メールの件名を取得
            ListView_GetItemText(hList, No, 0, szSubject, sizeof(szSubject));
            wsprintf(strMsg, "「%s」を印刷しますか?", szSubject);
            //wsprintf(strMsg, "%d番目のメールを印刷しますか?", No);
            Ret = MessageBox(hWnd, strMsg, "印刷の確認", MB_YESNO | MB_ICONQUESTION);
            if(Ret == IDYES){
              MPrint(hWnd);
            }
          }
          break;
        case IDM_RCVMAIL:
          // メールの受信
          // エディットボックスの内容を削除する
          SetWindowText(hEdit, "");

          // 基本設定がされていないとき
          if(strcmp(szPopServer, "") == 0 || strcmp(szUserName, "") == 0 || strcmp(szPass, "") == 0){
            MessageBox(hWnd, "メール受信の設定ができていません", "Mail Viewer", MB_OK | MB_ICONSTOP);
            break;
          }

          // まずはPOP3 サーバーに接続
          if((s = NMailPop3Connect(szPopServer)) != INVALID_SOCKET){
            // POP3 認証 & メールタイトル一覧表示
            if(List_Mail(s, szPopServer, szUserName, szPass, hList, hStatus) >= 0){
              NMailPop3Close(s);
            }
            else{
              MessageBox(hWnd, "認証に失敗しました", "Mail Viewer", MB_OK | MB_ICONSTOP);
              DestroyWindow(hProgress);
              NMailPop3Close(s);
            }
          }
          else{
            MessageBox(hWnd, "接続に失敗しました", "Mail Viewer", MB_OK | MB_ICONSTOP);
            DestroyWindow(hProgress);
            NMailPop3Close(s);
          }
          break;
        case IDM_REPLY:
          // メールの返信
          //if(No > 0){
          if(No >= 0){
            bReply = TRUE;
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG4), hWnd, (DLGPROC)NewMailProc);
          }
          break;
        case IDM_DELETE:
          // メールの削除
          //if(No > 0){
          if(No >= 0){
            // テキストボックスを初期化
            SetWindowText(hEdit, "");
            // メールデータファイル名を取得する
            ListView_GetItemText(hList, No, 4, szFileName, sizeof(szFileName));
            ListView_GetItemText(hList, No, 0, szSubject, sizeof(szSubject));
            wsprintf(strMsg, "「%s」を削除しますか?", szSubject);
            //wsprintf(strMsg, "%d番目のメールを削除しますか?", No);
            Ret = MessageBox(hWnd, strMsg, "削除の確認", MB_YESNO | MB_ICONQUESTION);
            if(Ret == IDYES){
              // 選択したメールを削除
              if(!DeleteFile(szFileName)){
                // 削除に失敗したとき
                MessageBox(hWnd, "削除に失敗しました", "MailViewer", MB_OK | MB_ICONSTOP);
                break;
              }
              else{
                // 削除が出来たとき
                //wsprintf(strMsg,"%d件目を削除しました\n", No);
                wsprintf(strMsg,"メールを削除しました\n", No);
                MessageBox(hWnd, strMsg, "MailViewer", MB_OK | MB_ICONINFORMATION);
              }

              // 受信メール一覧の更新
              SetLocalMail(hList);

              // 選択したメールを削除
              /*if((s = NMailPop3Connect(szPopServer)) != INVALID_SOCKET){
                if(NMailPop3Authenticate(s, szUserName, szPass, bApop) >= 0){
                  if(NMailPop3DeleteMail(s, No) >= 0){
                    wsprintf(strMsg,"%d件目を削除しました\n", No);
                    MessageBox(hWnd, strMsg, "MailViewer", MB_OK | MB_ICONINFORMATION);
                  }
                  else{
                    MessageBox(hWnd, "削除に失敗しました", "MailViewer", MB_OK | MB_ICONSTOP);
                  }
                }
                NMailPop3Close(s);

                // リストの更新
                SendMessage(hWnd, WM_COMMAND, IDM_RCVMAIL, 0);
              }
              else{
                MessageBox(hWnd, "POP3の接続に失敗しました", "MailViewer", MB_OK | MB_ICONINFORMATION);
              }*/
            }
          }
          break;
        case IDM_HEADER:
          // ヘッダ表示
          //if(No > 0){
          if(No >= 0){
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hWnd, (DLGPROC)HeaderProc);
            SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)"");
          }
          break;
        case IDM_SET:
          // メールの設定
          DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, (DLGPROC)MailSetProc);
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)"");
          break;
        case IDM_EXIT:
          SendMessage(hWnd, WM_CLOSE, 0, 0);
          break;
        case IDM_HELP:
          HtmlHelp(hWnd, "mailviewer.chm::/00.html > mailviewer01", HH_DISPLAY_TOC, NULL);
          break;
        case IDM_ABOUT:
          VersionNo = NMailGetVersion();
          DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hWnd, (DLGPROC)AboutProc);
          SendMessage(hStatus, SB_SETTEXT, 0 | 0, (LPARAM)"");
          break;
      }
      return 0;
    case WM_CLOSE:
      // HTMLヘルプが開いていたら閉じる
      if(HtmlHelp(hWnd, "mailviewer.chm", HH_GET_WIN_HANDLE, (DWORD)"mailviewer01")){
        HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);
      }

      // レジストリへの書き込み
      RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Angelic Software\\MailViewer", 0, "MailViewer", 0, KEY_ALL_ACCESS, NULL, &hRegKey, &Result);
      RegSetValueEx(hRegKey, "Smtp Address", 0, REG_SZ, (LPBYTE)szSmtpServer, strlen(szSmtpServer)+1);
      RegSetValueEx(hRegKey, "Pop3 Address", 0, REG_SZ, (LPBYTE)szPopServer, strlen(szPopServer)+1);
      RegSetValueEx(hRegKey, "From Name", 0, REG_SZ, (LPBYTE)szName, strlen(szName)+1);
      RegSetValueEx(hRegKey, "Mail Address", 0, REG_SZ, (LPBYTE)szMailAddr, strlen(szMailAddr)+1);
      RegSetValueEx(hRegKey, "User Name", 0, REG_SZ, (LPBYTE)szUserName, strlen(szUserName)+1);
      RegSetValueEx(hRegKey, "Password", 0, REG_SZ, (LPBYTE)szPass, strlen(szPass)+1);
      RegSetValueEx(hRegKey, "APop", 0, REG_DWORD, (LPBYTE)&bApop, sizeof(DWORD));
      RegSetValueEx(hRegKey, "Pop Before SMTP", 0, REG_DWORD, (LPBYTE)&bPSmtp, sizeof(DWORD));
      RegSetValueEx(hRegKey, "Server Mail Del", 0, REG_DWORD, (LPBYTE)&bSMailDel, sizeof(DWORD));

      RegCloseKey(hRegKey);

      // ウィンドウハンドルを破棄
      DestroyWindow(hWnd);
      DestroyWindow(hStatus);
      DestroyWindow(hEdit);
      break;
    case WM_DESTROY:
      HtmlHelp(NULL, NULL, HH_UNINITIALIZE, dwCookie);
      NMailEndWinSock();
      PostQuitMessage(0);
      break;
    default:
      return(DefWindowProc(hWnd, msg, wParam, lParam));
  }
  return (0L);
}

(省略)

// 添付ファイルを展開して保存ダイアログ
LRESULT CALLBACK AttachFileProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HWND hList, hFDEdit, hFBtn, hFDBtn;
  
  BROWSEINFO bi;
  ITEMIDLIST *lpid;
  HRESULT hr;
  LPMALLOC pMalloc = NULL;        // IMallocへのポインタ
  BOOL bDir = FALSE;

  HANDLE hFile;              // ファイルハンドル
  HGLOBAL hMem;              // グローバルハンドル
  DWORD dwFSizeHigh, dwFSize, dwAccBytes;  // バイト数
  char *lpszBuf;              // ファイルバッファ
  char f_id[TEMP_MAX], *PertId;      // 分割メールのID
  int no;                  // 添付ファイルの個数
  int ret;                // 戻り値

  // 添付メール展開用変数
  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];

  switch(msg){
    case WM_INITDIALOG:
      CenterWindow(hDlg, hParent);
      hList = GetDlgItem(hDlg, IDC_LIST1);
      hFDBtn = GetDlgItem(hDlg, IDC_FILEBTN);
      hFBtn = GetDlgItem(hDlg, IDC_BUTTON1);
      return TRUE;
    case WM_COMMAND:
      switch(LOWORD(wParam)){
      case IDC_BUTTON1:
        AttachFileOpen(hDlg, szAtFile, szAtFileName);

        // ファイルを開く
        hFile = CreateFile(szAtFile, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        
        if(hFile == INVALID_HANDLE_VALUE){
          MessageBox(hDlg, "ファイルをオープンできません", "Error", MB_OK);
          return FALSE;
        }
        
        // ファイルサイズを調べる
        dwFSize = GetFileSize(hFile, &dwFSizeHigh);
        
        if(dwFSizeHigh != 0){
          MessageBox(hDlg, "ファイルが大きすぎます", "Error", MB_OK);
          CloseHandle(hFile);
          return FALSE;
        }

        // ファイルを読み込むためのメモリ領域を確保
        hMem = GlobalAlloc(GHND, dwFSize + 1);
        
        if(hMem == NULL){
          MessageBox(hDlg, "メモリを確保できません", "Error", MB_OK);
          CloseHandle(hFile);
          return FALSE;
        }
        
        // メモリ領域をロックしてファイルを読み込む
        lpszBuf = (char *)GlobalLock(hMem);
        ReadFile(hFile, lpszBuf, dwFSize, &dwAccBytes, NULL);
        lpszBuf[dwFSize] = '\0';
        
        // szAtFileDataのメモリ領域を確保する
        szAtFileData = (char *)malloc(sizeof(char) * dwFSize);

        if(szAtFileData == NULL){
          MessageBox(hDlg, "メモリ確保に失敗しました", "メモリ確保失敗", MB_OK |MB_ICONSTOP);
          return FALSE;
        }

        // メールファイルの中身をコピーする
        strcpy((char *)szAtFileData, lpszBuf);
        
        // ファイルを閉じる
        CloseHandle(hFile);
        GlobalUnlock(hMem);
        GlobalFree(hMem);
        
        // ファイルが添付されているかを確認する
        if((no = NMailAttachmentFileStatus(szAtFileData, f_id, TEMP_MAX)) != NMAIL_NO_ATTACHMENT_FILE){
          if(no == 1){
            PertId = f_id;
          }
          hList = GetDlgItem(hDlg, IDC_LIST1);
          if(no == 0 || PertId == f_id){
            SendMessage(hList, LB_INSERTSTRING, (WPARAM)0, (LPARAM)szAtFile);
            SendMessage(hList, LB_SETCURSEL, (WPARAM)0, 0L);
            EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
          }
        }
        else{
          // 添付ファイルがないのでメッセージを出して終了
          MessageBox(hDlg, "このメールに、添付ファイルはありません", "添付ファイルなし", MB_OK |MB_ICONINFORMATION);
        }

        return TRUE;

      case IDC_FILEBTN:
        memset(&bi, 0, sizeof(BROWSEINFO));
        bi.hwndOwner = hDlg;
        bi.lpfn = SHMyProc;
        bi.ulFlags = BIF_EDITBOX | BIF_STATUSTEXT | BIF_VALIDATE;
        bi.lpszTitle = "展開先ディレクトリ指定";
        lpid = SHBrowseForFolder(&bi);
        
        if(lpid == NULL){
          return FALSE;
        }
        else{
          hr = SHGetMalloc(&pMalloc);
          if(hr == E_FAIL){
            MessageBox(hDlg, "SHGetMalloc Error", "Error", MB_OK);
            return FALSE;
          }
          SHGetPathFromIDList(lpid, szDir);
          if(szDir[strlen(szDir) - 1] != '\\'){
            strcat(szDir, "\\");
          }

          hFDEdit = GetDlgItem(hDlg, IDC_EDIT1);

          // 展開先フォルダをセットする
          SetWindowText(hFDEdit, szDir);

          pMalloc->Free(lpid);
          pMalloc->Release();
          bDir = TRUE;
        }
        return TRUE;

        case IDOK:
          // 添付ファイルの展開
          ret = NMailAttachmentFileFirst(Temp, subject, date, from, header, body, szDir, FileName, szAtFileData, NULL);
          if(ret == NMAIL_SUCCESS){
            NMailAttachmentFileClose(Temp);
            wsprintf(strMsg, "%sに%sを展開しました。", szDir, FileName);
            MessageBox(hDlg, strMsg, "Mail Viewer", MB_OK | MB_ICONINFORMATION);
          }
          // メモリの解放
          free(szAtFileData);
          EndDialog(hDlg, IDOK);
          return TRUE;
        case IDCANCEL:
          EndDialog(hDlg, IDOK);
          return TRUE;
        default:
          return FALSE;
      }
      default:
        return FALSE;
  }
  return TRUE;
}

(省略)

// ダイアログを中央に表示する
BOOL CenterWindow(HWND hwndChild, HWND hwndParent)
{
  BOOL bResult;
  RECT rcChild, rcParent, rcWorkArea;
  int   wChild, hChild, wParent, hParent;
  int   xNew, yNew;

  GetWindowRect(hwndChild,&rcChild);
  wChild = rcChild.right - rcChild.left;
  hChild = rcChild.bottom - rcChild.top;

  if(hwndParent){
    GetWindowRect(hwndParent,&rcParent);
  }
  else{
    GetWindowRect(GetDesktopWindow(),&rcParent);
  }
  
  wParent = rcParent.right - rcParent.left;
  hParent = rcParent.bottom - rcParent.top;

  bResult = SystemParametersInfo(SPI_GETWORKAREA,sizeof(RECT),&rcWorkArea,0);

  if(!bResult){
    rcWorkArea.left = rcWorkArea.top = 0;
    rcWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
    rcWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
  }

  xNew = rcParent.left + ((wParent-wChild) / 2);

  if(xNew < rcWorkArea.left){
    xNew = rcWorkArea.left;
  }
  else if((xNew+wChild) > rcWorkArea.right){
    xNew = rcWorkArea.right - wChild;
  }

  yNew = rcParent.top  + ((hParent-hChild) / 2);

  if(yNew < rcWorkArea.top){
    yNew = rcWorkArea.top;
  }
  else if((yNew+hChild) > rcWorkArea.bottom){
    yNew = rcWorkArea.bottom - hChild;
  }

  return SetWindowPos(hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE);
}


wclrp ( 'o')  URL  2007-03-20 08:26:52  No: 64730

コンパイルの指定でスタックを増やすだけで解決するんじゃない。
VC++6.0のスタックの増やし方は知らん。

サブルーチンに分けろよ。
ダイアログ出すときに使わないローカル変数のせいでスタックを大量に使っている。


瀬戸っぷ  2007-03-20 09:33:31  No: 64731

長いソースを貼られても、ちょっと読んでる時間はないです。

とりあえず…
ウィンドゥプロシージャ内の変数、もう少し整理してください。
WM_CREATEでつかわないモノまで確保されることになります。
case文の後にブロック切って、その中で使うモノだけにすれば
プロシージャ内でのローカル変数の使用量は減らせるハズです。

# 猫でも…はブロック分けになっていないのか…

InitCommonControlsEx()はWinMain()でやれば十分では?

# VCではデフォルトのスタックサイズは1Mほどです。
# リンカオプションで拡張できますが、配列など大きなモノを使う場合は
# ヒープから取るようにした方がいいです。
## MAX_PATHな配列5つくらいはローカルでよく取りますけど…


みけにゃん  URL  2007-03-21 10:32:24  No: 64732

とりあえずWndProc内のコードでサブルーチン化可能な
コードをサブルーチン化(レジストリのところとか)して

InitCommonControlsEx()など別にWndProcでしなくても
OKな初期化関数をWinMainに移動したり、無駄使いしていた
WndProcのszFileName[TEMP_MAX]とszSubject[TEMP_MAX]を
グローバルに移動(既にこの名前の変数が存在するので
名前を変えて)した事により、添付ファイル取り出し用の
ダイアログを開こうとして強制終了(実際はStack Overflow)する
現象が解決しました。

私のプログラムの知識が足りないばかりにご迷惑をおかけして
本当に申し訳ありませんです。

もう少し工夫出来そうな所を探して、コードをもう少し
見やすいように作っていこうと思います。

ありがとうございました。


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

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






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