1. 程式人生 > >軟件工程結對編程第2次作業 - 圖形界面四則運算生成工具

軟件工程結對編程第2次作業 - 圖形界面四則運算生成工具

for -- 代碼 har 實現 icon ott presto str

圖形界面的四則運算生成工具

一個簡單的圖形界面四則運算生成工具 by Linaria with ??

環境

  • 操作系統:Windows 10
  • 語言:C++ / XML
  • 集成開發環境:Visual studio 2017

界面

主界面

技術分享圖片

關於頁面

技術分享圖片

界面設計基於開源UI庫 duilib

代碼實現

全部代碼托管在Coding

題目生成

int PrintQuestions(int amount, int symbolCount, int maxNumber, bool haveBrackets, bool haveFloat, char* outPath) {
    int a, b;
    float
c, d; std::ofstream questionFile; questionFile.open(outPath); if (questionFile.fail()) { return -1; } if (!haveBrackets) { if (!haveFloat) { for (int i = 0; i < amount; i++) { if (100 == maxNumber) { a = rand() % 100
+ 1; b = rand() % 100 + 1; } if (10 == maxNumber) { a = rand() % 10 + 1; b = rand() % 10 + 1; } questionFile << a << GetSymbols(symbolCount) << b << "=\n"
; } } else { for (int i = 0; i < amount; i++) { if (100 == maxNumber) { c = rand() * 0.001 + 1; d = rand() * 0.001 + 1; } else { c = rand() * 0.0001 + 1; d = rand() * 0.0001 + 1; } questionFile << c << GetSymbols(symbolCount) << d << "=\n"; } } } else { int r = 0, e; if (!haveFloat) { for (int i = 0; i < amount; i++) { r = 0; e = rand() % 2 + 1; if (e == 1) { questionFile << "("; r++; } if (100 == maxNumber) { a = rand() % 100 + 1; b = rand() % 100 + 1; } else { a = rand() % 10 + 1; b = rand() % 10 + 1; } questionFile << a << GetSymbols(symbolCount); e = rand() % 2 + 1; if (1 == e) { questionFile << "("; r++; } questionFile << b << GetSymbols(symbolCount); if (100 == maxNumber) { a = rand() % 100 + 1; b = rand() % 100 + 1; } else { a = rand() % 10 + 1; b = rand() % 10 + 1; } questionFile << a; e = rand() % 2 + 1; if (e == 1 && r != 0) { questionFile << ")"; r--; } if (r == 2) { questionFile << ")" << GetSymbols(symbolCount) << b; r--; } if (r != 0) { questionFile << ")="; } else { questionFile << "="; } questionFile << "\n"; } } else { for (int i = 0; i < amount; i++) { r = 0; e = rand() % 2 + 1; if (e == 1) { questionFile << "("; r++; } if (100 == maxNumber) { c = rand() * 0.001 + 1; d = rand() * 0.001 + 1; } else { c = rand() * 0.0001 + 1; d = rand() * 0.0001 + 1; } questionFile << c << GetSymbols(symbolCount); e = rand() % 2 + 1; if (e == 1) { questionFile << "("; r++; } questionFile << d << GetSymbols(symbolCount); if (100 == maxNumber) { c = rand() * 0.001 + 1; d = rand() * 0.001 + 1; } else { c = rand() * 0.0001 + 1; d = rand() * 0.0001 + 1; } questionFile << c; e = rand() % 2 + 1; if (e == 1 && r != 0) { questionFile << ")"; r--; } if (r == 2) { questionFile << ")"; r--; } questionFile << GetSymbols(symbolCount) << d; if (r != 0) { questionFile << ")="; } else { questionFile << "="; } questionFile << "\n"; } } } questionFile.close(); return 0; }

界面繪制及事件響應

class ToolsFrameWnd : public CWindowWnd, public INotifyUI {
  public:
    LPCTSTR GetWindowClassName() const {
        return _T("UIMainFrame");
    };
    UINT GetClassStyle() const {
        return CS_DBLCLKS;
    };
    void OnFinalMessage(HWND /*hWnd*/) {
        delete this;
    };

