LAPTOP-T815PCOQ\25526
2024-12-17 876ad153fd25c0605f516b0f3a6407999db69131
SourceCode/Bond/BondEq/View/RecipeListDlg.cpp
@@ -19,11 +19,120 @@
CRecipeListDlg::CRecipeListDlg(CWnd* pParent /*=nullptr*/)
   : CDialogEx(IDD_DIALOG_RECIPE_LIST, pParent)
{
   m_nInitialWidth = 0;
   m_nInitialHeight = 0;
   m_staticCurrRecipe = new CBLLabel();
}
CRecipeListDlg::~CRecipeListDlg()
{
   if (m_staticCurrRecipe != nullptr) {
      delete m_staticCurrRecipe;
      m_staticCurrRecipe = nullptr;
   }
   for (auto& pair : m_mapFonts) {
      if (pair.second) {
         pair.second->DeleteObject();
         delete pair.second;
      }
   }
   m_mapFonts.clear();
}
CFont* CRecipeListDlg::GetOrCreateFont(int nFontSize)
{
   auto it = m_mapFonts.find(nFontSize);
   if (it != m_mapFonts.end()) {
      return it->second;
   }
   CFont* font = new CFont();
   LOGFONT logFont = { 0 };
   _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
   logFont.lfHeight = -nFontSize;
   logFont.lfQuality = CLEARTYPE_QUALITY;
   font->CreateFontIndirect(&logFont);
   m_mapFonts[nFontSize] = font;
   return font;
}
void CRecipeListDlg::AdjustControls(float dScaleX, float dScaleY)
{
   CWnd* pWnd = GetWindow(GW_CHILD);
   while (pWnd) {
      int nCtrlID = pWnd->GetDlgCtrlID();
      if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end()) {
         CRect originalRect = m_mapCtrlLayouts[nCtrlID];
         CRect newRect(
            static_cast<int>(originalRect.left * dScaleX),
            static_cast<int>(originalRect.top * dScaleY),
            static_cast<int>(originalRect.right * dScaleX),
            static_cast<int>(originalRect.bottom * dScaleY));
         TCHAR szClassName[256];
         GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
         if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd;
            pGridCtrl->SetDefCellHeight(newRect.Height() / 21);
            pGridCtrl->ExpandColumnsToFit(TRUE);
            pGridCtrl->ExpandLastColumn();
            pGridCtrl->Invalidate();
            pGridCtrl->UpdateWindow();
         }
         pWnd->MoveWindow(&newRect);
         AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
      }
      pWnd = pWnd->GetNextWindow();
   }
}
void CRecipeListDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
   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 < 24) fontSize = 24;
   // 获取或创建字体
   CFont* pFont = GetOrCreateFont(fontSize);
   pWnd->SetFont(pFont);
   pWnd->Invalidate(); // 刷新控件显示
}
void CRecipeListDlg::AdjustLabelFont(CBLLabel& label)
{
   if (label.m_hWnd == nullptr) {
      return;
   }
   // 获取控件的矩形区域
   CRect rect;
   label.GetClientRect(&rect);
   // 动态计算字体大小,基于控件的高度
   int fontSize = rect.Height() / 2; // 控件高度的一半作为字体大小
   if (fontSize < 8) fontSize = 8;   // 最小字体大小
   if (fontSize > 30) fontSize = 30; // 最大字体大小
   // 设置字体大小
   label.SetFontSize(fontSize);
   // 刷新控件显示
   label.Invalidate();
   label.UpdateWindow();
}
void CRecipeListDlg::InitRecipeLise()
@@ -56,17 +165,17 @@
   m_grid.SetItemText(nRowIdx, nColIdx++, _T("No."));
   m_grid.SetColumnWidth(nColIdx, 10);
   m_grid.SetItemText(nRowIdx, nColIdx++, _T("名称"));
   m_grid.SetColumnWidth(nColIdx, 50);
   m_grid.SetColumnWidth(nColIdx, 120);
   m_grid.SetItemText(nRowIdx, nColIdx++, _T("描述"));
   m_grid.SetColumnWidth(nColIdx, 30);
   m_grid.SetItemText(nRowIdx, nColIdx++, _T("创建时间"));
   m_grid.SetFixedRowSelection(FALSE);
   m_grid.SetFixedColumnSelection(FALSE);
   m_grid.SetEditable(TRUE);
   m_grid.SetRowResize(FALSE);
   m_grid.SetColumnResize(TRUE);
   m_grid.ExpandColumnsToFit(TRUE);
   m_grid.SetFixedRowSelection(FALSE);     // 设置固定行不可选中
   m_grid.SetFixedColumnSelection(FALSE);  // 设置固定列不可选中
   m_grid.SetEditable(FALSE);            // 设置单元格可编辑
   m_grid.SetRowResize(FALSE);            // 设置行不可调整大小
   m_grid.SetColumnResize(TRUE);         // 设置列可调整大小
   m_grid.ExpandColumnsToFit(TRUE);      // 自动调整列宽
   m_grid.SetListMode(TRUE);            // 启用列表模式
   m_grid.EnableSelection(TRUE);         // 启用选择
   m_grid.SetSingleRowSelection(TRUE);      // 自动整行高亮(限制为单行选择)
