2012-08-12 39 views
9

Office XP शैली के साथ एक केंद्रित/चयनित सूचीबॉक्स आइटम दिखाने का सबसे आसान और साफ तरीका क्या होगा?चयन आयत जैसे कार्यालय XP विषय के साथ एक सूची बॉक्स कैसे बनाएं?

इस नमूना छवि विचार को दिखाने के लिए अधिक स्पष्ट:

enter image description here

मुझे लगता है मैं लिस्टबॉक्स शैली या तो lbOwnerDrawFixed या lbOwnerDrawVariable और फिर OnDrawItem ईवेंट को संशोधित करने के लिए सेट की आवश्यकता है?

यह वह जगह है जहाँ मैं कर रहा हूँ अटक, मैं वास्तव में यकीन है कि क्या कोड में वहाँ लिखने के लिए कर रहा हूँ, अब तक मैंने कोशिश की:

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
begin 
    with (Control as TListBox).Canvas do 
    begin 
    if odSelected in State then 
    begin 
     Brush.Color := $00FCDDC0; 
     Pen.Color := $00FF9933; 
     FillRect(Rect); 
    end; 

    TextOut(Rect.Left, Rect.Top, TListBox(Control).Items[Index]); 
    end; 
end; 

मैं जाना जाता है चाहिए कि काम नहीं होगा, मैं अजीब के सभी प्रकार के विवरण अधिक महत्वपूर्ण बात यह है कि मैं क्या यह काम करने के लिए बदलने की जरूरत है

enter image description here

मैं गलत क्या कर रहा हूँ,: बातों पर जा रहे हैं?

धन्यवाद।

+0

