Как получить ячейку из панели макета стола VB.Net -- vb.net поле с участием tablelayoutpanel пол Связанный проблема

How do I get the cell from a table layout panel vb.net


-1
vote

проблема

русский

Как получить, какую ячейку пользователь нажал, если он не имеет контроля в ячейке. То, что мне действительно нужно, для изображения появляются в месте ячейки, когда он нажал, но не в нем.

Я представляю, это будет похоже на этот псевдо код

 <код> if (x > y)   MACRO(x, y); do_something(); 0  

или что-то. Спасибо за любую помощь.

Английский оригинал

How do I get which cell the user clicked if it has no control in the cell. What I really need is for an image to appear at the cell location when it's clicked but not in it.

I imagine it would be similar to this pseudo code

myimage.location = get.cellLocation() 

or something. Thanks for any help.

</div
     

Список ответов

0
 
vote
vote
Лучший ответ
 

На основании вашей необходимости иметь таблицу стилей «Шахматы», которая принимает нажатие, я создал это. У меня не было необходимости в этом, но я подумал, что это будет веселая диверсия. Этот пример создает 63 клеток, поэтому очень близко к тому, что вы хотите. Так как он рассчитывается на лету, вы должны быть в состоянии переделать его для того, что вам нужно.

Во-первых, ваша форма будет настроена с PictureBox (проще рендер без расчета полей и athnot) с именем <код> picBoard , другой <код> PictureBox называется <код> picTile , а затем <код> Label назван <код> lblDetails стыкован внизу, чтобы действовать в качестве строки состояния. Мой <код> InitializeComponent выглядит так:

 <Код>   private void InitializeComponent()   {      this.picBoard = new System.Windows.Forms.PictureBox();      this.picTile = new System.Windows.Forms.PictureBox();      this.lblDetails = new System.Windows.Forms.Label();      ((System.ComponentModel.ISupportInitialize)(this.picBoard)).BeginInit();      ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();      this.SuspendLayout();      //       // picBoard      //       this.picBoard.Location = new System.Drawing.Point(12, 21);      this.picBoard.Name = "picBoard";      this.picBoard.Size = new System.Drawing.Size(360, 280);      this.picBoard.TabIndex = 0;      this.picBoard.TabStop = false;      //       // picTile      //       this.picTile.BackColor = System.Drawing.Color.Red;      this.picTile.Location = new System.Drawing.Point(143, 67);      this.picTile.Name = "picTile";      this.picTile.Size = new System.Drawing.Size(51, 51);      this.picTile.TabIndex = 1;      this.picTile.TabStop = false;      this.picTile.Visible = false;      //       // lblDetails      //       this.lblDetails.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;      this.lblDetails.Dock = System.Windows.Forms.DockStyle.Bottom;      this.lblDetails.Location = new System.Drawing.Point(0, 326);      this.lblDetails.Name = "lblDetails";      this.lblDetails.Size = new System.Drawing.Size(393, 23);      this.lblDetails.TabIndex = 2;      this.lblDetails.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;      //       // Form1      //       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;      this.ClientSize = new System.Drawing.Size(393, 349);      this.Controls.Add(this.lblDetails);      this.Controls.Add(this.picTile);      this.Controls.Add(this.picBoard);      this.Name = "Form1";      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;      this.Text = "Grid Test";      ((System.ComponentModel.ISupportInitialize)(this.picBoard)).EndInit();      ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();      this.ResumeLayout(false);    }   

Вот полная часть Form Code, а также пользовательский класс, <код> CellDetails , внизу (я не чувствовал, что сделать отдельный) Отказ Имейте в виду, что это просто то, что я создал в спешке, чтобы увидеть, как трудно было бы для вас. Если у вас есть какие-либо вопросы относительно того, что происходит, просто спросите.

 <Код> picBoard0  

Конечный результат выглядит что-то подобное:

Пример динамического сетки

Если вы знаете, сколько строк и столбцов, которые вы хотите, вы можете рассчитать его ширину / высоту ячейки, разделив <код> picBoard1 по количеству, а не предопределенным размером ячейки. Это также будет полезно, если вы можете изменить размер, что приведет к изменению размера ячейки. Просто измените код, чтобы рассчитать таким образом, а затем вызовите его <код> picBoard2 после размера. Вы, вероятно, захотите добавить строку, как <код> picBoard3 на вершине.

Это, вероятно, не нужно упомянуть, но если кто-то еще приходит вместе: если вам просто нужно ударить тестирование на невидимые клетки (без рендеринга), вы можете полностью удалить <код> picBoard4 событие. Если вы хотите сетки строки и не заполненные коробки, измените <код> picBoard5 на <код> picBoard6 и используйте <код> picBoard7 вместо <код> picBoard8 С <Кодом> picBoard9 , вы также можете сделать пунктирные линии, пунктирные и т. Д.

 

Based on your need for having a 'chess' style table that accepts clicking, I have created this. I didn't have a need for it, but I figured it would be a fun diversion. This example creates 63 cells, so it's very close to what you're wanting. Since it's calculated on the fly, you should be able to rework it for what you need.

First, your form will be set up with a PictureBox (easier to render without calculating margins and whatnot) named picBoard, another PictureBox called picTile, and then a Label named lblDetails docked at the bottom to act as a status bar. My InitializeComponent looks like this:

  private void InitializeComponent()   {      this.picBoard = new System.Windows.Forms.PictureBox();      this.picTile = new System.Windows.Forms.PictureBox();      this.lblDetails = new System.Windows.Forms.Label();      ((System.ComponentModel.ISupportInitialize)(this.picBoard)).BeginInit();      ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();      this.SuspendLayout();      //       // picBoard      //       this.picBoard.Location = new System.Drawing.Point(12, 21);      this.picBoard.Name = "picBoard";      this.picBoard.Size = new System.Drawing.Size(360, 280);      this.picBoard.TabIndex = 0;      this.picBoard.TabStop = false;      //       // picTile      //       this.picTile.BackColor = System.Drawing.Color.Red;      this.picTile.Location = new System.Drawing.Point(143, 67);      this.picTile.Name = "picTile";      this.picTile.Size = new System.Drawing.Size(51, 51);      this.picTile.TabIndex = 1;      this.picTile.TabStop = false;      this.picTile.Visible = false;      //       // lblDetails      //       this.lblDetails.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;      this.lblDetails.Dock = System.Windows.Forms.DockStyle.Bottom;      this.lblDetails.Location = new System.Drawing.Point(0, 326);      this.lblDetails.Name = "lblDetails";      this.lblDetails.Size = new System.Drawing.Size(393, 23);      this.lblDetails.TabIndex = 2;      this.lblDetails.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;      //       // Form1      //       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;      this.ClientSize = new System.Drawing.Size(393, 349);      this.Controls.Add(this.lblDetails);      this.Controls.Add(this.picTile);      this.Controls.Add(this.picBoard);      this.Name = "Form1";      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;      this.Text = "Grid Test";      ((System.ComponentModel.ISupportInitialize)(this.picBoard)).EndInit();      ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();      this.ResumeLayout(false);    } 

Here is the entirety of the Form code, as well as a custom class, CellDetails, at the bottom (I didn't feel like making a separate one). Keep in mind this is just something I created in a hurry to see how difficult it would be for you. If you have any questions as to what is going on, just ask.

   public partial class Form1 : Form    {        List<CellDetails> cells = new List<CellDetails>();       // Defines the size of each cell.       const int cCellSize = 40;       int boardLeft = 0;       int boardTop = 0;       public Form1()       {          InitializeComponent();           picTile.Size = new Size(cCellSize, cCellSize);           picBoard.MouseMove += PicBoard_MouseMove;          picBoard.MouseClick += PicBoard_MouseClick;          picBoard.Paint += PicBoard_Paint;          CreateCells();           boardLeft = picBoard.Location.X;          boardTop = picBoard.Location.Y;       }        private void PicBoard_Paint(object sender, PaintEventArgs e)       {          if (cells.Count > 0)          {             bool alt = false;             SolidBrush cellBrush1 = new SolidBrush(Color.LightGray);             SolidBrush cellBrush2 = new SolidBrush(Color.DarkGray);              foreach (CellDetails cell in cells)             {                e.Graphics.FillRectangle((alt ? cellBrush1 : cellBrush2), cell.Dimension);                alt = !alt;             }              cellBrush1.Dispose();             cellBrush2.Dispose();          }       }        private void PicBoard_MouseClick(object sender, MouseEventArgs e)       {          CellDetails cell = FindCell(e);          if (cell != null && cell.Location.X > -1 && cell.Location.Y > -1)          {             picTile.Location = new Point(cell.Dimension.X + boardLeft, cell.Dimension.Y + boardTop);             picTile.Visible = true;          }          else          {             picTile.Visible = false;          }       }        private void PicBoard_MouseMove(object sender, MouseEventArgs e)       {          CellDetails cell = FindCell(e);          string details;           if (cell == null || cell.Location.X < 0 || cell.Location.Y < 0)          {             details = "Could not find cell";          } else          {             details = string.Format("Row: {0}, Col: {1}", cell.Location.Y, cell.Location.X);          }          lblDetails.Text = String.Format("{0}, {1} = {2}", e.X, e.Y, details);       }        private CellDetails FindCell(MouseEventArgs e)       {          CellDetails ret = null;          foreach (CellDetails cell in cells)          {             if (cell.Dimension.Contains(e.Location))             {                ret = cell;                break;             }          }          return ret;       }        private void CreateCells()       {          CellDetails cell;          Point cellLoc;          int rows = (picBoard.ClientSize.Height / cCellSize);          int cols = (picBoard.ClientSize.Width / cCellSize);           // Loop through the rows          for (int row = 0; row < rows; row++)          {             // Loop through the columns             for (int col = 0; col < cols; col++)             {                cell = new CellDetails();                cellLoc = new Point();                cellLoc.Y = row + 1;                 cellLoc.X = col + 1;                 cell.Location = cellLoc;                cell.Dimension = new Rectangle(col * cCellSize, row * cCellSize, cCellSize, cCellSize);                cells.Add(cell);             }          }          lblDetails.Text = String.Format("Generated {0} cells.", cells.Count);       }     }    public class CellDetails    {       public CellDetails() { }       public Rectangle Dimension { get; set; }       public Point Location { get; set; }    } 

The end result looks something like this:

Dynamic Grid Example

If you know how many rows and columns you want, you can have it calculate the cell width/height by dividing up the ClientSize by the counts instead of by a predefined cell size. This would also be helpful if you can resize, which would result in a varying cell size. Just alter the code to calculate that way, and then have it call CreateCells after resizing. You'll probably want to add a line like if (cells.Count > 0) cells.Clear(); at the top, too.

It probably doesn't need mentioning, but in case someone else comes along: If you just need hit testing for invisible cells (no rendering), you can completely remove the Paint event. If you are wanting grid lines and not filled boxes, change FilledRectangle to DrawRectangle, and use a Pen instead of SolidBrush. With the Pen, you can also make lines dotted, dashed, etc.

</div
 
 
 
 
0
 
vote

Проблема в том, что нет фактической «ячейки» контейнерного контейнера. Клетки динамически на основе <код> ColumnCount и <код> RowCount наряду с соответствующим <код> ColumnStyles и <код> RowStyles .

Если ваши стили используют фиксированные размеры, вы можете написать свой собственный метод для вычисления и хранения деталей каждой ячейки - возможно, в структуре или классу, содержащем <код> Rectangle для каждой ячейки (местоположение будет быть рассчитанным, и размер может быть получен из парного <код> ColumnStyle и <код> RowStyle ) и <код> Point или 2 <код> int Для хранения колонны и строки. Тогда в MouseClick событие RowCount0 , вы можете использовать <код> RowCount1 и проверять его против всех клеточных прямоугольников, используя <код> RowCount2 . Затем используйте <код> RowCount3 метода <код> RowCount4 для перемещения управления. Например:

 <код> RowCount5  

Если какая-либо из ваших столбцов или строк имеет динамическое размещение (процент, и т. Д.), Тогда вам придется больше работать, чтобы рассчитать детали каждого.

Если позиционирование может измениться, вам нужно будет повторить расчеты. Поэтому вы хотели бы убедиться, что каждый набор расчетов выполнен внутри метода, который можно назвать из изменений событий и т. Д.

Если вы не хотите проходить через все это сумасшествие, есть пара других вещей, которые вы можете сделать (и, может быть, больше, но это только в верхней части головы):

  1. Поместите тот же тип управления, например, RowCount6 , в каждую ячейку. Когда один нажал, установите изображение на ваш контроль источника. Когда нажат другой, очистите предыдущий, а затем установите новый.

  2. Делайте некоторую управляющую замену магии, поместив любой тип управления, например, <код> RowCount7 , в каждую ячейку. Когда один нажал, удалите его из клетки и поместите свой контроль изображения в него. Когда нажатие другого, удалите его, укажите элемент управления изображением на его месте, а затем установите первый удаленный элемент управления в исходную ячейку.

Я думаю, что первый вариант будет самым простым. Но окончательный подход зависит от вас.

 

The problem is that there isn't an actual "cell" container collection. The cells are dynamic based on the ColumnCount and RowCount, along with the corresponding ColumnStyles and RowStyles.

If your styles are using fixed sizes, you can write your own method to calculate and store the details of each cell -- probably in a struct or class containing a Rectangle for each cell (location would be calculated, and the size could be retrieved from the paired ColumnStyle and RowStyle) and a Point or 2 int for storing column and row. Then, in the MouseClick event of the TableLayoutPanel, you can use the e.Location and check it against all of the cell Rectangles using Rectangle.Contains. Then, use the SetCellPosition method of the TableLayoutPanel to move the control around. For example:

tableLayoutPanel1.SetCellPosition(pictureBox1, new TableLayoutPanelCellPosition(1, 1)); 

If any of your columns or rows have dynamic sizing (percentage, etc), then you'll have to do more work to calculate the details of each one.

If the positioning can change, you'll need to redo the calculations. Therefore, you would want to make sure each set of calculations is done inside of a method that can be called from Resize events, etc.

If you don't want to go through all of this craziness, there are a couple of other things you can do (and maybe more, but these are just off the top of my head):

  1. Put the same control type, such as PictureBox, into each cell. When one is clicked, set the image to that of your source control. When another is clicked, clear out the previous one and then set the new one.

  2. Do some control swapping magic by putting any type of control, such as a Label, into each cell. When one is clicked, remove it from the cell and put your image control into it. When another one is clicked, remove it, put the image control in its place, and then put the first removed control back in the original cell.

I would think the first option would be the easiest. But, the final approach is up to you.

</div
 
 
     
     

Связанный проблема

0  Предварительные изображения в приложении Windows RT  ( Preloading images in windows rt app ) 
У меня есть приложение для хранения Windows, работающее на Windows RT, который включает в себя список изображений. Из них довольно много, поэтому при загрузке...

0  Можно ли программно получить общую ссылку Dropbox, не отправляя пользователя на страницу входа в Dropbox?  ( Is it possible to programmatically get a shared dropbox link without sending the ) 
Я разрабатываю веб-приложение в VB.NET 4.5 и с помощью третьей стороны: <Код> Dropnet . Я задаюсь вопросом, возможно ли получить общую ссылку из Dropbox- прог...

0  У FileHelpers есть классы, которые могут поддерживать неограниченную длину записи данных?  ( Does filehelpers have classes which can support unlimited data record length ) 
<код> <FixedLengthRecord(FixedMode.AllowVariableLength)> Public Class FileRecord <FieldFixedLength(1)> <FieldTrim(TrimMode.Both), FieldOptional()> ...

0  Не удается прочитать последовательные данные, полученные в TextBox  ( Cannot read serial data recieved to textbox ) 
Я пытаюсь написать свои последовательные данные, полученные в текстовое поле из класса в мою форму. Я использую код: <код> Public Shared Sub DataReceviedH...

2  VS2008 - VB.NET Шрифт Dialog - Фильтровальные шрифты по кодовой странице / языке  ( Vs2008 vb net font dialog filter fonts by codepage language ) 
Обновление (в ответ на первый ответ, от Passant Hans): Я думаю, что я не объяснил моего использования достаточно хорошо. Это приложение будет разработано для ...

3  Печать в принтере PDF программно  ( Printing to a pdf printer programmatically ) 
Я пытаюсь программно распечатать существующий файл в PDF в Visual Basic 2008. Наши текущие соответствующие активы: Visual Studio 2008 Professional Adobe Acr...

0  Как сравнить пароль с соленым хешированным паролем  ( How to compare password with salted hashed password ) 
У меня есть пользователь MySQL таблицы с двумя полями пользователя varchar () и паролем соленые хешированные md5 28 байт / "128 укусов" - Веб-форма ASP.NET с ...

3  Как использовать свойство тега с формами и кодом в VB 2012?  ( How do i use the tag property with forms and code in vb 2012 ) 
Я пишу программу, используя базу данных для клиентов и техников. Основная форма (CUSTORCTINCIDENTS) имеет настроенную систему, которая открывает другую форму ...

0  Как я могу изменить формат инфрагистического ультрастатетитора?  ( How can i change the format of the infragistics ultradatetimeeditor ) 
Мне нужно по умолчанию, чтобы установить формат, такой как «DD-MMM-YYYY» в UltrAdateTimeeditor. ...

2  Веб-страница ASP.NET в устройство подключения к порту USB (COM) сервера  ( Asp net web page to device connect to servers usb com port ) 
Я работаю над способом отправлять команды на доску Arduino с веб-сайта. Доска Arduino подключается к компьютеру через порт USB (COM-порт). Мне удалось подкл...

1  Не может получить доступ к существующим константам проекта  ( Cannot access referenced project constants ) 
У меня есть проблема с использованием модуля в нескольких проектах в том же решении (регулярный проект и тестовый проект для модульных тестов). Я пытаюсь след...

2  Замените оператор импорта и загрузите DLL в код для использования объекта?  ( Replace imports statement and load dll in code to use object ) 
У меня в настоящее время есть приложения, которые используют бесплатную библиотеку регистрации NLOG (DLL), которую я ссылаюсь в моем проекте VB.NET (Импорт оп...

0  Как я могу прочитать, что является URL-адресом назначения, когда требуется перенаправление?  ( How can i read what the destination url is when a redirect is requested ) 
Я использую <код> MasterPage с панелью динамической меню по всей странице. Если пользователь запросил перенаправить обратно на страницу входа в систему (HOME...

0  Ошибка, генерирующая XML из XSD (с помощью xsd.exe) vb.net  ( Error generating xml from an xsd using xsd exe vb net ) 
Хорошо, посмотрите, что я пытаюсь сделать, это построить XML через XSD для этого, я использую класс, который я построен с инструментом xsd.exe (voucher_build_...

0  Как прекратить вставку записей в таблице SQL, когда предел достигнут  ( How to stop inserting records in sql table when a limit is reached ) 
Я использую vb.net и sql server 2005. Моя проблема в том, что я хочу дать пользователю сообщение, если ограничение делегата достиг этого курса. Видишь, у ...

Связанный проблема

0  Предварительные изображения в приложении Windows RT 
0  Можно ли программно получить общую ссылку Dropbox, не отправляя пользователя на страницу входа в Dropbox? 
0  У FileHelpers есть классы, которые могут поддерживать неограниченную длину записи данных? 
0  Не удается прочитать последовательные данные, полученные в TextBox 
2  VS2008 - VB.NET Шрифт Dialog - Фильтровальные шрифты по кодовой странице / языке 
3  Печать в принтере PDF программно 
0  Как сравнить пароль с соленым хешированным паролем 
3  Как использовать свойство тега с формами и кодом в VB 2012? 
0  Как я могу изменить формат инфрагистического ультрастатетитора? 
2  Веб-страница ASP.NET в устройство подключения к порту USB (COM) сервера 
1  Не может получить доступ к существующим константам проекта 
2  Замените оператор импорта и загрузите DLL в код для использования объекта? 
0  Как я могу прочитать, что является URL-адресом назначения, когда требуется перенаправление? 
0  Ошибка, генерирующая XML из XSD (с помощью xsd.exe) vb.net 
0  Как прекратить вставку записей в таблице SQL, когда предел достигнут