简单地说,用tcxdbbuttonedit定制成一个能显示字符的日期控件.
首先建立此类.重构creat方法,在create加上  properties.OnButtonClick:=buttonclick;
在buttonclick中,呼叫一个日期控件,因为字段的格式是'yyyymmdd',在返回的时候就用formatdatatime格式化一下再赋给控件.使用此控件的时候,为了使它显示出日期格式,所以把它的editmask设置成!0000/00/00;1
从日期控件中返回字符型日期都没问题.问题出在删除这个控件里的值时,移到焦点到别处,就会出现'编辑值非法'的错误,这个问题花了一两天,最终找到一个解决办法:在控件的keyup里面,判断edittext是否为空,若为空,则    databinding.DataSource.DataSet.FieldByName(databinding.DataField).Clear;
然后在onvalidate事件里,判断editmask若不为空,且长度不等于10的时候,就
showmessage('输入的日期无效');
abort;编辑值非法的问题算是解决了,但问题又出现了.
当手动输入日期,再post的时候,就会出现:
'多步操作产生错误,请检查每一步值的状态.'真是晕死了,花了我三四天,弄得我烦死了,哪位高手能救救我啊一.如果有成熟的字符日期控件最好,请您发一个给我.不胜感激!
二.解决'编辑值非法'的问题有没有更好的问题.
三.最后,上面都不行,解决'多步操作产生错误,请检查每一步值的状态.'的问题,您也是我的救星啊.

解决方案 »

  1.   

    unit klDateEdit;interfaceuses
    {$IFDEF DELPHI6}
      Variants,
    {$ENDIF}
    //{$IFDEF VCL}
      Windows, Messages,
    //{$ENDIF}
      Classes, Controls, DB, DBCtrls, SysUtils,dialogs, forms,graphics,mask,stdctrls,
     cxButtonEdit, cxCalc,ComCtrls,CommCtrl,
      cxCalendar, cxCheckBox, cxClasses, cxContainer, cxCurrencyEdit, cxCustomData,
      cxDataUtils, cxDB, cxDropDownEdit, cxEdit, cxHyperLinkEdit, cxImage,
      cxImageComboBox, cxListBox, cxMaskEdit, cxMemo, cxMRUEdit, cxRadioGroup,
      cxSpinEdit, cxTextEdit, cxTimeEdit,cxdbedit;
    type
      Efieldtype=(ctext,cdate,cdatetime);  Tdatebuttonedit =class(TcxDBbuttonEdit)
      private  ffieldtype:Efieldtype;
      protected  public
        constructor Create(AOwner: TComponent); overload; override;
        constructor Create(AOwner: TComponent; AIsInplace: Boolean); reintroduce; overload;
        procedure buttonclick(sender:TObject;AButtonIndex:integer);
        procedure validate(Sender: TObject;var DisplayValue: Variant;
              var ErrorText: TCaption; var Error: Boolean);
        procedure klkeyup(Sender: TObject;var Key: Word; Shift: TShiftState);
      published
        property fieldtype:efieldtype read ffieldtype write ffieldtype default ctext;
        property Anchors;
        property AutoSize;
        property BeepOnEnter;
        property Constraints;
        property DataBinding;
        property DragCursor;
        property DragKind;
        property DragMode;
        property Enabled;
        property ImeMode;
        property ImeName;
        property ParentColor;
        property ParentFont;
        property ParentShowHint;
        property PopupMenu;
        property Properties;
        property ShowHint;
        property Style;
        property StyleDisabled;
        property StyleFocused;
        property StyleHot;
        property TabOrder;
        property TabStop;
        property Visible;
        property OnClick;
    {$IFDEF DELPHI5}
        property OnContextPopup;
    {$ENDIF}
        property OnDblClick;
        property OnDragDrop;
        property OnDragOver;
        property OnEditing;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseEnter;
        property OnMouseLeave;
        property OnMouseMove;
        property OnMouseUp;
        property OnStartDrag;
        property OnEndDock;
        property OnStartDock;
      end;procedure Register;implementation
    uses klmonthdate,publicunit;procedure Tdatebuttonedit.buttonclick(sender:TObject;AButtonIndex: Integer);
    var
      fklcalendar:Tfrmcalendar;
    begin
      if Properties.ReadOnly then exit;
      fklcalendar:=Tfrmcalendar.Create(nil);
      with fklcalendar do
      begin
        Parent:=self.Parent;
        Top:=self.ClientOrigin.y+self.Height;
        left:=self.ClientOrigin.x;
        case ffieldtype of
        ctext:
          begin
          fieldtype:='text';
          if length(trim(self.Text))=10 then
            monthcalendar1.Date:=strtodatetime(self.Text) else
            monthcalendar1.Date:=now;
          end;//    cdate:
    //    cdatetime:
        end;
        showmodal;
        if resultvalue<>'' then
        self.DataBinding.DataSource.DataSet.FieldByName(self.DataBinding.DataField).Value:=resultvalue;
      end;
      freeandnil(fklcalendar);
    end;constructor Tdatebuttonedit.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      properties.OnButtonClick:=buttonclick;
      style.BorderStyle:=ebs3d;
      Properties.EditMask:='!0000/00/00;1';
      OnKeyup:=klkeyup;
      properties.onValidate:=Validate;
    end;constructor Tdatebuttonedit.Create(AOwner: TComponent; AIsInplace: Boolean);
    begin
      inherited Create(AOwner);
      properties.OnButtonClick:=buttonclick;
      style.BorderStyle:=ebs3d;
      self.Properties.EditMask:='!0000/00/00;1';
      OnKeyup:=klkeyup;
      properties.onValidate:=Validate;
    end;
    procedure Tdatebuttonedit.klkeyup(Sender: TObject;
      var Key: Word; Shift: TShiftState);begin
      if databinding.DataSource.DataSet.state in [dsinsert,dsedit] then
      if (key=vk_delete) or (key=vk_back) then
      begin
        if (displayvalue='    -  -  ') or (strtimescount('_',displayvalue)=8)then
        begin
          databinding.DataSource.DataSet.FieldByName(databinding.DataField).Clear;
        end;
      end;end;procedure Tdatebuttonedit.validate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    begin  if (length(trim(displayvalue))<10) or (pos('_',displayvalue)>0) then
      begin    if ((pos('_',displayvalue)=0) and (length(trim(displayvalue))>4)) or
        ((pos('_',displayvalue)>0) and (strtimescount('_',displayvalue)<>8)) then
        begin
          showmessage('输入日期无效');
          abort;
        end;
      end;
    end;procedure Register;
    begin
      RegisterComponents('Data Controls', [Tdatebuttonedit]);
    end; {of Register}
    {of uniut}
    end.
      

  2.   

    嗯,检查了一下,是发现把size改成了10,修改回来就好了
    谢谢啊!不过现在又发现一个问题,如果手动输入日期,结果保存在数据库里的是yyyy-mm-,而不是yyyymmdd,怎么会把掩码-也保存到数据库呢,并且后面的日期也被挤掉了.
      

  3.   

    unit klDateEdit;interfaceuses
    {$IFDEF DELPHI6}
      Variants,
    {$ENDIF}
    //{$IFDEF VCL}
      Windows, Messages,
    //{$ENDIF}
      Classes, Controls, DB, DBCtrls, SysUtils,dialogs, forms,graphics,mask,stdctrls,
     cxButtonEdit, cxCalc,ComCtrls,CommCtrl,
      cxCalendar, cxCheckBox, cxClasses, cxContainer, cxCurrencyEdit, cxCustomData,
      cxDataUtils, cxDB, cxDropDownEdit, cxEdit, cxHyperLinkEdit, cxImage,
      cxImageComboBox, cxListBox, cxMaskEdit, cxMemo, cxMRUEdit, cxRadioGroup,
      cxSpinEdit, cxTextEdit, cxTimeEdit,cxdbedit;
    type
      Efieldtype=(ctext,cdate,cdatetime);  Tdatebuttonedit =class(TcxDBbuttonEdit)
      private  ffieldtype:Efieldtype;
      protected  public
        constructor Create(AOwner: TComponent); overload; override;
        constructor Create(AOwner: TComponent; AIsInplace: Boolean); reintroduce; overload;
        procedure buttonclick(sender:TObject;AButtonIndex:integer);
        procedure validate(Sender: TObject;var DisplayValue: Variant;
              var ErrorText: TCaption; var Error: Boolean);
        procedure klkeyup(Sender: TObject;var Key: Word; Shift: TShiftState);
      published
        property fieldtype:efieldtype read ffieldtype write ffieldtype default ctext;
        property Anchors;
        property AutoSize;
        property BeepOnEnter;
        property Constraints;
        property DataBinding;
        property DragCursor;
        property DragKind;
        property DragMode;
        property Enabled;
        property ImeMode;
        property ImeName;
        property ParentColor;
        property ParentFont;
        property ParentShowHint;
        property PopupMenu;
        property Properties;
        property ShowHint;
        property Style;
        property StyleDisabled;
        property StyleFocused;
        property StyleHot;
        property TabOrder;
        property TabStop;
        property Visible;
        property OnClick;
    {$IFDEF DELPHI5}
        property OnContextPopup;
    {$ENDIF}
        property OnDblClick;
        property OnDragDrop;
        property OnDragOver;
        property OnEditing;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseEnter;
        property OnMouseLeave;
        property OnMouseMove;
        property OnMouseUp;
        property OnStartDrag;
        property OnEndDock;
        property OnStartDock;
      end;procedure Register;implementation
    uses klmonthdate,publicunit;procedure Tdatebuttonedit.buttonclick(sender:TObject;AButtonIndex: Integer);
    var
      fklcalendar:Tfrmcalendar;
    begin
      if Properties.ReadOnly then exit;
      fklcalendar:=Tfrmcalendar.Create(nil);
      with fklcalendar do
      begin
        Parent:=self.Parent;
        Top:=self.ClientOrigin.y+self.Height;
        left:=self.ClientOrigin.x;
        case ffieldtype of
        ctext:
          begin
          fieldtype:= 'text ';
          if length(trim(self.Text))=10 then
            monthcalendar1.Date:=strtodatetime(self.Text) else
            monthcalendar1.Date:=now;
          end;//    cdate:
    //    cdatetime:
        end;
        showmodal;
        if resultvalue < > ' ' then
        self.DataBinding.DataSource.DataSet.FieldByName(self.DataBinding.DataField).Value:=resultvalue;
      end;
      freeandnil(fklcalendar);
    end;constructor Tdatebuttonedit.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      properties.OnButtonClick:=buttonclick;
      style.BorderStyle:=ebs3d;
      Properties.EditMask:= '!0000/00/00;1 ';
      OnKeyup:=klkeyup;
      properties.onValidate:=Validate;
    end;constructor Tdatebuttonedit.Create(AOwner: TComponent; AIsInplace: Boolean);
    begin
      inherited Create(AOwner);
      properties.OnButtonClick:=buttonclick;
      style.BorderStyle:=ebs3d;
      self.Properties.EditMask:= '!0000/00/00;1 ';
      OnKeyup:=klkeyup;
      properties.onValidate:=Validate;
    end;
    procedure Tdatebuttonedit.klkeyup(Sender: TObject;
      var Key: Word; Shift: TShiftState);begin
      if databinding.DataSource.DataSet.state in [dsinsert,dsedit] then
      if (key=vk_delete) or (key=vk_back) then
      begin
        if (displayvalue= '    -  -   ') or (strtimescount( '_ ',displayvalue)=8)then
        begin
          databinding.DataSource.DataSet.FieldByName(databinding.DataField).Clear;
        end;
      end;end;procedure Tdatebuttonedit.validate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    begin
      if (length(trim(displayvalue)) <10) or (pos( '_ ',displayvalue) >0) then
      begin
        if ((pos( '_ ',displayvalue)=0) and (length(trim(displayvalue)) >4)) or
        ((pos( '_ ',displayvalue) >0) and (strtimescount( '_ ',displayvalue) < >8)) then
        begin
          showmessage( '输入日期无效 ');
          abort;
        end;
      end;
      if (length(trim(displayvalue))=10) and (pos('_',displayvalue)=0) then
      try
    databinding.DataSource.DataSet.FieldByName(databinding.DataField).asstring:=formatdatetime('yyyymmdd',strtodatetime(displayvalue));
      except
        showmessage('输入日期无效');
      end;end;procedure Register;
    begin
      RegisterComponents( 'Data Controls ', [Tdatebuttonedit]);
    end; {of Register}
    {of uniut}
    end.
    加上一个判断就可以解决那个问题了,并且还能判断输入的日期是否有效.谢谢.这个控件就可以用了.