ソフトウェア開発 Win32プログラミング

画像を「開く」ダイアログ

戻る


これより、画像を「開く」ダイアログを実装する方法を説明する。

画像を「開く」ダイアログでは、自動的に縮小版表示に切り替えておくと画像がすぐに見えて作業がはかどる。それを実現する方法は「開く」ダイアログのフックである。

しかし、Windows 2000以降でlStructSizeメンバーに古い構造体のサイズ(OPENFILENAME_SIZE_VERSION_400)を設定してフックをした場合、左に古いプレースバー(places bar)のない、古いダイアログが表示されてしまう。これを防ぐため、#include の前に

#define _WIN32_WINNT 0x0500

を記述して、Windows 2000以降の場合は、lStructSizeメンバーに新しい構造体のサイズを指定する。

#define _WIN32_WINNT 0x0500
 
#include <windows.h>
#include <shlobj.h>
#include <tchar.h>
#include <string.h>

// ファイル名
TCHAR g_szFileName[MAX_PATH] = TEXT("無題");
// ディレクトリ
TCHAR g_szDir[MAX_PATH];
 
// フィルタ
TCHAR g_szOpenFilter[] = 
    TEXT("すべての画像ファイル (*.gif;*.jpg;*.png;*.bmp)\0*.gif;*.jpg;*.png;*.bmp\0")
    TEXT("GIF (*.gif)\0*.gif\0")
    TEXT("JPEG (*.jpg)\0*.jpg\0")
    TEXT("PNG (*.png)\0*.png\0")
    TEXT("BMP (*.bmp)\0*.bmp\0")
    TEXT("すべてのファイル (*.*)\0*.*\0\0");
TCHAR g_szSaveFilter[] = 
    TEXT("GIF (*.gif)\0*.gif\0")
    TEXT("JPEG (*.jpg)\0*.jpg\0")
    TEXT("PNG (*.png)\0*.png\0")
    TEXT("BMP (*.bmp)\0*.bmp\0")
    TEXT("すべてのファイル (*.*)\0*.*\0\0");
 
// ファイルを読み込む
BOOL LoadFile(HWND hWnd, LPCTSTR pszFileName)
{
    // ここにファイルを読み込むコードを記述してください。
    MessageBox(hWnd, pszFileName, TEXT("開く"), MB_ICONINFORMATION);
    return TRUE;
}
 
// ファイルを保存する
BOOL SaveFile(HWND hWnd, LPCTSTR pszFileName, INT nFileType)
{
    // ここにファイルを保存するコードを記述してください。
    TCHAR szCaption[128];
    wsprintf(szCaption, TEXT("保存 nFileType == %d"), nFileType);
    MessageBox(hWnd, pszFileName, szCaption, MB_ICONINFORMATION);
    return TRUE;
}
 
#define SHVIEW_THUMBNAILS_98    0x7030      // 98(未確認)
#define SHVIEW_THUMBNAILS_2K    0x7031      // 2000
#define SHVIEW_THUMBNAILS_XP    0x702D      // XP
#define SHVIEW_THUMBNAILS_VISTA 0x704F      // Vista
// Windows 7は未確認。

UINT SHVIEW_THUMBNAILS;         // 縮小版表示のコマンド
BOOL g_fWin2000Plus = FALSE;    // Windows 2000以降か?
 
// バージョンを調べる
BOOL CheckVersionForOFN(VOID)
{
    OSVERSIONINFO info;
 
    SHVIEW_THUMBNAILS = 0;
    g_fWin2000Plus = FALSE;
 
    info.dwOSVersionInfoSize = sizeof(info);
    if (GetVersionEx(&info))
    {
        if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
        {
            switch(info.dwMajorVersion)
            {
            case 4:     // Windows NT 4
                // 縮小表示できない。
                break;
 
            case 5:
                switch(info.dwMinorVersion)
                {
                case 0:     // Windows 2000
                    SHVIEW_THUMBNAILS = SHVIEW_THUMBNAILS_2K;
                    g_fWin2000Plus = TRUE;
                    return TRUE;
 
                case 1:     // Windows XP
                    SHVIEW_THUMBNAILS = SHVIEW_THUMBNAILS_XP;
                    g_fWin2000Plus = TRUE;
                    return TRUE;
                }
                break;
 
            case 6:
                switch(info.dwMinorVersion)
                {
                case 0:     // Windows Vista
                    SHVIEW_THUMBNAILS = SHVIEW_THUMBNAILS_VISTA;
                    g_fWin2000Plus = TRUE;
                    return TRUE;
 
                case 1:     // Windows 7
                    g_fWin2000Plus = TRUE;
                    return FALSE;
                }
                break;
            }
        }
        else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
        {
            if (info.dwMajorVersion == 4)
            {
                switch(info.dwMinorVersion)
                {
                case 0:     // Windows 95
                    // 縮小表示できない。
                    return FALSE;
 
                case 10:    // Windows 98
                    SHVIEW_THUMBNAILS = SHVIEW_THUMBNAILS_98;
                    return TRUE;
 
                case 90:    // Windows Me
                    g_fWin2000Plus = TRUE;
                    // FIXME: 自動的に縮小版にすることができない?
                    return FALSE;
                }
            }
        }
    }
    return FALSE;
}
 
