2009-08-20 5 views
5

ユーザーが選択する必要がある(潜在的に大きい)項目のリストがあります。私はユーザーが最初の数文字を入力することを許可したいです希望の項目のリスト内の正しい場所にジャンプする。デフォルトでは、各キーの押下はその文字で始まる最初の項目にジャンプするので、最初にの文字を入力することはできません。文字です。これを行う簡単な方法はありますか?任意のCodeProjectまたは他のそのような例?最初の数文字を入力してリストボックス項目に移動します。

私は何時間も探していて、IAutocompleteのサンプルをいくつでも見つけましたが、結果がリストにあることを保証する必要があるので、ここでは役に立たないでしょう。

私が考えることができる唯一の方法は、CListBoxから派生し、自分自身のキーストロークをキャプチャし、アイテムを見つけ、十分な休止後に新しいキーストロークが新しい検索を開始するようにタイマーを実行することです。 MFCのジョックではありませんが、これは大変です。任意のヒントを高く評価しました。

明確な注記:私の究極の目標は、実際にはDropDownListスタイルのComboBox(つまり編集ボックスなし)のキーボード動作を取得することです。エディットボックスがないとほとんどのオートコンプリートコードが除外され、ComboBox機能が必要なため、CListCtrlを単独で使用することはできません。

答えて

10

