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

バージョン情報ダイアログを作る

戻る


ハイパーリンク付きのバージョン情報ダイアログ(about dialog)を作成する方法を以下に示す。

#include <windows.h>
#include <winver.h>
#include <dlgs.h>

#define MAX_LINK 256

HINSTANCE g_hInstance;
HBITMAP g_hbm;
HICON g_hIcon;
HICON g_hIconSmall;
HCURSOR g_hcurHand;

typedef struct
{
    WORD wLanguage;
    WORD wCodePage;
} LANGANDCODEPAGE;

LRESULT CALLBACK
LinkWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    WNDPROC fnWndProc;
    RECT rc;
    POINT pt;
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR szText[MAX_LINK];
    HFONT hFont;
    HPEN hPen;
    HGDIOBJ hFontOld, hPenOld;
    COLORREF clr;
    HBRUSH hbr;

    fnWndProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    switch(uMsg)
    {
    case WM_SETFOCUS:
    case WM_KILLFOCUS:
        /* 再描画 */
        InvalidateRect(hWnd, NULL, TRUE);
        break;

    case WM_SETCURSOR:
        /* カーソルのセット */
        SetCursor(g_hcurHand);
        break;

    case WM_GETDLGCODE:
        /* プッシュボタンのようにふるまう */
        /* 方向キーは無効化 */
        return DLGC_DEFPUSHBUTTON | DLGC_WANTARROWS;

    case WM_MOUSEMOVE:
        GetClientRect(hWnd, &rc);
        pt.x = (SHORT)LOWORD(lParam);
        pt.y = (SHORT)HIWORD(lParam);
        if (PtInRect(&rc, pt))
        {
            SetTimer(hWnd, 999, 200, NULL);
        }
        else
            KillTimer(hWnd, 999);
        InvalidateRect(hWnd, NULL, TRUE);
        break;

    case WM_TIMER:
        GetClientRect(hWnd, &rc);
        GetCursorPos(&pt);
        ScreenToClient(hWnd, &pt);
        if (!PtInRect(&rc, pt))
            PostMessage(hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y));
        break;

    case WM_ERASEBKGND:
        GetClientRect(hWnd, &rc);
        hbr = (HBRUSH)SendMessage(GetParent(hWnd), WM_CTLCOLORSTATIC, wParam, (LPARAM)hWnd);
        FillRect((HDC)wParam, &rc, hbr);
        return TRUE;

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        if (hdc != NULL)
        {
            GetWindowText(hWnd, szText, MAX_LINK);
            GetClientRect(hWnd, &rc);
            GetCursorPos(&pt);
            ScreenToClient(hWnd, &pt);

            if (PtInRect(&rc, pt))
            {
                /* ハイライト描画 */
                InflateRect(&rc, -2, -2);
                clr = SetBkColor(hdc, RGB(255, 255, 192));
                ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
                SetBkColor(hdc, clr);
                /* 下線とテキストの色 */
                clr = RGB(192, 0, 0);
            }
            else
            {
                /* 下線とテキストの色 */
                clr = RGB(0, 0, 255);
            }

            SetBkMode(hdc, TRANSPARENT);
            hFont = (HFONT)SendMessage(GetParent(hWnd), WM_GETFONT, 0, 0);
            hFontOld = SelectObject(hdc, hFont);

            /* テキスト描画 */
            SetTextColor(hdc, clr);
            TextOut(hdc, 3, 3, szText, lstrlen(szText));
            /* 下線描画のためにテキストサイズ計算 */
            rc.left = 3;
            rc.top = 3;
            DrawText(hdc, szText, -1, &rc, DT_CALCRECT | DT_SINGLELINE);

            SelectObject(hdc, hFontOld);

            /* 下線描画 */
            hPen = CreatePen(PS_SOLID, 0, clr);
            hPenOld = SelectObject(hdc, hPen);
            MoveToEx(hdc, rc.left, rc.bottom, NULL);
            LineTo(hdc, rc.right, rc.bottom);
            SelectObject(hdc, hPenOld);
            DeleteObject(hPen);

            /* フォーカス枠描画 */
            if (GetFocus() == hWnd)
            {
                GetClientRect(hWnd, &rc);
                DrawFocusRect(hdc, &rc);
            }

            EndPaint(hWnd, &ps);
        }
        break;

    case WM_DESTROY:
        KillTimer(hWnd, 999);
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)fnWndProc);
        break;

    case WM_APP + 999:
        /* ウィンドウの大きさを文字列に合わせる */
        GetWindowText(hWnd, szText, MAX_LINK);
        GetClientRect(hWnd, &rc);
        hdc = GetDC(hWnd);
        rc.left = 0;
        rc.top = 0;
        hFont = (HFONT)SendMessage(GetParent(hWnd), WM_GETFONT, 0, 0);
        hFontOld = SelectObject(hdc, hFont);
        DrawText(hdc, szText, -1, &rc, DT_CALCRECT | DT_SINGLELINE);
        SelectObject(hdc, hFontOld);
        rc.right += 6;
        rc.bottom += 6;
        MapWindowPoints(hWnd, GetParent(hWnd), (POINT *)&rc, 2);
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
        ReleaseDC(hWnd, hdc);
        InvalidateRect(hWnd, NULL, TRUE);
        break;

    case WM_LBUTTONDOWN:
        /* キーボードフォーカスを自分に当てる */
        SendMessage(GetParent(hWnd), WM_NEXTDLGCTL, (WPARAM)hWnd, 1);
        /* FALL THRU */

    default:
        return CallWindowProc(fnWndProc, hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

BOOL OnInitDialog(HWND hDlg)
{
    TCHAR szModule[MAX_PATH], szBuffer[128];
    DWORD dwSize, dwHandle;
    LPVOID Data;
    LANGANDCODEPAGE *plgcode;
    VS_FIXEDFILEINFO *pvsffi;
    UINT uLen;
    LPTSTR psz;
    HWND hwndLink;
    WNDPROC fnWndProc;

    /* アイコンを読み込み、ダイアログにセットする。 */
    g_hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(1));
    g_hIconSmall = LoadImage(g_hInstance, MAKEINTRESOURCE(1), IMAGE_ICON,
        GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
    SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)g_hIcon);
    SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)g_hIconSmall);

    /* ポインタを読み込む */
    g_hcurHand = LoadCursor(g_hInstance, MAKEINTRESOURCE(1));

    /* ビットマップをセットする */
    g_hbm = LoadBitmap(g_hInstance, MAKEINTRESOURCE(1));
    SendDlgItemMessage(hDlg, stc4, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hbm);

    /* バージョン情報を取得する */
    GetModuleFileName(NULL, szModule, MAX_PATH);
    dwSize = GetFileVersionInfoSize(szModule, &dwHandle);
    if (dwSize)
    {
        Data = LocalAlloc(LPTR, dwSize);
        if (Data != NULL)
        {
            if (GetFileVersionInfo(szModule, dwHandle, dwSize, Data))
            {
                if (VerQueryValue(Data, TEXT("\\VarFileInfo\\Translation"), 
                                  (LPVOID *)&plgcode, &uLen))
                {
                    wsprintf(szBuffer, TEXT("\\StringFileInfo\\%04x%04x\\ProductName"),
                        plgcode->wLanguage, plgcode->wCodePage);
                    if (VerQueryValue(Data, szBuffer, (LPVOID *)&psz, &uLen))
                    {
                        SetDlgItemText(hDlg, stc1, psz);
                    }
                    wsprintf(szBuffer, TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"),
                        plgcode->wLanguage, plgcode->wCodePage);
                    if (VerQueryValue(Data, szBuffer, (LPVOID *)&psz, &uLen))
                    {
                        wsprintf(szBuffer, TEXT("Version %s"), psz);
                        SetDlgItemText(hDlg, stc2, szBuffer);
                    }
                    else if (VerQueryValue(Data, TEXT("\\"), (LPVOID *)&pvsffi, &uLen) &&
                             pvsffi->dwSignature == 0xFEEF04BD)
                    {
                        wsprintf(szBuffer, TEXT("Version %d.%d.%d.%d"),
                            HIWORD(pvsffi->dwProductVersionMS),
                            LOWORD(pvsffi->dwProductVersionMS),
                            HIWORD(pvsffi->dwProductVersionLS),
                            LOWORD(pvsffi->dwProductVersionLS));
                        SetDlgItemText(hDlg, stc2, szBuffer);
                    }
                }
            }
            LocalFree(Data);
        }
    }

    /* リンクをサブクラス化する */
    hwndLink = GetDlgItem(hDlg, stc3);
    fnWndProc = (WNDPROC)SetWindowLongPtr(hwndLink, GWLP_WNDPROC, (LONG_PTR)LinkWndProc);
    SetWindowLongPtr(hwndLink, GWLP_USERDATA, (LONG_PTR)fnWndProc);
    SendMessage(hwndLink, WM_APP + 999, 0, 0);

    return TRUE;
}


