تحجيم عرض قائمة منسدلة ComboBox

ال TComboBox مكون يجمع بين مربع تحرير وقائمة "اختيار" للتمرير. يمكن للمستخدمين تحديد عنصر من القائمة أو الكتابة مباشرة في مربع التحرير.

قائمة منسدلة

عندما يكون مربع التحرير والسرد في حالة منسدلة ، يرسم Windows نوع عنصر تحكم مربع قائمة لعرض عناصر مربع التحرير والسرد للتحديد.

ال خاصية DropDownCount يحدد الحد الأقصى لعدد العناصر المعروضة في القائمة المنسدلة.

ال عرض القائمة المنسدلة بشكل افتراضي ، يساوي عرض مربع التحرير والسرد.

عندما يتجاوز طول (سلسلة) العناصر عرض مربع التحرير والسرد ، يتم عرض العناصر على أنها قطع!

لا يوفر TComboBox طريقة لتعيين عرض القائمة المنسدلة الخاصة به :(

تحديد عرض قائمة منسدلة ComboBox

يمكننا تحديد عرض القائمة المنسدلة عن طريق إرسال خاص رسالة Windows إلى مربع التحرير والسرد. الرسالة CB_SETDROPPEDWIDTH ويرسل الحد الأدنى للعرض المسموح به بالبكسل لمربع قائمة مربع التحرير والسرد.

لتشفير حجم القائمة المنسدلة إلى 200 بكسل مثلاً ، يمكنك القيام بما يلي:


SendMessage (theComboBox. مقبض ، CB_SETDROPPEDWIDTH ، 200 ، 0) ؛ 

لا بأس بهذا إلا إذا كنت متأكدًا من كل صندوق البريد الخاص بك. العناصر لا تزيد عن 200 بكسل (عند رسمها).

instagram viewer

لضمان عرض قائمة منسدلة دائمًا بعرض كافٍ ، يمكننا حساب العرض المطلوب.

فيما يلي وظيفة للحصول على العرض المطلوب للقائمة المنسدلة وتعيينها:

إجراء ComboBox_AutoWidth (مقدار ثابت theComboBox: TCombobox) ؛ مقدار ثابت
HORIZONTAL_PADDING = 4 ، فار
itemsFullWidth: عدد صحيح ؛ idx: عدد صحيح ؛ itemWidth: عدد صحيح ؛ ابدأ
itemsFullWidth: = 0؛ // الحصول على الحد الأقصى المطلوب من العناصر في حالة القائمة المنسدلةإلى عن على معرف: = 0 إلى -1 + theComboBox. العناصر. العد فعلابدأ
itemWidth: = theComboBox. اللوحة القماشية. TextWidth (theComboBox. البنود [idx]) ؛ Inc (itemWidth، 2 * HORIZONTAL_PADDING) ؛ إذا (itemWidth> itemsFullWidth) ثم itemsFullWidth: = itemWidth؛ النهاية; // قم بتعيين عرض القائمة المنسدلة إذا لزم الأمرإذا (itemsFullWidth> theComboBox. العرض) ثم. ابدأ// تحقق مما إذا كان هناك شريط تمريرإذا theComboBox. DropDownCount ثم
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL) ؛ SendMessage (theComboBox. مقبض ، CB_SETDROPPEDWIDTH ، itemsFullWidth ، 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 (فار الرسالة: TMessage) ؛ فار
cr ، lbr: TRect ؛ ابدأ// رسم مربع القائمة مع عناصر مربع التحرير والسرد
إذا الرسالة. Msg = WM_CTLCOLORLISTBOX ثم. ابدأ
GetWindowRect (ComboBox3.Handle، cr) ؛ // مستطيل مربع قائمة
GetWindowRect (رسالة. LParam ، lbr) ؛ // انقله إلى اليسار لمطابقة الحد الأيمنإذا سجل تجاري. يمين <> lbr. حق ثم
MoveWindow (رسالة. LParam ، lbr. اليسار- (lbr. حق clbr. يمين) ، lbr. الأعلى ، lbr. اليمين- lbr. اليسار ، ر. أسفل- lbr. الأعلى ، صحيح) ؛ النهايةآخر
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 (فار الرسالة: TMessage) ؛ عامة{الإعلانات العامة}النهاية; 

وهذا كل شيء. التعامل مع جميع :)