diff --git a/ChangeLog.md b/ChangeLog.md index 6149fc9..95bdb0f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,13 +1,15 @@ ## Change Log ### 3.21-3.27 * `Visio`的`UML`类图初步制作 -* 随机信号的生成[^1] -### 5.24 -* 随机信号的完善 +### 5.28 +* 模拟信号的生成 + +### 5.29 +* 模拟信号的完善 ### 5.30 -* control view +* 侧边信息栏 ### 5.31 * 全谱区 @@ -16,4 +18,14 @@ * 模拟信号 * 开始、结束、暂停 -[^1]: Xiao M, Hu R, Ge L Q, et al. Study of a full-digital multi-waveform nuclear pulse signal generator[J]. Applied Radiation and Isotopes, 2022, 179: 110028. \ No newline at end of file +### 6.1 +* 光标显示 +* 量程 +* 对数量程 + +### 6.2 +* 曲线平滑 + +## Bugs +1. 点击其他视图时,工具栏(ToolBar)和菜单栏(Menu)无法使用,失去焦点 +2. 最开始无法通过方向键左右移动或调整量程 diff --git a/MCA/ControlView.cpp b/MCA/ControlView.cpp index 8e1e297..b017eb8 100644 --- a/MCA/ControlView.cpp +++ b/MCA/ControlView.cpp @@ -1,10 +1,10 @@ // ControlView.cpp: 实现文件 // +#include #include #include "pch.h" -#include "math.h" #include "MCA.h" #include "MCADoc.h" @@ -24,7 +24,7 @@ CControlView::CControlView() , m_nTotalCount(0) , m_nPartCount(0) , m_nMaxCount(0) - , m_nRange(4) + , m_nLC(4) , m_nCursor1(0) , m_nCursor2(1023) , m_nCursorROI(0) @@ -46,7 +46,7 @@ void CControlView::DoDataExchange(CDataExchange* pDX) DDX_Text(pDX, IDC_MCOUNT, m_nMaxCount); DDX_Control(pDX, IDC_MODE, m_ComboMode); DDX_Control(pDX, IDC_AXIS, m_ComboAxis); - DDX_Text(pDX, IDC_RANGE, m_nRange); + DDX_Text(pDX, IDC_RANGE, m_nLC); DDX_Text(pDX, IDC_CURSOR1, m_nCursor1); DDX_Text(pDX, IDC_CURSOR2, m_nCursor2); DDX_Text(pDX, IDC_CURSORROI, m_nCursorROI); @@ -55,18 +55,36 @@ void CControlView::DoDataExchange(CDataExchange* pDX) BEGIN_MESSAGE_MAP(CControlView, CFormView) ON_WM_SIZE() + ON_WM_TIMER() + ON_COMMAND(ID_STA_START, &CControlView::OnStaStart) ON_COMMAND(ID_STA_STOP, &CControlView::OnStaStop) - ON_UPDATE_COMMAND_UI(ID_STA_START, &CControlView::OnUpdateStaStart) - ON_UPDATE_COMMAND_UI(ID_STA_STOP, &CControlView::OnUpdateStaStop) ON_COMMAND(ID_STA_CLEAR, &CControlView::OnStaClear) - ON_UPDATE_COMMAND_UI(ID_STA_CLEAR, &CControlView::OnUpdateStaClear) - ON_WM_TIMER() ON_COMMAND(ID_SIMU_CO, &CControlView::OnSimuCo) ON_COMMAND(ID_SIMU_CS, &CControlView::OnSimuCs) ON_COMMAND(ID_SIMU_NA, &CControlView::OnSimuNa) -END_MESSAGE_MAP() + ON_COMMAND(ID_AXIS_LINEAR, &CControlView::OnAxisLinear) + ON_COMMAND(ID_AXIS_LOG, &CControlView::OnAxisLog) + ON_COMMAND(ID_RANGE_AUTO, &CControlView::OnRangeAuto) + ON_COMMAND(ID_RANGE_D4, &CControlView::OnRangeD4) + ON_COMMAND(ID_RANGE_D2, &CControlView::OnRangeD2) + ON_COMMAND(ID_RANGE_M2, &CControlView::OnRangeM2) + ON_COMMAND(ID_RANGE_M4, &CControlView::OnRangeM4) + ON_COMMAND(ID_DATA_ORIGIN, &CControlView::OnDataOrigin) + ON_COMMAND(ID_DATA_3, &CControlView::OnData3) + ON_COMMAND(ID_DATA_5, &CControlView::OnData5) + ON_UPDATE_COMMAND_UI(ID_STA_START, &CControlView::OnUpdateStaStart) + ON_UPDATE_COMMAND_UI(ID_STA_STOP, &CControlView::OnUpdateStaStop) + ON_UPDATE_COMMAND_UI(ID_STA_CLEAR, &CControlView::OnUpdateStaClear) + ON_UPDATE_COMMAND_UI(ID_SIMU_CO, &CControlView::OnUpdateSimuCo) + ON_UPDATE_COMMAND_UI(ID_SIMU_CS, &CControlView::OnUpdateSimuCs) + ON_UPDATE_COMMAND_UI(ID_SIMU_NA, &CControlView::OnUpdateSimuNa) + ON_UPDATE_COMMAND_UI(ID_RANGE_AUTO, &CControlView::OnUpdateRangeAuto) + ON_UPDATE_COMMAND_UI(ID_DATA_ORIGIN, &CControlView::OnUpdateDataOrigin) + ON_UPDATE_COMMAND_UI(ID_DATA_3, &CControlView::OnUpdateData3) + ON_UPDATE_COMMAND_UI(ID_DATA_5, &CControlView::OnUpdateData5) +END_MESSAGE_MAP() // CControlView 诊断 @@ -84,6 +102,37 @@ void CControlView::Dump(CDumpContext& dc) const #endif #endif //_DEBUG +int CControlView::roundupPowerof2(int val) +{ + if ((val & (val - 1)) == 0) return val; + int andv = 1 << 30; + while ((andv & val) == 0) andv = andv >> 1; + return andv << 1; +} + +double CControlView::GetMilliTime() +{ + std::chrono::milliseconds ms = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ); + return ms.count() / 1000.; +} + +void CControlView::UpdateValue() +{ + // 更新信息 + m_nTotalCount = pDoc->GetTotal(0, 1023); + m_nMaxCount = pDoc->GetMax(0, 1023); + m_nPartCount = pDoc->GetTotal(m_nCursor1, m_nCursor2); + m_nCursorROICount = pDoc->m_nChannelCount[m_nCursorROI]; + + m_nTime += GetMilliTime() - m_nT0; + m_nTimeStr.Format(_T("%.1f"), m_nTime); + m_nT0 = GetMilliTime(); + + // 更新屏幕信息 + UpdateData(FALSE); +} // CControlView 消息处理程序 void CControlView::OnSize(UINT nType, int cx, int cy) @@ -120,12 +169,76 @@ void CControlView::OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHi { } -double CControlView::GetMilliTime() +void CControlView::OnTimer(UINT_PTR nIDEvent) { - std::chrono::milliseconds ms = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ); - return ms.count() / 1000.; + if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); + + // 生成随机信号 + int n = rand() % 50 + 25; + pDoc->RandomPeak(m_sSource, n); + + // 平滑数据 + for (int i = 0; i < 1024; i++) pDoc->m_nChannelSmooth[i] = pDoc->m_nChannelCount[i]; + OutputDebugString(m_sSmoothType); + if (m_sSmoothType == "S3") { + pDoc->m_nChannelSmooth[0] = (5.0 * pDoc->m_nChannelCount[0] + 2.0 * pDoc->m_nChannelCount[1] - pDoc->m_nChannelCount[2]) / 6.0; + for (int i = 1; i < 1023; i++) + pDoc->m_nChannelSmooth[i] = (pDoc->m_nChannelCount[i - 1] + pDoc->m_nChannelCount[i] + pDoc->m_nChannelCount[i + 1]) / 3.0; + pDoc->m_nChannelSmooth[1023] = (5.0 * pDoc->m_nChannelCount[1023] + 2.0 * pDoc->m_nChannelCount[1022] - pDoc->m_nChannelCount[1021]) / 6.0; + } + else if (m_sSmoothType == "S5") { + pDoc->m_nChannelSmooth[0] = (3.0 * pDoc->m_nChannelCount[0] + 2.0 * pDoc->m_nChannelCount[1] + pDoc->m_nChannelCount[2] - pDoc->m_nChannelCount[4]) / 5.0; + pDoc->m_nChannelSmooth[1] = (4.0 * pDoc->m_nChannelCount[0] + 3.0 * pDoc->m_nChannelCount[1] + 2 * pDoc->m_nChannelCount[2] + pDoc->m_nChannelCount[3]) / 10.0; + for (int i = 2; i < 1022; i++) + pDoc->m_nChannelSmooth[i] = (pDoc->m_nChannelCount[i - 2] + pDoc->m_nChannelCount[i - 1] + pDoc->m_nChannelCount[i] + pDoc->m_nChannelCount[i + 1] + pDoc->m_nChannelCount[i + 2]) / 5.0; + pDoc->m_nChannelSmooth[1022] = (4.0 * pDoc->m_nChannelCount[1023] + 3.0 * pDoc->m_nChannelCount[1022] + 2 * pDoc->m_nChannelCount[1021] + pDoc->m_nChannelCount[1020]) / 10.0; + pDoc->m_nChannelSmooth[1023] = (3.0 * pDoc->m_nChannelCount[1023] + 2.0 * pDoc->m_nChannelCount[1022] + pDoc->m_nChannelCount[1021] - pDoc->m_nChannelCount[1019]) / 5.0; + } + for (int i = 0; i < 1024; i++) pDoc->m_nChannelSmooth[i] = max(0, pDoc->m_nChannelSmooth[i]); + + // 更新信息 + UpdateValue(); + + // 判断终止 + CString tmp; + m_ComboMode.GetWindowText(tmp); + if (tmp == "时间" && m_nTime >= m_nCond) OnStaStop(); + if (tmp == "计数" && m_nTotalCount >= m_nCond) OnStaStop(); + + // 修改坐标轴 + m_ComboAxis.GetWindowText(tmp); + if (tmp == "对数") { + m_bAutoFlag = FALSE; + m_sAxisMode = "Log"; + m_sRangeMode = "Auto"; + } + else m_sAxisMode = "Linear"; + + // 判断量程 + if (m_sRangeMode == "Auto" && m_nMaxCount >= m_nLC) m_nLC *= 2; + + pDoc->UpdateAllViews(NULL); + CFormView::OnTimer(nIDEvent); +} + +BOOL CControlView::PreTranslateMessage(MSG* pMsg) +{ + if (pMsg->message == WM_KEYDOWN && pMsg->wParam >= 0x25 && pMsg->wParam <= 0x28) { + if (pMsg->wParam == VK_LEFT) m_nCursorROI = max(m_nCursor1, m_nCursorROI - 1); + if (pMsg->wParam == VK_RIGHT) m_nCursorROI = min(m_nCursor2, m_nCursorROI + 1); + if (pMsg->wParam == VK_UP) { + m_nLC *= 2; + m_bAutoFlag = TRUE; + m_sRangeMode = (CString)"Manual"; + } + if (pMsg->wParam == VK_DOWN) { + m_nLC = m_nLC > 1 ? m_nLC / 2 : 1; + m_bAutoFlag = TRUE; + m_sRangeMode = (CString)"Manual"; + } + return TRUE; + } + return CFormView::PreTranslateMessage(pMsg); } void CControlView::OnStaStart() @@ -133,9 +246,9 @@ void CControlView::OnStaStart() // 重置结束条件 m_nT0 = GetMilliTime(); // 设置状态 - startFlag = FALSE; - stopFlag = TRUE; - clearFlag = FALSE; + m_bStartFlag = FALSE; + m_bStopFlag = TRUE; + m_bClearFlag = FALSE; ((CEdit*)GetDlgItem(IDC_COND))->EnableWindow(FALSE); // 获取屏幕值至变量 UpdateData(TRUE); @@ -145,15 +258,15 @@ void CControlView::OnStaStart() void CControlView::OnUpdateStaStart(CCmdUI* pCmdUI) { - pCmdUI->Enable(startFlag); + pCmdUI->Enable(m_bStartFlag); } void CControlView::OnStaStop() { // 设置状态 - startFlag = TRUE; - stopFlag = FALSE; - clearFlag = TRUE; + m_bStartFlag = TRUE; + m_bStopFlag = FALSE; + m_bClearFlag = TRUE; ((CEdit*)GetDlgItem(IDC_COND))->EnableWindow(TRUE); // 停止更新 KillTimer(1); @@ -161,66 +274,162 @@ void CControlView::OnStaStop() void CControlView::OnUpdateStaStop(CCmdUI* pCmdUI) { - pCmdUI->Enable(stopFlag); + pCmdUI->Enable(m_bStopFlag); } void CControlView::OnStaClear() { - CMCADoc* pDoc = (CMCADoc*)GetDocument(); + if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); // 重置 + m_nLC = 4; m_nTime = 0; m_nMaxCount = 0; m_nPartCount = 0; m_nTotalCount = 0; m_nTimeStr = (CString)"0.0"; - // 获取屏幕值至变量 + // 更新屏幕信息 UpdateData(FALSE); // 设置曲线 - for (int i = 0; i < pDoc->m_nChannelNum; i++) - pDoc->m_nChannelCount[i] = 0; + for (int i = 0; i < 1024; i++) pDoc->m_nChannelCount[i] = 0; + for (int i = 0; i < 1024; i++) pDoc->m_nChannelSmooth[i] = 0; pDoc->UpdateAllViews(NULL); } void CControlView::OnUpdateStaClear(CCmdUI* pCmdUI) { - pCmdUI->Enable(clearFlag); -} - -void CControlView::OnTimer(UINT_PTR nIDEvent) -{ - CString tmp; - CMCADoc* pDoc = (CMCADoc*)GetDocument(); - m_nTotalCount = pDoc->GetTotal(0, 1023); - m_nMaxCount = pDoc->GetMax(0, 1023); - m_nPartCount = pDoc->GetTotal(m_nCursor1, m_nCursor2); - - m_nTime += GetMilliTime() - m_nT0; - m_nTimeStr.Format(_T("%.1f"), m_nTime); - m_nT0 = GetMilliTime(); - - m_ComboMode.GetWindowText(tmp); - if (tmp == "时间" && m_nTime >= m_nCond) OnStaStop(); - if (tmp == "计数" && m_nTotalCount >= m_nCond) OnStaStop(); - - UpdateData(FALSE); - - int n = rand() % 50 + 25; - ((CMCADoc*)GetDocument())->RandomPeak(source, n); - ((CMCADoc*)GetDocument())->UpdateAllViews(NULL); - CFormView::OnTimer(nIDEvent); + pCmdUI->Enable(m_bClearFlag); } void CControlView::OnSimuCo() { - source = (CString)"Co60"; + m_sSource = (CString)"Co60"; + m_bCoFlag = FALSE; + m_bCsFlag = TRUE; + m_bNaFlag = TRUE; + OnStaClear(); + OnStaStart(); +} + +void CControlView::OnUpdateSimuCo(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bCoFlag); } void CControlView::OnSimuCs() { - source = (CString)"Cs137"; + m_sSource = (CString)"Cs137"; + m_bCoFlag = TRUE; + m_bCsFlag = FALSE; + m_bNaFlag = TRUE; + OnStaClear(); + OnStaStart(); +} + +void CControlView::OnUpdateSimuCs(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bCsFlag); } void CControlView::OnSimuNa() { - source = (CString)"Na22"; + m_sSource = (CString)"Na22"; + m_bCoFlag = TRUE; + m_bCsFlag = TRUE; + m_bNaFlag = FALSE; + OnStaClear(); + OnStaStart(); } + +void CControlView::OnUpdateSimuNa(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bNaFlag); +} + +void CControlView::OnAxisLinear() +{ + m_sAxisMode = (CString)"Linear"; +} + +void CControlView::OnAxisLog() +{ + m_sAxisMode = (CString)"Log"; +} + +void CControlView::OnRangeAuto() +{ + m_sRangeMode = (CString)"Auto"; + m_bAutoFlag = FALSE; + m_nLC = roundupPowerof2(m_nMaxCount); +} + +void CControlView::OnUpdateRangeAuto(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bAutoFlag); +} + +void CControlView::OnRangeD4() +{ + m_sRangeMode = (CString)"Manual"; + m_nLC /= 4; + m_bAutoFlag = TRUE; +} + +void CControlView::OnRangeD2() +{ + m_sRangeMode = (CString)"Manual"; + m_nLC /= 2; + m_bAutoFlag = TRUE; +} + +void CControlView::OnRangeM2() +{ + m_sRangeMode = (CString)"Manual"; + m_nLC *= 2; + m_bAutoFlag = TRUE; +} + +void CControlView::OnRangeM4() +{ + m_sRangeMode = (CString)"Manual"; + m_nLC *= 4; + m_bAutoFlag = TRUE; +} + +void CControlView::OnDataOrigin() +{ + m_sSmoothType = (CString)"Origin"; + m_bOriginFlag = FALSE; + m_bTSmoothFlag = TRUE; + m_bFSmoothFlag = TRUE; +} + +void CControlView::OnUpdateDataOrigin(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bOriginFlag); +} + +void CControlView::OnData3() +{ + m_sSmoothType = (CString)"S3"; + m_bOriginFlag = TRUE; + m_bTSmoothFlag = FALSE; + m_bFSmoothFlag = TRUE; +} + +void CControlView::OnUpdateData3(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bTSmoothFlag); +} + +void CControlView::OnData5() +{ + m_sSmoothType = (CString)"S5"; + m_bOriginFlag = TRUE; + m_bTSmoothFlag = TRUE; + m_bFSmoothFlag = FALSE; +} + +void CControlView::OnUpdateData5(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bFSmoothFlag); +} \ No newline at end of file diff --git a/MCA/ControlView.h b/MCA/ControlView.h index ee27ef0..528c46d 100644 --- a/MCA/ControlView.h +++ b/MCA/ControlView.h @@ -2,6 +2,8 @@ #include +#include "MCADoc.h" + // CControlView 窗体视图 class CControlView : public CFormView @@ -28,12 +30,26 @@ protected: DECLARE_MESSAGE_MAP() public: - afx_msg void OnSize(UINT nType, int cx, int cy); - virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/); + CMCADoc* pDoc = nullptr; + int roundupPowerof2(int val); double GetMilliTime(); + void UpdateValue(); + + // 消息处理 + afx_msg void OnSize(UINT nType, int cx, int cy); + virtual void OnInitialUpdate(); + virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/); + afx_msg void OnTimer(UINT_PTR nIDEvent); + virtual BOOL PreTranslateMessage(MSG* pMsg); // 选择信息 - CString source = (CString)"Cs137"; + CString m_sSource = (CString)"Cs137"; + CString m_sAxisMode = (CString)"Linear"; + CString m_sRangeMode = (CString)"Auto"; + CString m_sSmoothType = (CString)"Origin"; + + // 量程 + int m_nLC; // 光标信息 int m_nCursor1; @@ -48,26 +64,50 @@ public: CString m_nTimeStr; int m_nTotalCount; int m_nPartCount; - int m_nMaxCount; - int m_nRange; + int m_nMaxCount; CComboBox m_ComboMode; CComboBox m_ComboAxis; - virtual void OnInitialUpdate(); // 菜单与工具栏响应 CMenu m_Menu; CToolBar m_wndToolBar; - BOOL startFlag = TRUE; - BOOL stopFlag = FALSE; - BOOL clearFlag = FALSE; afx_msg void OnStaStart(); - afx_msg void OnUpdateStaStart(CCmdUI* pCmdUI); afx_msg void OnStaStop(); - afx_msg void OnUpdateStaStop(CCmdUI* pCmdUI); afx_msg void OnStaClear(); - afx_msg void OnUpdateStaClear(CCmdUI* pCmdUI); - afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnSimuCo(); afx_msg void OnSimuCs(); afx_msg void OnSimuNa(); + afx_msg void OnAxisLinear(); + afx_msg void OnAxisLog(); + afx_msg void OnRangeAuto(); + afx_msg void OnRangeD4(); + afx_msg void OnRangeD2(); + afx_msg void OnRangeM2(); + afx_msg void OnRangeM4(); + afx_msg void OnDataOrigin(); + afx_msg void OnData3(); + afx_msg void OnData5(); + + // 点击状态 + BOOL m_bStartFlag = TRUE; + BOOL m_bStopFlag = FALSE; + BOOL m_bClearFlag = FALSE; + BOOL m_bCoFlag = TRUE; + BOOL m_bCsFlag = FALSE; + BOOL m_bNaFlag = TRUE; + BOOL m_bAutoFlag = FALSE; + BOOL m_bOriginFlag = FALSE; + BOOL m_bTSmoothFlag = TRUE; + BOOL m_bFSmoothFlag = TRUE; + + afx_msg void OnUpdateStaStart(CCmdUI* pCmdUI); + afx_msg void OnUpdateStaStop(CCmdUI* pCmdUI); + afx_msg void OnUpdateStaClear(CCmdUI* pCmdUI); + afx_msg void OnUpdateSimuCo(CCmdUI* pCmdUI); + afx_msg void OnUpdateSimuCs(CCmdUI* pCmdUI); + afx_msg void OnUpdateSimuNa(CCmdUI* pCmdUI); + afx_msg void OnUpdateRangeAuto(CCmdUI* pCmdUI); + afx_msg void OnUpdateDataOrigin(CCmdUI* pCmdUI); + afx_msg void OnUpdateData3(CCmdUI* pCmdUI); + afx_msg void OnUpdateData5(CCmdUI* pCmdUI); }; diff --git a/MCA/DetailView.cpp b/MCA/DetailView.cpp index 9fdec91..43deb9a 100644 --- a/MCA/DetailView.cpp +++ b/MCA/DetailView.cpp @@ -39,6 +39,7 @@ void CDetailView::OnDraw(CDC* pDc) if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); L = pView->m_nCursor1; R = pView->m_nCursor2; + // CRect rect; GetClientRect(&rect); @@ -46,20 +47,34 @@ void CDetailView::OnDraw(CDC* pDc) // ɫɫ CDC MemDC; + MemDC.CreateCompatibleDC(pDc); + CBitmap Bitmap, * OldBitmap; - CPen pen(PS_SOLID, 2, RGB(255, 255, 255)); + CPen pen(PS_SOLID, 3, RGB(255, 255, 255)); CPen* oldpen = MemDC.SelectObject(&pen); - GetClientRect(&rect); - MemDC.CreateCompatibleDC(pDc); Bitmap.CreateCompatibleBitmap(pDc, rect.Width(), rect.Height()); OldBitmap = MemDC.SelectObject(&Bitmap); MemDC.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(119, 7, 243)); // ͼ - MemDC.MoveTo(1, rect.Height() - pDoc->m_nChannelCount[L]); - for (int i = L; i <= R; i++) - MemDC.LineTo((i - L) * ZF, rect.Height() - pDoc->m_nChannelCount[i]); + int nMaxCount = pDoc->GetMax(L, R) ? pDoc->GetMax(L, R) * 5 / 4 : 1; + int nX = (pView->m_nCursorROI - pView->m_nCursor1) * ZF; + if (pView->m_sAxisMode == "Linear") { + MemDC.MoveTo(1, rect.Height() - pDoc->m_nChannelSmooth[L] * rect.Height() / nMaxCount); + for (int i = L; i <= R; i++) + MemDC.LineTo((i - L) * ZF, rect.Height() - pDoc->m_nChannelSmooth[i] * rect.Height() / nMaxCount); + } + else { + MemDC.MoveTo(1, rect.Height() - log10(max(pDoc->m_nChannelSmooth[L], 1)) * rect.Height() / log10(nMaxCount)); + for (int i = L; i <= R; i++) + MemDC.LineTo((i - L) * ZF, rect.Height() - log10(max(pDoc->m_nChannelSmooth[i], 1)) * rect.Height() / log10(nMaxCount)); + } + // ƹ + pen.CreatePen(PS_SOLID, 5, RGB(0, 255, 0)); + MemDC.SelectObject(&pen); + MemDC.MoveTo(nX, 0); + MemDC.LineTo(nX, rect.Height()); //ͷԴ pDc->BitBlt(0, 0, rect.Width(), rect.Width(), &MemDC, 0, 0, SRCCOPY); @@ -90,10 +105,10 @@ void CDetailView::Dump(CDumpContext& dc) const // CDetailView Ϣ - void CDetailView::OnPaint() { if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); + if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); CPaintDC dc(this); // device context for painting OnPrepareDC(&dc); OnDraw(&dc); @@ -110,30 +125,39 @@ void CDetailView::OnLButtonDown(UINT nFlags, CPoint point) if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); int nX = point.x / ZF + pView->m_nCursor1; pView->m_nCursorROI = nX; - pView->m_nCursorROICount = pDoc->m_nChannelCount[nX]; - - CPen pen; - CDC* pDC = GetDC(); - pen.CreatePen(PS_SOLID, 5, RGB(255, 180, 20)); - CPen* oldpen = pDC->SelectObject(&pen); - CRect rect; - GetClientRect(&rect); - pDC->SetROP2(R2_XORPEN); // - pDC->MoveTo(point.x, 0); //ƹ - pDC->LineTo(point.x, rect.Height()); - pDC->SelectObject(oldpen); - pen.DeleteObject(); - + pDoc->UpdateAllViews(NULL); CView::OnLButtonDown(nFlags, point); } - void CDetailView::OnRButtonDown(UINT nFlags, CPoint point) { if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); pView->m_nCursor1 = 0; pView->m_nCursor2 = 1023; - + pDoc->UpdateAllViews(NULL); CView::OnRButtonDown(nFlags, point); } + +BOOL CDetailView::PreTranslateMessage(MSG* pMsg) +{ + if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); + if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); + if (pMsg->message == WM_KEYDOWN) { + if (pMsg->wParam == VK_LEFT) pView->m_nCursorROI = max(pView->m_nCursor1, pView->m_nCursorROI - 1); + if (pMsg->wParam == VK_RIGHT) pView->m_nCursorROI = min(pView->m_nCursor2, pView->m_nCursorROI + 1); + if (pMsg->wParam == VK_UP) { + pView->m_nLC *= 2; + pView->m_bAutoFlag = TRUE; + pView->m_sRangeMode = (CString)"Manual"; + } + if (pMsg->wParam == VK_DOWN) { + pView->m_nLC = pView->m_nLC > 1 ? pView->m_nLC / 2 : 1; + pView->m_bAutoFlag = TRUE; + pView->m_sRangeMode = (CString)"Manual"; + } + pDoc->UpdateAllViews(NULL); + return TRUE; + } + return CView::PreTranslateMessage(pMsg); +} diff --git a/MCA/DetailView.h b/MCA/DetailView.h index 8e55f02..8b01cf3 100644 --- a/MCA/DetailView.h +++ b/MCA/DetailView.h @@ -36,4 +36,5 @@ public: afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + virtual BOOL PreTranslateMessage(MSG* pMsg); }; diff --git a/MCA/MCA.rc b/MCA/MCA.rc index 5832fb6..ed78e8c 100644 Binary files a/MCA/MCA.rc and b/MCA/MCA.rc differ diff --git a/MCA/MCADoc.cpp b/MCA/MCADoc.cpp index 1b59242..ca85a58 100644 --- a/MCA/MCADoc.cpp +++ b/MCA/MCADoc.cpp @@ -39,8 +39,8 @@ CMCADoc::CMCADoc() noexcept srand((unsigned)time(0)); - m_nChannelCount = new int[m_nChannelNum]; - for (int i = 0; i < m_nChannelNum; i++) m_nChannelCount[i] = 0; + for (int i = 0; i < 1024; i++) m_nChannelCount[i] = 0; + for (int i = 0; i < 1024; i++) m_nChannelSmooth[i] = 0; freopen_s(&stream_tmp, "data/Co60.txt", "r", stdin); for (int i = 0; i < 1024; i++) @@ -196,14 +196,14 @@ void CMCADoc::RandomPeak(CString name, int n) int CMCADoc::GetTotal(int L, int R) { int cSum = 0; - for (int i = L; i <= min(m_nChannelNum-1, R); i++) cSum += m_nChannelCount[i]; + for (int i = L; i <= min(1023, R); i++) cSum += m_nChannelCount[i]; return cSum; } int CMCADoc::GetMax(int L, int R) { int cMax = 0; - for (int i = L; i <= min(m_nChannelNum - 1, R); i++) + for (int i = L; i <= min(1023, R); i++) if (m_nChannelCount[i] > cMax) cMax = m_nChannelCount[i]; return cMax; diff --git a/MCA/MCADoc.h b/MCA/MCADoc.h index 2a6b56a..73b15aa 100644 --- a/MCA/MCADoc.h +++ b/MCA/MCADoc.h @@ -15,8 +15,8 @@ protected: // 仅从序列化创建 // 特性 public: - int m_nChannelNum = 1024; - int *m_nChannelCount; + int m_nChannelCount[1024]; + int m_nChannelSmooth[1024]; private: // reference spectrum diff --git a/MCA/MCAView.cpp b/MCA/MCAView.cpp index 029e0b7..1bafee5 100644 --- a/MCA/MCAView.cpp +++ b/MCA/MCAView.cpp @@ -45,7 +45,7 @@ BOOL CMCAView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: 在此处通过修改 // CREATESTRUCT cs 来修改窗口类或样式 - + return CView::PreCreateWindow(cs); } diff --git a/MCA/MainFrm.cpp b/MCA/MainFrm.cpp index 0f83fbb..7caac7b 100644 --- a/MCA/MainFrm.cpp +++ b/MCA/MainFrm.cpp @@ -7,10 +7,9 @@ #include "MCA.h" #include "MainFrm.h" - -#include "ControlView.h" -#include "DetailView.h" #include "TotalView.h" +#include "DetailView.h" +#include "ControlView.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -121,9 +120,6 @@ void CMainFrame::Dump(CDumpContext& dc) const // CMainFrame 消息处理程序 - - - void CMainFrame::OnLoadToolBarIcon() { HICON icon; diff --git a/MCA/TotalView.cpp b/MCA/TotalView.cpp index d834c3b..5af4d90 100644 --- a/MCA/TotalView.cpp +++ b/MCA/TotalView.cpp @@ -1,5 +1,6 @@ // TotalView.cpp : 实现文件 // +#include #include "pch.h" @@ -35,27 +36,45 @@ void CTotalView::OnDraw(CDC* pDc) { // 背景颜色、笔颜色等设置 CDC MemDC; + MemDC.CreateCompatibleDC(pDc); + CRect rect; CBitmap Bitmap, * OldBitmap; - CPen pen(PS_SOLID, 2, RGB(0, 0, 0)); + CPen pen(PS_SOLID, 3, RGB(0, 0, 0)); CPen* oldpen = MemDC.SelectObject(&pen); - + GetClientRect(&rect); - MemDC.CreateCompatibleDC(pDc); Bitmap.CreateCompatibleBitmap(pDc, rect.Width(), rect.Height()); OldBitmap = MemDC.SelectObject(&Bitmap); MemDC.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(36, 217, 163)); // 绘图 - MemDC.MoveTo(1, rect.Height() - pDoc->m_nChannelCount[0]); - for (int i = 0; i < pDoc->m_nChannelNum; i++) - MemDC.LineTo(2 * i + 1, rect.Height() - pDoc->m_nChannelCount[i]); + if (pView->m_sAxisMode == "Linear") { + MemDC.MoveTo(1, rect.Height() - pDoc->m_nChannelSmooth[0] * rect.Height() / pView->m_nLC); + for (int i = 0; i < 1024; i++) + MemDC.LineTo(2 * i + 1, rect.Height() - pDoc->m_nChannelSmooth[i] * rect.Height() / pView->m_nLC); + } + else { + MemDC.MoveTo(1, rect.Height() - log10(max(pDoc->m_nChannelSmooth[0], 1)) * rect.Height() / log10(pView->m_nLC)); + for (int i = 0; i < 1024; i++) + MemDC.LineTo(2 * i + 1, rect.Height() - log10(max(pDoc->m_nChannelSmooth[i], 1)) * rect.Height() / log10(pView->m_nLC)); + } + // 绘制光标竖线 + pen.CreatePen(PS_SOLID, 5, RGB(255, 0, 0)); + MemDC.SelectObject(&pen); + MemDC.MoveTo(2 * pView->m_nCursor1 + 1, 0); + MemDC.LineTo(2 * pView->m_nCursor1 + 1, rect.Height()); + pen.CreatePen(PS_SOLID, 5, RGB(0, 255, 0)); + MemDC.SelectObject(&pen); + MemDC.MoveTo(2 * pView->m_nCursor2 + 1, 0); + MemDC.LineTo(2 * pView->m_nCursor2 + 1, rect.Height()); - //释放资源    - pDc->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY); + //释放资源 MemDC.SelectObject(oldpen); - MemDC.SelectObject(OldBitmap); pen.DeleteObject(); + + pDc->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY); + MemDC.SelectObject(OldBitmap); Bitmap.DeleteObject(); MemDC.DeleteDC(); } @@ -84,6 +103,7 @@ void CTotalView::Dump(CDumpContext& dc) const void CTotalView::OnPaint() { if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); + if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); CPaintDC dc(this); // device context for painting OnPrepareDC(&dc); OnDraw(&dc); @@ -100,7 +120,11 @@ void CTotalView::OnLButtonDown(UINT nFlags, CPoint point) if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); int nX = (point.x - 1) / 2; - if (nX < pView->m_nCursor2) pView->m_nCursor1 = nX; + if (nX < pView->m_nCursor2) { + pView->m_nCursor1 = nX; + pView->m_nCursorROI = max(pView->m_nCursor1, pView->m_nCursorROI); + } + pDoc->UpdateAllViews(NULL); CView::OnLButtonDown(nFlags, point); } @@ -109,6 +133,33 @@ void CTotalView::OnRButtonDown(UINT nFlags, CPoint point) if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); int nX = (point.x - 1) / 2; - if (nX > pView->m_nCursor1) pView->m_nCursor2 = nX; + if (nX > pView->m_nCursor1) { + pView->m_nCursor2 = nX; + pView->m_nCursorROI = min(pView->m_nCursor2, pView->m_nCursorROI); + } + pDoc->UpdateAllViews(NULL); CView::OnRButtonDown(nFlags, point); -} \ No newline at end of file +} + +BOOL CTotalView::PreTranslateMessage(MSG* pMsg) +{ + if (pDoc == NULL) pDoc = (CMCADoc*)GetDocument(); + if (pView == NULL) pView = (CControlView*)pDoc->GetView(RUNTIME_CLASS(CControlView)); + if (pMsg->message == WM_KEYDOWN) { + if (pMsg->wParam == VK_LEFT) pView->m_nCursorROI = max(pView->m_nCursor1, pView->m_nCursorROI - 1); + if (pMsg->wParam == VK_RIGHT) pView->m_nCursorROI = min(pView->m_nCursor2, pView->m_nCursorROI + 1); + if (pMsg->wParam == VK_UP) { + pView->m_nLC *= 2; + pView->m_bAutoFlag = TRUE; + pView->m_sRangeMode = (CString)"Manual"; + } + if (pMsg->wParam == VK_DOWN) { + pView->m_nLC = pView->m_nLC > 1 ? pView->m_nLC / 2 : 1; + pView->m_bAutoFlag = TRUE; + pView->m_sRangeMode = (CString)"Manual"; + } + pDoc->UpdateAllViews(NULL); + return TRUE; + } + return CView::PreTranslateMessage(pMsg); +} diff --git a/MCA/TotalView.h b/MCA/TotalView.h index 595ecf7..b4415da 100644 --- a/MCA/TotalView.h +++ b/MCA/TotalView.h @@ -35,4 +35,5 @@ public: afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + virtual BOOL PreTranslateMessage(MSG* pMsg); };