When using Delphi for database design, it is inevitable to involve the input of date fields. However, compared with Microsoft's access 97 Chinese version, the display and input methods of date fields provided by Delphi itself are not suitable for Chinese people's habits. Therefore, many solutions have been proposed for the processing of date fields, but the processing results are not uniform in display and input. For example, the format of "yyyy year mm month dd day" can be realized when displaying, but it still needs to be input when inputting. Use "yyyy-mm-dd" according to foreign customs Input in the form; it is always troublesome to use TdateTimePicker for selection input; some methods also need to modify some setting properties of the system, so the system properties need to be adjusted when publishing software; using third-party controls also requires The control is packaged and released. Moreover, the commonly used date formats such as "1999" and "November 1999" are not processed accordingly. Here, based on my own practice, I use the combination of TField's OnGetText and OnSetText events in order to achieve the unification of display and input of date fields, and can handle our common dates such as "1999" and "November 1999" The display and input of forms are all implemented using the events provided by Delphi, and there is no need to modify any system settings. After corresponding expansion, it can also be used for time display and input, such as "hh point mm minute" etc. At the same time, since the events of TField are directly controlled, whether using TDBGrid or TDBEdit, they can be processed in a unified manner without having to consider them separately. A similar approach can also be applied to date input in non-database applications.
1 Basic idea
Use the EditMask property of TField to serve as both a display and input mask. The display of the date field is processed in the OnGetText event of TField, and the validity judgment of the input value is processed in the OnSetText event. To reuse code, put the procedures and functions called by the OnGetText and OnSetText event handlers into a separate unit.
2 Specific implementation code
{Display and judgment unit}
unit DBDateEditMaskTrans;
interface
uses
Windows, SysUtils, Controls, Forms, Db;
{Date field display process, called in the OnGetText event}
PRocedure DateFieldGetText(Sender: TField; var Text: String);
{Date field input judgment function, called in the OnSetText event}
function DateFieldSetText(Sender: TField; const Text: String):Boolean;
implementation
procedure DateFieldGetText(Sender: TField; var Text: String);
var
dDate:TDate;
wYear,wMonth,wDay:Word;
aryTestYMD:Array [1..2] of Char;{Temporary array for test input mask}
iYMD:Integer;
begin
dDate:=Sender.AsDateTime;
DecodeDate(dDate,wYear,wMonth,wDay);
{Test the format contained in the input mask.}
aryTestYMD:='year';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=1;
aryTestYMD:='month';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=2;
aryTestYMD:='Day';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=3;
case iYMD of
1:{The input mask is in the format of "yyyy year".}
Text:=IntToStr(wYear)+'year';
2: {The input mask is in the format of "yyyy year mm month".}
Text:=IntToStr(wYear)+'year'+IntToStr(wMonth)+'month';
3: {The input mask is in the format of "yyyy year mm month dd day".}
Text:=IntToStr(wYear)+'year'+IntToStr(wMonth)+'month' +IntToStr(wDay)+'day';
else {Default is: "yyyy year mm month dd day" format.}
Text:=IntToStr(wYear)+'year'+IntToStr(wMonth)+'month' +IntToStr(wDay)+'day';
end;
end;
function DateFieldSetText(Sender: TField; const Text: String):Boolean;
var
dDate:TDate;
sYear,sMonth,sDay:String;
aryTestYMD:Array [1..2] of Char;
iYMD:Integer;
begin
{Get the date entered by the user}
sYear:=Copy(Text,1,4);
sMonth:=Copy(Text,7,2);
SDay:=Copy(Text,11,2);
{Test the format contained in the input mask.}
aryTestYMD:='year';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=1;
aryTestYMD:='month';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=2;
aryTestYMD:='Day';
if StrScan(PChar(Sender.EditMask),
aryTestYMD[1])< >nil then
iYMD:=3;
{Use Try...Except to convert input date}
try
begin
case iYMD of
1: {The input mask is in the format of "yyyy year".}
begin
dDate:=StrToDate(sYear+'-01-01') ;{The default date format of Chinese Windows is: yyyy-mm-dd. The same below}
Sender.AsDateTime:=dDate;
end;
2: {The input mask is in the format of "yyyy year mm month".}
begin
dDate:=StrToDate(sYear+'-'+sMonth+'-01');
Sender.AsDateTime:=dDate;
end;
3: {The input mask is in the format of "yyyy year mm month dd day".}
begin
dDate:=StrToDate(sYear+'-'+sMonth+'-'+sDay);
Sender.AsDateTime:=dDate;
end;
else {Default is: "yyyy year mm month dd day" format.}
begin
dDate:=StrToDate(sYear+'-'+sMonth+'-'+sDay);
Sender.AsDateTime:=dDate;
end;
end;
DateFieldSetText:=True;
end;
except
{Date conversion error}
begin
application.MessageBox(PChar(Text+'Not a valid date!'), 'Error',mb_Ok+mb_IconError);
DateFieldSetText:=False;
end;
end;
end;
end.
{main window unit}
unit Main;
interface
uses
…{omit other content}
procedure Table1BirthdayGetText(Sender: TField; var Text: String;DisplayText: Boolean);
procedure Table1BirthdaySetText(Sender: TField; const Text: String);
private
{Private declarations}
public
{Public declarations}
……{slightly}
implementation
{Include custom units}
uses DBDateEditMaskTrans;
{$R *.DFM}
...{Other processes omitted}
procedure TForm1.FormActivate(Sender: TObject);
{Set the input mask of a date field, which can be placed in the TField field definition. }
begin
Table1.FieldByName('Birthday').EditMask:= '99-99-99;1;_';
end;
procedure TForm1.Table1BirthdayGetText(Sender: TField; var Text: String;DisplayText: Boolean);
begin
DateFieldGetText(Sender,Text);
end;
procedure TForm1.Table1BirthdaySetText(Sender: TField; const Text: String);
begin
if DateFieldSetText(Sender,Text)=False then
Abort; {Conversion failed, date is illegal}
end;
end.