またまたブログエディターから時数超過です!、っと怒られましたので、ウィンドウの操作系であるメンバー変数のOnVersion関数までを「その1」とし、ユーザー定義関数とダイアログ関連を「その2」で解説します。(字数制限があるので大分手抜きですが。)

 

/////////////////////////////////////////////
//ユーザー定義関数
//*.albファイルを読む
//newone: TRUE-先頭、FALSE-m_Selectedの位置
/////////////////////////////////////////////
bool CMyWnd::ReadAlbum() {

    //現在登録された写真がある場合
    if(g_Album.GetCount()) {
        int res = MessageBox(m_hWnd, "現在イメージデータが残っています。\n"\
                        "削除しますか?(はい)、追加しますか(いいえ)、"\
                        "処理を中止しますか(キャンセル)",
                        "削除確認", MB_YESNOCANCEL | MB_ICONQUESTION);
        switch(res) {
        case IDYES:
            g_Album.DeleteAll();
            break;
        case IDNO:
            break;
        case IDCANCEL:
            return FALSE;
        }
    }
    //g_FileNameのファイルをg_Fileにも見込めたか?
    if(!g_File.FromFile(g_FileName.ToChar())) {    //albファイルを読み込めたか?
        MessageBox(m_hWnd, "albファイルを読み込めませんでした", "エラー",
                    MB_OK | MB_ICONERROR);
        g_FileName = "";                        //ファイル名データを初期化
        return FALSE;
    }
    //アルバムに写真データ読込
    CSTR fn, cmt;
    while(g_File.Next(fn)) {    //ファイル名の切り出し
        g_File.Next(cmt);        //コメントの切り出し
        if(!g_Album.Add(fn.ToChar(), "", cmt.ToChar())) {    //写真の追加
            MessageBox(m_hWnd, "写真を追加できませんでした", "エラー", MB_OK | MB_ICONERROR);
            g_Album.DeleteAll();//途中まで読み込んだファイルがあれば削除する
            g_Album.SetCol(255, 255, 255, 255);                //Alph = 255、白色で
            g_Album.Cls();                                    //画面クリアー
            g_File = "";        //一旦読み込んだファイルを廃棄
            g_FileName = "";    //ファイル名データを初期化
            return FALSE;
        }
    }
    return TRUE;
}
//(解説:アルバムファイルを読み、CPHOTOクラス配列に落とす処理です。既にあるデータに追加もできるようにしています。)

bool CMyWnd::ShowAlbum(bool newone) {

    //読み込んだアルバムファイル名をステータスバーに表示
    SBar.SetText(2, g_FileName.ToChar());
    //メニュー、ボタンを初期状態から変える
    ChangeState(TRUE);
    //メニュー、ツールバーボタンの初期状態
    ChangeMode(g_ShowMode);
    //新しいアルバム(newone == TRUE)なら先頭の写真を選択
    if(newone)
        g_Album.Select(0);
    //スライダーを写真の先頭にセットする
    g_Slider.SetRange(0, g_Album.GetCount() - 1);    //スライダーの範囲を0~イメージ数 - 1に設定
    g_Slider.SetPosition(g_Album.GetSelected());    //現在選択されている写真を選択
    //Alph = 255、白色で画面クリアー
    g_Album.SetCol(255, 255, 255, 255);
    g_Album.Cls();
    //写真の表示
    if(g_ShowMode) {    //単一表示の場合
        ShowWindow(g_Slider.GetHandle(), SW_SHOW);    //スライダーを表示
        g_Album.ShowImg(FALSE, FALSE);                //写真を画面中央にサイズを調整して表示
    }
    else {                //サムネイル表示の場合
        ShowWindow(g_Slider.GetHandle(), SW_HIDE);    //スライダーを非表示
        //サムネイル上の選択写真枠設定色とペン
        g_Album.SetCol(128, 255, 64, 64);
        g_Album.SetPen(8);
        g_Album.ShowThumbnail(g_ThumbSize);
    }
    return TRUE;
}
//(解説:モード別に写真画像を表示する処理です。内容は既に説明している通りです。)

