在Visual Studio中,我如何从项目资源文件夹加载一个.png图像?

3
我正在开发一个适用于Windows Mobile PDA的应用程序,但我在从资源文件夹获取.png图像时遇到了问题。
我在项目资源文件夹中有许多图像,我只想使用代码以编程方式绘制一个带有来自项目资源文件夹的背景图像的图像框。
例如:
  PictureBox pictureBoxBlueCounter = new PictureBox();

  //pictureBoxBlueCounter = new System.Windows.Forms.PictureBox();
  pictureBoxBlueCounter.Image = global::StrikeOutMobile.Properties.Resources.counter_square_blue;
  pictureBoxBlueCounter.Location = new System.Drawing.Point(30, 30);
  pictureBoxBlueCounter.Name = "pictureBoxblueCounter";
  pictureBoxBlueCounter.Size = new System.Drawing.Size(240, 210);
  pictureBoxBlueCounter.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  Controls.Add(pictureBoxBlueCounter);

目前,上述代码会给我一个“TargetInvocationException was unhandled”错误,我不知道该如何解决!

我该如何解决这个问题?

以下是完整的TargetInvocationException信息:

  System.Reflection.TargetInvocationException was unhandled
  Message="TargetInvocationException"
  StackTrace:
       at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
       at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
       at System.Resources.ResourceReader.CreateResource(Type objType, Type[] ctorParamTypes, Object[] ctorParameters)
       at System.Resources.ResourceReader.LoadBitmap(Int32 typeIndex)
       at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
       at System.Resources.ResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode)
       at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase)
       at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture)
       at StrikeOutMobile.Properties.Resources.get_counter_square_blue()
       at StrikeOutMobile.FormGameBoard.drawBlue()
       at StrikeOutMobile.FormGameBoard.menuItemPosition1_Click(Object sender, EventArgs e)
       at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
       at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
       at Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal)
       at System.Windows.Forms.Form.ShowDialog()
       at StrikeOutMobile.Main.menuItem1_Click(Object sender, EventArgs e)
       at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
       at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
       at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
       at System.Windows.Forms.Application.Run(Form fm)
       at StrikeOutMobile.Program.Main()

  InnerException:
       Message="Exception"
       StackTrace:
            at Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
            at System.Drawing.Bitmap._InitFromMemoryStream(MemoryStream mstream)
            at System.Drawing.Bitmap..ctor(Stream stream)
            at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstructorInfo rtci, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
            at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
            at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
            at System.Resources.ResourceReader.CreateResource(Type objType, Type[] ctorParamTypes, Object[] ctorParameters)
            at System.Resources.ResourceReader.LoadBitmap(Int32 typeIndex)
            at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
            at System.Resources.ResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode)
            at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase)
            at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture)
            at StrikeOutMobile.Properties.Resources.get_counter_square_blue()
            at StrikeOutMobile.FormGameBoard.drawBlue()
            at StrikeOutMobile.FormGameBoard.menuItemPosition1_Click(Object sender, EventArgs e)
            at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
            at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam)
            at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
            at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
            at Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal)
            at System.Windows.Forms.Form.ShowDialog()
            at StrikeOutMobile.Main.menuItem1_Click(Object sender, EventArgs e)
            at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
            at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam)
            at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
            at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
            at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
            at System.Windows.Forms.Application.Run(Form fm)
            at StrikeOutMobile.Program.Main()

你能贴出完整的 exception.ToString() 吗?TargetInvocationException 的内部异常很可能会指示真正的问题... - Nick Guerrera
感谢您抽出时间查看我的问题,Nick!我现在已经添加了完整的异常信息! - Exile
你是在UI线程上执行这个操作吗? - Rich Schuler
5个回答

2

好的,像往常一样,我又小题大做了!

以下是我解决问题的方法:

private void menuItemPosition1_Click(object sender, EventArgs e)
{
    Graphics graphicsCanvas = this.pictureBoxBoard.CreateGraphics();
    graphicsCanvas.DrawImage(global::StrikeOutMobile.Properties.Resources.counter_square_blue, 60, 60);
}

private void pictureBoxBoard_Paint(object sender, PaintEventArgs e)
{

}

原来我需要一个画布(就像在J2ME中一样),但与J2ME不同的是,这个画布实际上并不需要做任何事情。

我不知道为什么这样可以,但它确实可以!

还要特别感谢Qberticus和Nick Guerrera的努力!


2
哦...不不。这样做是不对的。.CreateGraphics() 不是绘制图形的正确方法,会导致视觉故障。请参阅此链接:http://www.bobpowell.net/creategraphics.htm - Quibblesome

1

Controls.Add(pictureBoxBoard); 应该改成 Controls.Add(pictureBoxBlueCounter); 吗?

编辑:

可能是控件句柄的问题。在设置 pictureBoxBlueCounter.Image 之前引用 pictureBoxBlueCounter.Handle,在 Add 之前引用 this.Handle,看看是否有问题。

编辑2:

检查 Resources.Designer.cs 文件,确保一切正常。也许文件名已更改,但在 Resources.resx 中没有反映出来。

编辑3:

您的设备是否有 gdiplus.dll?从这里获得提示

编辑4:

您是在 UI 线程上执行此操作吗?如果不是,那可能就是问题所在。


哦,是的,你说得对,那只是一个打字错误!在代码中应该是pictureBoxBlueCounter!我现在就去修复它! - Exile
Resources.Designer.cs 看起来没问题(所有文件名都匹配,没有看起来不对的地方)。另外,引用pictureBoxBlueCounter.Handle好像不起作用!非常感谢您的努力! - Exile
当您尝试在InitializeComponent()或构造函数中以非编程方式使用PNG时会发生什么? - Rich Schuler

1

你之前释放了这个资源吗?如果你从这种资源文件中释放位图,你会得到相同类型的内部异常堆栈跟踪。我今天做了这件事,感觉很有趣!

嗯...有点意思

顺便说一下,如果在反射期间动态调用函数时发生异常,你会得到一个TargetInvocationException。你会注意到ResourceReader.CreateResource()就是这样做的。它包装了原始异常(可以通过.InnerException属性获取)。


0

我看了一下堆栈,很明显是.NET Compact Framework特定的代码,因为最后几个方法在标准程序集中找不到。我从未在Windows Mobile上使用过.NET CF,但我的猜测是PDA在加载位图时耗尽了内存。

尝试使用小型.png文件,看看是否有所不同。


1
我不认为RAM是这里的问题。我正在尝试加载的最大.png文件大小只有7kb!! - Exile
好的,既然如此,我已经没有更多的想法了。 - Nick Guerrera

0

这个星期我又遇到了一个类似的问题。不知道是什么原因导致的,因为当时很赶,所以没有深入研究。我还收到了神秘的“异常”消息。

以下是我观察到的一些事情。

  • 只有在附加调试时才会发生。
  • 总是同一张图片(640x310)。
  • 该图片与其他图片一样是 .png 格式(另一张 640x310 的图片却没有问题)。
  • 将图片转换为 jpeg 格式似乎可以解决问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接