面向对象的程序(http://blog.csdn.net/qi_jianzhou/archive/2006/03/31/646124.aspx)

在做一个查询时,我用到了面向对象的一些知识,现在总结一下
 
程序中需要查询功能,查询要灵活,界面统一。这样许多的查询窗体的界面都是一样的,要是一个窗体一个窗体的做,而且界面是一样的,就是功能不同,很累的,我就想该怎么做省事呢?想到了Delphi 的窗体继承的特性,对,我可以先做一个模板,然后让别的窗体继承这个窗体,不就达到界面的统一了,而且继承的窗体也可以在原窗体的基础上再添加控件,好就这么做了
我先做了一个窗体如图
功能很简单, [查找]   [导出到 Excel] [打印] [关闭]
然后别的窗体来继承这个窗体,一个继承的窗体如下
没有什么变动,再看看别
也就是功能不一样,界面是一样的
这样就省了不少的力气,好,开始做查询的功能吧
根据不同的选择,要生成不同的 Sql 语句进行查询…….. 查询的功能完成,可以查询了
这个查询很麻烦的,要是在第二个窗体中也这很写,第三个窗体中再写,代码有好多的重复的,怎么办呢?刚学了学面向对象,能不能用面向对象来解决呢?看了看继承窗体的代码
TFocDeliverySearchForm = class(TFocSearchModelForm)   ---à  从模板窗体继承
    DBGridEh1: TDBGridEh;
    Panel1: TPanel;
    spbtFinder: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure btSearchClick(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure DBGridEh1DblClick(Sender: TObject);
    procedure btExcelClick(Sender: TObject);
    procedure btPrintClick(Sender: TObject);
    procedure ComboFieldChange(Sender: TObject);
 protected
    function createSqlStr():string;override;
    { Private declarations }
 public
    Qj_Name,Qj_NameID:string;
 end;
 
这不是从 TFocSearchModelForm 这个类继承来的吗?根据面向对象的特点,我可以把这些生成 Sql 语句的代码放到父类里,然后子类不就可以用了吗?但还有一个问题是查询的表是不同的,那该怎么做呢?
终于解决了,在父类中做一个虚拟方法,这个虚拟方法中我写主要的判断语句,也就是判断Edit 里的内容,还有选择的是按什么查询。这个方法在每个继承的窗体中是一样的,继承的特性就是所的继承的控件的命名也是一样的。
好,代码如下:
 
 
Protected    // 一定要用 protected 这个修饰符,这样在派生类中才可以看到这里定义的
 
    sField,dField,iField:string;    // 字符串字段,日期字段,数字字段
 
    dValue,dValueDate1,dValueDate2:string; // 日期值
 
    iValue,iValue1,iValue2:string;         // 数字值
 
    sValue:string;                      // 字符值
 
    sOp:string;                     // 字符串的操作
    dOp:string;                     // 日期的操作
    iOp:string;                     // 数字的操作
 
 
    theSqlStr :string;
    QuerySear:TQuery;
    ds:TDataSource;
    function CreateSqlStr():string;virtual;         // 虚方法
    procedure receiptPerson(sender:tobject);        // 收款人
    procedure customerName(sender:tobject);       // 客户名称
    procedure stockName(sender:tobject);          // 材料名称
 
……..
……..
function TFocSearchModelForm.CreateSqlStr:string;
var
 sqlStr:string;                  // sql
begin
 // 字符
 sOp := self.ComboFunction.Text;
 if self.edLookupText.Text <> '' then
 begin
    if sOP = '起始内容' then
       sValue := ' like '''+self.edLookupText.Text+'%'''+sValue;
    if sOp = '包含内容' then
       sValue := ' like ''%'+self.edLookupText.Text+'%'''+sValue;
 end
 else
    sValue := '';
 
 // 日期
 dOp := self.ComboDateFunction.Text;
 if not ( (self.MaskEdit1.Text = '    - - ') and (self.MaskEdit2.Text='    - - ') ) then
 begin
 
    if self.MaskEdit1.Text = '    - - ' then dValueDate1 := dateTostr(now)
    else dValueDate1 := self.MaskEdit1.Text;
 
    if not TPublicFunction.StringIsDate(dValueDate1) then
    begin
      result := 'error';
      exit;
    end;
 
    if self.MaskEdit2.Text = '    - - ' then dValueDate2 := dateTostr(now)
    else dValueDate2 := self.MaskEdit2.Text;
 
    if dOP = '期间' then
    begin
       if not TPublicFunction.StringIsDate(dValueDate2) then
       begin
         result := 'error';
         exit;
       end;
       dValueDate1 := dValueDate1+' '+self.edTime1.Text+':'+self.edTime2.Text;
       dValueDate2 := dValueDate2+' '+self.edTime3.Text+':'+self.edTime4.Text;
       dValue := ' between '''+dValueDate1+''' and '''+dValueDate2+'''';
 
      
    end
    else
    if dOp = '等于' then
    begin
       dValueDate1 := dValueDate1+' '+self.edTime1.Text+':'+self.edTime2.Text;
       dValue := ' = '''+dValueDate1+'''';
    end
    else
    begin
       dValueDate1 := dValueDate1+' '+self.edTime1.Text+':'+self.edTime2.Text;
       dValue := ''''+dValueDate1+'''';
    end;
 end
 else       // 日期同时为空
 begin
     dValue := '';
 end;
 
 // 数字
 iOp := self.ComboValueFunction.Text;
 if not ( (trim(self.Edit1.Text) = '') and (trim(self.Edit2.Text) = '') ) then
 begin
    iValue1 := trim(self.Edit1.Text);
    ivalue2 := trim(self.Edit2.Text);
    if iOp = '区间' then
    begin
       if iValue1 = '' then iValue1 := '0';
       if ivalue2 = '' then iValue2 := '999999';
       ivalue := ' between '+iValue1+' and '+iValue2;
    end
    else
    if iOp = '=任意值' then
    begin
       iValue1 := '';
       iValue2 := '';
       iValue := '';
    end
    else
    begin
       if iValue1 <> '' then
       iValue := ' '+iOp+iValue1+' ';
    end;
 end
 else
 begin
      iValue := '';
 end;
 
 // 派生类要加上 select * from 表名       这句可以放在该位置以前的任意位置
 SqlStr := SqlStr + ' where ' ;
 if sValue <> '' then
 begin
    SqlStr := SqlStr + sField+sValue+' and ';
 end;
 if dValue <> '' then
 begin
    SqlStr := SqlStr + dField+dValue+' and ';
 end;
 if iValue <> '' then
 begin
    SqlStr := SqlStr + iField+iValue+' and ';
 end;
  // 派生类要加了编号 = 编号              这个一定要放在这里位置不能动
 result := sqlStr;
end;
 
 
父类的方法做好了,子类呢?也就是继承的窗体该怎么做呢?继承的窗体,先看看上面的加了蓝颜色的注释
看完了,再看看继承的窗体是如何来 Override 这个方法的
 
function CreateSqlStr:string;override;                       // 生成 sql 语句
…..
……
function TFocOrderSearchForm.CreateSqlStr:string;
var
 ss:string;
begin
 self.theSqlStr := ' select * from focorder ';         // 这里看到了父类的说明 
 case self.ComboField.ItemIndex of
     0 : sField := 'customername';
     1 : sField := 'orderstatus';
     2 : sField := 'contactPerson';
 end;
 
 case self.ComboDate.ItemIndex of
     0 : dField := 'DateArrival';
     1 : dField := 'DateRequested';
     2 : dField := 'DateFinished';
     3 : dField := 'PromptDate';
 end;
 
 case self.ComboValue.ItemIndex of
     0 : iField := 'TotalAmount';
     1 : iField := 'PrepayAmt';
     2 : iField := 'PaidAmt';
     3 : iField := 'ReceivableAmt';
 end;
 
 ss := inherited createSqlstr;                       // 这里是执行父类的方法,取得这个
                                               // sql 语句
 if ss = 'error' then                               // 如果是 error 则再向上返回,退出
 begin
     result:=ss;
     exit;
 end;
 self.theSqlStr := self.theSqlStr + ss;                // 开组合这些 sql 语句了
 
 self.theSqlStr := self.theSqlStr + ' orderid= orderid ';   // 又找到了一个这里的作用是
                                               // 最后一个 and 也可以用上
 //showmessage(self.theSqlStr);
end;
 
组合好 sql 语句了,好,看看查询按纽该怎么做了。
 
 
//--------------------- 父类的查询按纽 ----------------------------//
procedure TFocSearchModelForm.btSearchClick(Sender: TObject);
begin
 with self.QuerySear do
 begin
      disableControls;
      if active then close;
      sql.Clear;
      sql.Add(theSqlStr);
      open;
      enableControls;
 end;
end;
//------------------------- 子类的查询按纽 -------------------------------//
procedure TFocOrderSearchForm.btSearchClick(Sender: TObject);
var
 ss:string;
begin
 self.iValue:='';
 self.dValue:='';
 self.sValue:='';
 //showmessage( self.CreateSqlStr);
 ss := self.CreateSqlStr;
 if ss = 'error' then         
 begin
     messagebox(0,pchar('输入的日期无效'),pchar('提示'),mb_ok+windows.MB_ICONWARNING);
     exit;
 end
 else
    inherited;          // 在这了,没有错误,好,执行父类的查询吧
  
end;
 
 
通过做这个,更加深入了解了面向对象,以上的这个可以应用在任何的查询中。
阅读更多
个人分类: Q&A
上一篇format函数的使用
下一篇在原数据库的基础上强制还原一数据库
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