los TComboBox El componente combina un cuadro de edición con una lista desplazable de "selección". Los usuarios pueden seleccionar un elemento de la lista o escribir directamente en el cuadro de edición.
La lista desplegable
Cuando un cuadro combinado está en estado desplegable, Windows dibuja un tipo de control de cuadro de lista para mostrar los elementos del cuadro combinado para su selección.
los Propiedad DropDownCount especifica el número máximo de elementos que se muestran en la lista desplegable.
los ancho de la lista desplegable sería, por defecto, igual al ancho del cuadro combinado.
Cuando la longitud (de una cadena) de elementos excede el ancho del cuadro combinado, los elementos se muestran como límite.
TComboBox no proporciona una forma de establecer el ancho de su lista desplegable :(
Arreglando el ancho de la lista desplegable de ComboBox
Podemos establecer el ancho de la lista desplegable enviando un especial Mensaje de Windows al cuadro combinado. El mensaje es CB_SETDROPPEDWIDTH y envía el ancho mínimo permitido, en píxeles, del cuadro de lista de un cuadro combinado.
Para codificar el tamaño de la lista desplegable a, digamos, 200 píxeles, puede hacer lo siguiente:
SendMessage (theComboBox. Asa, CB_SETDROPPEDWIDTH, 200, 0);
Esto solo está bien si está seguro de que todos sus theComboBox. Los elementos no tienen más de 200 px (cuando se dibujan).
Para garantizar que siempre tengamos la lista desplegable lo suficientemente amplia, podemos calcular el ancho requerido.
Aquí hay una función para obtener el ancho requerido de la lista desplegable y configurarlo:
procedimiento ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
itemsFullWidth: entero; idx: entero; itemWidth: entero; empezar
itemsFullWidth: = 0; // obtener el máximo necesario con los elementos en estado desplegablepara idx: = 0 a -1 + theComboBox. Artículos. Contar hacerempezar
itemWidth: = theComboBox. Lona. TextWidth (theComboBox. Artículos [idx]); Inc (itemWidth, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) luego itemsFullWidth: = itemWidth; final; // establece el ancho del menú desplegable si es necesarioSi (itemsFullWidth> theComboBox. Ancho) entonces. empezar// verifica si habría una barra de desplazamientoSi theComboBox. DropDownCount luego
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. Handle, CB_SETDROPPEDWIDTH, itemsFullWidth, 0); final; final;
El ancho de la cadena más larga se utiliza para el ancho de la lista desplegable.
¿Cuándo llamar a ComboBox_AutoWidth?
Si rellena previamente la lista de elementos (en tiempo de diseño o al crear el formulario), puede llamar al procedimiento ComboBox_AutoWidth dentro del formulario OnCreate controlador de eventos.
Si cambia dinámicamente la lista de elementos del cuadro combinado, puede llamar al procedimiento ComboBox_AutoWidth dentro del OnDropDown controlador de eventos: ocurre cuando el usuario abre la lista desplegable.
Una prueba
Para una prueba, tenemos 3 cuadros combinados en un formulario. Todos tienen elementos con su texto más ancho que el ancho real del cuadro combinado. El tercer cuadro combinado se coloca cerca del borde derecho del borde del formulario.
La propiedad Items, para este ejemplo, está precargada: llamamos a nuestro ComboBox_AutoWidth en el controlador de eventos OnCreate para el formulario:
// OnCreate del formularioprocedimiento TForm. FormCreate (remitente: TObject); empezar
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); final;
¡No hemos llamado a ComboBox_AutoWidth para Combobox1 para ver la diferencia!
Tenga en cuenta que, cuando se ejecuta, la lista desplegable de Combobox2 será más amplia que Combobox2.
La lista desplegable completa está cortada para "Colocación cerca del borde derecho"
Para Combobox3, el que se encuentra cerca del borde derecho, la lista desplegable se corta.
Enviar el CB_SETDROPPEDWIDTH siempre extenderá el cuadro de lista desplegable a la derecha. Cuando su cuadro combinado está cerca del borde derecho, extender el cuadro de lista más a la derecha daría como resultado que se corte el cuadro de lista.
Necesitamos extender de alguna manera el cuadro de lista a la izquierda cuando este sea el caso, ¡no a la derecha!
CB_SETDROPPEDWIDTH no tiene forma de especificar en qué dirección (izquierda o derecha) extender el cuadro de lista.
Solución: WM_CTLCOLORLISTBOX
Justo cuando se muestra la lista desplegable, Windows envía el mensaje WM_CTLCOLORLISTBOX a la ventana principal de un cuadro de lista, a nuestro cuadro combinado.
Ser capaz de manejar el WM_CTLCOLORLISTBOX para el cuadro combinado de borde casi a la derecha resolvería el problema.
El Todopoderoso WindowProc
Cada control VCL expone la propiedad WindowProc, el procedimiento que responde a los mensajes enviados al control. Podemos usar la propiedad WindowProc para reemplazar o subclasificar temporalmente el procedimiento de ventana del control.
Aquí está nuestro WindowProc modificado para Combobox3 (el que está cerca del borde derecho):
// ComboBox3 WindowProc modificadoprocedimiento TForm. ComboBox3WindowProc (var Mensaje: TMessage); var
cr, lbr: TRect; empezar// dibujar el cuadro de lista con elementos del cuadro combinado
si mensaje. Msg = WM_CTLCOLORLISTBOX entonces. empezar
GetWindowRect (ComboBox3.Handle, cr); // rectángulo de cuadro de lista
GetWindowRect (Mensaje. LParam, lbr); // muévelo a la izquierda para que coincida con el borde derechoSi cr. Derecha <> lbr. Derecho luego
MoveWindow (Mensaje. LParam, lbr. Izquierda- (lbr. Right-clbr. Derecha), lbr. Arriba, lbr. Derecha-lbr. Izquierda, lbr. Bottom-lbr. Arriba, cierto); finalmás
ComboBox3WindowProcORIGINAL (Mensaje); final;
Si el mensaje que recibe nuestro cuadro combinado es WM_CTLCOLORLISTBOX, obtenemos el rectángulo de su ventana, también obtenemos el rectángulo del cuadro de lista que se mostrará (GetWindowRect). Si parece que el cuadro de lista aparecerá más a la derecha, lo movemos a la izquierda para que el cuadro combinado y el borde derecho del cuadro de lista sean los mismos. Tan fácil como eso :)
Si el mensaje no es WM_CTLCOLORLISTBOX, simplemente llamamos al procedimiento de manejo de mensajes original para el cuadro combinado (ComboBox3WindowProcORIGINAL).
Finalmente, todo esto puede funcionar si lo hemos configurado correctamente (en el controlador de eventos OnCreate para el formulario):
// OnCreate del formularioprocedimiento TForm. FormCreate (remitente: TObject); empezar
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // adjuntar WindowProc modificado / personalizado para ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; final;
Donde en la declaración del formulario tenemos (completo):
tipo
TForm = clase(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;procedimiento FormCreate (remitente: TObject); privado
ComboBox3WindowProcORIGINAL: TWndMethod; procedimiento ComboBox3WindowProc (var Mensaje: TMessage); público{Declaraciones públicas}final;
Y eso es. Todo manejado :)