// OFNのフックプロシージャ
UINT APIENTRY OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LPOFNOTIFY lpNotify;
    HWND hwndDefView;
    switch(uMsg)
    {
    case WM_NOTIFY:
        lpNotify = (LPOFNOTIFY)lParam;
        switch(lpNotify->hdr.code)
        {
        case CDN_FOLDERCHANGE:
            hwndDefView = FindWindowEx(GetParent(hDlg), NULL, TEXT("SHELLDLL_DefView"), NULL);
            // 縮小版を表示
            SendMessage(hwndDefView, WM_COMMAND, SHVIEW_THUMBNAILS, 0);
            break;
        }
        break;
    }
    return 0;
}
 
// 「開く」ダイアログ
BOOL DoOpen(HWND hWnd)
{
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH];
 
    szFileName[0] = 0;
 
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.hwndOwner           = hWnd;
    ofn.lpstrFilter         = g_szOpenFilter;
    ofn.nFilterIndex        = 1;
    ofn.lpstrFile           = szFileName;
    ofn.nMaxFile            = MAX_PATH;
    ofn.lpstrInitialDir     = g_szDir;
    ofn.lpstrDefExt         = TEXT("gif");
 
    if (CheckVersionForOFN())
    {
        ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_FILEMUSTEXIST |
                    OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK;
        ofn.lpfnHook = OFNHookProc;
    }
    else
    {
        ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_FILEMUSTEXIST |
                    OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
    }
 
    if (g_fWin2000Plus)
        ofn.lStructSize = sizeof(OPENFILENAME);
    else
        ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
 
    if (GetOpenFileName(&ofn))
    {
        LPTSTR p;
        lstrcpy(g_szFileName, ofn.lpstrFile);
        lstrcpy(g_szDir, ofn.lpstrFile);
        p = _tcsrchr(g_szDir, _T('\\'));
        *p = 0;
        return LoadFile(hWnd, g_szFileName);
    }
    return FALSE;
}
 
// 「名前を付けて保存」ダイアログ
BOOL DoSaveAs(HWND hWnd)
{
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH];
 
    lstrcpy(szFileName, g_szFileName);
 
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.hwndOwner           = hWnd;
    ofn.lpstrFilter         = g_szSaveFilter;
    ofn.nFilterIndex        = 1;
    ofn.lpstrFile           = szFileName;
    ofn.nMaxFile            = MAX_PATH;
    ofn.lpstrInitialDir     = g_szDir;
    ofn.lpstrDefExt         = TEXT("gif");
 
    if (CheckVersionForOFN())
    {
        ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT |
                    OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
        ofn.lpfnHook = OFNHookProc;
    }
    else
    {
        ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT |
                    OFN_PATHMUSTEXIST;
    }
 
    if (g_fWin2000Plus)
        ofn.lStructSize = sizeof(OPENFILENAME);
    else
        ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
 
    if (GetSaveFileName(&ofn))
    {
        LPTSTR p;
        lstrcpy(g_szFileName, ofn.lpstrFile);
        lstrcpy(g_szDir, ofn.lpstrFile);
        p = _tcsrchr(g_szDir, _T('\\'));
        *p = 0;
        return SaveFile(hWnd, g_szFileName, ofn.nFilterIndex);
    }
    return FALSE;
}
 
int main(void)
{
    LPITEMIDLIST pidl;
 
    //if (SHGetSpecialFolderLocation(NULL, CSIDL_MYPICTURES, &pidl) != NOERROR)
        SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
    SHGetPathFromIDList(pidl, g_szDir);
    CoTaskMemFree(pidl);
 
    DoOpen(NULL);
    DoSaveAs(NULL);
 
    return 0;
}

今回フックは、「開く」ダイアログにあるSHELLDLL_DefViewクラスのウィンドウにOSのバージョンに応じて、適当なコマンドのWM_COMMANDメッセージを送ることで縮小版表示にする。

コマンドの値は、Spy++、SpyGuruなどのソフトを使ってSHELLDLL_DefViewクラスのウィンドウに届くWM_COMMANDのwParamの値を調べれば得られる。ただし、Windows Meの場合は特殊らしく、縮小版表示の設定はうまくいかなかった。

ソース: open2.zip

参考


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system &