自訂 Open 對話框 (`CPersistOpenDlg`) 子類化 `SHELLDLL_DefView` 以記住視圖模式 (縮略圖/清單/詳細資料)。但發現:切換資料夾時會銷毀重建 View,導致 `OnDestroy` 儲存的是舊資料夾的視圖模式,而非關閉對話框時的模式。
class CListViewShellWnd : public CWnd {
CPersistOpenDlg* m_pDialog; // 回指父對話框
UINT m_lastViewMode;
void OnDestroy() {
m_lastViewMode = GetViewMode(); // 記住當前模式
// 關鍵:發送自訂訊息要求重新子類化新 View
m_pDialog->PostMessage(MYWM_POSTINIT);
}
};
class CPersistOpenDlg : public CFileDialog {
CListViewShellWnd m_wndListViewShell;
bool m_bFirstInit = true;
LRESULT OnPostInit(WPARAM wParam, LPARAM) {
if (wParam) { // 首次初始化
SubclassShellView();
RestoreViewMode(); // 從登錄還原
} else { // View 重建後
SubclassShellView(); // 僅重新子類化,不還原模式
}
return 0;
}
void SubclassShellView() {
HWND hView = FindShellView();
if (hView && m_wndListViewShell.m_hWnd != hView) {
m_wndListViewShell.UnsubclassWindow();
m_wndListViewShell.SubclassWindow(hView);
}
}
};
warning LNK4243: DLL 包含 /clr 編譯物件,無法搭配 /NOENTRY 連結;映像可能無法正常執行
// MixedDLL.h
#ifdef MIXEDDLL_EXPORTS
#define MIXED_API __declspec(dllexport)
#else
#define MIXED_API __declspec(dllimport)
#endif
MIXED_API BOOL InitializeMixedDLL();
MIXED_API BOOL TerminateMixedDLL();
// MixedDLL.cpp
#include <_vcclrit.h> // CRT 內部標頭
BOOL InitializeMixedDLL() {
return __crt_dll_initialize(); // 相當於 _DllMainCRTStartup(DLL_PROCESS_ATTACH)
}
BOOL TerminateMixedDLL() {
return __crt_dll_terminate(); // 相當於 _DllMainCRTStartup(DLL_PROCESS_DETACH)
}
// 應用程式主視窗或 CWinApp::InitInstance
class CMixedDLLInitializer {
public:
CMixedDLLInitializer() { InitializeMixedDLL(); }
~CMixedDLLInitializer() { TerminateMixedDLL(); }
};
// 全域實例,確保在 main/WinMain 前初始化,結束後終止
CMixedDLLInitializer g_mixedDLLInit;
若 Mixed DLL 由另一個 Native DLL 隱性連結載入,不能在全域建構子中呼叫 `__crt_dll_initialize` (會造成載入器死結)。解決方式:
// MixedDLL.cpp
#define TRACE_MIXED(msg) TRACE(_T("MixedDLL: %s\n"), _T(msg))
CMixedDLLInitializer::CMixedDLLInitializer() {
// 錯誤示範:TRACE 在 CRT 初始化前呼叫會 Crash
// TRACE_MIXED("Before init");
InitializeMixedDLL();
TRACE_MIXED("After init"); // 正確:CRT 已初始化
}