| | |
| | | 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() |
| | |
| | | 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); // 自动整行高亮(限制为单行选择) |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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) |
| | |
| | | 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() |
| | | |
| | | |
| | |
| | | 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() |
| | | { |
| | |
| | | // 刷新网格控件 |
| | | 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; |
| | | } |