TOpenDialog 預設檔案列表為「詳細資料」檢視。使用者希望一開啟即顯示「大圖示」模式,提升圖片/縮圖辨識度。
WM_UPDATEUISTATE 修改 ListView 風格對話框顯示時,系統會送出 WM_UPDATEUISTATE,此時尋找嵌套結構:
TOpenDialog → SHELLDLL_DefView → SysListView32,直接修改 ListView 的 GWL_STYLE。
FARPROC OldDlgOpenProc 儲存原視窗程序。NewDlgOpenProc 攔截 WM_UPDATEUISTATE。OnShow 時 SetWindowLong(GWL_WNDPROC) 掛鉤;OnClose 時還原。static LRESULT CALLBACK NewDlgOpenProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_UPDATEUISTATE) {
HWND hShell = FindWindowEx(GetParent(hWnd), NULL, "SHELLDLL_DefView", NULL);
HWND hList = FindWindowEx(hShell, NULL, "SysListView32", NULL);
if (hList) {
// 清除低 4 位風格位,設為 LVS_ICON (0x0000)
SetWindowLong(hList, GWL_STYLE,
(GetWindowLong(hList, GWL_STYLE) & 0xFFFFFFF0) | LVS_ICON);
}
}
return CallWindowProc(OldDlgOpenProc, hWnd, uMsg, wParam, lParam);
}
void __fastcall TForm1::OpenDialogShow(TObject *Sender)
{
OldDlgOpenProc = (FARPROC)SetWindowLong(
OpenDialog1->Handle, GWL_WNDPROC, (LONG)NewDlgOpenProc);
}
void __fastcall TForm1::OpenDialogClose(TObject *Sender)
{
SetWindowLong(OpenDialog1->Handle, GWL_WNDPROC, (LONG)OldDlgOpenProc);
}
FCIDM_SHVIEW_LARGEICON(推薦)Shell 內部定義了檢視模式切換命令 ID,直接發送 WM_COMMAND 給 SHELLDLL_DefView 即可,無需修改視窗風格,相容性更佳。
const DWORD FCIDM_SHVIEW_LARGEICON = 28713; // 大圖示
const DWORD FCIDM_SHVIEW_SMALLICON = 28714; // 小圖示
const DWORD FCIDM_SHVIEW_LIST = 28715; // 列表
const DWORD FCIDM_SHVIEW_REPORT = 28716; // 詳細資料
const DWORD FCIDM_SHVIEW_THUMBNAIL = 28717; // 縮圖 (XP+)
const DWORD FCIDM_SHVIEW_TILE = 28718; // 平鋪 (XP+)
WndProc + 自訂訊息void __fastcall TForm1::WndProc(TMessage &Msg)
{
if (Msg.Msg == WM_USER + 1) {
HWND hDlg = (HWND)Msg.WParam;
HWND hCtrl = FindWindowEx(hDlg, NULL, "SHELLDLL_DefView", NULL);
if (hCtrl)
SendMessage(hCtrl, WM_COMMAND, FCIDM_SHVIEW_LARGEICON, 0);
}
TForm::WndProc(Msg);
}
void __fastcall TForm1::DlgOpenOnShow(TObject *Sender)
{
HWND hDlg = GetParent(((TOpenDialog*)Sender)->Handle);
PostMessage(Handle, WM_USER + 1, (WPARAM)hDlg, 0);
}
| 維度 | 方案一:修改風格 | 方案二:Shell 命令 |
|---|---|---|
| 相容性 | 可能受 ListView 版本影響 | 官方支援,跨版本穩定 |
| 代碼複雜度 | 需子類別化、管理 WNDPROC | 僅需 PostMessage + WndProc |
| 副作用風險 | 風格位操作可能衝突 | 純命令觸發,無副作用 |
| 支援模式 | 僅風格位定義的四種 | 含縮圖、平鋪等新模式 |
TOpenDialog 必須設定 OnShow 事件,並在表單啟用自訂訊息處理。![]()
掌握 Shell 內部命令 ID,不只解決檢視模式問題,更能控制排序、群組、預覽窗格等進階 Shell 檢視行為。