簡體   English   中英

輸入子類編輯控件的驗證以僅接受浮點數

[英]Input validation of a subclassed edit control to only accept floating point numbers

在我目前的項目中,過去幾天我一直在使用子類化編輯框。 到目前為止,我成功地對我的編輯框進行了子類化並驗證了輸入,使其只接受數字,逗號,減號和鍵盤命令。

但是很長一段時間我現在仍然堅持改進輸入驗證。 我希望我的編輯框的行為如下:

  • 僅在第一個位置接受減號
  • 只接受一個前導零
  • 只接受一個逗號
  • 領先零后強制逗號
  • 通過“后退”,“刪除”,選擇全部然后粘貼某些字符來刪除單個字符或選擇文本時管理這些情況

我當前形式的代碼如下所示,幾乎沒有提供我上面指定的高級驗證要求:

inline LRESULT CALLBACK decEditBoxProc(HWND hWnd,
                                       UINT msg, 
                                       WPARAM wParam, 
                                       LPARAM lParam,
                                       UINT_PTR uIdSubclass,
                                       DWORD_PTR dwRefData)
{
    if(msg == WM_CHAR)
    {
        decEditBoxData* data = reinterpret_cast<decEditBoxData*>(ULongToPtr(dwRefData));

        bool isDigit          = (wParam >= '0' && wParam <= '9');
        bool isZero           = ((wParam == '0') && !data->blockZero);
        bool isSign           = (wParam == '-');
        bool isComma          = ((wParam == '.' || wParam == ',') && !data->blockComma);
        bool isValidCommand   = (wParam == VK_RETURN  
                                || wParam == VK_DELETE 
                                || wParam == VK_BACK);


        // Restrict comma to one.
        if(isComma && data->nCommas > 0)
            return FALSE;
        else if(isComma && data->nCommas == 0)
            data->nCommas++;

        // Restrict trailing zeroes to one.
        if(isZero && data->nTrailingZeroes > 0)
            return FALSE;
        else if(isZero && data->nTrailingZeroes == 0)
            data->nTrailingZeroes++;

        // Filter everything but digits, commas and valid commands.
        if(!isDigit && !isValidCommand && !isComma)
            return FALSE;
    }
    return DefSubclassProc(hWnd, msg, wParam, lParam);
}

任何關於如何通過算法解決這個問題的想法都非常感激。

UPDATE

感謝David Heffernan和IInspectable的建議,我能夠(幾乎)解決我的問題,而無需繼承編輯控件。

在對話框過程中(包含編輯控件):

switch(msg)
{
case WM_COMMAND:
   switch(LOWORD(wParam))
   {
      case IDC_IN_REAL:
         if(HIWORD(wParam)==EN_CHANGE) onEditChange(hDlg, IDC_IN_REAL);
         break;

      case IDC_IN_IMAG:
         if(HIWORD(wParam)==EN_CHANGE) onEditChange(hDlg, IDC_IN_IMAG);
         break;
    }
    break;
}

使用onEditChange:

void onEditChange(HWND hDlg, int ctrlID)
{
    HWND hEdit    = GetDlgItem(hDlg, ctrlID);
    size_t len    = GetWindowTextLength(hEdit)+1;
    wchar_t* cstr = new wchar_t[len];
    GetWindowText(hEdit, cstr, len);

    std::wstring wstr(cstr);

    if(!(tools::isFloat(wstr)))
    {
        EDITBALLOONTIP bln;
        bln.cbStruct = sizeof(EDITBALLOONTIP);
        bln.pszTitle = L"Error";
        bln.pszText  = L"Not a valid floating point character.\nUse '.' instead of ','";
        bln.ttiIcon  = TTI_ERROR;
        Edit_ShowBalloonTip(hEdit, &bln);
    }
    delete [] cstr;
}

和isFloat():

bool tools::isFloat(std::wstring str)
{
    std::wistringstream iss(str);
    float f;
    wchar_t wc;
    if(!(iss >> f) || iss.get(wc))
        return false;
    return true;
}

我可能會為用戶添加更多視覺反饋,但現在這並不重要。

然而,這個問題尚未得到解答。 我的意圖是允許“,”作為可能的小數點。

你需要一台狀態機。 首先宣布你的州。

enum InputState
{
  NoCharacters
  MinusSign
  LeadingZero
  PreDecimalPoint
  PostDecimalPoint
}
InputState mState = NoCharacters

每當用戶輸入字符時,使用開關塊根據mState的值調用不同的驗證函數。

bool ValidCharacter(char input)
{
  switch (mState)
  {
        case NoCharacters:
          return NoCharacters(input);
        case MinusSign:
          return MinusSign(input);
        /// etc
  }
}

因此,例如,當mState == NoCharacters時調用的函數將接受任何數字,小數點或減號。 然后,如果字符是減號,則將mState更改為MinusSign;如果字符為零,則將其更改為LeadingZero,等等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM