From 50a42e5d72e2f8cf92ff9b2273e0442977dbcefd Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期三, 18 十二月 2024 18:28:02 +0800
Subject: [PATCH] 1. 对话框基类添加动态控件管理 2. 对话框基类主题切换功能
---
SourceCode/Bond/BondEq/CBaseDlg.cpp | 166 +++++++++++++++++++++++++++++++++-------
SourceCode/Bond/BondEq/CBaseDlg.h | 35 +++++++-
2 files changed, 166 insertions(+), 35 deletions(-)
diff --git a/SourceCode/Bond/BondEq/CBaseDlg.cpp b/SourceCode/Bond/BondEq/CBaseDlg.cpp
index d424513..2ddd896 100644
--- a/SourceCode/Bond/BondEq/CBaseDlg.cpp
+++ b/SourceCode/Bond/BondEq/CBaseDlg.cpp
@@ -2,9 +2,16 @@
#include "CBaseDlg.h"
#include "GridCtrl.h"
+// 全局主题对象
+Theme g_lightTheme = { RGB(255, 255, 255), RGB(0, 0, 0), RGB(240, 240, 240), RGB(200, 200, 200) };
+Theme g_darkTheme = { RGB(40, 40, 40), RGB(255, 255, 255), RGB(60, 60, 60), RGB(80, 80, 80) };
+
+CFont g_defaultFont;
+Theme* g_currentTheme = &g_lightTheme;
+
IMPLEMENT_DYNAMIC(CBaseDlg, CDialogEx)
-CBaseDlg::CBaseDlg(UINT id, CWnd* pPage) : CDialogEx(id, pPage)
+CBaseDlg::CBaseDlg(UINT id, CWnd* pPage) : CDialogEx(id, pPage), m_bResizing(false)
{
m_nInitialWidth = 0;
m_nInitialHeight = 0;
@@ -12,23 +19,21 @@
CBaseDlg::~CBaseDlg()
{
- for (auto& pair : m_mapFonts) {
- if (pair.second) {
- pair.second->DeleteObject();
- delete pair.second;
- }
- }
+ // shared_ptr会自动清理内存,不需要手动删除
m_mapFonts.clear();
+ m_mapCtrlLayouts.clear();
+ m_mapControls.clear();
}
CFont* CBaseDlg::GetOrCreateFont(int nFontSize)
{
auto it = m_mapFonts.find(nFontSize);
if (it != m_mapFonts.end()) {
- return it->second;
+ return it->second.get();
}
- CFont* font = new CFont();
+ // 使用 shared_ptr 来管理字体对象
+ auto font = std::make_shared<CFont>();
LOGFONT logFont = { 0 };
_tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
logFont.lfHeight = -nFontSize;
@@ -36,17 +41,15 @@
font->CreateFontIndirect(&logFont);
m_mapFonts[nFontSize] = font;
- return font;
+ return font.get();
}
void CBaseDlg::SetDefaultFont()
{
CFont* defaultFont = GetOrCreateFont(12);
- // 遍历所有控件,应用默认字体
CWnd* pWnd = GetWindow(GW_CHILD);
while (pWnd) {
- // 跳过特殊控件(如 MFCGridCtrl)
TCHAR szClassName[256];
GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
@@ -59,13 +62,87 @@
}
}
+BOOL CBaseDlg::AddControl(UINT nCtrlID, CWnd* pControl)
+{
+ // 确保控件不重复添加
+ if (m_mapControls.find(nCtrlID) != m_mapControls.end()) {
+ return FALSE; // 控件已经存在
+ }
+
+ m_mapControls[nCtrlID] = std::unique_ptr<CWnd>(pControl);
+ return TRUE;
+}
+
+BOOL CBaseDlg::RemoveControl(UINT nCtrlID)
+{
+ auto it = m_mapControls.find(nCtrlID);
+ if (it != m_mapControls.end()) {
+ m_mapControls.erase(it);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CBaseDlg::UpdateControlText(UINT nCtrlID, const CString& strText)
+{
+ auto it = m_mapControls.find(nCtrlID);
+ if (it != m_mapControls.end()) {
+ CWnd* pWnd = it->second.get();
+ if (pWnd->GetSafeHwnd() != nullptr)
+ {
+ pWnd->SetWindowText(strText);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+CWnd* CBaseDlg::GetControl(UINT nCtrlID)
+{
+ auto it = m_mapControls.find(nCtrlID);
+ if (it != m_mapControls.end()) {
+ return it->second.get();
+ }
+ return nullptr;
+}
+
+void CBaseDlg::SwitchTheme(ThemeType themeType)
+{
+ // 使用 map 来根据 themeType 查找主题
+ static const std::unordered_map<ThemeType, Theme*> themeMap = {
+ { ThemeType::Light, &g_lightTheme },
+ { ThemeType::Dark, &g_darkTheme }
+ };
+
+ // 设置当前主题
+ auto it = themeMap.find(themeType);
+ if (it != themeMap.end()) {
+ g_currentTheme = it->second;
+ }
+ else {
+ g_currentTheme = &g_lightTheme;
+ }
+
+ // 更新控件的外观
+ CWnd* pWnd = GetWindow(GW_CHILD);
+ while (pWnd) {
+ pWnd->Invalidate(); // 重绘控件
+ pWnd = pWnd->GetNextWindow();
+ }
+
+ // 更新对话框背景颜色
+ SetBackgroundColor(g_currentTheme->backgroundColor);
+}
+
void CBaseDlg::AdjustControls(float dScaleX, float dScaleY)
{
+ if (m_bResizing) return; // 防止在调整过程中重复调整
+
+ m_bResizing = true;
CWnd* pWnd = GetWindow(GW_CHILD);
while (pWnd) {
int nCtrlID = pWnd->GetDlgCtrlID();
- if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end())
- {
+ if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end()) {
CRect originalRect = m_mapCtrlLayouts[nCtrlID];
CRect newRect(
static_cast<int>(originalRect.left * dScaleX),
@@ -95,6 +172,7 @@
}
pWnd = pWnd->GetNextWindow();
}
+ m_bResizing = false;
}
void CBaseDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
@@ -102,17 +180,14 @@
TCHAR szClassName[256];
GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
- // 跳过特殊控件(如 MFCGridCtrl)
if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
return;
}
- // 根据控件高度动态调整字体大小
int fontSize = nHeight / 2;
if (fontSize < 8) fontSize = 8;
if (fontSize > 32) fontSize = 32;
- // 获取或创建字体
CFont* pFont = GetOrCreateFont(fontSize);
pWnd->SetFont(pFont);
@@ -122,35 +197,44 @@
BEGIN_MESSAGE_MAP(CBaseDlg, CDialogEx)
ON_WM_SIZE()
ON_WM_GETMINMAXINFO()
+ ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
BOOL CBaseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
- // TODO: 在此添加额外的初始化
+ // 获取当前语言
+ LANGID langId = GetUserDefaultLangID();
+ if (langId == LANG_CHINESE) {
+ // 加载中文资源
+ }
+ else {
+ // 加载英文资源
+ }
+
+ // 获取对话框的工作区(屏幕可用区域)
CRect screenRect, dlgRect, clientRect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
-
GetClientRect(&clientRect);
m_nInitialWidth = clientRect.Width();
m_nInitialHeight = clientRect.Height();
- // 初始化默认字体
+ // 设置默认字体
CFont* pDefaultFont = GetOrCreateFont(12);
- // 遍历所有子控件,记录初始位置并设置默认字体
+ // 遍历子窗口(控件)
CWnd* pWnd = GetWindow(GW_CHILD);
while (pWnd) {
int nCtrlID = pWnd->GetDlgCtrlID();
if (nCtrlID != -1) {
- // 记录控件初始布局
+ // 保存控件的初始布局
CRect ctrlRect;
pWnd->GetWindowRect(&ctrlRect);
ScreenToClient(&ctrlRect);
m_mapCtrlLayouts[nCtrlID] = ctrlRect;
- // 跳过特殊控件(如 MFCGridCtrl)
+ // 排除不需要操作的控件(如自定义控件 GridCtrl)
TCHAR szClassName[256];
GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
@@ -158,12 +242,13 @@
continue;
}
- // 设置默认字体
+ // 设置控件的默认字体
pWnd->SetFont(pDefaultFont);
}
pWnd = pWnd->GetNextWindow();
}
+ // 将对话框居中
GetWindowRect(&dlgRect);
int dlgWidth = dlgRect.Width() * 2;
int dlgHeight = dlgRect.Height() * 2;
@@ -179,31 +264,50 @@
int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
- return TRUE; // return TRUE unless you set the focus to a control
- // 异常: OCX 属性页应返回 FALSE
+ return TRUE;
}
void CBaseDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
- // TODO: 在此处添加消息处理程序代码
if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
return;
}
+ // 检查尺寸变化是否足够大,避免频繁调整
+ //static int lastWidth = 0, lastHeight = 0;
+ //if (abs(cx - lastWidth) < 10 && abs(cy - lastHeight) < 10) {
+ // return;
+ //}
+
+ //lastWidth = cx;
+ //lastHeight = cy;
+
+ // 计算比例并调整布局
float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
- // 遍历对话框中的所有控件
AdjustControls(dScaleX, dScaleY);
}
void CBaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
- // TODO: 在此添加消息处理程序代码和/或调用默认值
- lpMMI->ptMinTrackSize.x = 400; // 最小宽度
- lpMMI->ptMinTrackSize.y = 300; // 最小高度
+ lpMMI->ptMinTrackSize.x = 400;
+ lpMMI->ptMinTrackSize.y = 300;
CDialogEx::OnGetMinMaxInfo(lpMMI);
+}
+
+HBRUSH CBaseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+ if (g_currentTheme) {
+ pDC->SetBkColor(g_currentTheme->backgroundColor);
+ pDC->SetTextColor(g_currentTheme->textColor);
+
+ // 返回背景画刷
+ return CreateSolidBrush(g_currentTheme->backgroundColor);
+ }
+
+ return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/CBaseDlg.h b/SourceCode/Bond/BondEq/CBaseDlg.h
index 053cd99..f817e60 100644
--- a/SourceCode/Bond/BondEq/CBaseDlg.h
+++ b/SourceCode/Bond/BondEq/CBaseDlg.h
@@ -1,4 +1,18 @@
#pragma once
+#include <memory>
+#include <unordered_map>
+
+enum class ThemeType {
+ Light, // 浅色主题
+ Dark // 深色主题
+};
+
+struct Theme {
+ COLORREF backgroundColor;
+ COLORREF textColor;
+ COLORREF buttonColor;
+ COLORREF borderColor;
+};
class CBaseDlg : public CDialogEx
{
@@ -8,22 +22,35 @@
CBaseDlg(UINT id, CWnd* pPage); // 标准构造函数
virtual ~CBaseDlg(); // 析构函数
+ // 字体管理
CFont* GetOrCreateFont(int nFontSize); // 获取或创建字体
void SetDefaultFont(); // 设置默认字体
+
+ // 动态控件管理
+ BOOL AddControl(UINT nCtrlID, CWnd* pControl); // 添加控件
+ BOOL RemoveControl(UINT nCtrlID); // 移除控件
+ BOOL UpdateControlText(UINT nCtrlID, const CString& strText); // 更新控件文本
+ CWnd* GetControl(UINT nCtrlID); // 获取控件
+
+ // 主题设置
+ void SwitchTheme(ThemeType themeType); // 切换主题
private:
void AdjustControls(float dScaleX, float dScaleY); // 调整控件大小
void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight); // 调整控件字体
private:
- int m_nInitialWidth; // 对话框初始宽度
- int m_nInitialHeight; // 对话框初始高度
- std::map<int, CFont*> m_mapFonts; // 控件字体
- std::map<int, CRect> m_mapCtrlLayouts; // 控件布局
+ bool m_bResizing; // 控件是否正在调整大小
+ int m_nInitialWidth; // 对话框初始宽度
+ int m_nInitialHeight; // 对话框初始高度
+ std::unordered_map<int, CRect> m_mapCtrlLayouts; // 控件布局
+ std::map<UINT, std::unique_ptr<CWnd>> m_mapControls; // 控件集合
+ std::unordered_map<int, std::shared_ptr<CFont>> m_mapFonts; // 控件字体
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
+ afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
\ No newline at end of file
--
Gitblit v1.9.3