2009-06-16 19 views
2

我希望我能夠很好地解釋我的問題,以便有人提供幫助。「智能」鏈接滾動條和編輯控件?

基本上,我有一個水平滾動條(範圍爲0到1000)和一個表示滾動條位置除以1000的編輯控件,以便用戶可以使用滾動條來選擇0到1至小數點後3位精度(.001,.002,...,.987等),或在編輯框中輸入自己的編號。當他們滾動滾動條時,編輯控件中的數字會發生變化以反映新的滾動位置。當輸入一個新號碼時,滾動條將自己設置到一個反映輸入號碼的新位置。與此同時,我還會使用該數字執行一些計算(通過滾動條或編輯控件)並在另一個對話框中顯示結果。

這是我的問題:我無法決定當用戶在編輯控件中輸入數字時要使用哪些事件處理程序來產生正確的行爲。

我使用一個名爲fuelMargin的double值變量來處理我的編輯控件和一個名爲fuelScroll的CScrollBar控件變量來處理滾動條。

在我的HSCROLL事件中,我將編輯控件設置爲滾動位置/ 1000。當用戶滾動滾動條時,編輯框被正確更新。

至於編輯框,我第一次嘗試是一個onChange事件:

void MarginDlg::OnEnChangeFueledit() 
{ 
    CEdit* editBox; 
    editBox = (CEdit*)GetDlgItem(IDC_FUELEDIT); 

    CString editString; 
    editBox->GetWindowText(editString); 

    if (editString.Compare(".") != 0 && editString.Compare("0.") != 0 
     && editString.Compare(".0") != 0 && editString.Compare("0.0") != 0 
     && editString.Compare(".00") != 0 && editString.Compare("0.00") != 0) 
    { 
     UpdateData(); 
     UpdateData(FALSE); 

     if (fuelMargin > 1) 
     { 
      UpdateData(); 
      fuelMargin = 1; 
      UpdateData(FALSE); 
     } 
     if (fuelMargin < 0) 
     { 
      UpdateData(); 
      fuelMargin = 0; 
      UpdateData(FALSE); 
     } 
     fuelScroll.SetScrollPos(int(fuelMargin*1000)); 
    } 
} 

我需要首先,如果在那裏語句從做一個的UpdateData()保持,當用戶試圖輸入一個數字如.5或.05或.005。儘管如此,它確實會產生一些不可思議的行爲;當用戶試圖輸入類似.56的內容時,在.5之後執行UpdateData(),數字變爲0.5,並且光標移動到最左側,所以如果他們試圖鍵入.56,他們會意外地結束鍵入60.5 - 這會變成1,因爲我不會讓他們輸入低於0或高於1的數字。但是,如果他們輸入0.56,則可以避免此行爲。

對於我的第二次嘗試,我評論了我的onchange事件,並把在ONKILLFOCUS事件,而不是:

void MarginDlg::OnEnKillfocusFueledit() 
{ 
    UpdateData(); 
    UpdateData(FALSE); 

    if (fuelMargin > 1) 
    { 
     UpdateData(); 
     fuelMargin = 1; 
     UpdateData(FALSE); 
    } 
    if (fuelMargin < 0) 
    { 
     UpdateData(); 
     fuelMargin = 0; 
     UpdateData(FALSE); 
    } 
    fuelScroll.SetScrollPos(int(fuelMargin*1000)); 
} 

所以現在用戶可以輸入完成他們的數量,一切都虎背熊腰,腳蹬dory的 - 只要他們點擊編輯框。在框失去焦點之前,滾動條不會移動,結果將不會被計算。

我想要計算結果,因爲框中的數字正在鍵入;我想讓滾動條隨着數字的輸入而移動。但我不希望輸入被打亂,即盒子中的實際數字發生了變化,或者光標以任何方式移動。

對此提出建議?

謝謝!

回答

2

用第一種方法,它看起來像你幾乎沒有:只有真正顯著的問題是,要的UpdateData一再呼籲()惹光標的位置作爲用戶輸入。

鑑於您試圖在控件之間進行相當複雜的交互,我建議不要在OnChange()中進行驗證,以便在用戶鍵入內容時,他可以鍵入他所輸入的內容想要(這是大多數數字編輯控件無論如何工作)。當用戶關閉對話框時,控件處於打開狀態(或者單擊按某種方式使用數據的按鈕),然後觸發驗證,並顯示適當的錯誤。

一旦你在的OnChange()驗證免費的,你可以通過簡單地沒有要求的UpdateData()中的OnChange()修復「光標移動」的問題。相反,只需解析「editString」中的數字,如果它位於有效範圍內,則更新滾動條。這樣,滾動條就會隨着用戶輸入而更新,如果他們輸入的值不正確,滾動條會保持放置狀態,當他們移動到下一個階段時會出錯。事情是這樣的(未測試):

void MarginDlg::OnEnChangeFueledit() 
{ 
    CString editString; 
    GetDlgItem(IDC_FUELEDIT)->GetWindowText(editString); 

    double editValue; 
    if ((sscanf(editString,"%lf",&editValue) == 1) 
    { 
    if (editValue >= 0.0) && (editValue <= 1.0)) 
     fuelScroll.SetScrollPos(int(editValue*1000)); 
    } 
} 

剩下的唯一重要的問題要注意的是,如果用戶鍵入一些無效的值,或數字超出有效範圍,然後在編輯控件和滾動條將不同步。對付,最簡單的方法是隻決定編輯控件是「主」的價值:那就是,當我們想知道用戶輸入的內容,我們總是看編輯控件,而不是滾動條,並且驗證數據。

至於你的第二種方法,一種可能的解決方案可能是實現一個計時器消息處理程序:在計時器處理程序中,你可以說相當於「如果用戶沒有輸入任何東西,我會假設他們'完成了,解析數字並更新滾動條「。不過,我並不那麼熱衷於此。

+0

我對我的onchange使用了這種方法,對結果非常滿意。謝謝! 我在killfocus中做了最小錯誤檢查,即確保數字在範圍內,如果不是,我將它設置爲0或1(並相應地更新滾動條)。我會喜歡在那裏更新我的結果,但我有一些問題...所以我目前正在調試的過程中。但非常感謝您的解決方案。 – Lauren 2009-06-17 15:56:37

0

我建議注意Enter鍵,然後執行UpdateData()以及OnKillFocus和OnChange。越用戶友好越好。

接下來,確保您的UpdateData()函數只能在方向你需要:

如果在編輯控件中輸入」 5" ,運行的UpdateData()函數時引發OnChange事件,但一定要只更新滾動條。在引發OnKillFocus之前,不要擔心將編輯控件更新爲「0.5」。反向(對編輯控件)的任何更新都會與您的光標混淆。如果你的編輯控件以某種方式綁定到這個雙變量和自動更新時VAR的變化,考慮離開彼此的雙重和你的編輯控件單獨直到OnKillFocus事件引發。

同樣的概念適用於其它方向也是如此。當用戶滾動時,不要弄亂滾動條。只需更新編輯控件並將其保留即可。

我要補充一點,XAML的數據綁定功能,真正幫助在這樣的情況下,如果你知道如何正確地使用它們。對於我們的本地類型開發人員來說,很不幸,僅僅使用事件處理程序來實現類似的功能是非常困難的。