Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Обработка кликов


Автор: stron 5.5.2004, 00:25
Я сейчас пишу карточную игру для 4-х игроков.(C#)
Соответственно, у меня есть 52 карты.

Карты показываю в PictureBox'ах.
У каждой карты есть свой весовой идентификатор.(раздаю их в другой части проги)
Для хранения таковой инфы создаю структуру:

Код

public struct pb
{
public PictureBox img;
public int weight;
.................................................
               public void pl_1_turn(object sender, System.EventArgs e)
 {
  MessageBox.Show(this.weight.ToString());
 }


}


Создаю массив из 52 элементов типа pb в программе.
В игре приходится обрабатывать клики по картам, соответственно при инициализации PictureBox'ов "приклеиваю" обработчик:

Код

public class Form1 : System.Windows.Forms.Form
{
         .........................................
         .........................................  
         this.s[i].img.Click += new System.EventHandler(this.s[i].pl_1_turn);
         .........................................
         .........................................
}


Вопрос:
Почему при клике на любую из карт в качестве weight выдаётся 0(его там не должно быть в принципе)?

А может кто подскажет ещё способ, как можно различать карты.


ЗЫ: Были у меня мысли как-нибудь перегрузить обработчик, но как это сделать я не придумал.

Автор: Kurt 5.5.2004, 03:00
Ну.. Какие тут могут быть соображения..
Т.к. я не вижу полного кода, все мои "изыскания" (smile.gif) могут быть неверными. Однако..
Сначала по вопросу почему у тебя не работает правильно..
"Разрешите задать Вам несколько вопросов?" smile.gif
1) Твои структуры ты должне был каким-то образом добавлять на форму. Для этого используем Controls.Add() (если я ошибаюсь - сразу сорри..). Так?
Посморим, на объявление этой ф-ции:
Код

[C#]
public virtual void Add(
  Control value
);

Вот! В качестве параметра она принимает либо класс Control, либо его наследник.
Твои структуры не являются контролами, поэтому рискну предположить, что ты добавлял только pb[i].img:
Код
this.Controls.Add(pb[i].img)

Если так, то обрати внимание - причем здесь остальные поля структуры? как тока ты добавил на форму - ты уже не связан с остальными полями..
Однако, я могу ошибаться - я не знаю, как оно в действительности реализовано..

2)Т.к. ты используешь СТРУКТУРУ, к-я является ТИПОМ, то она везде передается ПО ЗНАЧЕНИЮ (за исключением автоматической распаковки..) - меняй/не меняй ее в ф-ции - это не окажет влияния..
Проверь, если не первая ошибка, то, можь, такое где есть..

Теперь так. Как я тебе предлагаю все эт дело реализовать..
Предлагаю написать свой КЛАСС-НАСЛЕДНИК от PictureBox! Добавь ему св-ва, к-е тебе нужны! Вобщем, я накрапал тебе маленький примерчик (можно компилить и запускать.. smile.gif). Здесь я добавил тока одно св-во - weight, однако, никто не мешает тебе добавить кучу других.. Еще здесь не совсем красиво сделано - я для простоты вшаю обработчик на клик в самом конструкторе - конечно, эт можно делать где угодно.
На форме 2 PictureBox'a, вернее их наследники.. Я все оформил массивом, поэтому без разницы - что 2, что 102 контрола. Тока возьми сначала картинку поменьше.. smile.gif
Здесь у первой картинки Weight=0, у 2-й - weight=1.
Итого:
Код

// created on 05.05.2004 at 3:50
using System;
using System.Drawing;
using System.Windows.Forms;

namespace MyPictureBoxes
{
public class frmMain : Form //класс-тестер
{
 private Image _img = new Bitmap("image1.bmp"); //любая небольшая картинка..
 private MyPictureBox[] _picBx = new MyPictureBox[2]; //наш массив контролов
 