switch(message) 
{ 
    case WM_CHAR:  
    if(HandleListBoxKeyStrokes(hwnd, wParam) == FALSE) 
       return FALSE; 

....

相続コード(propably完全に完了していない):リストボックスの挿入を処理し、あなたのメッセージループ内

どこか不必要な痛み、私は本当の正解は単にLBS_SORTを使用することであることを発見しました。このスタイルを指定するだけで、基本的なバニラリストボックスは、私が求めていた増分検索のキーボードショートカットスタイルをサポートします。 LBS_SORT(またはコンボボックスのCBS_SORT)がなければ、刺激的でほとんど役に立たないジャンプから最初の文字のみの動作になります。私のリストの内容はソートされた順序で追加されたので、LBS_SORTは試していませんでした。

カスタムコントロールなどを調べるのに数十時間かかるので、MicrosoftのドキュメントではLBS_SORTの説明のこの重要な動作上の違いについては言及していないためです。

貢献したすべての人に感謝します。

+0

解決策に戻ってくる+1 - ありがとう、私はリストボックスについて知りませんでした。私はあなたの痛みを再感じています。ドキュメンテーション8-( – RichieHindle

1

代わりに CListView CListCtrlを使用できますか?彼らはデフォルトでそれのように動作します。

+0

まあ、わかりません。 CListView(Google、MSDN、Visual Studio Help)に関するドキュメントはほとんどないようですので、使用方法はわかりません。 Visual Studio .NET 2003にはまだ影響があります。どのようにCListViewを試してみましょうか? – rfeague

+0

@ rfeague:申し訳ありません! MFCは、 "ListView"である基になるコントロールの名前にもかかわらず、CListCtrlを呼び出します。これは、ダイアログエディタツールボックスの「リストコントロール」と呼ばれています。 – RichieHindle

+0

ありがとうリッチー。これは正しい方向に進んでいますが、CListCtrlの癖が私を狂ってしまっています。私はそれを私のリストを表示するために得ることができ、(ほとんど)右の項目にいくつかの文字が入力されたときにジャンプしますが、それは最初に選択された項目を表示にスクロールせず、アイテムが選択されたとき(ただし、選択されている場合のみ) 私は正しい答えをくれたと思います。ありがとうございます。これらの残りの問題に関してあなたが持っているかもしれない他のポインタは、大歓迎です。私はこの単純な問題に、どれくらいの時間を投資したのか、信じられません。 – rfeague

3

私はコアWin32でこのような機能を実装しました。コードをheresします。ずっと後

/* ======================================================================== */ 
/* ======================================================================== */ 
#define RETURNr(a, b) // homegrown asserts 

BOOLEAN HandleListBoxKeyStrokes(HWND hwnd, UINT theKey) 

{ 
    #define MAXCHARCACHEINTERVALL 600.0 // Max. milisecs time offset to consider as typed 'at once' 
    static char sgLastChars[255] = {'0'}; 
    static double sgLastCharTime = 0.; 

static HWND sgLasthwnd = NULL; 


if(GetSecs() - sgLastCharTime > MAXCHARCACHEINTERVALL || 
    sgLasthwnd != hwnd) 
    *sgLastChars = 0; 

if(theKey == ' ' && *sgLastChars == 0) 
    return TRUE; 

sgLastCharTime = GetSecs(); 
sgLasthwnd = hwnd; 

AppendChar(sgLastChars, toupper(theKey)); 

if(strlen(sgLastChars) > 1) 
{ 
     LONG l = GetWindowLong(hwnd, GWL_STYLE); 
     Char255 tx; 
     GetClassName(hwnd, tx, sizeof(tx)); 
     if( (! stricmp(tx, "Listbox") && 
       ! (l & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))) || 
      (! stricmp(tx, "ComboBox") && // combo Box support 
       l & CBS_DROPDOWNLIST && 
       ! (l & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)))) 
     { 
      long Count, l, BestMatch = - 1, BestMatchOff = 0; 
      long LBcmdSet[] = {LB_GETCOUNT, LB_GETTEXTLEN , LB_GETTEXT}; 
      long CBcmdSet[] = {CB_GETCOUNT, CB_GETLBTEXTLEN, CB_GETLBTEXT}; 
      long *cmdSet = (! stricmp(tx, "ComboBox")) ? CBcmdSet : LBcmdSet; 

      RETURNr((Count = SendMessage(hwnd, cmdSet[0], 0, 0)) != LB_ERR, 0); 
      for(int i = 0; i < Count; i++) 


     { 
        RETURNr((l = SendMessage(hwnd, cmdSet[1], i, 0)) != LB_ERR, TRUE); 
        RETURNr(l < sizeof(tx), TRUE); 
        RETURNr((l = SendMessage(hwnd, cmdSet[2], i, (LPARAM)&tx)) != LB_ERR, TRUE); 
        strupr(tx); 
        if(! strncmp(tx, sgLastChars, strlen(sgLastChars))) 
        { 
         SelListBoxAndNotify(hwnd, i); 
         return FALSE; 
        } 
        char *p; 
        if(p = strstr(tx, sgLastChars)) 
        { 
         int off = p - tx; 
         if(BestMatch == -1 || off < BestMatchOff) 
         { 
          BestMatch = i; 
          BestMatchOff = off; 
         } 
        } 
       } 
       // If text not found at start of string see if it matches some part inside the string 
       if(BestMatch != -1) 
         SelListBoxAndNotify(hwnd, BestMatch); 
       // Nothing found - dont process 
       return FALSE; 
      } 
     } 
     return TRUE; 
    } 
    /* ======================================================================== */ 
    /* ======================================================================== */ 

    void SelListBoxAndNotify(HWND hwnd, int index) 

    { 
    // i am sorry here - this is some XVT-toolkit specific code. 
    // it has to be replaced with something similar for native Win32 
     WINDOW win = xvtwi_hwnd_to_window(hwnd); 
     WINDOW parent = xvt_vobj_get_parent(win); 
     xvt_list_set_sel(win, index, 1); 
     EVENT evt; 
     memset(&evt, 0, sizeof(evt)); 
     evt.type = E_CONTROL; 
     evt.v.ctl.id = GetDlgCtrlID(hwnd); 
     evt.v.ctl.ci.v.lbox.dbl_click = FALSE; 
     xvt_win_dispatch_event(parent, &evt); 
    } 
    /* ======================================================================== */ 
    /* ======================================================================== */ 

double GetSecs(void) 

{ 
     struct timeb timebuffer; 
     ftime(&timebuffer); 
     return (double)timebuffer.millitm + 
       ((double)timebuffer.time * 1000.) - // Timezone needed for DbfGetToday 
       ((double)timebuffer.timezone * 60. * 1000.); 
} 
    /* ======================================================================== */ 
    /* ======================================================================== */ 

char AppendChar(char *tx, char C) 

{  int i; 

     i = strlen(tx); 
     tx[i ] = C; 
     tx[i + 1] = 0; 
     return(C); 
} 
+0

うわー、ありがとうStefan!私はこれを試してみましょう。私はこれを通常のComboBoxに簡単に適用できるように見えますが、これはすばらしいでしょう。 – rfeague

関連する問題