System.ComponentModel.Win32Exception: 'Error creating window handle.'
System.ComponentModel.Win32Exception: 'Error creating window handle.'
我的问题是:
System.ComponentModel.Win32Exception: 'Error creating window handle'.
我知道我可以用 Dispose()
解决这个问题,但是当我在程序中使用它时,我显示另一个错误:
System.ObjectDisposedException: 'Can not access a disposed object.
Object name: 'PictureBox'. '
我使用以下代码:
private void SetUpPuzzle_Click(int parts)
{
Panel P = new Panel
{
Size = new Size(200, 200),
Location = new Point(394, 62),
};
Controls.Add(P);
Control board = P;
int total = parts * parts;
var PB = new PictureBox[total];
var imgarray = new Image[total];
var img = User_Image.Image;
int W = img.Width / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
int H = img.Height / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
int size = 200 / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
for (int x = 0; x < parts; x++)
{
for (int y = 0; y < parts; y++)
{
var index = x * parts + y;
imgarray[index] = new Bitmap(W, H);
using (Graphics graphics = Graphics.FromImage(imgarray[index]))
graphics.DrawImage(img, new Rectangle(0, 0, W, H),
new Rectangle(x * W, y * H, W, H), GraphicsUnit.Pixel);
PB[index] = new PictureBox
{
Name = "P" + index,
Size = new Size(size, size),
Location = new Point(x * size, y * size),
Image = imgarray[index],
SizeMode = PictureBoxSizeMode.StretchImage
};
PB[index].MouseEnter += Images_M_E;
PB[index].MouseLeave += Images_M_L;
PB[index].MouseClick += Form_MouseClick;
*PB[index].Dispose();
*board.Controls.Add(PB[index]);
}
}
}
当我要创建 10,000 个对象时
显示此错误。
我发表评论 PB[index].Dispose();
并且有效。
private void SetUpPuzzle(int parts)
{
// Comment ***********
//Panel P = new Panel
//{
// Size = new Size(200, 200),
// Location = new Point(394, 62),
//};
//Controls.Add(P);
//Control board = P; ***********
int total = parts * parts;
var PB = new PictureBox[total];
var imgarray = new Image[total];
var img = User_Image.Image;
int W =Convert.ToInt32(img.Width / Math.Sqrt(parts));
int H = Convert.ToInt32(img.Height / Math.Sqrt(parts));
int size = Convert.ToInt32(200 / Math.Sqrt(parts));
for (int x = 0; x < parts; x++)
{
for (int y = 0; y < parts; y++)
{
var index = x * parts + y;
imgarray[index] = new Bitmap(W, H);
using (Graphics graphics = Graphics.FromImage(imgarray[index]))
graphics.DrawImage(img, new Rectangle(0, 0, W, H),
new Rectangle(x * W, y * H, W, H), GraphicsUnit.Pixel);
PB[index] = new PictureBox
{
Name = "P" + index,
Size = new Size(size, size),
Location = new Point(x * size, y * size),
Image = imgarray[index],
SizeMode = PictureBoxSizeMode.StretchImage
};
PB[index].MouseEnter += Form1_MouseEnter;
PB[index].MouseLeave += Form1_MouseLeave;
PB[index].MouseClick += Form1_MouseClick;
//Comment
//PB[index].Dispose(); < -----------------
// Add PB in Panel in form
panel1.Controls.Add(PB[index]);
}
}
// after add all refresh panel
panel1.Refresh();
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
throw new NotImplementedException();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private void Form1_MouseEnter(object sender, EventArgs e)
{
throw new NotImplementedException();
}
然后在您的按钮中调用 SetUpPuzzle
方法,例如:
private void button1_Click(object sender, EventArgs e)
{
SetUpPuzzle(10);
}
我的问题是:
System.ComponentModel.Win32Exception: 'Error creating window handle'.
确实如此。您正在为 Winforms
应用程序创建 太多控件。
并且处理它们并没有真正帮助,因为您不能再使用已处理的对象..
要拥有这种大型拼图(10k 块),您需要改变使用 PictureBoxes
(或任何其他 Controls
)来显示以不同的方式处理拼图。这已在 中提出,但你只想拥有 100 件,记得吗?
最常见的方法是:保存一个图像列表(当它们 <= 256x256 像素时,请将它们放入 ImageList
!)并在面板的 Paint
事件中绘制它们。这将消除与 PictureBoxes
.
相关的所有开销
(旁白:有人可能认为这不会对所有 DrawImage
调用都有效。但是所有这些 PictureBoxes
还需要在其所有表面上绘制所有像素,所以这不是问题。但它们也必须承担(在引擎盖下)功能齐全的开销 windows
(请参阅错误消息!),这就是为什么系统只能拥有有限数量的它们;始终尝试保持控件数量< 1k!)
您必须将放置逻辑移动到版块的 Paint
事件中,并且还必须更改事件模型..:[=39=]
您不必让每个 PictureBox
响应自己的事件,而是必须找到一种方法来完成董事会事件中的所有工作。这必须有所不同,具体取决于事件。
由于我们不知道您有哪些活动、他们做什么以及他们的工作需要哪些数据,因此很难提供所有必要的详细信息,所以我只指出几件事.. :
没有可以使用的 Enter
或 Leave
事件。相反,您需要通过在 MouseMove 事件中对其进行测试来检测是否进入了一块区域。如果您保留 List<Rectangle>
,则可以使用 Rectangle.Contains(e.Location)
进行此测试。
您可以检测到鼠标点击,但随后必须找出点击了哪个区域。如果 MouseMove 的输入和离开逻辑正常工作,您可以使用其结果来了解点击的位置。
类似的想法可以用于所有其他事件;有些很简单,有些需要一点计算,但它们都很快而且很容易实现..
要优化性能,请尝试使图像大小合适并使用 Format32bppPArgb 作为像素格式,因为这样显示速度更快。
另一种选择是直接从 Paint
事件中的原始图像中提取像素数据,使用与现在创建它们相同的计算。 (有一个DrawImage
overlay,使用两个Rectangles
,一个确定目标,一个确定源区..)这样可以节省GDI
句柄,至少在你不能使用的情况下一个 ImageList
。
永远为成长做计划!为了更好的实现,请创建一个 Piece
class。它应该包含 Rectangle
和 ImageList
的 Images
集合中的整数索引。它还可以有一个方法 Switch(Piece otherPiece)
可以切换 Rectangles
或索引。
祝你好运:-)
我遇到这个异常是因为无限循环创建新的 UI 控件并设置其属性。循环多次后,当更改控件可见时抛出此异常属性。我发现用户对象和 GDI 对象(来自任务管理器)都很大。
我猜你的问题与系统资源被那些 UI 控件耗尽的原因类似。
我的问题是:
System.ComponentModel.Win32Exception: 'Error creating window handle'.
我知道我可以用 Dispose()
解决这个问题,但是当我在程序中使用它时,我显示另一个错误:
System.ObjectDisposedException: 'Can not access a disposed object. Object name: 'PictureBox'. '
我使用以下代码:
private void SetUpPuzzle_Click(int parts)
{
Panel P = new Panel
{
Size = new Size(200, 200),
Location = new Point(394, 62),
};
Controls.Add(P);
Control board = P;
int total = parts * parts;
var PB = new PictureBox[total];
var imgarray = new Image[total];
var img = User_Image.Image;
int W = img.Width / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
int H = img.Height / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
int size = 200 / (int.Parse(Math.Sqrt(double.Parse(parts.ToString())).ToString()));
for (int x = 0; x < parts; x++)
{
for (int y = 0; y < parts; y++)
{
var index = x * parts + y;
imgarray[index] = new Bitmap(W, H);
using (Graphics graphics = Graphics.FromImage(imgarray[index]))
graphics.DrawImage(img, new Rectangle(0, 0, W, H),
new Rectangle(x * W, y * H, W, H), GraphicsUnit.Pixel);
PB[index] = new PictureBox
{
Name = "P" + index,
Size = new Size(size, size),
Location = new Point(x * size, y * size),
Image = imgarray[index],
SizeMode = PictureBoxSizeMode.StretchImage
};
PB[index].MouseEnter += Images_M_E;
PB[index].MouseLeave += Images_M_L;
PB[index].MouseClick += Form_MouseClick;
*PB[index].Dispose();
*board.Controls.Add(PB[index]);
}
}
}
当我要创建 10,000 个对象时
显示此错误。
我发表评论 PB[index].Dispose();
并且有效。
private void SetUpPuzzle(int parts)
{
// Comment ***********
//Panel P = new Panel
//{
// Size = new Size(200, 200),
// Location = new Point(394, 62),
//};
//Controls.Add(P);
//Control board = P; ***********
int total = parts * parts;
var PB = new PictureBox[total];
var imgarray = new Image[total];
var img = User_Image.Image;
int W =Convert.ToInt32(img.Width / Math.Sqrt(parts));
int H = Convert.ToInt32(img.Height / Math.Sqrt(parts));
int size = Convert.ToInt32(200 / Math.Sqrt(parts));
for (int x = 0; x < parts; x++)
{
for (int y = 0; y < parts; y++)
{
var index = x * parts + y;
imgarray[index] = new Bitmap(W, H);
using (Graphics graphics = Graphics.FromImage(imgarray[index]))
graphics.DrawImage(img, new Rectangle(0, 0, W, H),
new Rectangle(x * W, y * H, W, H), GraphicsUnit.Pixel);
PB[index] = new PictureBox
{
Name = "P" + index,
Size = new Size(size, size),
Location = new Point(x * size, y * size),
Image = imgarray[index],
SizeMode = PictureBoxSizeMode.StretchImage
};
PB[index].MouseEnter += Form1_MouseEnter;
PB[index].MouseLeave += Form1_MouseLeave;
PB[index].MouseClick += Form1_MouseClick;
//Comment
//PB[index].Dispose(); < -----------------
// Add PB in Panel in form
panel1.Controls.Add(PB[index]);
}
}
// after add all refresh panel
panel1.Refresh();
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
throw new NotImplementedException();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private void Form1_MouseEnter(object sender, EventArgs e)
{
throw new NotImplementedException();
}
然后在您的按钮中调用 SetUpPuzzle
方法,例如:
private void button1_Click(object sender, EventArgs e)
{
SetUpPuzzle(10);
}
我的问题是:
System.ComponentModel.Win32Exception: 'Error creating window handle'.
确实如此。您正在为 Winforms
应用程序创建 太多控件。
并且处理它们并没有真正帮助,因为您不能再使用已处理的对象..
要拥有这种大型拼图(10k 块),您需要改变使用 PictureBoxes
(或任何其他 Controls
)来显示以不同的方式处理拼图。这已在
最常见的方法是:保存一个图像列表(当它们 <= 256x256 像素时,请将它们放入 ImageList
!)并在面板的 Paint
事件中绘制它们。这将消除与 PictureBoxes
.
(旁白:有人可能认为这不会对所有 DrawImage
调用都有效。但是所有这些 PictureBoxes
还需要在其所有表面上绘制所有像素,所以这不是问题。但它们也必须承担(在引擎盖下)功能齐全的开销 windows
(请参阅错误消息!),这就是为什么系统只能拥有有限数量的它们;始终尝试保持控件数量< 1k!)
您必须将放置逻辑移动到版块的 Paint
事件中,并且还必须更改事件模型..:[=39=]
您不必让每个 PictureBox
响应自己的事件,而是必须找到一种方法来完成董事会事件中的所有工作。这必须有所不同,具体取决于事件。
由于我们不知道您有哪些活动、他们做什么以及他们的工作需要哪些数据,因此很难提供所有必要的详细信息,所以我只指出几件事.. :
没有可以使用的
Enter
或Leave
事件。相反,您需要通过在 MouseMove 事件中对其进行测试来检测是否进入了一块区域。如果您保留List<Rectangle>
,则可以使用Rectangle.Contains(e.Location)
进行此测试。您可以检测到鼠标点击,但随后必须找出点击了哪个区域。如果 MouseMove 的输入和离开逻辑正常工作,您可以使用其结果来了解点击的位置。
类似的想法可以用于所有其他事件;有些很简单,有些需要一点计算,但它们都很快而且很容易实现..
要优化性能,请尝试使图像大小合适并使用 Format32bppPArgb 作为像素格式,因为这样显示速度更快。
另一种选择是直接从 Paint
事件中的原始图像中提取像素数据,使用与现在创建它们相同的计算。 (有一个DrawImage
overlay,使用两个Rectangles
,一个确定目标,一个确定源区..)这样可以节省GDI
句柄,至少在你不能使用的情况下一个 ImageList
。
永远为成长做计划!为了更好的实现,请创建一个 Piece
class。它应该包含 Rectangle
和 ImageList
的 Images
集合中的整数索引。它还可以有一个方法 Switch(Piece otherPiece)
可以切换 Rectangles
或索引。
祝你好运:-)
我遇到这个异常是因为无限循环创建新的 UI 控件并设置其属性。循环多次后,当更改控件可见时抛出此异常属性。我发现用户对象和 GDI 对象(来自任务管理器)都很大。
我猜你的问题与系统资源被那些 UI 控件耗尽的原因类似。