 //конструктор
 public frmMain(String title)
 {
  for(int i=0; i<2; i++) //вот до чего лень доводит! :)
  {
   this._picBx[i] = new MyPictureBox();
   this._picBx[i].Image = this._img;
   this._picBx[i].Left = i*170; //чтоб картинки не сливались..
   this._picBx[i].Weight = i; //наше новое поле!
   this.Controls.Add(this._picBx[i]); //добавляем ОБРАТИ ВНИМАНИЕ наследника Control
  }
  this.Text = title; //просто присваиваем заголовок форме - так красивше. :)
  return;
 }
 
 public static void Main()
 {
  Application.Run(new frmMain("PictureBox Test.."));
  return;
 }
}


//собственно, наш класс
public class MyPictureBox : PictureBox
{
 private int _weight; //новое поле

 public int Weight //property к нему..
 {
  set
  {
   this._weight = value;
  }
  get
  {
   return this._weight;
  }
 }

 //конструктор - здесь мы устанавливаем обработчик - это можно сделать практически где угодно..
 public MyPictureBox()
 {
  this.Click += new System.EventHandler(this.OnMyPictureClick);
 }

 //обработчик - просто выводим MessageBox
 private void OnMyPictureClick(Object sender, System.EventArgs e)
 {
  MessageBox.Show("Weight="+this._weight.ToString(),"From MyPictuteBox");
  return;
 }
}


}


Все. Похоже?..
Надеюсь, хоть чем-то помог.

З.Ы. Если я прав - с тебя игра! smile.gif

Автор: stron 6.5.2004, 16:07
Цитата

Если так, то обрати внимание - причем здесь остальные поля структуры? как тока ты добавил на форму - ты уже не связан с остальными полями..

Ошибку понял.

Цитата

за исключением автоматической распаковки..

Честно говоря, я не знаю, что такое автоматическая распаковка. smile.gif

Буду писать класс-наследник.


Спасибо, что помог! smile.gif

Автор: Kurt 6.5.2004, 16:54
Да не за что..
Приходите еще.. smile.gif

Автор: Kurt 6.5.2004, 17:36
Да, чуть не забыл..
Цитата
Честно говоря, я не знаю, что такое автоматическая распаковка


УПАКОВКА (boxing) - процесс, при котором происходит явное преобразование структурного типа в ссылочный. Что при этом происходит: в управляемой куче (по-моему, так это называется.. smile.gif) создается новый объект, в который копируется данные старого объекта из стека.
Как все это происходит? Очень просто.
Допустим, у нас есть переменная типа int:
Код
int IntVar = 777;

Упаковываем (достаем из стека, создаем объект в куче и получаем ссылку на него):
Код
object objIntVar = IntVar;

Прошу заметить, "object" тут пишется с маленькой буквы.

Существует противоположная ей операция, кя называется РАСПАКОВКА (unboxing) - преобразование ссылки на объект из управляемой кучи в структурный тип. Следует отметить, что .NET Framework автоматически производит проверку на совместимость между типом объекта из кучи и структурным типом, в к-й мы хотим произвести распаковку.
Вот как производится распаковка:
Код
int NewIntVar = (int)objIntVar;

Если Framework обнаружит несовместимость типов, то выдается исключение InvalidCastException:
Код

...
try
{//пытаемся преобразовать, допустим, в строку:
string myStr = (string)objIntVar
}
catch (InvalidCastException e)
{
Console.WriteLine("Attention-attention!! Error: "+ e.ToString());
};

Все.
Да, возникает законный вопрос - а вообще зачем этим стоит интересоваться? Ну.. Тут несколько аспектов. Во-первых, чтоб избежать, на мой взгляд, трудно обнаружимых ошибок, и во вторых, операции с переменными в стеке выполняются несколько быстрее, поэтому это стоит учитывать при оптимизации приложения. С другой стороны, увлекаться этим тоже не стоит - все-таки процесс распаковки занимает некоторое время, и кроме того, в современных ООП-программах тяжело обойтись без объектов. smile.gif
В конце хочу заметить, что в ряде случаев, процессы упаковки/распаковки производятся автоматически, без нашего участия.
Например:
Код

//пусть у нас есть функция void MyFunction(object obj)
int IntVar = 11;
MyFunction(IntVar); //здесь произойдет автоматическая упаковка..

В принципе, все.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)