גודל גודל רוחב הנפתח של ComboBox

ה TComboBox רכיב משלב תיבת עריכה עם רשימת "פיק" הניתנת לגלילה. משתמשים יכולים לבחור פריט מהרשימה או להקליד ישירות לתוך תיבת עריכה.

רשימה נפתחת

כאשר תיבת משולבת במצב נפתח Windows מצייר סוג של בקרת רשימה כדי להציג פריטי תיבות משולבים לבחירה.

ה נכס DropDownCount מציין את המספר המרבי של הפריטים המוצגים ברשימה הנפתחת.

ה רוחב הרשימה הנפתחת היה כברירת מחדל שווה לרוחב התיבה המשולבת.

כאשר אורך (של מחרוזת) של פריטים עולה על רוחב הקומבוקס, הפריטים מוצגים כניתוק!

TComboBox לא מספק דרך להגדיר את רוחב הרשימה הנפתחת שלה :(

תיקון רוחב הרשימה הנפתחת של ComboBox

אנו יכולים לקבוע את רוחב הרשימה הנפתחת על ידי שליחת מיוחד הודעת Windows לתיבת המשולבת. המסר הוא CB_SETDROPPEDWIDTH ושולח את הרוחב המינימלי המותר, בפיקסלים, של תיבת הרשימה של תיבת משולבת.

כדי לבצע קידוד קשיח בגודל הרשימה הנפתחת, נניח, 200 פיקסלים, אתה יכול לעשות:


SendMessage (theComboBox. ידית, CB_SETDROPPEDWIDTH, 200, 0); 

זה בסדר רק אם אתה בטוח שכל ה- ComboBox שלך. הפריטים אינם ארוכים מ- 200 פיקסלים (כאשר מצויירים).

כדי להבטיח שתמיד תצוגת הרשימה הנפתחת רחבה מספיק, נוכל לחשב את הרוחב הנדרש.

instagram viewer

להלן פונקציה לקבלת הרוחב הנדרש של הרשימה הנפתחת ולהגדיר אותה:

תהליך ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
פריטים מלאים רוחב: מספר שלם; idx: מספר שלם; פריט רוחב: מספר שלם; התחל
פריטים מלאים רוחב: = 0; // קבל את המקסימום הדרוש עם הפריטים במצב הנפתחל idx: = 0 ל -1 + theComboBox. פריטים. לספור לעשותהתחל
פריט רוחב: = theComboBox. בד. רוחב טקסט (theComboBox. פריטים [idx]); Inc (פריט רוחב, 2 * HORIZONTAL_PADDING); if (פריט רוחב> פריטים מלא רוחב) לאחר מכן itemsFullWidth: = פריט רוחב; סוף; // הגדר את רוחב הנפתחת במידת הצורךאם (פריטים מלאים רוחב> theComboBox. רוחב) אז. התחל// בדוק אם יש סרגל גלילהאם theComboBox. DropDownCount לאחר מכן
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. ידית, CB_SETDROPPEDWIDTH, פריטים מלא רוחב, 0); סוף; סוף; 

רוחב המחרוזת הארוכה ביותר משמש לרוחב הרשימה הנפתחת.

מתי להתקשר ל- ComboBox_AutoWidth?
אם תמלאו מראש את רשימת הפריטים (בזמן העיצוב או בעת יצירת הטופס) תוכלו להתקשר לפרוצדורת ComboBox_AutoWidth בתוך הטופס OnCreate מנהל אירועים.

אם תשנה באופן דינמי את רשימת פריטי התיבה המשולבת, תוכל להתקשר להליך ComboBox_AutoWidth בתוך OnDropDown מטפל באירועים - מתרחש כאשר המשתמש פותח את הרשימה הנפתחת.

מבחן
לבדיקה יש לנו 3 תיבות משולבות בטופס. לכולם פריטים שהטקסט שלהם רחב יותר מרוחב התיבה המשולבת בפועל. תיבת המשולבת השלישית ממוקמת בסמוך לקצה הימני של גבול הטופס.

נכס הפריטים, למשל, ממלא מראש - אנו קוראים ComboBox_AutoWidth שלנו במטפל האירועים OnCreate עבור הטופס:

