通知一个控件另一个控件有状态更改



我正在使用C++Builder Enterprise,需要一些想法。

我有一个Form,上面有一堆TButtonTSpeedButton控件。我希望在按下某个按钮时,禁用它和其他几个按钮,同时启用其他几个按钮(即状态更改(。

问题是我在很多地方复制了启用/禁用代码。我曾考虑过以某种方式使用TNotifyEvent委派来提醒按钮状态更改,但我认为委派技术在这种情况下不起作用。我想避免创建一堆TButton/TSpeedButton的子类。

我还想尝试使用VCL提供的技术,因为每个组件都有一个观察者列表,我想知道我是否可以以某种方式利用它。

我值2美分。。

我已经为你的问题做了概念验证,需要做更多的工作,但我认为这是可行的,应该做你想做的事。

如果有兴趣,我会做更多的工作并发布。

在窗体上查找类类型的所有控件

---TControlAgent->FindTControl(这个,"TButton"(;

我在表格上添加了4个按钮,在按钮1点击事件、中添加了下面的代码

TControlAgent->SetControlProperty("Enabled"、"TButton"、false、true、"Button3"(;

在这种情况下,希望类名称为TButton、state=true或false的具有Enabled属性的控件执行该操作,但排除名为TButton3 的控件

结果是,除了按钮3 外,表单上的所有T按钮都被设置为禁用

(注意:排除选项将是从任何操作中排除的控件的查找列表,或者能够设置非状态的状态,例如Enabled=!true或!false(

在按钮3的点击事件中,我放置了以下代码;

TControlAgent->SetControlProperty("Enabled"、"TButton"、true、true、"(;

这样做的结果是重新启用所有控件,这只是一个想法,但通过额外的工作,可以对窗体集合中的任何窗体的单亲窗体中的任何控件执行任何操作。

我还认为有可能引发事件,这只是一个疯狂的想法。。。

使用berlin 10.1 的.h文件


//---------------------------------------------------------------------------
#ifndef TControlAgentH
#define TControlAgentH
//---------------------------------------------------------------------------
#include <System.SysUtils.hpp>
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <System.TypInfo.hpp>
#include <vector>
#include <algorithm>
//---------------------------------------------------------------------------
class PACKAGE TControlAgent : public TComponent
{
private:
std::vector<TControl*> FControls;
protected:
public:
std::vector<UnicodeString> excludeControlNames;
__fastcall TControlAgent(TComponent* Owner);
TControl * __fastcall GetControl(TControl* ctrl, UnicodeString property);
void __fastcall FindTControl(TForm *f, UnicodeString className);
TControl* __fastcall SetControlProperty(UnicodeString property, UnicodeString className, bool state, bool exec, UnicodeString excludeControlName   );
__published:
};
//---------------------------------------------------------------------------
#endif

.cpp文件


//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "TControlAgent.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
//---------------------------------------------------------------------------
// component to act as agent for other components derived from TControl
//
//  Components have properties and events, is it possible to get all TControls into a vector
//  then be able to get a property of a component then fire an event or carry out an action
//  on the component!!!!
//---------------------------------------------------------------------------
static inline void ValidCtrCheck(TControlAgent *)
{
new TControlAgent(NULL);
}
//---------------------------------------------------------------------------
__fastcall TControlAgent::TControlAgent(TComponent* Owner)
: TComponent(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::FindTControl(TForm *f, UnicodeString className)
{
FControls.clear();
for(int i = 0; i < f->ControlCount; i++)
{
if(f->Controls[i]->ClassName() == className)  //control classes that to set as a group
FControls.push_back(f->Controls[i]);
}
//note:  could have a function that appends other class names
}
//---------------------------------------------------------------------------
TControl* __fastcall TControlAgent::SetControlProperty(UnicodeString property, UnicodeString className, bool state, bool exec, UnicodeString excludeControlName  )
{
PPropInfo propinfo;
for(int i = 0; i < FControls.size(); i++)
{
if(FControls[i]->ClassName() == className)
{
propinfo = GetPropInfo(FControls[i], property);
if (!propinfo)
continue;
if(exec && FControls[i]->Name != excludeControlName )
{
if(property == "Enabled")
FControls[i]->Enabled = state;
}
}
}
}
//---------------------------------------------------------------------------
namespace Tcontrolagent
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TControlAgent)};
RegisterComponents(L"SQLite", classes, 0);
}
}
//---------------------------------------------------------------------------

***更新*****TControlAgent 的研究进展

显然仍在进行中,但这段代码有效,用TPanel创建一个表单,添加6个TButtons

添加一个TControl Agent,根据下面的表单代码设置OnButtonClick事件

TControlAgent代码.h

//---------------------------------------------------------------------------
#ifndef TControlAgentH
#define TControlAgentH
//---------------------------------------------------------------------------
#include <System.SysUtils.hpp>
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <System.TypInfo.hpp>
#include <vector>
#include <algorithm>
class TControls;
class TControlGroup;
typedef void __fastcall (__closure *TControlAgentOnClick)(System::TObject *Sender, TControls *ctrl);
typedef void __fastcall (__closure *TButtonClickEvent)(System::TObject *Sender);
enum action {aEnabled, aOnClick, aChange};
enum tcontrols {tbutton, tedit, tcombo, tcheckbox};
//---------------------------------------------------------------------------
class PACKAGE TControlAgent : public TComponent
{
private:
std::vector<TControls*> FControls;
std::vector<TControlGroup*> FControlGroups;
TControlAgentOnClick FClickSupliment;
TButtonClickEvent FOnButtonClick;
bool FButtonClickRedirect;
protected:
public:
std::vector<UnicodeString> excludeControlNames;  // not implemented yet
std::vector<TControlGroup*> __fastcall Groups();
std::vector<TControls*> __fastcall Controls(int GroupIndex);
__fastcall TControlAgent(TComponent* Owner);
TControl * __fastcall GetControl(TControl* ctrl, UnicodeString property);
void __fastcall FindTControl(TForm *f, UnicodeString className);
void __fastcall FindTControl(TPanel *p, UnicodeString GroupName, bool ClearIfControlsExists);
void __fastcall SetControlProperty(TControl *ctrl, bool state, int Action);
int __fastcall GetGroup(String name);
void __fastcall SetControlClickEvent(String ClassName, String GroupName, String ExcludeGroup, int tControlType);
void __fastcall SetButtonPropValue(TButton* b, String Property, String Value, bool v);
int __fastcall AddTControl(TControl* c, String Group);
void __fastcall SetButtonPropValue(String Group, String ExcludeGroup,int TControlType,String Property,String GroupValue,bool GroupV,String excludeGroupValue,bool excludeGroupV);

__published:
__property bool TButtonClick = {read = FButtonClickRedirect, write = FButtonClickRedirect };
__property TControlAgentOnClick OnClickSuppliment={read=FClickSupliment, write=FClickSupliment};
__property TButtonClickEvent OnButtonClick = {read = FOnButtonClick, write = FOnButtonClick };
};
//---------------------------------------------------------------------------
class TControlGroup
{
public:
UnicodeString GroupName;
std::vector<TControls*> GroupControls;
__fastcall TControlGroup();
};
//---------------------------------------------------------------------------
class TControls
{
public:
TControl* ctrl;
bool WantButtonOnClick;
bool WantControlOnChange;
bool FireStateChange;
bool WantOnClickSupliment;
bool state;
__fastcall TControls();
};
#endif

.cpp

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "TControlAgent.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
//---------------------------------------------------------------------------
// component to act as agent for other components derived from TControl
//
//  Components have properties and events, is it possible to get all TControls into a vector
//  then be able to get a property of a component then fire an event or carry out an action
//  on the component!!!!
//---------------------------------------------------------------------------
struct IsCtrlGroup {
String _name;
IsCtrlGroup(String name) : _name(name)
{
}
bool operator()(const TControlGroup * item) const
{
return (item->GroupName == _name);
}
};
//---------------------------------------------------------------------------
struct IsClassName {
String _name;
IsClassName(String name) : _name(name)
{
}
bool operator()(const TControl * item) const
{
return (item->ClassName() == _name);
}
};
//---------------------------------------------------------------------------
struct IsCtrl {
TControl* _ctrl;
IsCtrl(TControl* ctrl) : _ctrl(ctrl) {
}
bool operator()(const TControls * item) const {
return (item->ctrl->Name == _ctrl->Name);
}
};
//---------------------------------------------------------------------------
static inline void ValidCtrCheck(TControlAgent *)
{
new TControlAgent(NULL);
}
//---------------------------------------------------------------------------
__fastcall TControlAgent::TControlAgent(TComponent* Owner)
: TComponent(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::FindTControl(TForm *f, UnicodeString className)
{
FControls.clear();
TControls* ctrl;
for(int i = 0; i < f->ControlCount; i++)
{
if(f->Controls[i]->ClassName() == className)  //control classes that to set as a group
{
TControls* ctrl = new TControls();
ctrl->ctrl = f->Controls[i];
ctrl->FireStateChange = false;
ctrl->WantOnClickSupliment = false;
FControls.push_back(ctrl);
}
}
//note:  could have a function that appends other class names
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::FindTControl(TPanel *p, UnicodeString GroupName, bool ClearIfControlsExists)
{
/*
group vector[]
--> controlsindex  vector[index]
*/
TControlGroup* g;
TControls* ctrl;
int i = -1;
int group_index = -1, controls_index = -1;
// check if group name exists in group vector
group_index = GetGroup(GroupName);
//clear controls vector if exists, controls will not exist if group does not exist...
if(ClearIfControlsExists && group_index > 0)
FControlGroups[group_index]->GroupControls.clear();
// if group does not exist, push new group onto vector
if(group_index == -1)
{
g = new TControlGroup();
g->GroupName = GroupName;
FControlGroups.push_back(g);
group_index = GetGroup(GroupName);
}
//group must bnow exist
for(i = 0; i < p->ControlCount; i++)
{
TControls* ctrl = new TControls();
ctrl->ctrl = p->Controls[i];
FControlGroups[group_index]->GroupControls.push_back(ctrl);
controls_index = FControlGroups[group_index]->GroupControls.size() -1;
FControlGroups[group_index]->GroupControls[controls_index]->ctrl = p->Controls[i];
}
}
//---------------------------------------------------------------------------
int __fastcall TControlAgent::AddTControl(TControl* c, String Group)
{
int  index;
TControlGroup* g;
int group_index = GetGroup(Group);
if(group_index == -1)
{
g = new TControlGroup();
g->GroupName = Group;
FControlGroups.push_back(g);
group_index = GetGroup(Group);
}
TControls* ctrl = new TControls();
ctrl->ctrl = c;
FControlGroups[group_index]->GroupControls.push_back(ctrl);
index = FControlGroups[group_index]->GroupControls.size()-1;
return(index);
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::SetControlClickEvent(String ClassName, String GroupName, String ExcludeGroup, int tControlType)
{
int group_index = GetGroup(GroupName);
for(int i = 0; i < FControlGroups[group_index]->GroupControls.size(); i++)
{
if(FControlGroups[group_index]->GroupControls[i]->ctrl->ClassName() == ClassName)
{
switch(tControlType)
{
case tbutton:
dynamic_cast<TButton*>(FControlGroups[group_index]->GroupControls[i]->ctrl)->OnClick = FOnButtonClick;
break;
case tedit:
break;
case tcombo:
break;
case tcheckbox:
break;
}
}
}
}
//---------------------------------------------------------------------------
std::vector<TControlGroup*> __fastcall TControlAgent::Groups()
{
return(FControlGroups);
}
//---------------------------------------------------------------------------
std::vector<TControls*> __fastcall TControlAgent::Controls(int GroupIndex)
{
return(FControlGroups[GroupIndex]->GroupControls);
}
//---------------------------------------------------------------------------
int __fastcall TControlAgent::GetGroup(String name)
{
int group_index =-1;
std::vector<TControlGroup*>::iterator found = std::find_if(FControlGroups.begin(), FControlGroups.end(), IsCtrlGroup(name));
if(found != FControlGroups.end())
group_index =  std::distance(FControlGroups.begin(), found);
return(group_index);
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::SetButtonPropValue(TButton* b, String Property, String Value, bool v)
{
PPropInfo propinfo;
propinfo = GetPropInfo(b, Property);
if (!propinfo)
return;
if(Value.IsEmpty())
SetPropValue(b, propinfo, v);
else
SetPropValue(b, propinfo, Value);
}
//---------------------------------------------------------------------------
void __fastcall TControlAgent::SetButtonPropValue(String Group,
                              String ExcludeGroup,
                              int TControlType,
                              String Property,
                              String GroupValue,
                              bool GroupV,
                              String excludeGroupValue,
                              bool excludeGroupV)
{
// Group can hold all TControls on a form
// ExcludeGroup contains TControls that will be excluded from an action on the Group controls
// Group is an existing group of TControls found on a container
// ExcludGroup is a group that can be found on a container or added to a Group
//  then parsed to this method in ExcludeGroup param
int i;
PPropInfo propinfo;
TControl *c;
int group_index = GetGroup(Group);
int exclude_Group_index = GetGroup(ExcludeGroup);
TControl* ctrl;
for(i = 0; i < FControlGroups[group_index]->GroupControls.size(); i++)
{
c = FControlGroups[group_index]->GroupControls[i]->ctrl;
//check if TControl is to be excluded
std::vector<TControls*>::iterator found = std::find_if(FControlGroups[exclude_Group_index]->GroupControls.begin(),
                                                       FControlGroups[exclude_Group_index]->GroupControls.end(),
                                                       IsCtrl(c));
// if found, control is in the exclude list so continue, do not apply
// property value change
if(found != FControlGroups[exclude_Group_index]->GroupControls.end())
{
c = (*found)->ctrl;
//set property value for exclude group controls
propinfo = GetPropInfo(c, Property);
if(propinfo)
{
if(excludeGroupValue.IsEmpty())
SetPropValue(c, propinfo, excludeGroupV);
else
SetPropValue(c, propinfo, excludeGroupValue);
}
continue;
}
//if it gets here, c is not in exclude list
propinfo = GetPropInfo(c, Property);
if (!propinfo)
return;

if(GroupValue.IsEmpty())
SetPropValue(c, propinfo, GroupV);
else
SetPropValue(c, propinfo, GroupValue);
}
}
//---------------------------------------------------------------------------
namespace Tcontrolagent
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TControlAgent)};
RegisterComponents(L"SQLite", classes, 0);
}
}
//---------------------------------------------------------------------------
__fastcall TControls::TControls(){}
//---------------------------------------------------------------------------
__fastcall TControlGroup::TControlGroup(){}

表单代码

.cpp

表单有一个T面板,上面有6个T按钮

@运行时TButton3被禁用

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "frmTControlTest.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "TControlAgent"
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
: TForm(Owner)
{
int i;
std::vector<TControls*> group_controls;
//get ALL controls on a container
ControlAgent1->FindTControl(p, "Group1", true);
//create the exclude (for want of a better name) groups
/*
add
edit
save
delete
cancel
exit
*/
ControlAgent1->AddTControl(bnSave, "Group2");
ControlAgent1->AddTControl(bnCancel, "Group2");
ControlAgent1->AddTControl(bnAdd, "Group3");
ControlAgent1->AddTControl(bnEdit, "Group3");
ControlAgent1->AddTControl(bnDelete, "Group3");
ControlAgent1->AddTControl(bnExit, "Group3");

i = ControlAgent1->GetGroup("Group1");
group_controls = ControlAgent1->Controls(i);
ControlAgent1->SetControlClickEvent("TButton", "Group1", "", tbutton);
}
//---------------------------------------------------------------------------
void __fastcall TForm3::ControlAgent1ButtonClick(TObject *Sender)
{
TButton* b;
if((b = dynamic_cast<TButton*>(Sender)) == bnAdd )
ControlAgent1->SetButtonPropValue("Group1", "Group2", tbutton, "Enabled", "", false, "", true);
if((b = dynamic_cast<TButton*>(Sender)) == bnCancel )
ControlAgent1->SetButtonPropValue("Group1", "Group3", tbutton, "Enabled", "", false, "", true);
if((b = dynamic_cast<TButton*>(Sender)) == bnSave )
{
ControlAgent1->SetButtonPropValue("Group1", "Group3", tbutton, "Enabled", "", false, "", true);
//Do Stuff
}

}
//---------------------------------------------------------------------------

最新更新