    void Init() {
        m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
        m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));
        m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));
        m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
        m_qAmount = static_cast<CTextUI*>(m_pm.FindControl(_T("Amount")));
        m_logPrint = static_cast<CTextUI*>(m_pm.FindControl(_T("logprint")));
        m_symbol = static_cast<CComboUI*>(m_pm.FindControl(_T("Symbol")));
        m_maxnumber = static_cast<CComboUI*>(m_pm.FindControl(_T("MaxNumber")));
        m_HaveBrackets = static_cast<CComboUI*>(m_pm.FindControl(_T("HaveBrackets")));
        m_HaveFloat = static_cast<CComboUI*>(m_pm.FindControl(_T("HaveFloat")));
        m_OutputMode = static_cast<CComboUI*>(m_pm.FindControl(_T("OutputMode")));
        m_OutputPath = static_cast<CComboUI*>(m_pm.FindControl(_T("OutputPath")));
    }

    void OnPrepare() {
    }

    void Notify(TNotifyUI& msg) {
        if (msg.sType == _T("windowinit")) OnPrepare();
        else if (msg.sType == _T("click")) {
            if (msg.pSender == m_pCloseBtn) {
                PostQuitMessage(0);
                return;
            } else if (msg.pSender->GetName() == _T("GButton")) {
                wstring amount(m_qAmount->GetText()); // lpcwstr to int
                int symbolCount = 0;
                wstring symbolName(m_symbol->GetText());
                wstring maxNumberText(m_maxnumber->GetText());
                int maxNumber = 10;
                wstring haveBracketsText(m_HaveBrackets->GetText());
                bool haveBrackets = false;
                wstring haveFloatText(m_HaveBrackets->GetText());
                bool haveFloat = false;
                wstring OutputPathText(m_OutputPath->GetText());
                char OutputPath[MAX_PATH];
                std::wcstombs(OutputPath, OutputPathText.c_str(), MAX_PATH);

                if (L"+ 和 -" == symbolName) {
                    symbolCount = 1;
                } else if (L"/ 和 *" == symbolName) {
                    symbolCount = 2;
                } else {
                    symbolCount = 3;
                }

                if (L"10" == maxNumberText) {
                    maxNumber = 10;
                } else {
                    maxNumber = 100;
                }

                if (L"是" == haveBracketsText) {
                    haveBrackets = true;
                } else {
                    haveBrackets = false;
                }

                if (L"是" == haveFloatText) {
                    haveFloat = true;
                } else {
                    haveFloat = false;
                }

                //int value = _wtoi(tempstr.c_str());
                if (!PrintQuestions(_wtoi(amount.c_str()), symbolCount, maxNumber, haveBrackets, haveFloat, OutputPath)) {
                    str.Format(_T("輸出到: %s 成功!"), m_OutputPath->GetText());
                } else {
                    str.Format(_T("輸出到: %s 失敗!"), m_OutputPath->GetText());
                }

                m_logPrint->SetText(str);
            } else if (msg.pSender == m_pMinBtn) {
                SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
                return;
            } else if (msg.pSender == m_pMaxBtn) {
                SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
                return;
            } else if (msg.pSender == m_pRestoreBtn) {
                SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
                return;
            }
        } else if (msg.sType == _T("selectchanged")) {
            CDuiString name = msg.pSender->GetName();
            CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("main_option_switch")));

            if (name == _T("main_option_main"))
                pControl->SelectItem(0);
            else if (name == _T("main_option_about"))
                pControl->SelectItem(1);
        }
    }

    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
        styleValue &= ~WS_CAPTION;
        ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
        m_pm.Init(m_hWnd);
        CDialogBuilder builder;
        CDialogBuilderCallbackEx cb;
        CControlUI* pRoot = builder.Create(_T("skin.xml"), (UINT)0, &cb, &m_pm);
        ASSERT(pRoot && "Failed to parse XML");
        m_pm.AttachDialog(pRoot);
        m_pm.AddNotifier(this);
        Init();
        return 0;
    }

    LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        ::PostQuitMessage(0L);
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        if (::IsIconic(*this)) bHandled = FALSE;

        return (wParam == 0) ? TRUE : FALSE;
    }

    LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        return 0;
    }

    LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        return 0;
    }

    LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        POINT pt;
        pt.x = GET_X_LPARAM(lParam);
        pt.y = GET_Y_LPARAM(lParam);
        ::ScreenToClient(*this, &pt);
        RECT rcClient;
        ::GetClientRect(*this, &rcClient);
        RECT rcCaption = m_pm.GetCaptionRect();

        if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right                 && pt.y >= rcCaption.top && pt.y < rcCaption.bottom) {
            CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));

            if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0 &&
                    _tcscmp(pControl->GetClass(), DUI_CTR_OPTION) != 0 &&
                    _tcscmp(pControl->GetClass(), DUI_CTR_TEXT) != 0)
                return HTCAPTION;
        }

        return HTCLIENT;
    }

    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        SIZE szRoundCorner = m_pm.GetRoundCorner();

        if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
            CDuiRect rcWnd;
            ::GetWindowRect(*this, &rcWnd);
            rcWnd.Offset(-rcWnd.left, -rcWnd.top);
            rcWnd.right++;
            rcWnd.bottom++;
            HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
            ::SetWindowRgn(*this, hRgn, TRUE);
            ::DeleteObject(hRgn);
        }

        bHandled = FALSE;
        return 0;
    }

    LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        MONITORINFO oMonitor = {};
        oMonitor.cbSize = sizeof(oMonitor);
        ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
        CDuiRect rcWork = oMonitor.rcWork;
        rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);
        LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
        lpMMI->ptMaxPosition.x = rcWork.left;
        lpMMI->ptMaxPosition.y = rcWork.top;
        lpMMI->ptMaxSize.x = rcWork.right;
        lpMMI->ptMaxSize.y = rcWork.bottom;
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        if (wParam == SC_CLOSE) {
            ::PostQuitMessage(0L);
            bHandled = TRUE;
            return 0;
        }

        BOOL bZoomed = ::IsZoomed(*this);
        LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);

        if (::IsZoomed(*this) != bZoomed) {
            if (!bZoomed) {
                CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));

                if (pControl) pControl->SetVisible(false);

                pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));

                if (pControl) pControl->SetVisible(true);
            } else {
                CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));

                if (pControl) pControl->SetVisible(true);

                pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));

                if (pControl) pControl->SetVisible(false);
            }
        }

        return lRes;
    }

    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) {
        LRESULT lRes = 0;
        BOOL bHandled = TRUE;

        switch (uMsg) {
            case WM_CREATE:
                lRes = OnCreate(uMsg, wParam, lParam, bHandled);
                break;

            case WM_CLOSE:
                lRes = OnClose(uMsg, wParam, lParam, bHandled);
                break;

            case WM_DESTROY:
                lRes = OnDestroy(uMsg, wParam, lParam, bHandled);
                break;

            case WM_NCACTIVATE:
                lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
                break;

            case WM_NCCALCSIZE:
                lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
                break;

            case WM_NCPAINT:
                lRes = OnNcPaint(uMsg, wParam, lParam, bHandled);
                break;

            case WM_NCHITTEST:
                lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
                break;

            case WM_SIZE:
                lRes = OnSize(uMsg, wParam, lParam, bHandled);
                break;

            case WM_GETMINMAXINFO:
                lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled);
                break;

            case WM_SYSCOMMAND:
                lRes = OnSysCommand(uMsg, wParam, lParam, bHandled);
                break;

            default:
                bHandled = FALSE;
        }

        if (bHandled) return lRes;

        if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;

        return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
    }

  protected:
    CPaintManagerUI m_pm;

  private:
    CButtonUI* m_pCloseBtn;
    CButtonUI* m_pMaxBtn;
    CButtonUI* m_pRestoreBtn;
    CButtonUI* m_pMinBtn;
    CTextUI* m_qAmount;
    CTextUI* m_logPrint;
    CComboUI* m_symbol;
    CComboUI* m_maxnumber;
    CComboUI* m_HaveBrackets;
    CComboUI* m_HaveFloat;
    CComboUI* m_OutputMode;
    CComboUI* m_OutputPath;
    CDuiString str;
};

題目輸出

技術分享圖片

如上圖所示,選擇了:題目數量:10,包括全部運算符,最大數:10,包含括號,包含小數,輸出到文件,結果如下:

(1.6359-(3.7624/3.7595)*1.4041)=
4.0836+(1.9374-3.7348)+3.3199=
1.4734/(1.0053*1.69/1.3788)=
(2.4893/3.4648-2.431*1.6617)=
1.7616/(2.8935-2.6519)/4.1556=
(2.1008-1.5844*1.3195/3.0485)=
1.1587/(3.9314+2.3458)+1.6618=
(2.5281*2.9589-3.0472)+3.3622=
(3.4179-(2.819/2.9815)/3.2888)=
(1.2634/(3.4272*3.6362)-1.4886)=

駕駛員:linaria

領航員:王海鵬

駕駛員評價

軟件工程結對編程第2次作業 - 圖形界面四則運算生成工具