Zmiana szerokości rozwijanej szerokości ComboBox

The TComboBox składnik łączy pole edycyjne z przewijalną listą „wybierz”. Użytkownicy mogą wybrać element z listy lub wpisać bezpośrednio w pole edycji.

Lista rozwijana

Gdy pole kombi jest w stanie rozwijanym, system Windows rysuje formant pola listy, aby wyświetlić elementy pola kombi do wyboru.

The Właściwość DropDownCount określa maksymalną liczbę elementów wyświetlanych na liście rozwijanej.

The szerokość listy rozwijanej byłby domyślnie równy szerokości pola kombi.

Kiedy długość (sznurka) przedmiotów przekracza szerokość skrzynki, przedmioty są wyświetlane jako odcięte!

TComboBox nie zapewnia sposobu ustawienia szerokości listy rozwijanej :(

Naprawianie szerokości listy rozwijanej ComboBox

Możemy ustawić szerokość listy rozwijanej, wysyłając specjalną Komunikat Windows do pola kombi. Wiadomość jest CB_SETDROPPEDWIDTH i wysyła minimalną dopuszczalną szerokość pola listy pola kombi w pikselach.

Aby zakodować na stałe rozmiar listy rozwijanej, powiedzmy, 200 pikseli, możesz:


SendMessage (theComboBox. Uchwyt, CB_SETDROPPEDWIDTH, 200, 0); 
instagram viewer

Jest to w porządku tylko wtedy, gdy masz pewność, że cały theComboBox. Przedmioty nie mają więcej niż 200 pikseli (po narysowaniu).

Aby mieć pewność, że lista rozwijana jest zawsze wystarczająco szeroka, możemy obliczyć wymaganą szerokość.

Oto funkcja pozwalająca uzyskać wymaganą szerokość listy rozwijanej i ustawić ją:

procedura ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
itemsFullWidth: liczba całkowita; idx: liczba całkowita; itemWidth: liczba całkowita; zaczynać
itemsFullWidth: = 0; // uzyskaj maksimum potrzebne dla przedmiotów w stanie rozwijanymdla idx: = 0 do -1 + theComboBox. Przedmiotów. Liczyć robićzaczynać
itemWidth: = theComboBox. Brezentowy. TextWidth (theComboBox. Przedmioty [idx]); Inc (itemWidth, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) następnie itemsFullWidth: = itemWidth; koniec; // w razie potrzeby ustaw szerokość listy rozwijanejgdyby (itemsFullWidth> theComboBox. Szerokość). zaczynać// sprawdź, czy będzie pasek przewijaniagdyby theComboBox. DropDownCount następnie
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. Uchwyt, CB_SETDROPPEDWIDTH, itemsFullWidth, 0); koniec; koniec; 

Szerokość najdłuższego ciągu jest używana do szerokości listy rozwijanej.

Kiedy zadzwonić do ComboBox_AutoWidth?
Jeśli wstępnie wypełnisz listę elementów (w czasie projektowania lub podczas tworzenia formularza), możesz wywołać procedurę ComboBox_AutoWidth w formularzu OnCreate moduł obsługi zdarzeń.

Jeśli dynamicznie zmienisz listę elementów pola kombi, możesz wywołać procedurę ComboBox_AutoWidth wewnątrz OnDropDown obsługa zdarzeń - występuje, gdy użytkownik otworzy listę rozwijaną.

Badanie
Do testu mamy 3 pola kombi w formularzu. Wszystkie mają elementy o szerszym tekście niż rzeczywista szerokość pola kombi. Trzecie pole kombi jest umieszczone w pobliżu prawej krawędzi granicy formularza.

W tym przypadku właściwość Items jest wstępnie wypełniona - wywołujemy ComboBox_AutoWidth w module obsługi zdarzeń OnCreate dla formularza:

// Forma OnCreateprocedura TForm. FormCreate (Sender: TObject); zaczynać
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); koniec; 

Nie nazwaliśmy ComboBox_AutoWidth dla Combobox1, aby zobaczyć różnicę!