BOOL CALLBACK
DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndLink;
    TCHAR szText[MAX_LINK];

    switch(uMsg)
    {
    case WM_INITDIALOG:
        return OnInitDialog(hDlg);

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case stc3:
            if (HIWORD(wParam) == STN_CLICKED)
            {
                /* リンクがクリックされた */
                hwndLink = GetDlgItem(hDlg, stc3);
                GetWindowText(hwndLink, szText, MAX_LINK);
                ShellExecute(hDlg, NULL, szText, NULL, NULL, SW_SHOWNORMAL);
            }
            break;

        case IDOK:
            EndDialog(hDlg, IDOK);
            break;

        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            break;
        }
        break;

#if 0
    case WM_CTLCOLORDLG:
    case WM_CTLCOLORSTATIC:
        /* 背景を白くする */
        return (BOOL)GetStockObject(WHITE_BRUSH);
#endif
    }
    return FALSE;
}

INT WINAPI WinMain(
    HINSTANCE   hInstance,
    HINSTANCE   hPrevInstance,
    LPSTR       pszCmdLine,
    INT         nCmdShow)
{
    g_hInstance = hInstance;
    DialogBox(hInstance, MAKEINTRESOURCE(1), NULL, DialogProc);
    return 0;
}

リソースファイルは次のようになっている。

