我能夠通過編寫自定義DDX_處理程序來做到這一點。我所使用的應用程序使用自定義控件(從CEdit派生的MCReal),它只接受控件中定義的可接受範圍之間的小數值。當用戶輸入非十進制值或範圍之外的值時,代碼將彈出自定義消息並將輸入的值恢復到對話框字段中。
這是通過創建自定義控件和自定義驗證處理程序來完成的。以下是DDX_例程的外觀:
void AFXAPI_EXPORT DDX_ProcessEditReal(CDataExchange* pDX, int nIDC, MCReal& mcr)
{
// prepare edit control
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
// does control exist yet?
if (!IsWindow(mcr.m_hWnd))
{
// subclass the control
if (!mcr.SubclassWindow(hWndCtrl))
{
ASSERT(false);
// possibly trying to subclass twice?
AfxThrowNotSupportedException();
}
return;
}
if (!ValidateMCRealCtrl (mcr, pDX->m_pDlgWnd, (pDX->m_bSaveAndValidate == TRUE)))
{
pDX->Fail();
}
}
我使用標準的DDX_例程作爲編寫自定義版本的起點。真正的工作是在做ValidateMCRealCtrl()
:
bool ValidateMCRealCtrl (MCReal &mcRealCtrl, CWnd *pParentWnd, bool bSaveAndValidate)
{
CString ctext;
double val = 0.0, r = 0.0;
double unit_factor = 0.0;
bool bDmsrg = false;
bool rc = false;
bool ret;
...
if (bSaveAndValidate) // Move from dialog to data
{
if (pParentWnd != nullptr && mcRealCtrl.CancelButtonClicked (pParentWnd))
{
return true;
}
if (!mcRealCtrl.IsWindowEnabled() || !mcRealCtrl.IsWindowVisible())
{
return true;; // don't update if not enabled
}
mcRealCtrl.GetWindowText (ctext);
...
// base field validation.
ret = mcRealCtrl.Validate();
if (!ret)
{
make_mcreal_str (r, ctext.GetBuffer (mcRealCtrl.maxlen), mcRealCtrl.maxlen, prec, mcRealCtrl.add_plus,
mcRealCtrl.m_strip_trailing == TRUE);
ctext.ReleaseBuffer();
InvalidRealField (mcRealCtrl); // Bad value
return false; // Reset Focus
}
...
ctext.ReleaseBuffer();
mcRealCtrl.SetWindowText (ctext);
}
else // Move from data to dialog
{
if (mcRealCtrl.angle) // If angle field...
{
val = mcRealCtrl.value * R2D; // Convert to degrees
}
else
{
val = mcRealCtrl.value; // Use data value
}
make_mcreal_str (val, ctext.GetBuffer (mcRealCtrl.maxlen), mcRealCtrl.maxlen, prec, mcRealCtrl.add_plus,
mcRealCtrl.m_strip_trailing == TRUE);
ctext.ReleaseBuffer();
mcRealCtrl.SetWindowText (ctext);
mcRealCtrl.SetLimitText (mcRealCtrl.maxlen);
}
...
return true;
}
(注:我已經更換了代碼,不屬於你的問題與「...」)
恢復字段值的工作發生在InvalidRealField()
。該代碼顯示一條彈出消息,並使用該字段的先前值(保存在實際的MCReal控件類中)更改之前恢復該值。
此框架並非專門用於恢復不正確的對話框字段值。它提供的遠不止這些,因爲控制類提供了一些額外的功能。但是,如果讓自定義類中定義的控件允許我提供自定義驗證。
如果失敗,UpdateData將返回FALSE,因此您可以修復它。調用UpdateData之前,您可以親自驗證控制值。將控件映射到CEdit。您還可以使用PreTranslateMessage並抑制按鍵強制用戶只輸入某些值。 –