我正在处理一个对话框,在启用OK按钮之前,必须满足其中的几个规则。
目前,页面上的任何操作(如输入数据或从下拉列表中选择项目等)都会调用一个名为ProcessEvent()的函数-该函数处理所有逻辑并启用或禁用OK按钮。
我的问题是,我发现很难使规则简明扼要和易于理解。
一些规则可以被对话框上的另一个操作否定,现在我已经结束了到处都是if else语句,或者这些语句很难阅读和遵循&扩展。
下面的代码是问题的简化,但演示得很好。如何更好地处理此问题(如果可能)
bool CWorkstation::ProcessEvent(void)
{
UpdateData();
CharCount = GetDlgItemInt(IDC_CharCount, NULL, FALSE); //get latest
if ( IsDlgButtonChecked(IDC_USEDBNAME))
{
if (!IsDlgButtonChecked(IDC_MAXDBNAME))
{
EnableNext(TRUE);
}
}
if (IsDlgButtonChecked(IDC_MAXDBNAME) && CharCount)
{
if (IsDlgButtonChecked(IDC_USEXMLNAME))
{
if ( PrefixName.IsEmpty() )
{
EnableNext(FALSE);
}
else
{
EnableNext(TRUE);
}
}
}
if (IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1)
{
EnableNext(TRUE);
}
if ( IsDlgButtonChecked(IDC_WSAUTONAME) || IsDlgButtonChecked(IDC_RENAMEIFDUP))
{
// TRACE("IDC_WSAUTONAME is Checked\n");
if ( IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1 )
{
if ( IsDlgButtonChecked(IDC_IDC_USESHORTNAME) )
{
EnableNext(TRUE);
}
else if ( IsDlgButtonChecked(IDC_USELONGNAME) )
{
EnableNext(TRUE);
}
else
{
EnableNext(FALSE);
}
}
if ( !IsDlgButtonChecked(IDC_USEPREFIX) )
{
if ( IsDlgButtonChecked(IDC_IDC_USESHORTNAME) || IsDlgButtonChecked(IDC_USELONGNAME) )
{
EnableNext(TRUE);
}
}
return false;
}
} 发布于 2010-03-25 21:19:04
我会将if/else语句分成多个函数,并对发送给EnableNext的参数执行&=。您应该只调用EnableNext一次。
所以,举个例子:
// in CWorkStation::ProcessEvent
bool enableNext = true; // start with true
enableNext &= Condition1(); // of course pick better names than Condition1
enableNext &= Condition2(); // this is just for an example
EnableNext(enableNext);其中Condition1()可能是:
bool Condition1()
{
return (IsDlgButtonChecked(IDC_USEDBNAME)
&& !IsDlgButtonChecked(IDC_MAXDBNAME));
}诸若此类。
这里发生的情况是enableNext变量以true开头。然后,您所做的每个&=都意味着如果任何ConditionX()函数返回false,那么enableNext将以false结束。只有在所有条件都为真的情况下,它才会在最后为真。
发布于 2010-03-25 23:01:52
这个问题可以用监听器的概念来解决。
您可以使每个图形用户界面组件都有一个isEnabled()方法,该方法根据某些条件检查其条件。当调用任何更改任何组件状态的操作时,都会在每个图形用户界面组件上调用isEnabled()。
通过这种方式,您可以拥有以下声明:
bool CheckBoxComponent::isValid() {
return isNameFilled() && isEmailChecked();
}
bool OkButton::canSend() {
return checkBoxName->isValid() && isEmailChecked();
}然后,在创建GUI组件时,您可以使每个组件通过listener相互连接。
这样,您就有了它们所属的每个组件的规则,并且不会有大量的if语句。
发布于 2010-03-25 21:14:52
尝试将规则制定为状态机可能会有所帮助,但这是否可行取决于它们的性质。在这种方法中,每当用户填写对话框中的某个字段,或选中复选框或其他任何内容时,您都会相应地更新状态机的状态。如果你拥有它,你可以使用Boost.Statechart来实现它。
https://stackoverflow.com/questions/2515722
复制相似问题