我在C#中的Winform项目中有一个带有加载图像的图片框。我定义了一个包含几个椭圆(X点,Y点,宽度,高度,ZoneID,ZoneDescription)的Struct,我在初始化表单时将其加载到Picturebox中。
我想尝试做两件事。 1)允许用户用鼠标移动到图片框中的图片上,一旦鼠标进入结构中标识的区域,它就会显示一个工具提示,显示结构中的ZoneDescription。
2)然后,当用户点击任意一个区域时,它应该生成一个响应,我可以捕获ZoneID(我已在结构中定义)。然后我将其添加到数据集中。这部分我可以做。
我只是不知道怎么去Pt1。 我在某处读到了我应该为所有区域定义一个MouseEnter事件处理程序和一个MouseLeave EventHandler,但我不知道该怎么做。 我已经在表单上有一个工具提示。
以下是包含区域的结构定义:
public struct TreatmentZone
{
public int nZoneID;
public string sZoneCode;
public string sZoneDesc;
public Color sbPaintbrush;
public int nZonewidth;
public int nZoneheight;
public int nZoneX;
public int nZoneY;
public TreatmentZone(int _ZoneID, string _sZoneCode,string _ZoneDesc, Color _sbBrush, int _ZoneX, int _ZoneY, int _Zonewidth, int _Zoneheight)
{
this.nZoneID = _ZoneID;
this.sZoneCode = _sZoneCode;
this.sZoneDesc = _ZoneDesc;
this.sbPaintbrush = _sbBrush;
this.nZoneX = _ZoneX;
this.nZoneY = _ZoneY;
this.nZonewidth = _Zonewidth;
this.nZoneheight = _Zoneheight;
}
};
TreatmentZone[] tZone = {
new TreatmentZone(1,"R1","Brain", Color.AliceBlue,155,35,30,20),
new TreatmentZone(5,"R2", "Hypothalamus", Color.AliceBlue,184,55,12,12)
};
private void pic_TreatmentZones1_RightSole_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(new System.Drawing.SolidBrush(tZone[0].sbPaintbrush), tZone[0].nZoneX, tZone[0].nZoneY, tZone[0].nZonewidth, tZone[0].nZoneheight);
e.Graphics.FillEllipse(new System.Drawing.SolidBrush(tZone[1].sbPaintbrush), tZone[1].nZoneX, tZone[1].nZoneY, tZone[1].nZonewidth, tZone[1].nZoneheight);
}
我如何在Pt1中执行所需的步骤?有没有人有我可以使用的代码示例?
答案 0 :(得分:0)
所以基本上你需要订阅MouseMove(用于胡佛)和PictureBox的Click Event。然后,您需要指定当前光标是否在治疗区域上并处理它。
我已经采用了您的代码并构建了一个小型演示。 请注意,我已更改了一些TREZone变量的名称以匹配C#命名约定。并且还将它们更改为属性。
注意:您需要在表单中添加工具提示。
public struct TreatmentZone
{
#region members
private readonly GraphicsPath path;
#endregion
//changed to properties
public int Id { get; private set; }
public string Code { get; private set; }
public string Description { get; private set; }
public Color Color { get; set; }
public int Width { get; private set; }
public int Height { get; private set; }
public int X { get; private set; }
public int Y { get; private set; }
public TreatmentZone(int zoneId, string zoneCode, string description, Color color, int x, int y, int width, int height)
{
this.Id = zoneId;
this.Code = zoneCode;
this.Description = description;
this.Color = color;
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
this.path = new GraphicsPath();
//needed for hittest
this.path.AddEllipse(this.X, this.Y, this.Width, this.Height);
}
//https://stackoverflow.com/questions/13285007/how-to-determine-if-a-point-is-within-an-ellipse
//This will check if the point (from mouse) is over ellips or not
public bool HitTest(Point point)
{
var x = point.X - this.X;
var y = point.Y - this.Y;
return this.path.IsVisible(x, y);
}
}
这是你的表格: 请注意我的PictureBox刚刚命名为pictureBox1
公共部分类Form1:表单 {
private readonly List<TreatmentZone> treatmentZones = new List<TreatmentZone>();
public Form1()
{
this.InitializeComponent();
this.treatmentZones.Add(new TreatmentZone(1, "a", "b", Color.Blue, 10, 10, 200, 400));
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var treatmentZone in this.treatmentZones)
{
using(var brush = new SolidBrush(treatmentZone.Color))
e.Graphics.FillEllipse(brush, treatmentZone.X, treatmentZone.Y, treatmentZone.Width, treatmentZone.Height);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
foreach (var treatmentZone in this.treatmentZones)
{
if(treatmentZone.HitTest(e.Location))
this.toolTip1.Show(treatmentZone.Description, this.pictureBox1, e.Location);
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
var location = this.pictureBox1.PointToClient(Cursor.Position);
foreach (var treatmentZone in this.treatmentZones)
{
if (treatmentZone.HitTest(location))
MessageBox.Show("Handle the click of " + treatmentZone.Code + ".");
}
}
}
答案 1 :(得分:0)
所以在我探索的最后,我按照这种方法做到了: (请记住,这是一个带Winforms的桌面应用程序)
1)创建一个图片框并加载图片 - 在这种情况下是一个png文件。 2)使用List对象在图片框内的此图像上创建多个可单击区域。在我的情况下,我想要椭圆形可点击区域。 3)列表对象的字段被加载到SQL表中(或者您可以手动将列表对象加载为类 - 它由您决定)
以下是我使用的代码:
包含可点击区域的类:
public class clsClickableZones
{
public int nZoneID { get; set; }
public string sZoneCode { get; set; }
public string sZoneDesc { get; set; }
public System.Drawing.Color sbPaintbrush { get; set; }
public int nZonewidth { get; set; }
public int nZoneheight { get; set; }
public int nZoneX { get; set; }
public int nZoneY { get; set; }
}
然后执行这个类。
在&#34; InitialiseComponent&#34;之后的公共表单事件上我打电话给我创建一个新的调用LoadClickableZones()。
在这个Form类中,我定义了包含值的Listobject:
List<clsClickableZones> tZones = new List<clsClickableZones>();
然后我用这个方法加载区域:
手动:
public void LoadClickableZone()
{
//this can now be loaded into table and pulled from dataset into class if so desired
//Use Test Colour for visibility sbPaintbrush=Color.Bisque and Transparent for functionality
System.Drawing.Color sbPCol = Color.Cornsilk;
//System.Drawing.Color sbPCol = Color.Transparent;
try
{
tZones.Add(new clsClickableZones() { nZoneID = 1, sZoneCode = "R1", sZoneDesc = "Zone 1", sbPaintbrush = sbPCol, nZoneX = 160, nZoneY = 30, nZonewidth = 25, nZoneheight = 20 });
tZones.Add(new clsClickableZones() { nZoneID = 2, sZoneCode = "R2", sZoneDesc = "Zone 2", sbPaintbrush = sbPCol, nZoneX = 184, nZoneY = 55, nZonewidth = 12, nZoneheight = 12 });
tZones.Add(new clsClickableZones() { nZoneID = 3, sZoneCode = "R3a", sZoneDesc = "Zone 3", sbPaintbrush = sbPCol, nZoneX = 160, nZoneY = 58, nZonewidth = 12, nZoneheight = 12 });
tZones.Add(new clsClickableZones() { nZoneID = 63, sZoneCode = "R3b", sZoneDesc = "Zone 4", sbPaintbrush = sbPCol, nZoneX = 177, nZoneY = 68, nZonewidth = 12, nZoneheight = 12 });
tZones.Add(new clsClickableZones() { nZoneID = 4, sZoneCode = "R4", sZoneDesc = "Zone 5", sbPaintbrush = sbPCol, nZoneX = 160, nZoneY = 90, nZonewidth = 25, nZoneheight = 15 });
tZones.Add(new clsClickableZones() { nZoneID = 5, sZoneCode = "R5", sZoneDesc = "Zone 6", sbPaintbrush = sbPCol, nZoneX = 160, nZoneY = 115, nZonewidth = 15, nZoneheight = 10 });
tZones.Add(new clsClickableZones() { nZoneID = 6, sZoneCode = "R6", sZoneDesc = "Zone 7", sbPaintbrush = sbPCol, nZoneX = 147, nZoneY = 80, nZonewidth = 10, nZoneheight = 10 });
tZones.Add(new clsClickableZones() { nZoneID = 7, sZoneCode = "R7", sZoneDesc = "Zone 8", sbPaintbrush = sbPCol, nZoneX = 186, nZoneY = 135, nZonewidth = 12, nZoneheight = 20 });
tZones.Add(new clsClickableZones() { nZoneID = 8, sZoneCode = "R8", sZoneDesc = "Zone 9", sbPaintbrush = sbPCol, nZoneX = 170, nZoneY = 145, nZonewidth = 20, nZoneheight = 30 });
tZones.Add(new clsClickableZones() { nZoneID = 9, sZoneCode = "R9", sZoneDesc = "Zone 10", sbPaintbrush = sbPCol, nZoneX = 151, nZoneY = 180, nZonewidth = 33, nZoneheight = 20 });
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error loading Zones", MessageBoxButtons.OK);
}
}
您也可以从SQL中的表中加载所有区域,如下所示:
public void LoadTreatmentZone_RSole()
{
//this can now be loaded into table and pulled from dataset into class if so desired
//Use Test Colour for visibility sbPaintbrush=Color.Bisque and Transparent for functionality
System.Drawing.Color sbPCol = Color.Cornsilk;
//System.Drawing.Color sbPCol = Color.Transparent;
try
{
string sSQL = "SELECT pkID, TreatmentAreaCode, TreatmentAreaDesc, ZoneX, ZoneY, ZoneH, ZoneW FROM myDB.lkMyZones ; ";
Datafeed cData = new Datafeed();
DataSet dsData = new DataSet();
cData.GetDataset(sSQL, ref dsData);
cData = null;
if (dsData.Tables[0].Rows.Count > 0)
{
foreach (DataRow row in dsData.Tables[0].Rows)
{
tZones.Add(new clsClickablesZones()
{
nZoneID = Convert.ToInt32(row["pkID"].ToString()),
sZoneCode = row["TreatmentAreaCode"].ToString(),
sZoneDesc = row["TreatmentAreaDesc"].ToString(),
sbPaintbrush = sbPCol,
nZoneX = Convert.ToInt32(row["ZoneX"].ToString()),
nZoneY = Convert.ToInt32(row["ZoneY"].ToString()),
nZonewidth = Convert.ToInt32(row["ZoneW"].ToString()),
nZoneheight = Convert.ToInt32(row["ZoneH"].ToString())
});
}
}
dsData = null;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error loading Treatment Zones - R Sole", MessageBoxButtons.OK);
}
}
现在可以使用Click事件单击每个区域,或者您可以使用MouseMove事件将鼠标悬停在其上,如下所示:
移动/点击事件的功能:
private int ZoneClickedRS(int mouseX, int mouseY,int ZoneArea)
{
int ix;
for (ix = 0; ix < tZones.Count; ix++)
{
if ((mouseX >= tZones[ix].nZoneX) && (mouseX <= (tZones[ix].nZoneX + tZones[ix].nZonewidth)) &&
(mouseY >= tZones[ix].nZoneY) && (mouseY <= (tZones[ix].nZoneY + tZones[ix].nZoneheight)))
return ix;
}
break;
return NOT_IN_ZONE;
}
调用来自MouseMove或MouseClick,如下所示:
private void pic_Zones_MouseClick(object sender, MouseEventArgs e)
{
int SelectedZoneID = ZoneClickedRS(e.X, e.Y,1);
if (SelectedZoneID == NOT_IN_ZONE)
return;
string sZone = tZones[SelectedZoneID].sZoneDesc;
miSelectedZoneID = tZones[SelectedZoneID].nZoneID; //Defined elsewhere
// For Testing:
//MessageBox.Show("The selected Zone:" + sZone, "Selected Zone", MessageBoxButtons.OK);
}
或者对于MouseMove(将数据传递给ToolTip控件,如下所示)
private void pic_Zones_MouseMove(object sender, MouseEventArgs e)
{
int SelectedZoneID = ZoneClickedRS(e.X, e.Y,1);
string sZone = "";
if (SelectedZoneID == NOT_IN_ZONE)
tipZoneArea.RemoveAll();
else
sZone = tZones[SelectedZoneID].sZoneDesc;
tipZoneArea.SetToolTip(pic_Zones, "Clicked" + sZone);
}
最后,为了让您的图片框上显示区域,您可以进行以下呼叫:
private void pic_Zones__Paint(object sender, PaintEventArgs e)
{
int ii;
for (ii = 0; ii < tZones.Count; ii++)
{
e.Graphics.FillEllipse(new System.Drawing.SolidBrush(tZones[ii].sbPaintbrush), tZones[ii].nZoneX, tZones[ii].nZoneY, tZones[ii].nZonewidth, tZones[ii].nZoneheight);
}
}