// CPjPage1.cpp: 实现文件 // #include "stdafx.h" #include "Servo.h" #include "CCjPage2.h" #include "afxdialogex.h" #include "RecipeManager.h" UINT btnID[] = { IDC_BUTTON_PORT1_PROCESS_START, IDC_BUTTON_PORT2_PROCESS_START, IDC_BUTTON_PORT3_PROCESS_START, IDC_BUTTON_PORT4_PROCESS_START }; // CPjPage1 对话框 IMPLEMENT_DYNAMIC(CCjPage2, CCjPageBase) CCjPage2::CCjPage2(CWnd* pParent /*=nullptr*/) : CCjPageBase(IDD_CJ_PAGE2, pParent) { m_nSelRadioId = 0; } CCjPage2::~CCjPage2() { } void CCjPage2::DoDataExchange(CDataExchange* pDX) { CCjPageBase::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CCjPage2, CCjPageBase) ON_WM_DESTROY() ON_EN_CHANGE(IDC_EDIT_PJ_ID, &CCjPage2::OnEnChangeEditPjId) ON_CBN_SELCHANGE(IDC_COMBO_RECIPE, &CCjPage2::OnCbnSelchangeComboRecipe) ON_BN_CLICKED(IDC_RADIO1, &CCjPage2::OnBnClickedRadio1) ON_BN_CLICKED(IDC_RADIO2, &CCjPage2::OnBnClickedRadio2) ON_BN_CLICKED(IDC_RADIO3, &CCjPage2::OnBnClickedRadio3) ON_BN_CLICKED(IDC_RADIO4, &CCjPage2::OnBnClickedRadio4) ON_NOTIFY(CSGN_SEL_CHANGED, IDC_GRID1, &CCjPage2::OnGridSelChanged) ON_NOTIFY(CSGN_MAT_CHANGED, IDC_GRID1, &CCjPage2::OnGridMatChanged) ON_BN_CLICKED(IDC_BUTTON_PORT1_PROCESS_START, &CCjPage2::OnBnClickedButtonPort1ProcessStart) ON_BN_CLICKED(IDC_BUTTON_PORT2_PROCESS_START, &CCjPage2::OnBnClickedButtonPort2ProcessStart) ON_BN_CLICKED(IDC_BUTTON_PORT3_PROCESS_START, &CCjPage2::OnBnClickedButtonPort3ProcessStart) ON_BN_CLICKED(IDC_BUTTON_PORT4_PROCESS_START, &CCjPage2::OnBnClickedButtonPort4ProcessStart) END_MESSAGE_MAP() // CPjPage1 消息处理程序 void CCjPage2::OnSetContext(void* pContext) { UpdatePjData(); } void CCjPage2::SetPjWarps(std::vector& pjs) { m_pjWarps = pjs; } BOOL CCjPage2::OnInitDialog() { CCjPageBase::OnInitDialog(); m_grid.SubclassDlgItem(IDC_GRID1, this); m_grid.InitGrid(4, 8); m_grid.SetColumnWidths(100, 220); m_grid.SetRowHeight(32); m_grid.SetHeaderHeight(36); m_grid.EnableColumnResize(FALSE); // 禁止拖动列宽 m_grid.SetShowMaterialToggle(TRUE); m_grid.DisableSystemScrollbars(); m_grid.ResizeWindowToFitAll(TRUE); // TRUE=包含非客户区(边框、标题栏) m_grid.SetNoScrollbarsMode(TRUE); // 彻底禁用滚动条 m_grid.FitWindowToContentNoScroll(TRUE); // 窗口尺寸刚好容纳全部内容(不出现滚动条) m_grid.SetPortInfo(0, _T("Port 1"), _T("")); m_grid.SetPortInfo(1, _T("Port 2"), _T("")); m_grid.SetPortInfo(2, _T("Port 3"), _T("")); m_grid.SetPortInfo(3, _T("Port 4"), _T("")); UpdatePjData(); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CCjPage2::OnDestroy() { CCjPageBase::OnDestroy(); // TODO: 在此处添加消息处理程序代码 } void CCjPage2::Resize() { CCjPageBase::Resize(); CWnd* pItem; CRect rcClient, rcItem; GetClientRect(&rcClient); pItem = GetDlgItem(IDC_GRID1); pItem->GetWindowRect(&rcItem); ScreenToClient(rcItem); int x = rcItem.left + 100 + 18; int y = 100; // 让控件窗口尺寸自动匹配当前列宽/行数(不出现滚动条) if (::IsWindow(m_grid.m_hWnd)) { CSize best = m_grid.CalcBestWindowSize(TRUE, -1, 2, 2); pItem->MoveWindow(rcItem.left, rcItem.top, best.cx, best.cy); pItem->Invalidate(); pItem->GetWindowRect(&rcItem); ScreenToClient(rcItem); y = rcItem.bottom; y += 18; } pItem = GetDlgItem(IDC_BUTTON_PORT1_PROCESS_START); pItem->GetWindowRect(&rcItem); pItem->MoveWindow(x, y, rcItem.Width(), rcItem.Height()); x += 220; pItem = GetDlgItem(IDC_BUTTON_PORT2_PROCESS_START); pItem->GetWindowRect(&rcItem); pItem->MoveWindow(x, y, rcItem.Width(), rcItem.Height()); x += 220; pItem = GetDlgItem(IDC_BUTTON_PORT3_PROCESS_START); pItem->GetWindowRect(&rcItem); pItem->MoveWindow(x, y, rcItem.Width(), rcItem.Height()); x += 220; pItem = GetDlgItem(IDC_BUTTON_PORT4_PROCESS_START); pItem->GetWindowRect(&rcItem); pItem->MoveWindow(x, y, rcItem.Width(), rcItem.Height()); x += 220; } int CCjPage2::OnApply() { //SERVO::CProcessJob* if (m_pContext == nullptr) return -1; PJWarp* pPjWarp = (PJWarp*)m_pContext; SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)pPjWarp->pj; // 更新名称 BOOL bOkName = TRUE; char szBuffer[256]; GetDlgItemText(IDC_EDIT_PJ_ID, szBuffer, 256); for (auto item : m_pjWarps) { if (item.pj != pProcessJob) { SERVO::CProcessJob* temp = (SERVO::CProcessJob*)item.pj; if (temp->id().compare(std::string(szBuffer)) == 0) { bOkName = FALSE; break; } } } if (!bOkName) { AfxMessageBox("不能使用和其它Process Job相同的ID"); return -1; } pProcessJob->setId(std::string(szBuffer)); // 更新配方 CString strRecipe; CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_RECIPE); int idx = pComboBox->GetCurSel(); if (idx >= 0) { pComboBox->GetLBText(idx, strRecipe); #ifdef UNICODE CT2A utf8Str(strRecipe, CP_UTF8); std::string recipe(utf8Str); #else std::string recipe(strRecipe.GetString()); #endif pProcessJob->setRecipe(SERVO::RecipeMethod::NoTuning, recipe); } // 更新Port int port = -1; static int ids[] = { IDC_RADIO1, IDC_RADIO2, IDC_RADIO3, IDC_RADIO4 }; for (int i = 0; i < 4; i++) { int state = ((CButton*)GetDlgItem(ids[i]))->GetCheck(); if (state == BST_CHECKED) port = i; } pPjWarp->port = port; if (pPjWarp->port != -1) { for (int i = 0; i < 8; i++) { pPjWarp->checkSlot[i] = m_grid.GetSlotChecked(pPjWarp->port, i); pPjWarp->material[i] = m_grid.GetSlotMaterialType(pPjWarp->port, i); } } ContentChanged(1); return 0; } void CCjPage2::UpdatePjData() { if (m_pContext == nullptr) return; m_bContentChangedLock = TRUE; CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_RECIPE); pComboBox->ResetContent(); std::vector vecRecipe = RecipeManager::getInstance().getAllPPID(); for (const auto& recipe : vecRecipe) { pComboBox->AddString(CString(recipe.c_str())); } // ComboBox PJWarp* pPjWarp = (PJWarp*)m_pContext; SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)pPjWarp->pj; SetDlgItemText(IDC_EDIT_PJ_ID, pProcessJob->id().c_str()); int idx = pComboBox->FindStringExact(-1, pProcessJob->recipeSpec().c_str()); if (idx != CB_ERR) pComboBox->SetCurSel(idx); // 4个checkbox static int ids[] = { IDC_RADIO1, IDC_RADIO2, IDC_RADIO3, IDC_RADIO4}; static char* pszUsed[] = { "Port1(已占用)", "Port2(已占用)", "Port3(已占用)", "Port4(已占用)" }; static char* pszUnUsed[] = { "Port1(可用)", "Port2(可用)", "Port3(可用)", "Port4(可用)" }; int portIndex = -1; bool enable[] = {true, true, true, true}; bool checked[] = { false, false, false, false }; for (auto item : m_pjWarps) { if (0 <= item.port && item.port <= 4 && item.pj != ((PJWarp*)m_pContext)->pj) { enable[item.port] = false; } } if (0 <= ((PJWarp*)m_pContext)->port && ((PJWarp*)m_pContext)->port <= 3) { checked[((PJWarp*)m_pContext)->port] = true; portIndex = ((PJWarp*)m_pContext)->port; m_nSelRadioId = ids[((PJWarp*)m_pContext)->port]; } for (int i = 0; i < 4; i++) { CButton* pButton = (CButton*)GetDlgItem(ids[i]); pButton->SetCheck(checked[i] ? BST_CHECKED : BST_UNCHECKED); pButton->SetWindowText(enable[i] ? pszUnUsed[i] : pszUsed[i]); pButton->EnableWindow(enable[i]); m_grid.SetPortAllocated(i, !checked[i], _T("")); GetDlgItem(btnID[i])->EnableWindow(checked[i]); } // 读取出真实数据 auto& master = theApp.m_model.getMaster(); int EQID[] = {EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4}; for (int p = 0; p < 4; p++) { SERVO::CLoadPort* pPort = (SERVO::CLoadPort*)master.getEquipment(EQID[p]); m_grid.SetPortInfo(p, (std::string("Port ") + std::to_string(p+1)).c_str(), pPort->getCassetteId().c_str() ); for (int i = 0; i < SLOT_MAX; ++i) { SERVO::CSlot* pSlot = pPort->getSlot(i); if (!pSlot) { continue; } // 设置 Panel ID SERVO::CGlass* pGlass = dynamic_cast(pSlot->getContext()); SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS(); if (pGlass != nullptr && pJobDataS != nullptr) { m_grid.SetSlotGlass(p, i, TRUE, pGlass->getID().c_str(), m_pjWarps[p].material[i]); } else { m_grid.SetSlotGlass(p, i, FALSE, nullptr, CCarrierSlotGrid::MAT_G1); } } } // 设置勾选数据 if (portIndex != -1) { for (int i = 0; i < 8; i++) { m_grid.SetSlotChecked(portIndex, i, ((PJWarp*)m_pContext)->checkSlot[i]); } } m_bContentChangedLock = FALSE; } void CCjPage2::OnEnChangeEditPjId() { ContentChanged(0); } void CCjPage2::OnCbnSelchangeComboRecipe() { ContentChanged(0); } void CCjPage2::OnBnClickedRadio1() { BOOL lock[] = {TRUE, TRUE, TRUE, TRUE}; if (IDC_RADIO1 == m_nSelRadioId) { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, 0); m_nSelRadioId = 0; } else { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO1); m_nSelRadioId = IDC_RADIO1; lock[0] = FALSE; } for (int i = 0; i < 4; i++) { m_grid.SetPortAllocated(i, lock[i], _T("")); GetDlgItem(btnID[i])->EnableWindow(!lock[i]); } ContentChanged(0); } void CCjPage2::OnBnClickedRadio2() { BOOL lock[] = { TRUE, TRUE, TRUE, TRUE }; if (IDC_RADIO2 == m_nSelRadioId) { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, 0); m_nSelRadioId = 0; } else { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO2); m_nSelRadioId = IDC_RADIO2; lock[1] = FALSE; } for (int i = 0; i < 4; i++) { m_grid.SetPortAllocated(i, lock[i], _T("")); GetDlgItem(btnID[i])->EnableWindow(!lock[i]); } ContentChanged(0); } void CCjPage2::OnBnClickedRadio3() { BOOL lock[] = { TRUE, TRUE, TRUE, TRUE }; if (IDC_RADIO3 == m_nSelRadioId) { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, 0); m_nSelRadioId = 0; } else { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO3); m_nSelRadioId = IDC_RADIO3; lock[2] = FALSE; } for (int i = 0; i < 4; i++) { m_grid.SetPortAllocated(i, lock[i], _T("")); GetDlgItem(btnID[i])->EnableWindow(!lock[i]); } ContentChanged(0); } void CCjPage2::OnBnClickedRadio4() { BOOL lock[] = { TRUE, TRUE, TRUE, TRUE }; if (IDC_RADIO4 == m_nSelRadioId) { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, 0); m_nSelRadioId = 0; } else { CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO4); m_nSelRadioId = IDC_RADIO4; lock[3] = FALSE; } for (int i = 0; i < 4; i++) { m_grid.SetPortAllocated(i, lock[i], _T("")); GetDlgItem(btnID[i])->EnableWindow(!lock[i]); } ContentChanged(0); } void CCjPage2::OnGridSelChanged(NMHDR* pNMHDR, LRESULT* pResult) { auto* nm = reinterpret_cast(pNMHDR); const int port = nm->port; const int slot = nm->slot; const BOOL chk = nm->checked; // 这里写你的业务逻辑 // 例如:更新状态栏 / 同步其它控件 / 统计数量 ContentChanged(0); /* if (m_pContext != nullptr) { PJWarp* pjWarp = (PJWarp*)m_pContext; for (int i = 0; i < 8; i++) { pjWarp->checkSlot[i] = m_grid.GetSlotChecked(port, i); pjWarp->material[i] = m_grid.GetSlotMaterialType(port, i); } } */ *pResult = 0; } void CCjPage2::OnGridMatChanged(NMHDR* pNMHDR, LRESULT* pResult) { auto* nm = reinterpret_cast(pNMHDR); const int port = nm->port; const int slot = nm->slot; const int mat = nm->material; // 1/2 // 例如:即刻刷新右侧预览/记录日志等 ContentChanged(0); /* if (m_pContext != nullptr) { PJWarp* pjWarp = (PJWarp*)m_pContext; for (int i = 0; i < 8; i++) { pjWarp->checkSlot[i] = m_grid.GetSlotChecked(port, i); pjWarp->material[i] = m_grid.GetSlotMaterialType(port, i); } } */ *pResult = 0; } void CCjPage2::OnBnClickedButtonPort1ProcessStart() { auto& master = theApp.m_model.getMaster(); auto port = (SERVO::CLoadPort*)master.getEquipment(EQ_ID_LOADPORT1); port->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr); } void CCjPage2::OnBnClickedButtonPort2ProcessStart() { auto& master = theApp.m_model.getMaster(); auto port = (SERVO::CLoadPort*)master.getEquipment(EQ_ID_LOADPORT2); port->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr); } void CCjPage2::OnBnClickedButtonPort3ProcessStart() { auto& master = theApp.m_model.getMaster(); auto port = (SERVO::CLoadPort*)master.getEquipment(EQ_ID_LOADPORT3); port->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr); } void CCjPage2::OnBnClickedButtonPort4ProcessStart() { auto& master = theApp.m_model.getMaster(); auto port = (SERVO::CLoadPort*)master.getEquipment(EQ_ID_LOADPORT4); port->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr); }