首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

CFileDialog 圖片預覽擴展:Hook 機制、模板定制與跨系統版本適配

     編輯:關於VC++

需求:在標準「開啟檔案」對話框右側加入圖片預覽區。本文採用 CFileDialog 派生 + Hook 截獲 CDN_SELCHANGE + 子對話框模板 方案,並解決 Win98/Win2000/XP 風格差異、多選緩衝區、預覽區佈局等實戰問題。

核心架構

class CFileDialogEx : public CFileDialog
{
    // Hook 回調靜態函數
    static UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
    // 內部預覽處理
    void OnSelChange(HWND hDlg);
    // ... 其他成員
};

1. 啟用 Hook 與自定義模板

建構函數中設定 m_ofn:

m_ofn.Flags |= OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE;
m_ofn.lpfnHook = OFNHookProc;
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG_HOOK); // 預覽區模板
m_ofn.hInstance = AfxGetInstanceHandle();

2. 模板對話框資源設計 (IDD_DIALOG_HOOK)

  • Style: Child, Border: None, 勾選 Clip siblings, Control。
  • 放置一個 Static Text (ID: IDC_PIC),屬性:Notify, Sunken,作為圖片顯示區。

3. Hook 截獲 CDN_SELCHANGE 觸發預覽

UINT_PTR CALLBACK CFileDialogEx::OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_NOTIFY)
    {
        OFNOTIFY* pNotify = (OFNOTIFY*)lParam;
        if (pNotify->hdr.code == CDN_SELCHANGE)
        {
            CFileDialogEx* pThis = (CFileDialogEx*)pNotify->hdr.lParam; // lParamCustData 傳 this
            pThis->OnSelChange(hDlg);
        }
    }
    return 0;
}

void CFileDialogEx::OnSelChange(HWND hDlg)
{
    // 取得選中檔案完整路徑
    TCHAR szPath[MAX_PATH];
    CommDlg_OpenSave_GetFilePath(GetParent(hDlg), szPath, MAX_PATH);
    // 載入圖片至 IDC_PIC (需自行實作 CPicture 載入 BMP/JPG/GIF 並 StretchBlt 繪製)
    // ...
}

4. 跨系統版本風格適配 (關鍵:lStructSize)

// 檢測 OS 版本決定結構體大小,控制對話框外觀
DWORD dwVer = GetVersion();
if (dwVer < 0x80000000) // NT 核心 (Win2000/XP/...)
    m_ofn.lStructSize = 88; // OPENFILENAME_SIZE_VERSION_400 (含 Places Bar)
else
    m_ofn.lStructSize = 76; // Win98 經典尺寸

此技巧讓同一套代碼在 Win98 顯示舊風格,在 2K/XP 顯示帶左側快捷列的新風格。

5. 多選緩衝區擴容 (解決 256 字元限制)

// 靜態大緩衝
TCHAR szBuf[4096] = {0};
dlg.m_ofn.lpstrFile = szBuf;
dlg.m_ofn.nMaxFile = 4096;
dlg.m_ofn.Flags |= OFN_ALLOWMULTISELECT;

或動態分配 (配合 CommDlg_OpenSave_GetSpec/GetFolderPath 取得實際所需大小)。

6. 預覽區佈局微調 (右側/底部/含核取方塊)

MSDN 規定:模板中 ID 為 stc32 的 Static 控制項位置決定預覽區放置邊界。

  • 預覽區在右側:stc32 放在模板右側,寬度即預覽區寬度。
  • 底部含核取方塊:stc32 放在核取方塊上方,高度 = 預覽區高度 + 核取方塊高度。

實測需反覆微調 stc32 位置才能達到預期佈局。

7. 使用範例

CFileDialogEx dlg(TRUE);
dlg.m_ofn.lpstrFilter = _T("圖片\0*.bmp;*.jpg;*.png\0所有\0*.*\0");
if (dlg.DoModal() == IDOK)
{
    POSITION pos = dlg.GetStartPosition();
    while (pos) { CString path = dlg.GetNextPathName(pos); /*處理*/ }
}

完整專案含 CPicture 多格式載入類、Hook 類、資源模板,可直接整合。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved