Question Estou criando um ComboBox Personalizado

Status
Not open for further replies.

Nilson

New member
Joined
Jul 11, 2008
Messages
1
Programming Experience
3-5
encontrei um problema na hora de carregar o ListBox sobre os objeto no formulário.
Ex. Se eu colocar ele Dentro de uma tabcontrol ou tableLayoutPanel o listbox não fica sobre os objeto.
Ai tentei alguma abordagem se sucesso.
Quando Consigo colocar o listbox sobre os controles ele fica fora da posição, que ele deveria ficar, que seria logo abaixo do textobox e do button.
vou deixar uma imagem para vocês verem como ele fica.

(Obs. Postei este código no fórum da Microsoft e fui banido do fórum por esta postagem) Decepcionante.

Se alguém puder me ajuda Agradeço.

veja código do controle


ControleComboBox:
 public partial class ComboBoxNCMD : UserControl
 {

     private Panel loadingPanel;
     private Label loadingLabel;



     private Panel comboPanel;
     private ListBox listBox;
     private Button dropdownButton;
     private TextBox textBox;

     private bool isDroppedDown = false;

     private int borderSize = 5;
     private int borderRadius = 15;

     // Propriedades para manipular as cores e bordas
     public Color BorderColor { get; set; } = Color.FromArgb(138, 43, 226); // Cor roxa para a borda
     public Color BackColorCustom { get; set; } = Color.FromArgb(11, 7, 17); // Cor escura de fundo
     public Color FundoLista { get; set; } = Color.FromArgb(35, 32, 39); // Cor escura do fundo da lista
     public Color TextColor { get; set; } = Color.White; // Cor do texto

     public int BorderSize
     {
         get { return borderSize; }
         set { borderSize = value; this.Invalidate(); }
     }
     public int BorderRadius
     {
         get { return borderRadius; }
         set { borderRadius = value; this.Invalidate(); }
     }


     // public bool CarregaDadosNoClick { get; set; } = true;




     private int TamanhoControle = 30;
     private IContainer components;


     private string[] items = new string[0];

     [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
     public string[] Items
     {
         get { return items; }
         set
         {
             items = value;
             UpdateListBoxItems(); // Atualize o ListBox e o TextBox quando Items é definido
             this.Invalidate();
         }

     }

     //private string[] items=null;

     //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
     //public string[] Items
     //{
     //    get { return items; }
     //    set
     //    {
     //        items = value;
     //    }
     //}

     public ComboBoxNCMD()
     {
         AdjustHeightToFont();

         InitializeComponent();
         InitializeCustomComboBox();

         InitializeLoadingPanel();


     }
     private void InitializeComponent()
     {
         SuspendLayout();
         //
         // ComboBoxNCMD
         //
         Name = "ComboBoxNCMD";

         ResumeLayout(false);
     }




     //usando para mostrar a mensagemde aguarde


     private void InitializeLoadingPanel()
     {
         // Inicializa o painel de carregamento
         loadingPanel = new Panel
         {
             Size = new Size(200, 100), // Ajuste o tamanho conforme necessário
             Location = new Point(0, 0),
             BackColor = Color.FromArgb(0, 0, 0, 0), // Cor de fundo transparente
             Dock = DockStyle.Fill, // Preenche todo o espaço do UserControl
             Visible = false // Inicialmente invisível
         };

         // Inicializa o rótulo de carregamento
         loadingLabel = new Label
         {
             Text = "Aguarde...",
             ForeColor = Color.White,
             BackColor = Color.FromArgb(0, 0, 0, 128), // Cor de fundo semi-transparente
             TextAlign = ContentAlignment.MiddleCenter,
             Dock = DockStyle.Fill // Preenche todo o painel
         };

         // Adiciona o rótulo ao painel
         loadingPanel.Controls.Add(loadingLabel);

         // Adiciona o painel ao UserControl
         this.Controls.Add(loadingPanel);

         this.LostFocus += ComboBoxNCMD_LostFocus;
         dropdownButton.LostFocus += ComboBoxNCMD_LostFocus;
         textBox.LostFocus += ComboBoxNCMD_LostFocus;

     }

     private void ComboBoxNCMD_LostFocus(object sender, EventArgs e)
     {
         if (isDroppedDown)
         {
             if (listBox.Focused == false)
             {
                 listBox.Visible = false;
                 isDroppedDown = false;
                 this.Height = TamanhoControle;
             }
         }
     }

     private void ShowLoadingPanel()
     {
         loadingPanel.Visible = true;
         // Caso o painel esteja em cima de outros controles, você pode garantir que ele esteja à frente
         loadingPanel.BringToFront();
     }

     private void HideLoadingPanel()
     {
         loadingPanel.Visible = false;
     }

     /// <summary>
     /// fin da mensagem de aguarde
     /// </summary>


     private void InitializeCustomComboBox()
     {
         // Inicializa o Panel que irá conter o TextBox e o Button
         comboPanel = new Panel
         {
             Width = this.Width - 4, // Ajuste para deixar espaço para a borda
             Height = TamanhoControle - 4, // Ajuste para a borda
             Location = new Point(2, 2), // Posicionado com espaço para a borda
             BackColor = BackColorCustom,
             Padding = new Padding(BorderSize)
         };

         // Inicializa o botão do dropdown
         dropdownButton = new Button
         {
             Width = 30,
             Height = TamanhoControle - 4, // Ajuste para a borda
             Location = new Point(this.Width - 34, 2), // Ajuste para a borda
             FlatStyle = FlatStyle.Flat,
             Image = CreateArrowImage(), // Cria um ícone de seta personalizado
             BackColor = BackColorCustom,
             FlatAppearance = { BorderSize = 0, MouseOverBackColor = Color.Transparent, MouseDownBackColor = Color.Transparent },
             TabStop = false,

         };

         // Inicializa o TextBox (área de texto)
         textBox = new TextBox
         {
             Width = this.Width - 34,
             Location = new Point(2, 6),
             ReadOnly = false,
             BackColor = BackColorCustom,
             ForeColor = TextColor,
             BorderStyle = BorderStyle.None,
             AutoCompleteMode = AutoCompleteMode.SuggestAppend,
             AutoCompleteSource = AutoCompleteSource.CustomSource,
         };

         // Inicializa o ListBox (a lista suspensa)
         listBox = new ListBox
         {
             Visible = false,
             Width = this.Width - 4, // Ajuste para a borda
             Height = 100,
             Location = new Point(2, TamanhoControle + 2), // Ajuste para a borda
             BackColor = FundoLista,
             ForeColor = TextColor,
             BorderStyle = BorderStyle.None,
             HorizontalScrollbar = true,

         };

         // Adiciona eventos
         dropdownButton.Click += DropdownButton_Click;
         //listBox.SelectedIndexChanged += ListBox_SelectedIndexChanged;
         listBox.Click += ListBox_Click;
         listBox.KeyDown += ListBox_KeyDown;
         textBox.Enter += TextBox_Enter;
         textBox.KeyDown += TextBox_KeyDown;

         // Adiciona o TextBox e o Button no Panel
         comboPanel.Controls.Add(textBox);
         comboPanel.Controls.Add(dropdownButton);
         this.Controls.Add(listBox);


         this.Controls.Add(comboPanel);



         ApplyColors();


     }

     // aqui e para indentificar a saida do controle

     // Evento para fechar a lista quando o usuário clicar fora do controle
     private void ParentForm_MouseDown(object sender, MouseEventArgs e)
     {
         if (isDroppedDown && !this.Bounds.Contains(e.Location))
         {
             listBox.Visible = false;
             isDroppedDown = false;
             this.Height = TamanhoControle;
         }
     }

     protected override void OnParentChanged(EventArgs e)
     {
         base.OnParentChanged(e);

         if (this.ParentForm != null)
         {
             this.ParentForm.MouseDown += ParentForm_MouseDown;
         }
     }
     //fim das função de vereficação




     private void ListBox_KeyDown(object sender, KeyEventArgs e)
     {
         if (e.KeyCode == Keys.Enter)
         {
             ListBox_Click(listBox, new EventArgs());
         }
     }

     private void ListBox_Click(object sender, EventArgs e)
     {
         if (listBox.SelectedIndex != -1)
         {
             textBox.Text = listBox.SelectedItem.ToString();
             listBox.Visible = false;
             isDroppedDown = false;
             this.Height = TamanhoControle;
         }
     }

     private void TextBox_KeyDown(object sender, KeyEventArgs e)
     {
         if (e.KeyCode == Keys.Up)
         {
             if (!isDroppedDown)
             {
                 this.Height = 125;
                 listBox.Visible = true;
                 listBox.BringToFront();
                 isDroppedDown = true;
             }
             if (listBox.Items.Count > 0)
             {
                 // Seleciona o último item
                 int ultimoIndice = 0;
                 listBox.SetSelected(ultimoIndice, true);

                 // Define o foco no ListBox
                 listBox.Focus();
             }

         }
         else if (e.KeyCode == Keys.Down)
         {
             if (!isDroppedDown)
             {
                 this.Height = 125;
                 listBox.Visible = true;
                 listBox.BringToFront();
                 isDroppedDown = true;
             }
             if (listBox.Items.Count > 0)
             {
                 // Seleciona o último item
                 int ultimoIndice = listBox.Items.Count - 1;
                 listBox.SetSelected(ultimoIndice, true);

                 // Define o foco no ListBox
                 listBox.Focus();
             }
         }
     }

     // Método para ajustar a altura do controle com base na fonte
     private void AdjustHeightToFont()
     {
         int textHeight = TextRenderer.MeasureText("A", this.Font).Height;
         this.Height = textHeight + 15;
         TamanhoControle = this.Height;
     }

     private void TextBox_Enter(object sender, EventArgs e)
     {
         UpdateListBoxItems();
         this.Height = TamanhoControle;
     }

     private void DropdownButton_Click(object sender, EventArgs e)
     {
         if (!isDroppedDown)
         {
             ShowListBox();
             //this.Height = 125;
             //listBox.Visible = true;

             //listBox.BringToFront();
             isDroppedDown = true;
         }
         else
         {
             HideListBox();
             //listBox.Visible = false;
             isDroppedDown = false;
             this.Height = TamanhoControle;
         }

         //UpdateListBoxItems();


     }






     private void ShowListBox()
     {
         if (listBox.Items.Count == 0) return; // Não mostrar se não houver itens

         isDroppedDown = true;

         // Calcula a posição absoluta em relação ao formulário
         Point absoluteLocation = this.Parent.PointToScreen(this.Location);

         // Remove o ListBox do controle atual e adiciona ao formulário
         Form parentForm = this.FindForm();
         if (!parentForm.Controls.Contains(listBox))
         {
             parentForm.Controls.Add(listBox);
         }

         // Define a posição e o tamanho do ListBox
         listBox.Location = new Point(absoluteLocation.X, absoluteLocation.Y + this.Height);
         listBox.Width = this.Width;
         listBox.Height = Math.Min(200, listBox.Items.Count * listBox.ItemHeight); // Altura máxima de 200px

         listBox.BringToFront();
         listBox.Visible = true;



         // Adiciona o evento para ocultar o ListBox ao clicar fora dele
         parentForm.Click += Form_ClickOutside;


     }




     private void HideListBox()
     {

         //listBox.Visible = false;
         //isDroppedDown = false;

         // Remove o ListBox do controle pai
         this.Parent.Controls.Remove(listBox);

         // Remove o evento de clique fora quando o ListBox é fechado
         this.FindForm().Click -= Form_ClickOutside;
     }

     private void Form_ClickOutside(object sender, EventArgs e)
     {
         // Oculta o ListBox quando clicar fora da área dele
         if (!listBox.Bounds.Contains(Cursor.Position))
         {
             HideListBox();
         }
     }

     private void UpdateListBoxItems()
     {
         ShowLoadingPanel();



         listBox.Items.Clear();
         textBox.AutoCompleteCustomSource.Clear();
         if (items != null)
         {
             if (items.Length > 0)
             {
                 foreach (var item in items)
                 {
                     listBox.Items.Add(item);
                     textBox.AutoCompleteCustomSource.Add(item);
                 }
             }
         }
         HideLoadingPanel();


     }

     private void ListBox_SelectedIndexChanged(object sender, EventArgs e)
     {
         if (listBox.SelectedIndex != -1)
         {
             textBox.Text = listBox.SelectedItem.ToString();
             listBox.Visible = false;
             isDroppedDown = false;
             this.Height = TamanhoControle;
         }
     }

     // Método para desenhar as bordas personalizadas
     private void PaintBorders(Graphics g, Rectangle rect, Color borderColor)
     {
         int borderRadius = this.BorderRadius;
         int borderSize = this.BorderSize;

         using (GraphicsPath path = new GraphicsPath())
         using (Pen pen = new Pen(borderColor, borderSize))
         {
             // Desenhe um retângulo com bordas arredondadas
             path.AddArc(rect.X, rect.Y, borderRadius, borderRadius, 180, 90);
             path.AddArc(rect.Right - borderRadius, rect.Y, borderRadius, borderRadius, 270, 90);
             path.AddArc(rect.Right - borderRadius, rect.Bottom - borderRadius, borderRadius, borderRadius, 0, 90);
             path.AddArc(rect.X, rect.Bottom - borderRadius, borderRadius, borderRadius, 90, 90);
             path.CloseFigure();

             g.DrawPath(pen, path);
         }
     }

     protected override void OnPaint(PaintEventArgs e)
     {
         base.OnPaint(e);

         // Desenha a borda no Panel
         Rectangle panelRect = new Rectangle(comboPanel.Location.X - 2, comboPanel.Location.Y - 2, comboPanel.Width + 4, comboPanel.Height + 4);
         PaintBorders(e.Graphics, panelRect, BorderColor);

         // Desenha a borda no ListBox se ele estiver visível
         if (isDroppedDown)
         {
             Rectangle listBoxRect = new Rectangle(listBox.Location.X - 2, listBox.Location.Y - 2, listBox.Width + 4, listBox.Height + 4);
             PaintBorders(e.Graphics, listBoxRect, BorderColor);
         }

         PaintRoundedBorders(e.Graphics, panelRect, BorderColor);
     }

     private void PaintRoundedBorders(Graphics g, Rectangle rect, Color borderColor)
     {
         int borderRadius = 10; // Ajuste o valor conforme necessário
         using (GraphicsPath path = new GraphicsPath())
         {
             path.AddArc(rect.X, rect.Y, borderRadius, borderRadius, 180, 90);
             path.AddArc(rect.X + rect.Width - borderRadius, rect.Y, borderRadius, borderRadius, 270, 90);
             path.AddArc(rect.X + rect.Width - borderRadius, rect.Y + rect.Height - borderRadius, borderRadius, borderRadius, 0, 90);
             path.AddArc(rect.X, rect.Y + rect.Height - borderRadius, borderRadius, borderRadius, 90, 90);
             path.CloseFigure();

             using (Pen pen = new Pen(borderColor, 2))
             {
                 g.DrawPath(pen, path);
             }
         }
     }

     public void ApplyColors()
     {
         comboPanel.BackColor = BackColorCustom;
         listBox.BackColor = FundoLista;
         dropdownButton.BackColor = BackColorCustom;
         textBox.BackColor = BackColorCustom;

         listBox.ForeColor = TextColor;
         dropdownButton.ForeColor = TextColor;
         textBox.ForeColor = TextColor;

         listBox.BringToFront();


         PaintBorders(this.CreateGraphics(), this.ClientRectangle, BorderColor);
     }

     private Image CreateArrowImage()
     {
         Bitmap arrowImage = new Bitmap(16, 16);
         using (Graphics g = Graphics.FromImage(arrowImage))
         {
             g.Clear(Color.Transparent);
             Pen pen = new Pen(Color.FromArgb(138, 43, 226), 2);
             g.DrawLine(pen, 4, 6, 8, 10);
             g.DrawLine(pen, 8, 10, 12, 6);
         }
         return arrowImage;
     }


     protected override void OnResize(EventArgs e)
     {
         base.OnResize(e);

         if (textBox != null && dropdownButton != null && listBox != null && comboPanel != null)
         {
             comboPanel.Width = this.Width - 4;
             textBox.Width = this.Width - 34;
             dropdownButton.Location = new Point(this.Width - 34, 2);
             listBox.Width = this.Width - 4;
         }
     }




 }
 

Attachments

  • WhatsApp Image 2024-09-08 at 14.51.30.jpeg
    WhatsApp Image 2024-09-08 at 14.51.30.jpeg
    121.1 KB · Views: 4
Please repost in English.
 
Status
Not open for further replies.
Back
Top