Delphi 原生日期顯示/輸入格式 (如 yyyy-mm-dd) 不符中文習慣。期望目標:
1999年11月25日、1999年11月、1999年TDBGrid、TDBEdit 等所有資料感知控件OnGetText:資料 → 顯示字串 (格式化輸出)OnSetText:輸入字串 → 資料 (解析驗證)EditMask:同時作為顯示/輸入遮罩,編碼格式資訊 (如含「年」、「月」、「日」)
unit DBDateEditMaskTrans;
interface
uses Windows, SysUtils, Controls, Forms, Db;
procedure DateFieldGetText(Sender: TField; var Text: String);
function DateFieldSetText(Sender: TField; const Text: String): Boolean;
implementation
procedure DateFieldGetText(Sender: TField; var Text: String);
var
D: TDateTime;
Y, M, Dd: Word;
MaskHasYear, MaskHasMonth, MaskHasDay: Boolean;
begin
D := Sender.AsDateTime;
DecodeDate(D, Y, M, Dd);
// 分析 EditMask 判斷格式
MaskHasYear := Pos('年', Sender.EditMask) > 0;
MaskHasMonth := Pos('月', Sender.EditMask) > 0;
MaskHasDay := Pos('日', Sender.EditMask) > 0;
if MaskHasYear and MaskHasMonth and MaskHasDay then
Text := Format('%d年%d月%d日', [Y, M, Dd])
else if MaskHasYear and MaskHasMonth then
Text := Format('%d年%d月', [Y, M])
else if MaskHasYear then
Text := Format('%d年', [Y])
else
Text := Format('%d年%d月%d日', [Y, M, Dd]); // 預設完整格式
end;
function DateFieldSetText(Sender: TField; const Text: String): Boolean;
var
Y, M, D: String;
DT: TDateTime;
MaskHasYear, MaskHasMonth, MaskHasDay: Boolean;
begin
Result := False;
MaskHasYear := Pos('年', Sender.EditMask) > 0;
MaskHasMonth := Pos('月', Sender.EditMask) > 0;
MaskHasDay := Pos('日', Sender.EditMask) > 0;
// 簡易解析:假設輸入格式固定對應 EditMask
try
Y := Copy(Text, 1, 4);
if MaskHasMonth then M := Copy(Text, Pos('年', Text)+1, 2) else M := '01';
if MaskHasDay then D := Copy(Text, Pos('月', Text)+1, 2) else D := '01';
// 組合為系統可識別格式 (yyyy-mm-dd)
DT := StrToDate(Y + '-' + M + '-' + D);
Sender.AsDateTime := DT;
Result := True;
except
Application.MessageBox(PChar(Text + ' 不是有效的日期!'), '錯誤', MB_OK + MB_ICONERROR);
Result := False;
end;
end;
end.
uses DBDateEditMaskTrans;
procedure TForm1.FormActivate(Sender: TObject);
begin
// 設定 EditMask:9=數字、\=逸出字元、;1;_ = 存儲字面字元、底線佔位
Table1.FieldByName('Birthday').EditMask := '9999\年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 not DateFieldSetText(Sender, Text) then
Abort; // 取消輸入
end;
'9999\年99\月99\日;1;_'
|||| || || || | |
|||| || || || | +-- 佔位符
|||| || || || +---- 存儲字面字元 (1=是)
|||| || || |+------- 分隔符
|||| || || +-------- 逸出 '日'
|||| || |+----------- 兩位數月份
|||| || +------------ 逸出 '月'
|||| |+--------------- 兩位數日期
|||| +---------------- 逸出 '年'
++++------------------- 四位數年份
hh點mm分、hh點mm分ss秒TEdit 的 OnExit/OnKeyPress 事件利用 TField.OnGetText/OnSetText 搭配 EditMask 編碼格式資訊,集中在通用單元實作解析/格式化邏輯,可達到「顯示輸入統一、中文化格式、零系統相依、全控件通用」的最佳效果。此模式同樣適用於時間、貨幣、自訂格式等場景。