मुझे नहीं लगता कि वहाँ एक सूची बॉक्स थीम चयन इस तरह। वहाँ ['LBCP_ITEM'] हैं (http://msdn.microsoft.com/en-us/library/windows/desktop/bb(v = vs.85) .aspx) सूची बॉक्स के लिए भाग, लेकिन वे बिल्कुल ठीक दिखते हैं गैर-मालिक तैयार सूची बॉक्स - उबाऊ। तो शायद आप थीम्ड चयन भागों उधार ले सकते हैं उदा। एंड्रयू जैसे पेड़ दृश्य से ['इस पोस्ट'] में वर्णित है (http://stackoverflow.com/a/10936108/960757)। आपको सूची बॉक्स राज्यों के लिए उस कोड को संशोधित करने की आवश्यकता होगी। – TLama

+0

यह वही है जो मैं चिंतित था, ट्रीव्यूव और लिस्टव्यू के विपरीत जो सूचीबद्ध रंगों को पेंटबॉक्स नहीं करता है। –

+3

हार्ड कोडिंग रंग जब, यह न भूलें कि उपयोगकर्ता के पास पूरी तरह से अलग रंग योजना हो सकती है। –

उत्तर

13

आप विभिन्न राज्यों के लिए आइटम पेंट करना भूल गए हैं। आपको यह निर्धारित करने की आवश्यकता है कि वर्तमान में आइटम किस स्थिति में है और इसके अनुसार इसे आकर्षित करें।

आपकी तस्वीर पर आपके पास क्या है, आप इस तरह से प्राप्त कर सकते हैं। हालांकि यह अच्छी तरह से लग रहा है नहीं करता है तो आप एकाधिक चयन करें सक्षम है और एक से अधिक आइटम का चयन किया है:

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    Offset: Integer; 
begin 
    with (Control as TListBox) do 
    begin 
    Canvas.Font.Color := Font.Color; 
    if (odSelected in State) then 
    begin 
     Canvas.Pen.Color := $00FF9932; 
     Canvas.Brush.Color := $00FDDDC0; 
    end 
    else 
    begin 
     Canvas.Pen.Color := Color; 
     Canvas.Brush.Color := Color; 
    end; 
    Canvas.Rectangle(Rect); 
    Canvas.Brush.Style := bsClear; 
    Offset := (Rect.Bottom - Rect.Top - Canvas.TextHeight(Items[Index])) div 2; 
    Canvas.TextOut(Rect.Left + Offset + 2, Rect.Top + Offset, Items[Index]); 
    end; 
end; 

और ItemHeight सेट से 16 के साथ परिणाम:

enter image description here

बोनस - निरंतर चयन :

यहां एक सतत चयन लागू करने का एक कठिन समाधान है। सिद्धांत पहले की तरह आइटम को आकर्षित करना है, लेकिन पिछले और अगले आइटम की चयन स्थिति के आधार पर किसी रंग की रेखाओं के साथ आइटम की सीमा शीर्ष और निचली रेखाओं को ओवरराइड करना है। इसके अलावा, वर्तमान आइटम के बाहर भी प्रस्तुत किया जाना चाहिए, क्योंकि आइटम चयन स्वाभाविक रूप से पड़ोसी वस्तुओं को पुनर्निर्मित करने के लिए नहीं बुलाता है। इस प्रकार क्षैतिज रेखाओं को ऊपर एक पिक्सेल चित्रित किया जाता है और वर्तमान आइटम सीमाओं के नीचे एक पिक्सेल (इन पंक्तियों के रंग सापेक्ष चयन राज्यों पर भी निर्भर करता है)।

यहां पर अजीब अजीब वस्तु वस्तुओं का उपयोग प्रत्येक आइटम की चयनित स्थिति को संग्रहीत करने के लिए है। मैंने ऐसा किया, क्योंकि ड्रैग & ड्रॉप आइटम चयन का उपयोग करते समय, Selected संपत्ति तब तक वास्तविक स्थिति नहीं लौटाती जब तक कि आप माउस बटन को छोड़ नहीं देते। सौभाग्य से, OnDrawItem पाठ्यक्रम की स्थिति वास्तविक स्थिति के साथ आग लगती है, इसलिए एक कामकाज के रूप में मैंने OnDrawItem घटना से इन राज्यों को संग्रहित किया है।

महत्वपूर्ण:

ध्यान दें, कि मैं वास्तविक चयन राज्य स्टोर करने के लिए है, इसलिए सावधान रहना, और जब आप कुछ और के लिए आइटम वस्तुओं का उपयोग कर रहे, इस वास्तविक स्टोर आइटम वस्तुओं का उपयोग कर रहा उदाहरण के लिए राज्यों बूलियन की एक सरणी में।

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
const 
    SelBackColor = $00FDDDC0; 
    SelBorderColor = $00FF9932; 
var 
    Offset: Integer; 
    ItemSelected: Boolean; 
begin 
    with (Control as TListBox) do 
    begin 
    Items.Objects[Index] := TObject((odSelected in State));  

    if (odSelected in State) then 
    begin 
     Canvas.Pen.Color := SelBorderColor; 
     Canvas.Brush.Color := SelBackColor; 
     Canvas.Rectangle(Rect); 
    end 
    else 
    begin 
     Canvas.Pen.Color := Color; 
     Canvas.Brush.Color := Color; 
     Canvas.Rectangle(Rect); 
    end; 

    if MultiSelect then 
    begin 
     if (Index > 0) then 
     begin 
     ItemSelected := Boolean(ListBox1.Items.Objects[Index - 1]); 
     if ItemSelected then 
     begin 
      if (odSelected in State) then 
      begin 
      Canvas.Pen.Color := SelBackColor; 
      Canvas.MoveTo(Rect.Left + 1, Rect.Top); 
      Canvas.LineTo(Rect.Right - 1, Rect.Top); 
      end 
      else 
      Canvas.Pen.Color := SelBorderColor; 
     end 
     else 
      Canvas.Pen.Color := Color; 
     Canvas.MoveTo(Rect.Left + 1, Rect.Top - 1); 
     Canvas.LineTo(Rect.Right - 1, Rect.Top - 1); 
     end; 

     if (Index < Items.Count - 1) then 
     begin 
     ItemSelected := Boolean(ListBox1.Items.Objects[Index + 1]); 
     if ItemSelected then 
     begin 
      if (odSelected in State) then 
      begin 
      Canvas.Pen.Color := SelBackColor; 
      Canvas.MoveTo(Rect.Left + 1, Rect.Bottom - 1); 
      Canvas.LineTo(Rect.Right - 1, Rect.Bottom - 1); 
      end 
      else 
      Canvas.Pen.Color := SelBorderColor; 
     end 
     else 
      Canvas.Pen.Color := Color; 
     Canvas.MoveTo(Rect.Left + 1, Rect.Bottom); 
     Canvas.LineTo(Rect.Right - 1, Rect.Bottom); 
     end; 
    end; 

    Offset := (Rect.Bottom - Rect.Top - Canvas.TextHeight(Items[Index])) div 2; 
    Canvas.Brush.Style := bsClear; 
    Canvas.Font.Color := Font.Color; 
    Canvas.TextOut(Rect.Left + Offset + 2, Rect.Top + Offset, Items[Index]); 
    end; 
end; 

और परिणाम:

enter image description here

+2

हाँ मैं यह जांचने के बारे में भूल गया कि राज्य का चयन किया गया था, लेकिन फिर भी मैं एक कामकाजी उत्तर से बहुत दूर था - कम से कम अब मैं देख सकता हूं कि मुझे क्या परिवर्तन करना चाहिए था। इसके अलावा मैं कई चयनों पर विचार करने के बारे में भूल गया, प्रभाव हालांकि बुरा नहीं है :) वैसे भी हमेशा के रूप में अच्छा जवाब TLama धन्यवाद;) –

+2

आपका स्वागत है! मल्टीइलेक्स्ट के बारे में जब आप आइटम के चारों ओर सीमा रखते हैं तो यह अधिक जटिल होता है। इस मामले में आपको अतिरिक्त आइटम की आवश्यकता है (यदि कोई है तो) और अगला आइटम (यदि कोई है तो) चुना गया है या नहीं। यदि ऐसा है, तो आपको निरंतर चयन ['इस तरह '] (http://i.imgur.com/hG7zG.png) प्राप्त करने के लिए वर्तमान में प्रस्तुत की गई वस्तु की ऊपरी या निचली सीमा रेखा को * छुपाएं * छुपाएं। – TLama

+1

उत्कृष्ट समाधान, मैंने अपने दूसरे स्क्रीनशॉट में दिखाए गए मल्टीइलेक्ट को काम करने की कोशिश की लेकिन मैं आपके अपडेट किए गए संस्करण की तुलना में कहीं भी नहीं था। यदि संभव हो तो मैं आपके उत्तर को दो बार स्वीकार करूंगा :) –

2

आपको फ़ंक्शन में पारित राज्य चर के मान को देखने की आवश्यकता है। यह आपको बताता है कि आइटम का चयन किया गया है या नहीं और फिर आप ब्रश और पेन को उचित रूप से सेट कर सकते हैं।

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