【BCB】【問題】有沒有 VCL 元件的 Edit 可以限制只輸入數字? |
尚未結案
|
mzhuang
一般會員 發表:6 回覆:11 積分:3 註冊:2002-08-12 發送簡訊給我 |
|
mzhuang
一般會員 發表:6 回覆:11 積分:3 註冊:2002-08-12 發送簡訊給我 |
|
海星
高階會員 發表:41 回覆:217 積分:106 註冊:2003-01-09 發送簡訊給我 |
|
mzhuang
一般會員 發表:6 回覆:11 積分:3 註冊:2002-08-12 發送簡訊給我 |
|
RedSnow
版主 發表:79 回覆:1322 積分:845 註冊:2003-12-15 發送簡訊給我 |
mzhuang 您好: 您可以直接使用 TEdit 物件,並配合一些檢查程序來完成您要的動作。 我依據您提供的數據做了一些測試,雖然未做最佳化處理,但是大體上是可行的,我將過程簡單描述如下,您可以依據實際的需要來擴充比對與檢查的項目: 設定一個全域變數,作為輸入不合法字元時,復原為原先內容之用。
AnsiString oldText; 將著寫一個自定函數,作為輸入內容的檢查,以便過濾掉不合法字元。
bool __fastcall TForm1::isNumber(const AnsiString nStr) { AnsiString chkStr="0123456789.-"; bool rc=true; for(int i=1; i<=nStr.Length(); i++){ if(chkStr.Pos(nStr.SubString(i,1)) == 0){ rc=false; break; } } return rc; }接著再寫一個檢查輸入內容範圍的程序如下,然後將各個 TEdit 的 OnChange 事件全部指向這個程序: void __fastcall TForm1::EditChange(TObject *Sender) { int err=0; TEdit *ed = (TEdit*)Sender; AnsiString txt = ed->Text; int tag = ed->Tag; int len=txt.Length(); if(len >= 1 && txt != "-" && txt != "."){ if(isNumber(txt)){ double f=double(StrToFloat(txt)); int n = int(f); switch (tag){ case 1: if(n < -1319760 || n > 2451287) err=2; break; case 2: if(f < -0.0000001278 || f > 9.999999876) err=2; break; case 3: if(f < 0.0001 || f > 100) err=2; break; default: break; } }else{ err = 1; } } if(err > 0){ AnsiString msg; if(err == 1){ msg = "輸入的字元不合法!"; }else{ msg = "數值超過範圍!"; } Beep(); ShowMessage(msg); ed->Text = oldText; // 恢復前一次輸入的內容 // 以下動作是將游標移至輸入框最右方的位置 ed->Perform(WM_KEYDOWN,VK_END,0); ed->Perform(WM_KEYUP,VK_END,0); }else{ oldText = ed->Text; // 將輸入的內容記錄下來備用 } }要使用時,依據需要將各個 TEdit 物件的 Tag 屬性設定為相對的數字,例如: Tag = 1 代表檢查範圍 -1319760~2451287 Tag = 2 代表檢查範圍 -0.0000001278~9.999999876 Tag = 3 代表檢查範圍 0.0001~100 ..... 這樣就可以了,但是上述的程序尚有一個小缺點,那就是在第三種 (Tag = 3) 狀態時,一輸入 "0" 就會觸發 "數值超過範圍!" 的提示訊息,因為 0 < 0.0001,所以您必須針對這種狀況再作進一步的檢查與處理動作,或是將檢查的動作放在另一個程序,例如按下某個 Button 後,才做輸入範圍的檢查,例如: 1. 將各個 TEdit 的 ReadOnly 屬性設為 true,不允許用戶直接修改內容。 2. 在各個 TEdit (或在旁邊另設一個 Button 物件) 的 OnClick 事件中觸發一個輸入資料的對話框 (自製的輸入視窗),對話框內設置一個 TEdit 及兩個 TButton 物件 (OK & Cancel),在 OK 按鈕的 onClick 事件中加上檢查的動作,若是內容沒問題就將內容傳回給呼叫對話框的 TEdit 物件,否則就顯示錯誤訊息要求更正內容,如下圖: 您參考看看吧。 |
mzhuang
一般會員 發表:6 回覆:11 積分:3 註冊:2002-08-12 發送簡訊給我 |
|
RedSnow
版主 發表:79 回覆:1322 積分:845 註冊:2003-12-15 發送簡訊給我 |
mzhuang 您好: 不太清楚您所謂 "會讓程式碼超長" 的認知是怎麼來的?我在範例程序前很清楚的標示著 "將各個 TEdit 的 OnChange 事件全部指向這個程序" 的說明,換言之;六百多個 TEdit 物件僅需一段 "副程式" 而已。 如果您的比對範圍不只三個,擔心在副程序內設定比對條件會太多的話,那麼您可以另設兩個全域變數來設定比對的範圍,然後再將副程序內的比對步驟簡化成一個,如果這樣子您仍嫌麻煩的話,那也可以考慮使用繼承的方式,將 TEdit 物件重新包裝一下,新增兩個屬性欄位分別作為輸入範圍最大值與最小值的設定之用,這樣就可以在比對的副程式之內直接取用 TEdit 的增設屬性來做比對,這樣子應該可以達到您所說的 "每個元件自己設條件" 的目標了。
|
mzhuang
一般會員 發表:6 回覆:11 積分:3 註冊:2002-08-12 發送簡訊給我 |
RedSnow 您好! 不知道是不是我有誤解您的意思了 ?
你說的 "將各個 TEdit 的 OnChange 事件全部指向這個程序"
是否代表可以用類似 dynamic_cast
|
RedSnow
版主 發表:79 回覆:1322 積分:845 註冊:2003-12-15 發送簡訊給我 |
mzhuang 您好: 您說的沒錯,只是因為已確認呼叫該程序的物件全部都是 TEdit,因此我在範例中直接寫成 TEdit *ed = (TEdit*)Sender; 這種方式。 而我所謂的 "將各個 TEdit 的 OnChange 事件全部指向這個程序",意思就是您僅需要先設定一個 TEdit 物件的 OnChange 事件,例如 Edit1Change(),然後其它的 TEdit 物件如 Edit2, Edit3....等,就直接在事件表 (Object Inspector) 的地方直接選擇 OnChange 事件為 Edit1Change 即可,無需逐一設定 Edit2Change, Edit3Change.... 等事件,也就是所有 TEdit 物件直接設定成 "共用" 同一個現存的事件處理程序。 我現在正好有空,因此也做了一些測試,我寫了一個繼承自 TEdit 的 TEditEx 元件,我在這個元件裡增加了三個屬性,分別是 CheckRange、MaxValue 與 MinValue,ChangeRange 是供程式判斷之用,看是否要比對輸入數值的大小而已,另外的 MaxValue 與 MinValue 這兩個屬性我使用了 double 的型態,分別是設定要比對數值的 "最大值" 與 "最小值",同時為了方便,我也作了將輸入的內容作了 "向右靠齊" 的設定。 我希望這個元件能符合您大部分的需求,因為是急就章的關係,所以並未做最佳化處裡,甚至還存在著一些缺點,但是您可以將它加強或修改成您所需要的功能,我也寫了一支使用的範例程式,程式裡邊是透過您說的 OnExit 事件來做檢查的,程式是用 BCB4 寫的,相信您可以順利的使用,如果有任何問題的話,我們再來討論一下好了。 自定元件之 EditEx.h
//--------------------------------------------------------------------------- #ifndef EditExH #define EditExH //--------------------------------------------------------------------------- #include自定元件之 EditEx.cpp //--------------------------------------------------------------------------- #include將上邊的程式編譯成元件並安裝好之後,可以自在 Sample 單元裡找到與 Edit 元件相同的圖示,而名稱為 EditEx 的元件。 測試這個元件時,請先建立一個測試用的專案,專案裡什麼都無須設定,僅開啟一個空的 Form 即可,然後按下列步驟做相關設定: 1. 在 Form 上邊設置三個 TEditEx 元件,並且將三個元件的 CheckRange 屬性都設為 true,接著將三個元件的 MaxValue 與 MinValue 屬性欄位個別設定成要檢查的 "最大" 與 "最小" 值,例如: EditEx1: MaxValue = 2451287 EditEx1: MinValue = -1319760 EditEx2: MaxValue = 9.999999876 EditEx2: MinValue = -0.0000001278 (輸入後會自動變成 -1.278E-7) EditEx3: MaxValue = 100 EditEx3: MinValue = 0.0001 2. 在 Unit1.h 檔案裡作下列設定: private: // User declarations AnsiString oldText; bool __fastcall isNumber(const AnsiString nChar);3. 在 Unit1.cpp 檔案內加上下列的敘述: bool __fastcall TForm1::isNumber(const AnsiString nStr) { AnsiString chkStr="0123456789.-"; bool rc=true; for(int i=1; i<=nStr.Length(); i ){ if(chkStr.Pos(nStr.SubString(i,1)) == 0){ rc=false; break; } } return rc; }4. 點選 Form 上的 EditEx1 元件,然後設定 OnChange 事件如下: void __fastcall TForm1::EditEx1Change(TObject *Sender) { TEditEx *ed = (TEditEx*)Sender; AnsiString txt = ed->Text; int tag = ed->Tag; int len=txt.Length(); if(len >= 1 && txt != "-" && txt != "."){ if(!isNumber(txt)){ Beep(); ShowMessage("輸入的字元不合法!"); ed->Text = oldText; ed->Perform(WM_KEYDOWN,VK_END,0); ed->Perform(WM_KEYUP,VK_END,0); }else{ oldText = ed->Text; } } }5. 點選 Form 上的 EditEx1 元件,然後設定 OnExit 事件如下: void __fastcall TForm1::EditEx1Exit(TObject *Sender) { TEditEx *ed = (TEditEx*)Sender; if(ed->CheckRange){ int err = 0; AnsiString txt = ed->Text; int tag = ed->Tag; int len=txt.Length(); if(len >= 1 && txt != "-" && txt != "."){ if(isNumber(txt)){ double f=double(StrToFloat(txt)); if(f < ed->MinValue || f > ed->MaxValue) err=2; }else{ err = 1; } } if(err > 0){ AnsiString msg; if(err == 1){ msg = "輸入的字元不合法!"; }else{ msg = "數值超過範圍!"; } Beep(); ShowMessage(msg); ed->SetFocus(); ed->Perform(WM_KEYDOWN,VK_END,0); ed->Perform(WM_KEYUP,VK_END,0); } } }6. 將 EditEx2 與 EditEx3 的 OnChange 事件處理程序指向 EditEx1Change,將 EditEx2 與 EditEx3 的 OnExit 事件處理程序指向 EditEx1Exit。 這樣子應該可以開始測試了。 |
RedSnow
版主 發表:79 回覆:1322 積分:845 註冊:2003-12-15 發送簡訊給我 |
mzhuang 您好: 我剛才又將 EditEx 元件加強了一下,現在的元件可做到下列動作: 1. 增加 Alignment 屬性,以設定輸入內容顯示對齊的種類,可設定 "向左"、"居中"、"向右" 對齊。 2. 增加 DataType 屬性,可指定輸入資料為文字或是數字,若本屬性設定為數字型態,則輸入資料時會過濾掉數字、小數點、減號以外的字元 (其它的 HotKey 也一併攔截掉了,若要操作剪貼、複製資料....等動作的話,必須透過滑鼠右鍵選單來操作)。 3. 增加 OnExit 時的檢查動作,如果 CheckRange 屬性設為 true 的話,則游標離開輸入欄位時,會檢查輸入的資料是否符合 MaxValue 及 MinValue 所設的範圍。 更新版本的內容如下: 自定元件之 EditEx.h
//--------------------------------------------------------------------------- #ifndef EditExH #define EditExH //--------------------------------------------------------------------------- #include自定元件之 EditEx.cpp //--------------------------------------------------------------------------- #include[/code] 將上邊的程式編譯成元件並安裝好之後,可以在元件盤的 Sample 單元裡找到名稱為 EditEx 的元件 (使用與 BCB 內建的 Edit 元件相同之圖示)。 測試新版本的這個元件時,請先建立一個測試用的專案,專案裡僅需開啟一個空的 Form 並做好下列設定即可: 1. 在 Form 上邊設置三個 TEditEx 元件。 2. 將三個元件的 CheckRange 屬性都設為 true。 3. 將三個元件的 DataType 屬性都設為 tdNumber。 4. 將三個元件的 MaxValue 與 MinValue 屬性欄位個別設定成要檢查的 "最大" 與 "最小" 值,例如: EditEx1: MaxValue = 2451287 EditEx1: MinValue = -1319760 EditEx2: MaxValue = 9.999999876 EditEx2: MinValue = -0.0000001278 (輸入後會自動變成 -1.278E-7) EditEx3: MaxValue = 100 EditEx3: MinValue = 0.0001 這樣子應該就可以了,開始測試吧! |
gmobug
一般會員 發表:10 回覆:28 積分:12 註冊:2004-02-04 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |