środa, 9 marca 2022

C# - Windows Form - Przesunięcie kontrolek na ekranie

W tym poście chciałbym opisać dynamiczną modyfikację kontrolek w Windows Form. 


Modyfikacja koloru panelu:


Gdy korzystamy z panelu (kontrola Panel, opcja zmiany działa z każdą kontrolką, w której można zmienić kolor) i chcemy zmienić jej kolor w trakcie działania programu. To możemy posłużyć się do tego celu TextBox.

Na samym początku wprowadzam ograniczenie aby kontrolka mogła przyjąć jedynie dane odpowiadające tylko wartością szesnastkowym. Tak aby uzyskać format koloru RGB888:

  1. private void TxtBox_OnlyHexValues_KeyPress(object sender, KeyPressEventArgs e)
  2. {
  3.     char c = e.KeyChar;
  4.     if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (char.IsControl(c))))
  5.     {
  6.         e.Handled = true;
  7.     }
  8. }

Kolor przetwarzany jest po wpisaniu 6 znaków:

  1. private void TxtBoxMaskColorRGB_TextChanged(object sender, EventArgs e)
  2. {
  3.     if (TxtBoxMaskColorRGB.Text.Length == 6)
  4.     {
  5.         Color colorValue = ColorTranslator.FromHtml("#" + TxtBoxMaskColorRGB.Text);
  6.         PanelMaskownica.BackColor = colorValue;
  7.     }
  8. }

Modyfikacja PictureBox:


Na samym początku trzeba utworzyć klasę PixtureBox, która pozwoli na przesuwanie obrazu na panelu:

  1.     class CustomPictureBox : PictureBox
  2.     {
  3.         public CustomPictureBox(IContainer container)
  4.         {
  5.             container.Add(this);
  6.         }
  7.  
  8.         Point point;
  9.  
  10.         protected override void OnMouseDown(MouseEventArgs e)
  11.         {
  12.             point = e.Location;
  13.             BringToFront();
  14.             base.OnMouseDown(e);
  15.         }
  16.  
  17.         protected override void OnMouseMove(MouseEventArgs e)
  18.         {
  19.             if (e.Button == MouseButtons.Left)
  20.             {
  21.                 this.Left += e.X - point.X;
  22.                 this.Top += e.Y - point.Y;
  23.                 BringToFront();
  24.             }
  25.             base.OnMouseMove(e);
  26.         }
  27.     }

Jest to dosyć popularna modyfikacja, łatwa do znalezienia w Internecie.

Aby obraz mógł wyświetlać kolor tła należy zastosować format PNG z transparentnym tłem. W Windows Form taki obraz przyjmie kolor tła w momencie załadowania obrazu. 

Ładowanie obrazu można wykonać przez wywołanie okna wyboru pliku (OpenFileDialog) z kontrolki button:

  1. private void BtnObraz1_Click(object sender, EventArgs e)
  2. {
  3.     OpenFileDialog open = new OpenFileDialog();
  4.     open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png";
  5.  
  6.     if (open.ShowDialog() == DialogResult.OK)
  7.     {
  8.         CuststomPictureBox1.Image = new Bitmap(open.FileName);
  9.         CuststomPictureBox1.BackColor = Color.Transparent;
  10.     }
  11. }

Aby obraz przyjmował kolor tła po jego przesunięciu po ekranie sprawdzam pozycję obrazu względem dwóch paneli jakie umieściłem na ekranie. Z nich pobieram kolor tła dla pictureBoxa:

  1. private void CuststomPictureBox6_MouseMove(object sender, MouseEventArgs e)
  2. {
  3.     PanelPosition_CustomPictureBox(CuststomPictureBox6.Location.X, CuststomPictureBox6.Location.Y, 6);
  4. }
  5.  
  6. private void PanelPosition_CustomPictureBox(int locationX, int locationY, int selectedPictureBox)
  7. {
  8.     int mainScreenPanelWidth = GetMainScreenPanelWidthSize();
  9.     int mainScreenPanelHeight = GetMainScreenPanelHeightSize();
  10.     int mainScreenPanelPosition_X = mainScreenPanelPositionX();
  11.     int mainScreenPanelPosition_Y = mainScreenPanelPositionY();
  12.  
  13.     if ((locationX >= mainScreenPanelPosition_X) &&
  14.         (locationX <= mainScreenPanelPosition_X + mainScreenPanelWidth) &&
  15.         (locationY >= mainScreenPanelPosition_Y) &&
  16.         (locationY <= mainScreenPanelPosition_Y + mainScreenPanelHeight))
  17.     {
  18.         Color colorValue = ColorTranslator.FromHtml("#" + TxtBoxDisplayColorRGB.Text);
  19.         ChangeBacgroundPictureBoxColor(selectedPictureBox, colorValue);
  20.     }
  21.     else
  22.     {
  23.         Color colorValue = ColorTranslator.FromHtml("#" + TxtBoxMaskColorRGB.Text);
  24.         ChangeBacgroundPictureBoxColor(selectedPictureBox, colorValue);
  25.     }
  26. }
  27.  
  28. private void ChangeBacgroundPictureBoxColor(int selectedPictureBox, Color selectColor)
  29. {
  30.     if(selectedPictureBox == 1)
  31.     {
  32.         CuststomPictureBox1.BackColor = selectColor;
  33.     }
  34.     else if (selectedPictureBox == 2)
  35.     {
  36.         CuststomPictureBox2.BackColor = selectColor;
  37.     }
  38.     else if (selectedPictureBox == 3)
  39.     {
  40.         CuststomPictureBox3.BackColor = selectColor;
  41.     }
  42.     else if (selectedPictureBox == 4)
  43.     {
  44.         CuststomPictureBox4.BackColor = selectColor;
  45.     }
  46.     else if (selectedPictureBox == 5)
  47.     {
  48.         CuststomPictureBox5.BackColor = selectColor;
  49.     }
  50.     else if (selectedPictureBox == 6)
  51.     {
  52.         CuststomPictureBox6.BackColor = selectColor;
  53.     }
  54. }

W celu usunięcia obrazu z kontrolki, po kliknięciu środkowego przycisku myszy czyszczę dane w kontrolce z obrazem.

  1. private void CuststomPictureBox6_MouseClick(object sender, MouseEventArgs e)
  2. {
  3.     if (e.Button == MouseButtons.Middle)
  4.     {
  5.         CuststomPictureBox6.Image = null;
  6.         CuststomPictureBox6.BackColor = Color.Transparent;
  7.     }
  8. }

Przesunięcie kontrolki:


W celu przesuniecie kontrolki na ekranie potrzebna jest obsługa trzech zdarzeń MouseUp, MouseDown oraz MouseMove:

  1. private void LabelTryb_MouseDown(object sender, MouseEventArgs e)
  2. {
  3.     mDown_LabelTryb = true;
  4. }
  5.  
  6. private void LabelTryb_MouseUp(object sender, MouseEventArgs e)
  7. {
  8.     mDown_LabelTryb = false;
  9. }
  10.  
  11. private void LabelTryb_MouseMove(object sender, MouseEventArgs e)
  12. {
  13.     if (mDown_LabelTryb)
  14.     {
  15.         LabelTryb.Location = new Point(LabelTryb.Location.X + e.Location.X, LabelTryb.Location.Y + e.Location.Y);
  16.         Label_ChangeColorBaseOnLocalization(LabelTryb.Location.X, LabelTryb.Location.Y, 1);
  17.     }
  18. }

Ruch obsługuje zmienna bool która ustawiana jest na wartość true jeśli nastąpiło kliknięcie na kontrolkę. W przesunięciu podawana jest nowa lokalizacja oraz nowy kolor tła bazujący na pozycji względem panelu. Identycznie jak to miało miejsce w przypadku kontrolki PictureBox.

Można także w dosyć łatwy sposób zmodyfikować wielkość czcionki podczas pracy programu:

  1. private void TxtBoxFontSize1_TextChanged(object sender, EventArgs e)
  2. {
  3.     if (System.Text.RegularExpressions.Regex.IsMatch(TxtBoxFontSize1.Text, "[^0-9]"))
  4.     {
  5.         MessageBox.Show("Pole może zawierać jedynie liczby");
  6.         TxtBoxFontSize1.Text = TxtBoxFontSize1.Text.Remove(TxtBoxFontSize1.Text.Length - 1);
  7.     }
  8.     else
  9.     {
  10.         if(!String.IsNullOrEmpty(TxtBoxFontSize1.Text))
  11.         {
  12.             LabelTryb.Font = new Font("Microsoft Sans Serif", int.Parse(TxtBoxFontSize1.Text), FontStyle.Bold);
  13.         }
  14.     }
  15. }

Dane o wielkości czcionki są pobierane z kontroli TextBox. Jeśli wartość jest poprawna to styl czcionki zostaje taki jaki był, natomiast wartość z pola tekstowego zastępuje wielkość czcionki.