@@ -78,7 +187,7 @@
void CRecipeListDlg::FillRecipeLise()
{
   // 清除数据行,保留表头
   for (int i = 1; i < m_grid.GetRowCount(); i++) {
   for (int i = m_grid.GetRowCount() - 1; i > 0; --i) {
      m_grid.DeleteRow(i);
   }
@@ -126,17 +235,77 @@
      m_grid.SetItemText(rowIdx, 2, description);                        // 配方描述
      m_grid.SetItemText(rowIdx, 3, createTime);                        // 创建时间
      m_grid.SetItemState(rowIdx, 0, GVIS_READONLY);
      m_grid.SetItemState(rowIdx, 1, GVIS_READONLY);
      m_grid.SetItemState(rowIdx, 3, GVIS_READONLY);
      ++rowIdx;
   }
   m_grid.ExpandColumnsToFit(FALSE);
   m_grid.ExpandLastColumn();
   m_grid.ExpandColumnsToFit(FALSE);   // 自动调整列宽
   m_grid.ExpandLastColumn();         // 最后一列填充网格
   // 刷新网格控件
   m_grid.Invalidate();
   m_grid.UpdateWindow();
}
void CRecipeListDlg::UpdateDataFile(const CString& strRecipeName, const CString& strNewDescription)
{
   CStdioFile file;
   CFileException fe;
   // 打开文件以读取和写入
   CString strFilePath;
   strFilePath.Format(_T("%s\\RecipeList.txt"), CToolUnits::getRecipePath().c_str());
   if (file.Open(strFilePath, CFile::modeReadWrite | CFile::shareDenyNone, &fe)) {
      CString strLine;
      CStringArray arrLines;
      BOOL bFound = FALSE;
      // 读取文件内容到内存
      while (file.ReadString(strLine)) {
         // 将这一行按逗号分割
         CStringArray arrColumns;
         int nPos = 0;
         while ((nPos = strLine.Find(_T(','))) != -1) {
            arrColumns.Add(strLine.Left(nPos));
            strLine = strLine.Mid(nPos + 1);
         }
         arrColumns.Add(strLine); // 最后一列
         // 如果第一列(配方名称)匹配,修改第二列(配方描述)
         if (arrColumns.GetSize() > 0 && arrColumns[0] == strRecipeName) {
            arrColumns[1] = strNewDescription; // 修改配方描述列
            bFound = TRUE;
         }
         // 将修改后的行保存回内存
         CString strUpdatedLine;
         for (int i = 0; i < arrColumns.GetSize(); ++i) {
            if (i > 0) strUpdatedLine += _T(",");
            strUpdatedLine += arrColumns[i];
         }
         arrLines.Add(strUpdatedLine);
      }
      if (bFound) {
         // 如果找到了配方名称,保存修改后的内容回文件
         file.SeekToBegin();
         file.SetLength(0);  // 清空文件内容
         for (int i = 0; i < arrLines.GetSize(); ++i) {
            file.WriteString(arrLines[i] + _T("\n"));
         }
      }
      else {
         // 如果没有找到配方名称,则追加新配方
         CString strNewLine;
         strNewLine.Format(_T("%s,%s,%s"), strRecipeName, strNewDescription, CToolUnits::getCurrentTimeString().c_str());
         file.SeekToEnd();
         file.WriteString(strNewLine + _T("\n"));
      }
      file.Close();
   }
   else {
      AfxMessageBox(_T("无法打开文件"));
   }
}
void CRecipeListDlg::DoDataExchange(CDataExchange* pDX)
@@ -149,6 +318,9 @@
BEGIN_MESSAGE_MAP(CRecipeListDlg, CDialogEx)
   ON_BN_CLICKED(IDC_BUTTON_CREATE_RECIPE, &CRecipeListDlg::OnBnClickedButtonCreateRecipe)
   ON_BN_CLICKED(IDC_BUTTON_DELETE_RECIPE, &CRecipeListDlg::OnBnClickedButtonDeleteRecipe)
   ON_BN_CLICKED(IDC_BUTTON_SELECT_RECIPE, &CRecipeListDlg::OnBnClickedButtonSelectRecipe)
   ON_NOTIFY(NM_DBLCLK, IDC_CUSTOM_RECIPE_LIST, &CRecipeListDlg::OnGridCellEditFinished)
   ON_WM_SIZE()