#include <windows.h>
#include <dlgs.h>

LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT

1 ICON "icon.ico"
1 BITMAP "katahiromz.bmp"
1 CURSOR "hand.cur"

1 DIALOG 0, 0, 170, 90
STYLE DS_MODALFRAME | DS_CENTER | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic"
{
    ICON    1, ico1, 10, 10, 18, 21
    LTEXT   "アプリケーション", stc1, 40, 10, 120, 12
    LTEXT   "(バージョン不明)", stc2, 40, 25, 120, 12
    LTEXT   "http://www.geocities.jp/katayama_hirofumi_mz/", stc3, 10, 41, 142, 14, SS_NOTIFY | WS_TABSTOP
    CONTROL "", stc4, "STATIC", SS_BITMAP, 9, 56, 72, 24
    DEFPUSHBUTTON   "OK", IDOK, 95, 65, 60, 14
}

/* バージョン情報 */
VS_VERSION_INFO VERSIONINFO
FILEVERSION     1,0,0,0
PRODUCTVERSION  1,0,2,0
FILEFLAGSMASK   0
#ifdef DEBUG
FILEFLAGS       VS_FF_DEBUG
#else
FILEFLAGS       0
#endif
FILEOS          VOS__WINDOWS32
FILETYPE        VFT_APP
FILESUBTYPE     VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
#if 1
        BLOCK "041103A4"    /* Japanese */
        BEGIN
            VALUE "CompanyName",        "片山博文MZ\0"
            VALUE "FileDescription",    "このファイルの説明です。\0"
            VALUE "LegalCopyright",     "Copyright (C) Katayama Hirofumi MZ. All rights reserved.\0"
            VALUE "LegalTrademarks",    "片山博文MZとKatayama Hirofumi MZは、片山博文MZの商標です。\0"
            VALUE "ProductName",        "AboutDlg\0"
            VALUE "ProductVersion",     "1.0\0"
        END
#else
        BLOCK "040904E4"    /* English */
        BEGIN
            VALUE "CompanyName",        "Katayama Hirofumi MZ\0"
            VALUE "FileDescription",    "This file's description\0"
            VALUE "LegalCopyright",     "Copyright (C) Katayama Hirofumi MZ. All rights reserved.\0"
            VALUE "LegalTrademarks",    "Katayama Hirofumi MZ is a trademark of Katayama Hirofumi MZ.\0"
            VALUE "ProductName",        "AboutDlg\0"
            VALUE "ProductVersion",     "1.0\0"
        END
#endif
    END
    BLOCK "VarFileInfo"
    BEGIN
#if 1
        /* Japanese */
        VALUE "Translation", 0x0411, 932
#else
        /* English */ 
        VALUE "Translation", 0x0409, 1252
#endif
    END
END

ソース: aboutdlg.zip


戻る

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

inserted by FC2 system