預設情況下,TOpenDialog 的檔案清單採用「清單」檢視。若希望對話方塊一開啟即顯示「大圖示」模式,需在對話方塊顯示前找到內部的 SysListView32 控制項並修改其視窗樣式。本文提供兩種做法:子類化攔截 WM_UPDATEUISTATE、以及發送 WM_COMMAND 切換檢視模式。
在 OnShow 事件設定子類化程序,OnClose 還原:
FARPROC OldDlgOpenProc = NULL;
static LRESULT CALLBACK NewDlgOpenProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_UPDATEUISTATE) {
HWND hShell = FindWindowEx(GetParent(hWnd), NULL, L"SHELLDLL_DefView", NULL);
HWND hListView = FindWindowEx(hShell, NULL, L"SysListView32", NULL);
if (hListView) {
SetWindowLong(hListView, GWL_STYLE,
(GetWindowLong(hListView, GWL_STYLE) & 0xFFFFFFF0) | LVS_ICON);
}
}
return CallWindowProc((WNDPROC)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);
}
關鍵點:LVS_ICON (0x0000) 為大圖示樣式,先以 & 0xFFFFFFF0 清除低 4 位元原有檢視樣式位,再 | LVS_ICON 設定新模式。
Shell 控制項支援特定命令 ID 切換檢視:
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; // 縮圖
const DWORD FCIDM_SHVIEW_TILE = 28718; // 並排
WndProc,處理自訂訊息 WM_USER+1。OnShow 事件發送自訂訊息給表單,WParam 傳遞對話方塊父視窗控制代碼。FindWindowEx 找到 SHELLDLL_DefView,發送 WM_COMMAND 配合命令 ID。void __fastcall TForm1::WndProc(TMessage &Msg)
{
if (Msg.Msg == WM_USER + 1) {
HWND hDlg = (HWND)Msg.WParam;
HWND hCtrl = FindWindowEx(hDlg, NULL, L"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);
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
OpenDialog1->Execute();
}
IFileDialog,傳統 TOpenDialog 仍相容但內部結構可能不同,若失效請改用 IFileDialog::SetOptions(FOS_FORCEFILESYSTEM | ...) 搭配 IFileDialogCustomize。方法二僅需幾行程式碼即可達成預設大圖示檢視,維護性優於子類化做法。開發者可依專案相容性需求選擇適當方案。