END_MESSAGE_MAP()
@@ -160,11 +332,87 @@
   CDialogEx::OnInitDialog();
   // TODO:  在此添加额外的初始化
   m_staticCurrRecipe->SubclassDlgItem(IDC_STATIC_CURR_RECIPE, this);
   m_staticCurrRecipe->SetBkColor(RGB(0, 110, 110));
   m_staticCurrRecipe->ModifyStyle(0, SS_NOTIFY);
   m_staticCurrRecipe->SetTextColor(RGB(255, 255, 255));
   m_staticCurrRecipe->SetAlignment(AlignCenter);
   m_staticCurrRecipe->SetDynamicFont(TRUE);
   m_staticCurrRecipe->SetWindowText(RecipeManager::getInstance().getCurrentRecipeName().c_str());
   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)
         TCHAR szClassName[256];
         GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
         if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            pWnd = pWnd->GetNextWindow();
            continue;
         }
         // 设置默认字体
         pWnd->SetFont(pDefaultFont);
      }
      pWnd = pWnd->GetNextWindow();
   }
   GetWindowRect(&dlgRect);
   int dlgWidth = dlgRect.Width() * 2;
   int dlgHeight = dlgRect.Height() * 2;
   if (dlgWidth > screenRect.Width()) {
      dlgWidth = screenRect.Width();
   }
   if (dlgHeight > screenRect.Height()) {
      dlgHeight = screenRect.Height();
   }
   int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
   int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
   MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
   InitRecipeLise();
   return TRUE;  // return TRUE unless you set the focus to a control
   // 异常: OCX 属性页应返回 FALSE
}
void CRecipeListDlg::OnSize(UINT nType, int cx, int cy)
{
   CDialogEx::OnSize(nType, cx, cy);
   // TODO: 在此处添加消息处理程序代码
   if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
      return;
   }
   float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
   float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
   // 遍历对话框中的所有控件
   AdjustControls(dScaleX, dScaleY);
   AdjustLabelFont(*m_staticCurrRecipe);
}
void CRecipeListDlg::OnBnClickedButtonCreateRecipe()
{
@@ -298,3 +546,50 @@
   // 刷新网格控件
   FillRecipeLise();
}
void CRecipeListDlg::OnBnClickedButtonSelectRecipe()
{
   // TODO: 在此添加控件通知处理程序代码
   int nSelect = -1;
   for (int i = 1; i < m_grid.GetRowCount(); i++) {
      if (m_grid.IsCellSelected(i, 1)) {
         nSelect = i;
         break;
      }
   }
   if (nSelect < 0) {
      AfxMessageBox(_T("请选择配方!"));
      return;
   }
   CString strSelectedRecipe = m_grid.GetItemText(nSelect, 1);
   if (RecipeManager::getInstance().loadRecipe(std::string(CT2A(strSelectedRecipe)))) {
      m_staticCurrRecipe->SetWindowText(strSelectedRecipe);
   }
   else {
      AfxMessageBox(_T("加载配方失败!"));
   }
}
void CRecipeListDlg::OnGridCellEditFinished(NMHDR* pNotifyStruct, LRESULT* pResult)
{
   // 获取修改的行列信息
   NM_GRIDVIEW* pItem = (NM_GRIDVIEW*)pNotifyStruct;
   int nRow = pItem->iRow;
   int nCol = pItem->iColumn;
   // 只处理“配方描述”列的修改
   if (nCol == 2) {
      CString strRecipeName = m_grid.GetItemText(nRow, 1);
      CInputDialog inputDialog(_T("配方描述"), _T("请输入配方描述:"));
      if (inputDialog.DoModal() != IDOK) {
         *pResult = 0;
         return;
      }
      CString strText = inputDialog.GetInputText();
      UpdateDataFile(strRecipeName, strText);
   }
   *pResult = 0;
}