¿Cómo puedo tener TComboBox con algunos elementos que están deshabilitados? Necesito que el usuario vea estos elementos, pero no pueda seleccionarlos.Delphi: ¿Es posible tener un cuadro combinado con elementos desactivados?
Gracias!
¿Cómo puedo tener TComboBox con algunos elementos que están deshabilitados? Necesito que el usuario vea estos elementos, pero no pueda seleccionarlos.Delphi: ¿Es posible tener un cuadro combinado con elementos desactivados?
Gracias!
Sí, y así es como se hace:
Caiga una TComboBox
en su forma, y establecer Style
a csOwnerDrawFixed
. A continuación, añadir los controladores de eventos
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
const
INDENT = 3;
begin
with TComboBox(Control) do
begin
FillRect(Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
inc(Rect.Left, INDENT);
if boolean(Items.Objects[Index]) then
SetTextColor(Canvas.Handle, clBlack)
else
SetTextColor(Canvas.Handle, clGray);
DrawText(Canvas.Handle,
PChar(Items[Index]),
length(Items[Index]),
Rect,
DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS)
end;
end;
y
procedure TForm1.ComboBox1CloseUp(Sender: TObject);
begin
with TComboBox(Sender) do
if (ItemIndex <> -1) and not boolean(Items.Objects[ItemIndex]) then
begin
beep;
Perform(CB_SHOWDROPDOWN, integer(true), 0);
end;
end;
Además, en la sección de interfaz de su formulario, antes de la declaración de la clase de formulario, agregue
TComboBox = class(StdCtrls.TComboBox)
protected
procedure WndProc(var Message: TMessage); override;
end;
y aplicar el WndProc
como
procedure TComboBox.WndProc(var Message: TMessage);
function NextItemIsDisabled: boolean;
begin
result := (ItemIndex < Items.Count - 1) and
not boolean(Items.Objects[ItemIndex + 1]);
end;
procedure SelectNextEnabledItem;
var
i: Integer;
begin
for i := ItemIndex + 1 to Items.Count - 1 do
if boolean(Items.Objects[i]) then
begin
ItemIndex := i;
Exit;
end;
beep;
end;
procedure KillMessages;
var
msg: TMsg;
begin
while PeekMessage(msg,
Handle,
WM_KEYFIRST,
WM_KEYLAST,
PM_REMOVE) do;
end;
function PrevItemIsDisabled: boolean;
begin
result := (ItemIndex > 0) and
not boolean(Items.Objects[ItemIndex - 1]);
end;
procedure SelectPrevEnabledItem;
var
i: Integer;
begin
for i := ItemIndex - 1 downto 0 do
if boolean(Items.Objects[i]) then
begin
ItemIndex := i;
Exit;
end;
beep;
end;
begin
case Message.Msg of
WM_KEYDOWN:
case Message.WParam of
VK_DOWN:
if NextItemIsDisabled then
begin
SelectNextEnabledItem;
KillMessages;
Exit;
end;
VK_UP:
if PrevItemIsDisabled then
begin
SelectPrevEnabledItem;
KillMessages;
Exit;
end;
end;
end;
inherited;
end;
Para probar el cuadro combinado, escribir, por ejemplo
procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1.Items.AddObject('Alpha', TObject(true));
ComboBox1.Items.AddObject('Beta', TObject(true));
ComboBox1.Items.AddObject('Gamma', TObject(false));
ComboBox1.Items.AddObject('Delta', TObject(true));
end;
Creo que se obtiene el significado de true
y false
aquí - que significa simplemente enabled
.
+1 por el esfuerzo, Andreas, aunque te dispararía si trabajáramos juntos y lo usaste (y también lo harían mis usuarios).
@Ken: Probablemente tampoco lo use, pero he visto este tipo de comboboxes no estándar cada vez más en los últimos años, especialmente en Internet (HTML + CSS + JavaScript), así que creo que no es * que * malo. –
Pero la aplicación de escritorio es * Windows *, que tiene estándares de interfaz de usuario para estas cosas. HTML/CSS/JS no lo hacen; prácticamente haces lo que quieres con ellos. (Pero te di el +1, aunque no estoy de acuerdo, tu respuesta fue acertada para la pregunta original.) :) –
No es fácil (y es una mala idea, ya que no es así como se comportan las cajas combinadas en Windows).
Tendría que dibujar usted mismo el cuadro combinado. Utilice la matriz Items.Objects para almacenar si el elemento está habilitado o deshabilitado, y verifique esa matriz antes de dibujar cada elemento para establecer los colores de manera apropiada.
También necesitaría manejar los eventos OnChange
y OnClick
, y agregar una forma de rastrear el último ItemIndex
seleccionado. En OnChange/OnClick
, desconecte el controlador de eventos, verifique el valor Objects[ItemIndex]
para ver si se permite una selección, si no configuró el ItemIndex
de nuevo en el último ItemIndex
seleccionado, y luego vuelve a habilitar el controlador de eventos.
¿Qué sucede si el usuario hace clic en el elemento aparentemente desactivado en el cuadro desplegable desplegable? El cuadro se cerrará y es posible que el usuario no se dé cuenta de que se revertió al último valor seleccionado. ¡Eso es confuso! –
Puede encontrar información adicional en el grupo de noticias aquí: http://groups.google.com/group/comp.lang.pascal.delphi.misc/browse_thread/thread/ea67221a7d3f7e13/17418f924fc64f43?lnk=raot&pli=1 – pritaeas
@Cosmin : De acuerdo. Como dije, no es así como funcionan los cuadros combinados en Windows. Por eso dije que era una idea terrible, y la tuya era mejor.También dije que no fue fácil. –
sólo tiene que añadir siguiente código en KeyPress
procedimiento
procedure Tform1.Combobox1editKeyPress(Sender: TObject; var Key: Char);
begin
Key:=#0;
end;
No es evidente por el título de la pregunta o de sus etiquetas, pero aquí es una implementación de un componente derivado de TComboBox con el apoyo elemento deshabilitado: http: // stackoverflow. com/questions/4356364 –
No haga esto. Viola lo que los usuarios esperan de los cuadros combinados. Encontrar otra forma. En cualquier caso, los comboboxes no son una buena forma de presentar datos al usuario de todos modos; si necesita que vean una descripción general de lo que pueden y no pueden hacer, no deberían tener que realizar un paso adicional (es decir, no tener presionar un botón desplegable). Todo se trata de la experiencia del usuario, ¡no te metas con eso! –