1.自绘按钮,修改为支持文字在按钮下,或在按钮右。
2.日志页,修改为“包含”和“排除”关键字,以及正则表达式的支持,便于在调试过程中快速观察日志
| | |
| | | m_hIcon[1] = nullptr; |
| | | m_nIconWidth = 0; |
| | | m_nFlashState = 0; |
| | | m_bTextRight = FALSE; |
| | | } |
| | | |
| | | |
| | |
| | | return m_nFlashState != 0; |
| | | } |
| | | |
| | | void CBlButton::SetTextRight() |
| | | { |
| | | m_bTextRight = TRUE; |
| | | } |
| | | |
| | | void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) |
| | | { |
| | | HDC hDC = lpDrawItemStruct->hDC; |
| | |
| | | HICON hIcon = this->IsWindowEnabled() ? m_hIcon[0] : m_hIcon[01]; |
| | | if (hIcon != nullptr) { |
| | | int xIcon = (rcClient.right - rcClient.top - m_nIconWidth) / 2; |
| | | if (m_bTextRight) { |
| | | xIcon = 15; |
| | | } |
| | | |
| | | if (m_hMenu != nullptr) xIcon -= 10; |
| | | int yIcon = (rcClient.bottom - rcClient.top - m_nIconWidth) / 2; |
| | | if (nTextLen != 0) { |
| | | if (nTextLen != 0 && !m_bTextRight) { |
| | | yIcon -= 8; |
| | | } |
| | | |
| | | DrawIconEx(hDC, xIcon, yIcon, |
| | | hIcon, m_nIconWidth, m_nIconWidth, 0, 0, DI_NORMAL); |
| | | rcText.top = yIcon + m_nIconWidth + 2; |
| | | if (m_bTextRight) { |
| | | rcText.left = xIcon + m_nIconWidth + 2; |
| | | } |
| | | else { |
| | | rcText.top = yIcon + m_nIconWidth + 2; |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | ::SetBkMode(hDC, TRANSPARENT); |
| | | ::SetTextColor(hDC, m_crText[state]); |
| | | |
| | | UINT format1 = m_bTextRight ? DT_LEFT : DT_CENTER; |
| | | if ((BS_MULTILINE & GetStyle()) == BS_MULTILINE) { |
| | | CRect rcBound; |
| | | int height = DrawTextA(hDC, szText, (int)strlen(szText), &rcBound, DT_CENTER | DT_CALCRECT | DT_EDITCONTROL); |
| | | rcText.top = rcBound.top + (rcClient.bottom - rcClient.top - height) / 2; |
| | | rcText.bottom = rcText.top + height; |
| | | DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_CENTER | DT_EDITCONTROL); |
| | | DrawTextA(hDC, szText, (int)strlen(szText), &rcText, format1 | DT_EDITCONTROL); |
| | | } |
| | | else { |
| | | if (m_hMenu != nullptr) { |
| | | rcText.right -= (10); |
| | | } |
| | | DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | DrawTextA(hDC, szText, (int)strlen(szText), &rcText, format1 | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | } |
| | | ::SelectObject(hDC, hOldFont); |
| | | |
| | |
| | | void Flash(int ms); |
| | | void StopFlash(); |
| | | BOOL IsFlash(); |
| | | void SetTextRight(); |
| | | |
| | | private: |
| | | BOOL CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame, |
| | |
| | | HICON m_hIcon[2]; |
| | | int m_nIconWidth; |
| | | int m_nFlashState; // 闪烁状态,0:不闪;1和2为闪烁切换中 |
| | | BOOL m_bTextRight; |
| | | |
| | | public: |
| | | virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/); |
| | |
| | | return (int)texts.size(); |
| | | } |
| | | |
| | | void CConfiguration::setFilterMode(int mode) |
| | | { |
| | | WritePrivateProfileString(_T("Logcat"), _T("FilterMode"), |
| | | std::to_string(mode).c_str(), m_strFilepath); |
| | | } |
| | | |
| | | int CConfiguration::getFilterMode() |
| | | { |
| | | return GetPrivateProfileInt(_T("Logcat"), _T("FilterMode"), 0, m_strFilepath); |
| | | } |
| | | |
| | | int CConfiguration::getP2RemoteEqReconnectInterval() |
| | | { |
| | | return GetPrivateProfileInt(_T("P2"), _T("RemoteEqReconnectInterval"), 20, m_strFilepath); |
| | |
| | | void setLogcatIncludeRegex(BOOL bRegex); |
| | | BOOL isLogcatIncludeRegex(); |
| | | int getCustomLogcatIncludeTexts(std::vector<std::string>& texts); |
| | | void setFilterMode(int mode); |
| | | int getFilterMode(); |
| | | BOOL getPortParms(unsigned int index, BOOL& bEnable, int& type, int& mode, |
| | | int& cassetteType, int& transferMode, BOOL& bAutoChangeEnable); |
| | | |
| | |
| | | BEGIN_MESSAGE_MAP(CLogEdit, CEdit) |
| | | ON_WM_CONTEXTMENU() |
| | | ON_WM_VSCROLL() |
| | | ON_WM_MOUSEWHEEL() |
| | | END_MESSAGE_MAP() |
| | | |
| | | void CLogEdit::SetMaxLineCount(int line) |
| | | { |
| | | m_nMaxLines = line; |
| | | m_nTrimLines = min(m_nMaxLines, 100); |
| | | m_nTrimLines = min(m_nMaxLines, 4000); |
| | | } |
| | | |
| | | void CLogEdit::OnContextMenu(CWnd* pWnd, CPoint point) |
| | |
| | | CEdit::OnVScroll(nSBCode, nPos, pScrollBar); |
| | | } |
| | | |
| | | BOOL CLogEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) |
| | | { |
| | | // 每次滚动时检查是否还在底部 |
| | | m_bAutoScroll = IsScrollBarAtBottom(); |
| | | return CEdit::OnMouseWheel(nFlags, zDelta, pt); |
| | | } |
| | | |
| | | BOOL CLogEdit::IsScrollBarAtBottom() |
| | | { |
| | | SCROLLINFO si = { sizeof(si), SIF_ALL }; |
| | |
| | | |
| | | void CLogEdit::AppendText(const char* pszText) |
| | | { |
| | | SetRedraw(FALSE); |
| | | SetRedraw(FALSE); |
| | | |
| | | // 裁剪逻辑 |
| | | int totalLines = GetLineCount(); |
| | | if (totalLines > m_nMaxLines) { |
| | | // 获取要删除的字符范围 |
| | | int startChar = LineIndex(0); // 第0行首字符位置 |
| | | int endChar = LineIndex(m_nTrimLines); // 第N行首字符位置 |
| | | // 剪切过多行 |
| | | int totalLines = GetLineCount(); |
| | | if (totalLines > m_nMaxLines) { |
| | | int startChar = LineIndex(0); |
| | | int endChar = LineIndex(m_nTrimLines); |
| | | if (startChar >= 0 && endChar > startChar) { |
| | | SetSel(startChar, endChar); |
| | | ReplaceSel(_T("")); |
| | | } |
| | | } |
| | | |
| | | if (startChar >= 0 && endChar > startChar) { |
| | | SetSel(startChar, endChar); |
| | | ReplaceSel(_T("")); // 删除前面行 |
| | | } |
| | | } |
| | | // 保存当前选择 |
| | | int start, end; |
| | | GetSel(start, end); |
| | | bool hasSelection = (start != end); |
| | | |
| | | int endPos = GetWindowTextLength(); |
| | | SetSel(endPos, endPos); |
| | | ReplaceSel(lpszText); |
| | | |
| | | int len = GetWindowTextLength(); |
| | | SetSel(len, len); |
| | | ReplaceSel(pszText); |
| | | if (m_bAutoScroll && !hasSelection) { |
| | | LineScroll(GetLineCount()); |
| | | } |
| | | |
| | | if (m_bAutoScroll) { |
| | | LineScroll(GetLineCount()); |
| | | } |
| | | // 恢复选择 |
| | | if (hasSelection) { |
| | | SetSel(start, end); |
| | | } |
| | | |
| | | SetRedraw(TRUE); |
| | | Invalidate(); |
| | | UpdateWindow(); |
| | | } |
| | | SetRedraw(TRUE); |
| | | |
| | | if (m_bAutoScroll && !hasSelection) { |
| | | Invalidate(); |
| | | UpdateWindow(); |
| | | } |
| | | } |
| | |
| | | DECLARE_MESSAGE_MAP() |
| | | afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); |
| | | afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); |
| | | public: |
| | | afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); |
| | | }; |
| | | |
| | |
| | | m_hbrBkgnd = nullptr; |
| | | m_pObserver = nullptr; |
| | | m_nLevel = 0; |
| | | m_strIncludeText = _T(""); |
| | | m_bIncludeRegex = FALSE; |
| | | m_strFilterText = _T(""); |
| | | m_bRegex = FALSE; |
| | | m_filterMode = FilterMode::Include; |
| | | } |
| | | |
| | | CPageLog::~CPageLog() |
| | |
| | | && pAny->getIntValue("exCode", level)) { |
| | | if (level >= m_nLevel) { |
| | | CString strText = pszLogMsg; |
| | | BOOL bInclude = TRUE; |
| | | if (!m_strIncludeText.IsEmpty()) { |
| | | if (!m_bIncludeRegex) { |
| | | bInclude = (strText.Find(m_strIncludeText) >= 0); |
| | | BOOL bMatch = TRUE; |
| | | if (!m_strFilterText.IsEmpty()) { |
| | | if (!m_bRegex) { |
| | | bMatch = (strText.Find(m_strFilterText) >= 0); |
| | | } |
| | | else { |
| | | bInclude = std::regex_search((LPTSTR)(LPCTSTR)strText, |
| | | std::regex((LPTSTR)(LPCTSTR)m_strIncludeText)); |
| | | CString strTemp = strText; |
| | | strTemp.TrimRight(); |
| | | bMatch = std::regex_match((LPTSTR)(LPCTSTR)strTemp, |
| | | std::regex((LPTSTR)(LPCTSTR)m_strFilterText)); |
| | | } |
| | | if (m_filterMode == FilterMode::Exclude) { |
| | | bMatch = !bMatch; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (bInclude) { |
| | | if (bMatch) { |
| | | strText.Replace("\n", "\r\n"); |
| | | AppendLog(level, (LPTSTR)(LPCTSTR)strText); |
| | | } |
| | |
| | | |
| | | // 缓存 |
| | | m_nLevel = theApp.m_model.m_configuration.getLogcatLevel(); |
| | | theApp.m_model.m_configuration.getLogcatIncludeText(m_strIncludeText); |
| | | m_bIncludeRegex = theApp.m_model.m_configuration.isLogcatIncludeRegex(); |
| | | theApp.m_model.m_configuration.getLogcatIncludeText(m_strFilterText); |
| | | m_bRegex = theApp.m_model.m_configuration.isLogcatIncludeRegex(); |
| | | theApp.m_model.m_configuration.getCustomLogcatIncludeTexts(m_customIncludeTexts); |
| | | m_customIncludeTexts.clear(); |
| | | m_customIncludeTexts.push_back("包含"); |
| | | m_customIncludeTexts.push_back("排除"); |
| | | |
| | | |
| | | // Level |
| | |
| | | strIcon1, IMAGE_ICON, 24, 24, |
| | | LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); |
| | | m_btnInclude.SetIcon(hIcon, hIcon, 24); |
| | | m_filterMode = (FilterMode)theApp.m_model.m_configuration.getFilterMode(); |
| | | m_btnInclude.SetTextRight(); |
| | | m_btnInclude.SetWindowText(m_filterMode == FilterMode::Include ? "包含" : "排除"); |
| | | |
| | | { |
| | | HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_INCLUDE)); |
| | |
| | | int i = 0; |
| | | for (auto& item : m_customIncludeTexts) { |
| | | i++; |
| | | InsertMenu(hSubMenu, 0, MF_BYPOSITION, 0x1998 + i, item.c_str()); |
| | | InsertMenu(hSubMenu, i, MF_BYPOSITION, 0x1998 + i, item.c_str()); |
| | | m_btnInclude.SetMenu(hMenu); |
| | | } |
| | | } |
| | | |
| | | |
| | | SetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText); |
| | | SetDlgItemText(IDC_EDIT_INCLUDE, m_strFilterText); |
| | | CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX); |
| | | pCheckBox->SetCheck(m_bIncludeRegex ? BST_CHECKED : BST_UNCHECKED); |
| | | pCheckBox->SetCheck(m_bRegex ? BST_CHECKED : BST_UNCHECKED); |
| | | |
| | | |
| | | // 内容 |
| | | m_logEdit.SetMaxLineCount(500); |
| | | m_logEdit.SetMaxLineCount(6000); |
| | | m_logEdit.SetLimitText(-1); |
| | | Resize(); |
| | | |
| | |
| | | void CPageLog::OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR); |
| | | int position = (int)pblbNmhdr->dwData; |
| | | std::string& strInclude = m_customIncludeTexts.at(position); |
| | | SetDlgItemText(IDC_EDIT_INCLUDE, strInclude.c_str()); |
| | | CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX); |
| | | m_bIncludeRegex = FALSE; |
| | | pCheckBox->SetCheck(BST_UNCHECKED); |
| | | |
| | | theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex); |
| | | theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText); |
| | | m_filterMode = (FilterMode)pblbNmhdr->dwData; |
| | | theApp.m_model.m_configuration.setFilterMode((int)m_filterMode); |
| | | m_btnInclude.SetWindowText(m_filterMode == FilterMode::Include ? "包含" : "排除"); |
| | | |
| | | *pResult = 0; |
| | | } |
| | | |
| | | void CPageLog::OnEnChangeEditInclude() |
| | | { |
| | | GetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText); |
| | | theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText); |
| | | GetDlgItemText(IDC_EDIT_INCLUDE, m_strFilterText); |
| | | theApp.m_model.m_configuration.setLogcatIncludeText(m_strFilterText); |
| | | } |
| | | |
| | | void CPageLog::OnBnClickedCheckRegex() |
| | | { |
| | | CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX); |
| | | m_bIncludeRegex = pCheckBox->GetCheck(); |
| | | theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex); |
| | | m_bRegex = pCheckBox->GetCheck(); |
| | | theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bRegex); |
| | | } |
| | |
| | | |
| | | #define ID_MSG_LOGDLG_HIDE WM_USER + 1023 |
| | | |
| | | |
| | | enum class FilterMode { |
| | | Include, // 只保留匹配行 |
| | | Exclude // 排除匹配行 |
| | | }; |
| | | |
| | | // CPageLog 对话框 |
| | | |
| | | class CPageLog : public CDialogEx |
| | |
| | | HBRUSH m_hbrBkgnd; |
| | | IObserver* m_pObserver; |
| | | int m_nLevel; |
| | | CString m_strIncludeText; |
| | | BOOL m_bIncludeRegex; |
| | | CString m_strFilterText; |
| | | BOOL m_bRegex; |
| | | std::vector<std::string> m_customIncludeTexts; |
| | | |
| | | private: |
| | | CBlButton m_btnLevel; |
| | | CBlButton m_btnInclude; |
| | | CLogEdit m_logEdit; |
| | | FilterMode m_filterMode; |
| | | |
| | | |
| | | // 对话框数据 |
| | |
| | | SetIcon(m_hIcon, FALSE); // 设置小图标 |
| | | |
| | | |
| | | // model init |
| | | theApp.m_model.init(); |
| | | |
| | | |
| | | // 菜单 |
| | | CMenu menu; |
| | | menu.LoadMenu(IDR_MENU_APP); |
| | |
| | | int height = GetSystemMetrics(SM_CYSCREEN); |
| | | MoveWindow((width - rcWnd.Width()) / 2, 0, rcWnd.Width(), rcWnd.Height(), TRUE); |
| | | |
| | | |
| | | // model init |
| | | theApp.m_model.init(); |
| | | |
| | | |
| | | SetTimer(TIMER_ID_CREATE_TERMINAL, 3000, nullptr); |