///////////////////////////////////
//ユーザー定義関数
//保存メニュー切替
//flag: FALSE-写真がなくなった場合
//flag: TRUE-データがある場合
//編集メニュー切替
//flag: FLASE-写真がなくなった場合
//flag: TRUE -写真がある場合
///////////////////////////////////
void CMyWnd::ChangeState(bool flag) {

    //ファイルメニューハンドルの取得
    HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 0);
    if(flag) {
        //アルバムの保存メニュー
        EnableMenuItem(hMenu, IDM_SAVE, MF_BYCOMMAND | MF_ENABLED);
        EnableMenuItem(hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_ENABLED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_SAVE, MAKELONG(TBSTATE_ENABLED, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_SAVEAS, MAKELONG(TBSTATE_ENABLED, 0));
    }
    else { 
        //アルバムの保存メニュー
        EnableMenuItem(hMenu, IDM_SAVE, MF_BYCOMMAND | MF_GRAYED);
        EnableMenuItem(hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_GRAYED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_SAVE, MAKELONG(0, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_SAVEAS, MAKELONG(0, 0));
    }
    //編集メニューハンドルの取得
    hMenu = GetSubMenu(GetMenu(m_hWnd), 1);
    if(flag) {
        //削除メニュー
        EnableMenuItem(hMenu, IDM_DEL, MF_BYCOMMAND | MF_ENABLED);
        //削除ボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_DEL, MAKELONG(TBSTATE_ENABLED, 0));
    }
    else { 
        //削除メニュー
        EnableMenuItem(hMenu, IDM_DEL, MF_BYCOMMAND | MF_GRAYED);
        //削除ボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_DEL, MAKELONG(0, 0));
    }
    //表示メニューハンドルの取得
    hMenu = GetSubMenu(GetMenu(m_hWnd), 2);
    //前へメニュー
    EnableMenuItem(hMenu, IDM_PREV, MF_BYCOMMAND | (flag ? MF_ENABLED : MF_GRAYED));
    //次へメニュー
    EnableMenuItem(hMenu, IDM_NEXT, MF_BYCOMMAND | (flag ? MF_ENABLED : MF_GRAYED));
    if(flag) {
        //前へボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_PREV, MAKELONG(TBSTATE_ENABLED, 0));
        //次へボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_NEXT, MAKELONG(TBSTATE_ENABLED, 0));
    }
    else { 
        //前へボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_PREV, MAKELONG(0, 0));
        //次へボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_NEXT, MAKELONG(0, 0));
    }
}
//(解説:データが無い、またはある場合のメニュー、ツールバーボタンの状態を変えます。)

///////////////////////////////////
//ユーザー定義関数
//表示メニュー切替
//flag: TRUE-標準表示
//FALSE-サムネイル表示
///////////////////////////////////
void CMyWnd::ChangeMode(bool flag) {

    HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 2);    //表示メニューハンドルの取得
    //メニューバー
    EnableMenuItem(hMenu, 0, MF_BYPOSITION | (flag ? MF_GRAYED : MF_ENABLED));
    EnableMenuItem(hMenu, 1, MF_BYPOSITION | (flag ? MF_ENABLED : MF_GRAYED));
    //メニューアイテム
    MENUITEMINFO mii;
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    if(flag) {
        //メニュー
        mii.fState = MFS_CHECKED;
        SetMenuItemInfo(hMenu, 1, TRUE, &mii);
        EnableMenuItem(hMenu, IDM_LARGE, MF_BYCOMMAND | MF_GRAYED);
        EnableMenuItem(hMenu, IDM_SMALL, MF_BYCOMMAND | MF_GRAYED);
        EnableMenuItem(hMenu, IDM_ORIG, MF_BYCOMMAND | MF_ENABLED);
        EnableMenuItem(hMenu, IDM_ADJT, MF_BYCOMMAND | MF_ENABLED);
        EnableMenuItem(hMenu, IDM_EDIT, MF_BYCOMMAND | MF_ENABLED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_NORM, MAKELONG(TBSTATE_PRESSED, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_EDIT, MAKELONG(TBSTATE_ENABLED, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_THUMNAIL, MAKELONG(TBSTATE_ENABLED, 0));
    }
    else { 
        //メニュー
        mii.fState = MFS_CHECKED;
        SetMenuItemInfo(hMenu, 0, TRUE, &mii);
        EnableMenuItem(hMenu, IDM_LARGE, MF_BYCOMMAND | MF_ENABLED);
        EnableMenuItem(hMenu, IDM_SMALL, MF_BYCOMMAND | MF_ENABLED);
        EnableMenuItem(hMenu, IDM_ORIG, MF_BYCOMMAND | MF_GRAYED);
        EnableMenuItem(hMenu, IDM_ADJT, MF_BYCOMMAND | MF_GRAYED);
        EnableMenuItem(hMenu, IDM_EDIT, MF_BYCOMMAND | MF_GRAYED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_NORM, MAKELONG(TBSTATE_ENABLED, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_EDIT, MAKELONG(0, 0));
        SendMessage(TBar.GetHandle(), TB_SETSTATE, IDM_THUMNAIL, MAKELONG(TBSTATE_PRESSED, 0));
    }
}
//(解説:表示モードを変えた場合にメニュー、ツールバーの状態を変化させます。)

///////////////////////////////////
//ユーザー定義関数
//回転、反転メニュー切替
///////////////////////////////////
void CMyWnd::ChangeRotateFlip(int n) {

    //既にチェックが入っているメニューアイテム
    static int old = 0;
    //表示メニューハンドルの取得
    HMENU hMenu = GetSubMenu(GetSubMenu(GetSubMenu(GetMenu(m_hWnd), 2), 1), 2);
    //メニューアイテム
    MENUITEMINFO mii;
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    mii.fState = MFS_ENABLED;
    //既に入っているチェックを外す
    SetMenuItemInfo(hMenu, old, TRUE, &mii);
    //新しくチェックを入れる
    mii.fState = MFS_CHECKED;
    SetMenuItemInfo(hMenu, n, TRUE, &mii);
    //回転、反転状況をステータスバーに表示
    SBar.SetText(1, g_RotateFlip[n]);
    old = n;
}
//(解説:回転表示のメニューアイテムのチェックを変化させます。)

///////////////////////////////
//RESIZEダイアログの関数定義
//コントロール関数
///////////////////////////////
bool RESIZEDLG::OnInit(WPARAM wParam, LPARAM lParam) {

    //作業用文字列変数
    char buff[MAX_PATH];
    //エラーチェック
    if(!g_Album.GetCount) {
        MessageBox(m_hWnd, "写真がありません", "エラー", MB_OK | MB_ICONERROR);
        EndModal(FALSE);
        return TRUE;
    }
    //現在選択されている写真のファイル名の表示
    SendItemMsg(IDC_SOURCE, WM_SETTEXT, 0, (LPARAM)g_Album.GetFileName());
    //画像形式をチェックして表示
    int n = g_ExtChk.CheckExt(g_Album.GetFileName(), IMGFILTER);
    if(!n) {
        MessageBox(m_hWnd, "対象ファイルではありません", "エラー", MB_OK | MB_ICONERROR);
        EndModal(FALSE);
        return TRUE;
    }
    else if(n > 2)
        n -= 1;
    lstrcpyW(m_Encoder, g_EncoderList[n - 1]);    //メンバー変数m_Encoderにエンコーダー名を保存
    wcstombs(buff, g_EncoderList[n - 1], 12);
    SendItemMsg(IDC_IMGTYPE, WM_SETTEXT, 0, (LPARAM)buff);
    //写真のファイル名からイメージインスタンスを生成
    mbstowcs(m_WName, g_Album.GetFileName(), MAX_PATH);
    m_pImage = new Image(m_WName);
    if(!m_pImage) {
        MessageBox(m_hWnd, "写真を読み込めませんでした", "エラー", MB_OK | MB_ICONERROR);
        EndModal(FALSE);
        return TRUE;
    }
    //読み込めたら現在の回転を適用する
    RotateFlipType rft = g_Album.GetRotateFlip();
    m_pImage->RotateFlip(rft);
    n = 0;
    switch(rft) {
    case RotateNoneFlipNone:
        n = 0;
        break;
    case Rotate90FlipNone:
        n = 1;
        break;
    case Rotate180FlipNone:
        n = 2;
        break;
    case Rotate270FlipNone:
        n = 3;
        break;
    }
    SendItemMsg(IDC_ROTATE, WM_SETTEXT, 0, (LPARAM)g_RotateFlip[n]);
    //幅と高さを取得してエディットボックスに代入
    m_ImgW = m_pImage->GetWidth();
    m_ImgH = m_pImage->GetHeight();
    wsprintf(buff, "%d", m_ImgW);
    SendItemMsg(IDC_WIDTH, WM_SETTEXT, 0, (LPARAM)buff);
    wsprintf(buff, "%d", m_ImgH);
    SendItemMsg(IDC_HEIGHT, WM_SETTEXT, 0, (LPARAM)buff);
    //スライダー初期設定-ハンドルの取得
    m_hSlider = GetDlgItem(m_hWnd, IDC_TRACKBAR);
    //20の目盛りを設定
    SendMessage(m_hSlider, TBM_SETTICFREQ, 20, 0);
    //0-100の範囲を設定
    SendMessage(m_hSlider, TBM_SETRANGE, TRUE, (LPARAM)MAKELONG(0, 100));
    //マウスクリックの際の移動量
    SendMessage(m_hSlider, TBM_SETPAGESIZE, 0, (LPARAM)10);
    //矢印キーの際の移動量
    SendMessage(m_hSlider, TBM_SETLINESIZE, 0, (LPARAM)1);
    //スライダーの位置を設定
    SendMessage(m_hSlider, TBM_SETPOS, TRUE, (LPARAM)100);
    //調整幅、高さをエディットボックスに代入
    wsprintf(buff, "%d", m_ImgW);
    SendItemMsg(IDC_ADJW, WM_SETTEXT, 0, (LPARAM)buff);
    wsprintf(buff, "%d", m_ImgH);
    SendItemMsg(IDC_ADJH, WM_SETTEXT, 0, (LPARAM)buff);
//(解説:長々と書いていますが、これは全てダイアログの初期設定です。結構コントロールがあり、且つImageクラスオブジェクトの情報を取ってコントロールに反映させることから長くなってしまいました。内容はコメントの通りです。)
    return TRUE;
}

bool RESIZEDLG::OnHScroll(WPARAM wParam, LPARAM lParam) {

    //作業用文字列変数
    char buff[MAX_PATH];
    //スライダー位置
    int pos;
    if(lParam != (LPARAM)m_hSlider)
        return FALSE;                    //スライダーからの通知でなければ何もしない
    switch(LOWORD(wParam)) {            //スライダーコントロールからの通知
    case SB_THUMBTRACK:                    //スライダーのドラッグ時と
    case SB_THUMBPOSITION:                //摘みを離した時に
        pos = HIWORD(wParam);            //スライダーの位置を取得
        break;
    default:                            //それ以外の場合HIWORD(wParam)は使えない
        pos = SendMessage(m_hSlider, TBM_GETPOS, 0, 0);    //TBM_GETPOSで位置を取得
        break;
    }
    int w = m_ImgW * pos / 100;
    int h = m_ImgH * pos / 100;
    wsprintf(buff, "%d", w);
    SendItemMsg(IDC_ADJW, WM_SETTEXT, 0, (LPARAM)buff);
    wsprintf(buff, "%d", h);
    SendItemMsg(IDC_ADJH, WM_SETTEXT, 0, (LPARAM)buff);
//(解説:スライダーを動かすと、0 - 100の数値が返ってくるので、それをImageオブジェクトの幅、高さ原寸にかけ、100で割り、調整幅、高さを求めて表示します。)
    return TRUE;
}

bool RESIZEDLG::OnIdok() {

    //処理の意向確認
    int res = MessageBox(m_hWnd, "ファイルを上書きしますか(はい)、"\
                        "別名保存しますか(いいえ)、処理を中止しますか(キャンセル)?",
                        "確認", MB_YESNOCANCEL | MB_ICONQUESTION);
    if(res == IDCANCEL) {
        //m_pImageのメモリーを解放
        delete m_pImage;
        EndModal(FALSE);
        return TRUE;
    }
    else if(res == IDNO) {
        //「ファイルを保存」ダイアログでパス、ファイル名を指定
        char* cp = g_Cmndlg.GetFileName(m_hWnd, "全てのファイル\0*.*\0\0", FALSE);
        if(!cp) {
            MessageBox(m_hWnd, "キャンセルされました", "エラー", MB_OK | MB_ICONERROR);
            return FALSE;
        }
            lstrcpy(m_NewName, cp);
    }
    else {    //IDYES
        //上書き用ファイル名("(Originalファイル名).bak")を設定
        lstrcpy(m_NewName, g_Album.GetFileName());
        lstrcpy(strstr(m_NewName, "."), ".bak");
    }
    //作業用文字列変数
    char buff[MAX_PATH];
    //縮小修正した幅、高さを取得
    SendItemMsg(IDC_ADJW, WM_GETTEXT, MAX_PATH, (LPARAM)buff);
    int w = atoi(buff);
    SendItemMsg(IDC_ADJH, WM_GETTEXT, MAX_PATH, (LPARAM)buff);
    int h = atoi(buff);
    //縮小画像用のBitmapオブジェクトをオリジナルの縦横比で生成
    Bitmap* pBitmap = new Bitmap(w, h);
    //Bitmapオブジェクトから出力用のGraphicsフレームオブジェクトを作成
    Graphics* pFrame = Graphics::FromImage(pBitmap);
    //Rectオブジェクトのフレームの矩形を生成
    Gdiplus::Rect rtFrame(0, 0, w, h);
    //画像の全体をフレームのrtFrameで表した矩形領域へ描画
    pFrame->DrawImage (m_pImage, rtFrame, 0, 0, m_ImgW, m_ImgH, UnitPixel);    //1ポイント == 1/72インチ
    // エンコーダのCLSIDを取得
    CLSID encoderClsid;
    if(GetEncoderClsid(m_Encoder, &encoderClsid) == -1) {    //m_Encoderに保存してあるエンコーダー型
        MessageBoxW(m_hWnd, m_WName, L"エンコーダーCLSIDの取得に失敗しました", MB_OK | MB_ICONERROR);
        //ビットマップのメモリーを解放
        delete pBitmap;
        //m_pImageのメモリーを解放
        delete m_pImage;
        EndModal(FALSE);
        return TRUE;
    }
    //EncoderParameters配列の第1オブジェクトを使って品質を指定
    LONG lQuality = 100;    //品質レベルは100の最高品質
    //EncoderParameters配列オブジェクト
    EncoderParameters EncoderParams;
    //先頭のEncoderParameterオブジェクト
    EncoderParams.Parameter[0].Guid = EncoderQuality;                    //品質であることを指定
    EncoderParams.Parameter[0].NumberOfValues = 1;                        //Valueの変数数は1つ
    EncoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;    //Valueの変数の長さ
    EncoderParams.Parameter[0].Value = (VOID*) &lQuality;                //品質指定
    EncoderParams.Count = 1;                                            //EncoderParameters配列は一つだけ
    //フレームとして使ったBitmapを指定エンコーダー、品質でファイルに保存
    mbstowcs(m_WName, m_NewName, MAX_PATH);
    pBitmap->Save(m_WName, &encoderClsid, &EncoderParams);
    //ビットマップのメモリーを解放
    delete pBitmap;
    //m_pImageのメモリーを解放
    delete m_pImage;
    //上書き処理
    if(res == IDYES) {
        DeleteFile(g_Album.GetFileName());            //オリジナルファイルを削除
        MoveFile(m_NewName, g_Album.GetFileName());    //縮小ファイルをオリジナル名に変更
    }
    EndModal(TRUE);
//(解説:可也細かくコメントを書いていますが、要すればダイアログで表示されている回転状態、調整幅、高さのImageオブジェクトをビットマップフレームに書き出し、選択されたエンコーダーでその型式のファイルで書きだします。「別名保存」の場合はそのファイル名そのままで、「上書き保存」の場合は(ImageのSaveメソッドが上書きを禁止しているので)一旦*.bakで書き出し、オリジナルを削除してからファイル名をオリジナルに変更します。)
    return TRUE;
}

bool RESIZEDLG::OnIdcancel() {

    //m_pImageのメモリーを解放
    delete m_pImage;
    EndModal(FALSE);
    return TRUE;
}
//(解説:Idokでも、Idcancelでも、newで生成したオブジェクト(メモリー割り付け)は必ずdelete処理するように気を付けてください。忘れるとメモリーリークが発生します。)

////////////////////////////////////////////////////
//ユーザー定義関数
//Image CODEC CLSIDの取得(出典:Microsoft Doc)
//formatに合致するCODECのCLSIDアドレスをpClsidに渡す
//戻り値:成功-Image CODEC配列(ImageCodecInfo)引数
//    失敗- -1
////////////////////////////////////////////////////
int RESIZEDLG::GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {

    //イメージCODECの数、サイズ取得
    UINT  num = 0;        //image encoderの数
    UINT  size = 0;        //image encoder配列のサイズ(バイト数)
    GetImageEncodersSize(&num, &size);
    if(size == 0) {
        return -1; //イメージCODECサイズ取得失敗
    }
    //イメージCODEC情報用クラス(ImageCodecInfo)
    ImageCodecInfo* pImageCodecInfo = NULL;
    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if(pImageCodecInfo == NULL) {
        return -1; //メモリ確保失敗
    }
    //イメージCODEC情報クラス取得
    GetImageEncoders(num, size, pImageCodecInfo);
    for(UINT j = 0; j < num; ++j) {
        //formatがCODECのMIME(Multipurpose Internet Mail Extensions)型なら
        if(wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
            //J番目のCODECのグローバル一意識別子(CLSID)を渡す
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;    //成功
        }  
    }
    free(pImageCodecInfo);
    return -1;            // 失敗 - 要求した種類のエンコーダが存在しなかった
}
//(解説:表題に書かれている通り、Microsoft Docのコードをベースにちょっと書き換えました。コメントも日本語にしているのでわかりやすいと思います。)

///////////////////////////////
//EDITダイアログの関数定義
//コントロール関数
///////////////////////////////
bool EDITDLG::OnInit(WPARAM wParam, LPARAM lParam) {

    //クライアントエリアサイズを記録
    RECT rec;
    GetClientRect(m_hWnd, &rec);
    m_Width = rec.right - rec.left;
    m_Height = rec.bottom - rec.top;
    //IDC_EDITコントロールを展開する(初期状態で0x7FFF-32,767字迄取り扱い可能)
    MoveWindow(GetDlgItem(m_hWnd, IDC_EDIT), 2, 2, m_Width - 4, m_Height - 36, TRUE);
    //コメントを読み込む
    SendItemMsg(IDC_EDIT, WM_SETTEXT, 0, (LPARAM)g_Album.GetComment());
    //IMEの変換状態を全角ひらがなにセットする
    m_hImc = ImmGetContext(GetDlgItem(m_hWnd, IDC_EDIT));
    ImmSetOpenStatus(m_hImc, TRUE);
    if(!ImmSetConversionStatus(m_hImc, IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE, IME_SMODE_PHRASEPREDICT))
        MessageBox(m_hWnd, "全角ひらがな連文節変換入力にセットできませんでした", "エラー", MB_OK | MB_ICONERROR);
    return TRUE;
}
//(解説:↑の「IMEの変換状態を全角ひらがなにセットする」のところがやや目新しいところです。

 

 

bool EDITDLG::OnSize(WPARAM wParam, LPARAM lParam) {

    //コントロールの位置、サイズ変更
    RECT rec;    //矩形取得用
    POINT pt;    //スクリーン座標変換用
    int w, h;    //幅、高さ計算用
    int diffx = LOWORD(lParam) - m_Width;    //前回と今回の差分
    int diffy = HIWORD(lParam) - m_Height;    //前回と今回の差分
    m_Width = LOWORD(lParam);                //今回の幅
    m_Height = HIWORD(lParam);                //今回の高さ
    //幅高さ変更-IDC_EDIT
    GetWindowRect(GetDlgItem(m_hWnd, IDC_EDIT), &rec);    //ウィンドウ位置取得
    w = rec.right - rec.left;
    h = rec.bottom - rec.top;
    pt.x = rec.left;
    pt.y = rec.top;
    ScreenToClient(m_hWnd, &pt);
    MoveWindow(GetDlgItem(m_hWnd, IDC_EDIT), pt.x, pt.y, w + diffx, h + diffy, TRUE);
    //左右上下移動-IDOK
    GetWindowRect(GetDlgItem(m_hWnd, IDOK), &rec);    //ウィンドウ位置取得
    w = rec.right - rec.left;
    h = rec.bottom - rec.top;
    pt.x = rec.left;
    pt.y = rec.top;
    ScreenToClient(m_hWnd, &pt);
    MoveWindow(GetDlgItem(m_hWnd, IDOK), pt.x + diffx, pt.y + diffy, w, h, TRUE);
    //クライアントエリアを再描画
    InvalidateRect(m_hWnd, NULL, TRUE);
    return TRUE;
}

bool EDITDLG::OnMinMax(WPARAM wParam, LPARAM lParam) {

    //典型的なウィンドウのサイズ制限処理
    MINMAXINFO *pmmi;
    pmmi = (MINMAXINFO*)lParam;
    pmmi->ptMinTrackSize.x = 320;    //クライアントエリア + 16
    pmmi->ptMinTrackSize.y = 240;    //クライアントエリア + 61
    return FALSE;                    //処理はDefWndProcに任す
}

bool EDITDLG::OnIdok() {

    //IMEを閉じる
    ImmSetOpenStatus(m_hImc, FALSE);
    ImmReleaseContext(GetDlgItem(m_hWnd, IDC_EDIT), m_hImc);
    //IDC_EDITコントロールの文字列を取得する(初期状態で0x7FFF-32,767字迄取り扱い可能)
    char buff[MAXCMT];
    //コメントを読み込む
    SendItemMsg(IDC_EDIT, WM_GETTEXT, MAXCMT, (LPARAM)buff);
    g_Album.SetComment(buff);
    EndModal(TRUE);
    return TRUE;
}

bool EDITDLG::OnIdcancel() {

    EndModal(FALSE);
    return TRUE;
}
//(解説:文字列の編集を行い、CPHOTOのm_Commentを更新する単なるエディットコントロール一つのダイアログですが、サイズを可変にしてコントロールサイズも変更し、最小サイズを制限しているのでコードが長くなっています。)

///////////////////////////////
//VERSIONダイアログの関数定義
//コントロール関数
///////////////////////////////
bool VERSIONDLG::OnIdok() {

    EndModal(TRUE);
    return TRUE;
}

ゼイ、ゼイ、という感じですが、やっと終わりにたどり着きました。お疲れさまでした。
次回はブログベースで最終でコンパイルとアルバムを実際に使用した雑感などを書いてみましょう。