如何知道 EditMask 的 TEXT已滿 |
答題得分者是:Justmade
|
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
請問各位兩個問題! 1.有一個TMaskEdit 的 EditMask 為 '>AAAA:999;1' 與 '>AAAA.A999;1' 與
'>999:AA.9;1' 三種, 分別有7,8,6三個長度, 在輸入時使用者可以自由切換三種MASK, 如果我想要判斷使用者是否在
TMaskEdit中已經輸入滿了, 然後就跳離去做其他事, 有沒有辦法直接用
MaskEdit內提供的function來解決, 我的意思是說如果我用一個陣列定義三
種格式的長度, 然後以 length(MaskEdit1.Text)=Masklen[x] 可以做到, 如果
不用任何變數的話呢>? 2.在TMaskEdit 輸入錯誤的格式時, 會觸發 TCustomEdit.ValidateError 的行
為, 但ValidateError 是 protected 宣告, 程式內無法使用, 是否有辦法可以
在程式內得知目前的MaskEdit 是否合法, 也就是說, 當系統進行
TCustomEdit.ValidateEdit後會釋放出一個True,False值來決定是否觸發
ValidateError, 那我要如何才能在程式中取得這個結果呢?
|
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
PD 大哥還在玩 MaskEdit 丫?
引言: 請問各位兩個問題! 1.有一個TMaskEdit 的 EditMask 為 '>AAAA:999;1' 與 '>AAAA.A999;1' 與 '>999:AA.9;1' 三種, 分別有7,8,6三個長度, 在輸入時使用者可以自由切換三種MASK, 如果我想要判斷使用者是否在 TMaskEdit中已經輸入滿了, 然後就跳離去做其他事, 有沒有辦法直接用 MaskEdit內提供的function來解決, 我的意思是說如果我用一個陣列定義三 種格式的長度, 然後以 length(MaskEdit1.Text)=Masklen[x] 可以做到, 如果 不用任何變數的話呢>?MaskEdit1.MaxLength 是隨著你的 EditMask 改變的,所以你不用定義陣列來記著每一個 Mask 的 Length。不過無論陣列及使用 MaxLength 都無法判斷是否輸入滿了,因為 length(MaskEdit1.Text 永遠都是滿的(空的位元自動以空白代替。 反之,MaskEdit1.SelStart 卻會由應你現在輸入的位置而改變,所以,當 MaskEdit1.SelStart = MaskEdit1.MaxLength 時,就是使用者完成輸入最後一字完之時。 引言: 2.在TMaskEdit 輸入錯誤的格式時, 會觸發 TCustomEdit.ValidateError 的行 為, 但ValidateError 是 protected 宣告, 程式內無法使用, 是否有辦法可以 在程式內得知目前的MaskEdit 是否合法, 也就是說, 當系統進行 TCustomEdit.ValidateEdit後會釋放出一個True,False值來決定是否觸發 ValidateError, 那我要如何才能在程式中取得這個結果呢?可以用 ValidateEdit try except 耶。 以下程序會在 MaskEdit1 符合 Mask 的要求及輸入完最後一個位元後跳到下一個 Control。 procedure TForm1.MaskEdit1Change(Sender: TObject); begin try MaskEdit1.ValidateEdit; if MaskEdit1.SelStart = MaskEdit1.MaxLength then Form1.ActiveControl := Form1.FindNextControl(Form1.ActiveControl,true,true,true); except end; end; |
channel
尊榮會員 發表:67 回覆:707 積分:854 註冊:2002-05-02 發送簡訊給我 |
|
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
|
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
沒有辦法, 這個案子要用到 maskedit, 上頭要求我要攔截下來所有的可能性的錯誤, 因為這關係到百萬人的資料, 我已經耗盡心力, 花在 maskedit 上有六天
了, 仍然無法解決! 回題, 我按你的做法, 在 edit.onchange上寫MaskEdit1.ValidateEdit;
會有兩個問題 案例 maskedit1.editmask='>AAAA-9999;0' 1.每當我輸入一個Char, 就會觸發 ValidateError 訊息, 這個還好解決
我設一個變數keyno, 改為
if keyno=#13 then try MaskEdit1.ValidateEdit; ....就可以避過 2.這個問題就麻煩了, 例如應該要輸入 DATA-0001 才是對 如果用if MaskEdit1.SelStart = MaskEdit1.MaxLength 會有問題 例如, 使用者輸入為 DATA-00 1, 當然 Length() 方式是=9無法偵測, 而if MaskEdit1.SelStart 則有很大變數 如果cursor在1後面, length也是9, 無法偵測, 如果在其他位置則會執行判斷 同時也會觸發 validateerror, 沒有問題 會為會有這樣的輸入發生了, 原因是 使用者打了 DATA-00, 然後不小心用游標鍵右移1格再打1, 而這個時候, ONCHANGE 中會觸發 Validateedit而發現錯誤 但現在問題來了 當使用者看到系統的ValidateError所發出的錯誤, 他再用游標鍵移到 空格, 填入一個 0, 使其資料補足了 DATA-0001, 但注意哦! 這時游標是停在 1的位置, 也就是說以if MaskEdit1.SelStart來判斷的話, length=8, 結果 if MaskEdit1.SelStart <> maxlength, 但之前我用的 length()=9, 最後 造成錯誤(因為if MaskEdit1.SelStart判斷不滿, 則不執行), 那這可怎麼解決呢? 我剛剛試了一個辦法, nLeng:= Length(trim(copy(eChass.Text,1,eChass.SelStart)) trim(copy(eChass.Text,eChass.SelStart 1,eChass.MaxLength))); if (nLeng=eChass.MaxLength) then ...這樣就可以解決因為空白所造成的問題, 當然這是因為我的 mask必須不為空 因為 AAAA-0000 是每一格都要填入, 如果是 aaaa-9999 那就不適用了 不知各位還有沒有更方便的寫法? 發表人 - P.D. 於 2003/03/25 14:40:15 |
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我上面的程序是不會觸發 錯誤 Message Box 的,因為用 Try Except 攔截了錯誤。當然,你用 Delphi 來 Run 時是會出現錯誤,但這只是在 Delphi IDE 中而不是使用者介面中,當你獨立的來執行程式時是不會出現 Exception 的,不用加 if key = #13。 唯一我想到的問題,就是如你所說當使用者空了一格而輸到最後一個字完後(仍不會出現 Exception 及 不會跳到下一 Control),回到空格補入資料,那時資料雖然正確但由於不是在最後一個位元所以不會自動跳到下一 Control。不過使用者仍可以用 Tab 或 Mouse 來跳到下一個 Control 的。
|
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
還有一個問題,你的 Mask 9999 那部份好像是接受空白的,所以即使留空了還是可通過 ValidateEdit。若空白是不合法的,可改成 :
try MaskEdit1.ValidateEdit; if (MaskEdit1.SelStart = MaskEdit1.MaxLength) and (pos(' ', MaskEdit1.Text) = 0) then Form1.ActiveControl := Form1.FindNextControl(Form1.ActiveControl,true,true,true); except end; |
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
其實我也想過當滿足了 ValidateEdit 便跳 Control (只要刪除了 if selstart = maxlength 即可),那樣即使使用者回到之前空了的位置一補入就會跳 Control 了,但問題是若使用者輸錯了要改時就會很煩。 比如說,資料應是 DATA-1234 但使用者輸入了 DATA-5678。之後他發覺了,按回到那裡修改,當他改5為1時,資料變為符合 DATA-1678 符合 ValidateEdit 便會自動跳 Control,要分四次修改。 所以我還是覺得當使用者自然的輸到最後一位又符合 ValidateEdit 的才自動跳行,否則情願等使用者自行 Tab 好了。
|
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
引言: 我上面的程序是不會觸發 錯誤 Message Box 的,因為用 Try Except 攔截了錯誤。當然,你用 Delphi 來 Run 時是會出現錯誤,但這只是在 Delphi IDE 中而不是使用者介面中,當你獨立的來執行程式時是不會出現 Exception 的,不用加 if key = #13。 唯一我想到的問題,就是如你所說當使用者空了一格而輸到最後一個字完後(仍不會出現 Exception 及 不會跳到下一 Control),回到空格補入資料,那時資料雖然正確但由於不是在最後一個位元所以不會自動跳到下一 Control。不過使用者仍可以用 Tab 或 Mouse 來跳到下一個 Control 的。我報告一下, 我這邊的實測 1. maskedit1.onchange try maskedit1.validateedit; except end; 真的會觸發 maskedit1.validateerror 因為我查過 mask.pas 中, validateedit的function, if not Validate(Str, Pos) then begin if not (csDesigning in ComponentState) then begin Include(FMaskState, msReEnter); SetFocus; end; SetCursor(Pos); ValidateError;這裡呼叫了 end; 所以雖然用 except來攔截, 但在執行if not Validate(Str, Pos) then 時, 並未觸發exception 的原則, 所以會出現 msssagebox, 我實測的確也出現, 另外因為我不希望出現的是英文訊息, (使用者level很低, 看不懂), 所以 我自己弄了一個 TxMaskEdit元件, 繼承TMaskEdit, 所以其實之前使用都是 以TxMaskEdit在做, 如下 unit xMaskEdit; interface uses Dialogs, Classes, Mask; {TxMaskEdit} type TxMaskEdit = class(TMaskEdit) protected procedure ValidateError; override; public maskErrorShowed: boolean; constructor Create(AOwner: TComponent); override; procedure ResetKey; published end; procedure TxMaskEdit.ValidateError; begin if not maskErrorShowed then begin MessageDlg(pChar('輸入的資料不齊全或不符合格式!' #13 '請補足資料 或 按[Esc]鍵 取消'),mtError, [mbCancel],0); end; // 這個變數原先目的是希望只會秀一次錯誤, 但目前似乎沒有用 maskErrorShowed:= True; end; procedure TxMaskEdit.ResetKey; begin maskErrorShowed:= False; end; procedure Register; begin RegisterComponents('Additional', [TxMaskEdit]); end; end. 我改寫原來的ValidateError procedure, 但問題來了, 我現在還查不到原因 是發生ValidateError時, 這個MessageBox會顯示兩次, 一次是 onchange時, validedateEdit所觸發的, 另一次???, 問題可能出在我的 onKeydown, 或 onKeypress, 但我現在無法找到真正原因 以上是第一點至於第二點, mask AAAA-0000, 0表該位置一定要輸入, 所以可以使用我上面 所提到的方法, 當然 9999是允許空白, 所以上例Length判斷就不適用了, 不 過本例是一定要用 AAAA-0000, 所以 SORRY, 上面是我"口"誤! 綜合以上結論, 透過Justmade 所提供的建議再加以變化, 目前可以攔截到所有 的錯誤, 唯一的問題是出現兩次的error message 我把這部份的程式貼出來, 大家參考看看 以下都是在 eData1 下的程式, eData1: TxMaskEdit; 其中有兩個private變數 nowKeyDown: Char, nowKeyLeng: integer 兩個 U_Var.Maskxxx[]陣列, 是由ini讀進來的 editMask 格式 procedure TForm_Cust.eData1Change(Sender: TObject); begin if nowKeyDown=#13 then try eData1.ValidateEdit; except end; end; procedure TForm_Cust.eData1KeyPress(Sender: TObject; var Key: Char); begin nowKeyDown:= Key; nowKeyLeng:= eData1.SelStart; end; procedure TForm_Cust.eData1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var nowkey: integer; nLeng: integer; begin nowkey:= -1; // Press F1~F10 可以線上變更 eData1.EditMask格式 if Key=VK_F1 then nowkey:= 0 else if Key=VK_F2 then nowkey:= 1 else if Key=VK_F3 then nowkey:= 2 else if Key=VK_F4 then nowkey:= 3 else if Key=VK_F5 then nowkey:= 4 else if Key=VK_F6 then nowkey:= 5 else if Key=VK_F7 then nowkey:= 6 else if Key=VK_F8 then nowkey:= 7 else if Key=VK_F9 then nowkey:= 8 else if Key=VK_F10 then nowkey:= 9 else if Key=VK_ESCAPE then eQChass.ResetKey else if key=VK_RETURN then begin nLeng:= Length(trim(copyeData1.Text,1,eData1.SelStart)) trim(copy(eData1.Text,eData1.SelStart 1,eData1.MaxLength))); if (nLeng<>eData1.MaxLength) then eData1.ResetKey; 因為我有使用DosMove, 所以, 當上述長度如果相等表示輸入成功, 所以會直接到 onExit Event上去做我要做的事, 我就不另寫出onexit部份了 end; if (nowkey>=0) and (nowkey<=9) then begin U_Var.MaskPos:= nowkey; eData1.EditMask:= U_Var.MaskStr[U_Var.MaskPos]; eData1.Update; eData1.SetFocus; end; end;發表人 - P.D. 於 2003/03/25 16:13:00 |
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我做時真的是不會顯示 Error Message 的耶... 1. 做一個新 Project
2. 放入一個 EditMask 並輸入 Mask
3. 在 onChange event 加入
try MaskEdit1.ValidateEdit; if (MaskEdit1.SelStart = MaskEdit1.MaxLength) and (pos(' ', MaskEdit1.Text) = 0) then Form1.ActiveControl := Form1.FindNextControl(Form1.ActiveControl,true,true,true); except end;4. 在 Delphi 執行時會引發 ValidateError 而引發 Exception, 但由於 try except 攔截了,所以 exception 只出現在 Delphi IDE 而沒出現在使用者介面 5. 獨立執行該 EXE, 便不會出現任何 Error, 而當 Text 合符條件而 Cursor 又在最後時會自動跳到下一 Control 我實作過兩次都是這樣耶... 現在在看你的程式段。 |
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
看到原因了
因為原來的 ValidateError 是用 Exception 的,所以我的 Try Except 就能攔截這個exception 使其不顯示錯誤訊息,但是你 subclass 了的 ValidateError 不是用 Exception 的,而是直接顯示錯誤信息,所以 Try Except 就欄截不了那個錯誤訊息了,而且因為沒錯誤,所以便再執行下一句的跳到下一元件,又再一次引發 ValidateEdit 而引發ValidateError而再出現你自訂的錯誤信息。 Rasie Exception 雖然有時很煩,但真的有他的妙用的,你取消了 Exception 而改為直接跳出 Error,所有的 Try Except 及 onApplicationError 都不能再因應情況而處理這個問題了。
|
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
感謝 Justmade 指教, 那有沒有辦法可以解決, 這部份實在不是我的專長, 謝謝了!
不要說我懶, 實在沒有時間! 剛才我改寫了 xMaskEdit 內容
{TxMaskEdit} type EMaskError = class(Exception); type TxMaskEdit = class(TMaskEdit) protected procedure ValidateError; override; public constructor Create(AOwner: TComponent); override; procedure ResetKey; published end; procedure Register; implementation constructor TxMaskEdit.Create(AOwner: TComponent); begin inherited Create(AOwner); end; procedure TxMaskEdit.ValidateError; begin raise EMaskError.Create('輸入的資料不齊全或不符合格式!' #13 '請補足資料 或 按[Esc]鍵 取消'); end;好像也沒有用, 還是攔不到! 發表人 - P.D. 於 2003/03/25 18:22:22 |
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
本案已全部完成 我報告最後修正結論 newkeyDown的變數全部取消,
TxMaskEdit 改寫
procedure TForm_Cust.eData1Change(Sender: TObject); begin try eData1.ValidateEdit; except end; end; procedure TForm_Cust.eData1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var nowkey: integer; nLeng: integer; begin nowkey:= -1; if Key=VK_F1 then nowkey:= 0 else if Key=VK_F2 then nowkey:= 1 else if Key=VK_F3 then nowkey:= 2 else if Key=VK_F4 then nowkey:= 3 else if Key=VK_F5 then nowkey:= 4 else if Key=VK_F6 then nowkey:= 5 else if Key=VK_F7 then nowkey:= 6 else if Key=VK_F8 then nowkey:= 7 else if Key=VK_F9 then nowkey:= 8 else if Key=VK_F10 then nowkey:= 9 else if key=VK_RETURN then begin nLeng:= Length(trim(copy(eData1.Text,1,eData1.SelStart)) trim(copy(eData1.Text,eData1.SelStart 1,eData1.MaxLength))); if (nLeng=eData1.MaxLength) then begin ...... end; end; if (nowkey>=0) and (nowkey<=9) then begin U_Var.MaskPos:= nowkey; eData1.EditMask:= U_Var.MaskStr[U_Var.MaskPos]; eData1.Update; eData1.SetFocus; end; end; procedure TForm_Cust.eData1KeyPress(Sender: TObject; var Key: Char); begin nowKeyLeng:= eData1.SelStart; end; // 以下是 xMaskEdit 部份 unit xMaskEdit; interface uses Dialogs, Classes, Mask, SysUtils; {TxMaskEdit} type EMaskError = class(Exception); type TxMaskEdit = class(TMaskEdit) private errMsg: string; protected procedure ValidateError; override; public constructor Create(AOwner: TComponent); override; published end; procedure Register; implementation constructor TxMaskEdit.Create(AOwner: TComponent); begin inherited Create(AOwner); errMsg:= '輸入的資料不齊全或不符合格式!' #13 '請補足資料 或 按[Esc]鍵 取消' end; procedure TxMaskEdit.ValidateError; begin raise EMaskError.Create(errMsg); end; procedure Register; begin RegisterComponents('Additional', [TxMaskEdit]); end; end.最後會秀出兩次errormessage的問題, 因為我使用DosMove 元件 其中一項properity EndnoBeep 如果為 False 則會造成兩次訊息, 改為True 就不會了, 感謝Justmade 兄鼎力支持! |
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |