2009-08-20 17 views
5

मेरे पास आइटमों की एक सूची है (संभावित रूप से बड़ी) जिसमें उपयोगकर्ता को एक का चयन करना होगा। मैं उपयोगकर्ता को सूची में सही स्थान पर जाने के लिए वांछित आइटम के पहले कुछ अक्षर टाइप करने की अनुमति देना चाहता हूं। डिफ़ॉल्ट रूप से, प्रत्येक कुंजीपटल उस पत्र से शुरू होने वाली पहली वस्तु पर कूद जाती है, इसलिए आप पहले कई अक्षरों को टाइप नहीं कर सकते हैं। क्या ऐसा करने का कोई सीधा तरीका है? कोई कोडप्रोजेक्ट या ऐसा कोई उदाहरण?पहले कुछ अक्षर टाइप करके सूचीबॉक्स आइटम पर जाएं

मैंने घंटों की तलाश की है, और IAutocomplete के लिए कई नमूने पाए हैं, लेकिन इससे यहां सहायता नहीं होगी क्योंकि मुझे यह गारंटी देने की आवश्यकता है कि परिणाम सूची में है।

एकमात्र तरीका मैं ऐसा करने के लिए सोच सकता हूं कि क्लाइस्टबॉक्स से प्राप्त करना, कुंजीस्ट्रोक को कैप्चर करना, आइटम ढूंढना, टाइमर चलाएं ताकि पर्याप्त रोक के बाद नए कीस्ट्रोक एक नई खोज शुरू कर सकें ... क्योंकि मैं ' एम एक एमएफसी जोक नहीं है, यह चुनौतीपूर्ण है। किसी भी सुझाव की बहुत सराहना की।

एक स्पष्टीकरण नोट: मेरा अंतिम लक्ष्य वास्तव में ड्रॉपडाउनलिस्ट शैली (यानी कोई संपादन बॉक्स) के कॉम्बोबॉक्स के लिए यह कीबोर्ड व्यवहार प्राप्त करना है। एक संपादन बॉक्स की कमी सबसे स्वतः पूर्ण कोड का नियम देती है, और कॉम्बोबॉक्स कार्यक्षमता की आवश्यकता का अर्थ है कि मैं स्वयं CListCtrl का उपयोग नहीं कर सकता।

उत्तर

10

ज्यादा के बाद अनावश्यक दर्द, मैंने पाया है कि वास्तविक सही उत्तर केवल LBS_SORT का उपयोग करना है। बस इस शैली को निर्दिष्ट करके, मूल वेनिला सूची बॉक्स मैं चाहता था कि वृद्धिशील खोज कुंजीपटल शॉर्टकट शैली का समर्थन करता है। एलबीएस_SORT (या एक combobox के लिए CBS_SORT) के बिना, आप परेशान और लगभग बेकार कूद-से-पहले-अक्षर-केवल व्यवहार प्राप्त करते हैं। मैंने LBS_SORT को आजमाया नहीं है क्योंकि मेरी सूची सामग्री क्रमबद्ध क्रम में जोड़ा गया था।

तो कस्टम नियंत्रण आदि के दर्जन या इतने घंटे, सब कुछ शून्य के लिए नहीं है क्योंकि माइक्रोसॉफ्ट दस्तावेज LBS_SORT के विवरण में इस महत्वपूर्ण व्यवहार अंतर का कोई उल्लेख नहीं करता है !!

योगदान देने वाले सभी लोगों के लिए धन्यवाद।

+0

+1 - धन्यवाद, मुझे सूची बॉक्स के बारे में पता नहीं था। मुझे तुम्हारा दर्द फिर से महसूस होता है। दस्तावेज़ीकरण। 8- ( – RichieHindle

1

क्या आप CListView CListCtrl का उपयोग कर सकते हैं? वे डिफ़ॉल्ट रूप से इस तरह काम करते हैं।

+0

अच्छा, मुझे नहीं पता। CListView (Google, MSDN, विजुअल स्टूडियो सहायता) पर लगभग कोई दस्तावेज़ीकरण नहीं लगता है, इसलिए मुझे नहीं पता कि इसका उपयोग कैसे किया जाए। मैं अभी भी विजुअल स्टूडियो .NET 2003 में हूं, अगर इसका कोई प्रभाव पड़ता है। CListView को कैसे आज़माएं इस पर कोई संकेतक? – rfeague

+0

@rfeague: क्षमा करें! अंतर्निहित नियंत्रण के लिए "ListView" नाम के बावजूद एमएफसी इसे CListCtrl कहते हैं। इसे संवाद संपादक टूलबॉक्स में "सूची नियंत्रण" कहा जाता है। – RichieHindle

+0

धन्यवाद रिची। यह सही दिशा में जा रहा है, लेकिन CListCtrl के quirks मुझे पागल बना रहे हैं। मैं इसे अपनी सूची प्रदर्शित करने के लिए प्राप्त कर सकता हूं, और कुछ अक्षर टाइप किए जाने पर यह सही आइटम पर जाता है, लेकिन यह प्रारंभ में चयनित आइटम को देखने में स्क्रॉल नहीं करता है, और यह अंत में elipses दिखाता है वस्तुओं का चयन करते समय (लेकिन केवल तभी चुने जाते हैं)। तो, मुझे लगता है कि आपने मुझे सही जवाब दिया है, और मैं आपको धन्यवाद देता हूं।इन शेष मुद्दों पर आपके पास जो भी अन्य पॉइंटर्स हो सकते हैं, उनका स्वागत होगा। मैं विश्वास नहीं कर सकता कि मैंने इस सरल-सरल मुद्दे में कितना समय निवेश किया है। – rfeague

3

मैंने कोर Win32 में ऐसी कार्यक्षमता लागू की है। कोड है

अपने संदेश पाश में कहीं न कहीं उस सूची बॉक्स डालने संसाधित करता है:

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

....

यहाँ कोड (propably पूरी तरह से पूरा नहीं हुआ):

/* ======================================================================== */ 
/* ======================================================================== */ 
#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

वाह, धन्यवाद स्टीफन! मैं इसे आज़मा दूंगा। ऐसा लगता है कि मैं इसे सामान्य कॉम्बोबॉक्स पर आसानी से लागू कर सकता हूं, जो शानदार होगा। समाधान के साथ वापस आने के लिए – rfeague

संबंधित मुद्दे