Zauważ, że po uruchomieniu lista rozwijana Combobox2 będzie szersza niż Combobox2.

Cała lista rozwijana jest odcięta dla „Umieszczenia w pobliżu prawej krawędzi”

W przypadku Combobox3, umieszczonego w pobliżu prawej krawędzi, lista rozwijana jest odcięta.

Wysłanie CB_SETDROPPEDWIDTH zawsze rozszerzy listę rozwijaną w prawo. Kiedy twój combobox znajduje się w pobliżu prawej krawędzi, rozszerzenie pola listy bardziej w prawo spowodowałoby odcięcie wyświetlania pola listy.

Musimy jakoś rozszerzyć pole listy w lewo, gdy tak jest, a nie w prawo!

CB_SETDROPPEDWIDTH nie ma możliwości określenia, w którym kierunku (w lewo lub w prawo), aby rozszerzyć pole listy.

Rozwiązanie: WM_CTLCOLORLISTBOX

Właśnie wtedy, gdy ma zostać wyświetlona lista rozwijana, system Windows wysyła komunikat WM_CTLCOLORLISTBOX do okna nadrzędnego pola listy - do naszego pola kombi.

Możliwość obsługi WM_CTLCOLORLISTBOX dla comboboxu blisko prawej krawędzi rozwiązałby problem.

Okno Wszechmogącego Proc
Każda kontrolka VCL ujawnia właściwość WindowProc - procedurę, która odpowiada na komunikaty wysyłane do kontrolki. Możemy użyć właściwości WindowProc, aby tymczasowo zastąpić lub podklasować procedurę okna kontrolki.

Oto nasz zmodyfikowany WindowProc dla Combobox3 (ten w pobliżu prawej krawędzi):

// zmodyfikowano ComboBox3 WindowProcprocedura TForm. ComboBox3WindowProc (var Wiadomość: TMessage); var
cr, lbr: TRect; zaczynać// rysowanie pola listy z elementami combobox
jeśli Wiadomość. Msg = WM_CTLCOLORLISTBOX. zaczynać
GetWindowRect (ComboBox3.Handle, cr); // prostokąt pola listy
GetWindowRect (komunikat. LParam, Ibr); // przesuń go w lewo, aby dopasować prawą ramkęgdyby cr. Prawo <> lbr. Dobrze następnie
MoveWindow (Wiadomość. LParam, lbr. Left- (lbr. Prawy klbr. Po prawej), lbr. Top, lbr. Right-lbr. Lewy, lbr. Bottom-lbr. Top, True); koniecjeszcze
ComboBox3WindowProcORIGINAL (komunikat); koniec; 

Jeśli wiadomość, którą otrzymuje nasze pole kombi, to WM_CTLCOLORLISTBOX, otrzymujemy prostokąt jego okna, otrzymujemy również prostokąt pola listy do wyświetlenia (GetWindowRect). Jeśli wydaje się, że pole listy pojawi się bardziej po prawej stronie - przesuwamy go w lewo, aby pole kombi i prawa ramka listy były takie same. To takie proste :)

Jeśli wiadomość nie jest WM_CTLCOLORLISTBOX, po prostu wywołujemy procedurę obsługi oryginalnej wiadomości dla pola kombi (ComboBox3WindowProcORIGINAL).

Wreszcie, wszystko to może działać, jeśli ustawiliśmy go poprawnie (w module obsługi zdarzeń OnCreate dla formularza):

// Forma OnCreateprocedura TForm. FormCreate (Sender: TObject); zaczynać
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // dołącz zmodyfikowane / niestandardowe WindowProc dla ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; koniec; 

Gdzie w deklaracji formularza mamy (całość):

rodzaj
TForm = klasa(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;procedura FormCreate (Sender: TObject); prywatny
ComboBox3WindowProcORIGINAL: TWndMethod; procedura ComboBox3WindowProc (var Wiadomość: TMessage); publiczny{Oświadczenia publiczne}koniec; 

I to wszystko. Wszystkie obsługiwane :)

instagram story viewer