1.自绘按钮,修改为支持文字在按钮下,或在按钮右。
2.日志页,修改为“包含”和“排除”关键字,以及正则表达式的支持,便于在调试过程中快速观察日志
已修改11个文件
159 ■■■■ 文件已修改
SourceCode/Bond/Servo/BlButton.cpp 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/BlButton.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/LogEdit.cpp 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/LogEdit.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageLog.cpp 62 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageLog.h 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/logcat_include.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/BlButton.cpp
@@ -36,6 +36,7 @@
    m_hIcon[1] = nullptr;
    m_nIconWidth = 0;
    m_nFlashState = 0;
    m_bTextRight = FALSE;
}
@@ -159,6 +160,11 @@
    return m_nFlashState != 0;
}
void CBlButton::SetTextRight()
{
    m_bTextRight = TRUE;
}
void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    HDC hDC = lpDrawItemStruct->hDC;
@@ -200,15 +206,24 @@
    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);
        if (m_bTextRight) {
            rcText.left = xIcon + m_nIconWidth + 2;
        }
        else {
        rcText.top = yIcon + m_nIconWidth + 2;
        }
    }
@@ -223,18 +238,19 @@
    ::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);
SourceCode/Bond/Servo/BlButton.h
@@ -53,6 +53,7 @@
    void Flash(int ms);
    void StopFlash();
    BOOL IsFlash();
    void SetTextRight();
private:
    BOOL CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
@@ -78,6 +79,7 @@
    HICON m_hIcon[2];
    int m_nIconWidth;
    int m_nFlashState;        // 闪烁状态,0:不闪;1和2为闪烁切换中
    BOOL m_bTextRight;
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
SourceCode/Bond/Servo/Configuration.cpp
@@ -92,6 +92,17 @@
    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);
SourceCode/Bond/Servo/Configuration.h
@@ -20,6 +20,8 @@
    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);
SourceCode/Bond/Servo/LogEdit.cpp
@@ -21,12 +21,13 @@
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)
@@ -60,6 +61,13 @@
    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 };
@@ -71,29 +79,39 @@
{
    SetRedraw(FALSE);
    // 裁剪逻辑
    // 剪切过多行
    int totalLines = GetLineCount();
    if (totalLines > m_nMaxLines) {
        // 获取要删除的字符范围
        int startChar = LineIndex(0);            // 第0行首字符位置
        int endChar = LineIndex(m_nTrimLines);    // 第N行首字符位置
        int startChar = LineIndex(0);
        int endChar = LineIndex(m_nTrimLines);
        if (startChar >= 0 && endChar > startChar) {
            SetSel(startChar, endChar);
            ReplaceSel(_T("")); // 删除前面行
            ReplaceSel(_T(""));
        }
    }
    // 保存当前选择
    int start, end;
    GetSel(start, end);
    bool hasSelection = (start != end);
    int len = GetWindowTextLength();
    SetSel(len, len);
    ReplaceSel(pszText);
    int endPos = GetWindowTextLength();
    SetSel(endPos, endPos);
    ReplaceSel(lpszText);
    if (m_bAutoScroll) {
    if (m_bAutoScroll && !hasSelection) {
        LineScroll(GetLineCount());
    }
    // 恢复选择
    if (hasSelection) {
        SetSel(start, end);
    }
    SetRedraw(TRUE);
    if (m_bAutoScroll && !hasSelection) {
    Invalidate();
    UpdateWindow();
}
}
SourceCode/Bond/Servo/LogEdit.h
@@ -20,5 +20,7 @@
    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);
};
SourceCode/Bond/Servo/PageLog.cpp
@@ -20,8 +20,9 @@
    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()
@@ -70,19 +71,24 @@
                    && 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);
                        }
@@ -110,9 +116,12 @@
    // 缓存
    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
@@ -135,6 +144,9 @@
        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));
@@ -143,19 +155,19 @@
        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();
@@ -290,28 +302,22 @@
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);
}
SourceCode/Bond/Servo/PageLog.h
@@ -7,6 +7,12 @@
#define ID_MSG_LOGDLG_HIDE        WM_USER + 1023
enum class FilterMode {
    Include,  // 只保留匹配行
    Exclude   // 排除匹配行
};
// CPageLog 对话框
class CPageLog : public CDialogEx
@@ -29,14 +35,15 @@
    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;
// 对话框数据
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -285,6 +285,10 @@
    SetIcon(m_hIcon, FALSE);        // 设置小图标
    // model init
    theApp.m_model.init();
    // 菜单
    CMenu menu;
    menu.LoadMenu(IDR_MENU_APP);
@@ -353,9 +357,6 @@
    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);
SourceCode/Bond/x64/Debug/Res/logcat_include.ico