// OnCreate של הטופסתהליך TForm. FormCreate (שולח: TObject); התחל
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); סוף; 

לא התקשרנו ל- ComboBox_AutoWidth עבור Combobox1 כדי לראות את ההבדל!

שים לב שכאשר הפעלה הרשימה הנפתחת של Combobox2 תהיה רחבה יותר מ- Combobox2.

הרשימה הנפתחת כולה נותקת ל"מיקום קרוב לקצה הימני "

עבור Combobox3, זה הממוקם בסמוך לקצה הימני, הרשימה הנפתחת נותקת.

שליחת CB_SETDROPPEDWIDTH תאריך תמיד את תיבת הרשימה הנפתחת ימינה. כאשר הקומבוקס שלך נמצא בקצה הימני, הרחבת תיבת הרשימה ימינה תגרום לתצוגה של תיבת הרשימה.

עלינו להרחיב איכשהו את תיבת הרשימה משמאל כאשר זהו המצב, ולא מימין!

ל- CB_SETDROPPEDWIDTH אין דרך לציין באיזה כיוון (משמאל או ימין) להרחיב את תיבת הרשימה.

הפיתרון: WM_CTLCOLORLISTBOX

בדיוק כשמוצגת הרשימה הנפתחת Windows שולח את הודעת WM_CTLCOLORLISTBOX לחלון האב של תיבת רשימה - לתיבת המשולבת שלנו.

היכולת לטפל ב- WM_CTLCOLORLISTBOX עבור הקומבוקס הקצה הימני יפתור את הבעיה.

חלון הקב"ה
כל בקרת VCL חושפת את המאפיין WindowProc - הנוהל המגיב להודעות שנשלחו לפקד. אנו יכולים להשתמש במאפיין WindowProc כדי להחליף או להחליף באופן זמני את נוהל החלון של הפקד.

להלן WindowProc שהשתנה עבור Combobox3 (זה ליד הקצה הימני):

// שונה ComboBox3 WindowProcתהליך TForm. ComboBox3WindowProc (var הודעה: TMessage); var
cr, lbr: TRECT; התחל// ציור את תיבת הרשימה עם פריטי קומבוקס
אם הודעה. Msg = WM_CTLCOLORLISTBOX לאחר מכן. התחל
GetWindowRect (ComboBox3.Handle, cr); // מלבן תיבת רשימה
GetWindowRect (הודעה. LParam, lbr); // העבר אותו שמאלה כדי להתאים לגבול הימניאם cr. מימין <> lbr. ימין לאחר מכן
MoveWindow (הודעה. LParam, lbr. שמאל- (lbr. Clbr ימני. מימין), lbr. למעלה, lbr. ימינה. שמאל, lbr. Lbr-bottom. למעלה, נכון); סוףאחר
ComboBox3WindowProcORIGINAL (הודעה); סוף; 

אם ההודעה שהתיבה המשולבת שלנו מקבלת היא WM_CTLCOLORLISTBOX אנו מקבלים את מלבן החלון שלה, אנו מקבלים גם את המלבן של תיבת הרשימה שתוצג (GetWindowRect). אם נראה שתיבת הרשימה תופיע יותר מצד ימין - אנו מעבירים אותה שמאלה כך שתיבת המשולבת והגבול הימני של תיבת הרשימה זהה. קל כמו זה :)

אם ההודעה אינה WM_CTLCOLORLISTBOX אנו פשוט קוראים לנוהל הטיפול בהודעות המקורי לתיבת המשולבת (ComboBox3WindowProcORIGINAL).

לבסוף, כל זה יכול לעבוד אם הגדרנו אותו נכון (במטפל האירועים OnCreate עבור הטופס):

// OnCreate של הטופסתהליך TForm. FormCreate (שולח: TObject); התחל
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // צרף WindowProc שונה / מותאם אישית עבור ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; סוף; 

איפה בהצהרת הטופס יש לנו (שלם):

סוג
TForm = מעמד(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;תהליך FormCreate (שולח: TObject); פרטי
ComboBox3WindowProcORIGINAL: TWndMethod; תהליך ComboBox3WindowProc (var הודעה: TMessage); ציבורי{הצהרות פומביות}סוף; 

וזה הכל. כולם מטופלים :)

instagram story viewer