您当前的位置: 首页 > 教程 > 图像 >
正文

[图像] 在窗体上绘制png图片

日期:2011-01-30
点击:

picturebox 是不支持 png 图片的,png 图片有一个很好的特性——支持半透明,我们可能看见有许多 png 图片都非常好看,那怎么显示在我们的窗体上呢?那就要用到 GDI+ 了。

今天我就给大家一个非常简单的例子,希望大家有所收获。介于新年即将到来,我们就使用下面这张 png 图片作为资源吧:

福
 
大家可以把这张 png 图片存为 icon.png,放到一个新建的文件夹中(一个项目一个文件夹是一个好习惯,要是桌面上到处是 aau 文件就糟了):
新建一个文件夹,将图片下载到文件夹中
 

GDI+ 在别的编程语言中调用起来可能不容易,但是在快手中已经有现成的封装好的库了,几句代码即可。我们要用到的就是 gdip 库。下面跟着我一起做吧。

新建一个窗体设计器,保存为 NewYear.aau(记得与刚才同文件夹哦),并切换到代码视图(Ctrl+U)

首先在头部加入对 gdip 库的引用:

  1. import gdip; 

有点感觉了吧,我们要操作 png 就得用这个库。接着,我们看看快手中有没有帮助文档,暂时没有。没关系,我们有万能的智能提示,我们知道,要画图,得有一块画板吧?画什么上去,那总得有一张图片吧?

我们尝试在代码编辑器中输入 gdip.,这点刚输完,智能提示就出来了,我们来研究一下:

快手智能提示
 
一个一个往下翻,总算翻到了画板,于是,我们按照提示,将我们的窗口传入,创建一块画板,接着我们就可以在这块画板上进行绘制了。
  1. var g = gdip.graphics(winform); 

很好,现在 g 这个变量就是一块画板了,同样的方法,我们创建一幅图像:

  1. var img = gdip.image("icon.png"); 

我们即使完全不会 GDI+ 也没关系,因为我们知道 image 是图片的意思,看智能提示也知道这就能创建一个图片对象。

接下来我们就可以使用 g.drawImageRect() 来绘制了。注意:现在 gdip 库的智能提示还没有完善,因此这个方法不会显示在智能提示中,但是我们可以通过库的源代码来找到这个方法,记得,快手库的源代码也是一个很好的文档。这里就补充一下 drawImageRect 的函数原型:

 drawImageRect(img,x1,y1,width,height) 
不难理解,img 就是我们创建的图片对象,x1, y1 是绘制的坐标,width,height 是绘制的宽度和高度。

  1. g.drawImageRect(img, 0, 0, 128, 128); 

我们就大功告成了。但你会说:“我运行的时候,窗口上什么都没有呀!”

是的,但是当我们将这些代码写到按钮的 oncommand 中,按下按钮是不是又会出现了?

这就涉及到了系统是怎样绘制窗体的,以及 Windows 的消息机制,这些部分我们将在以后的文章中详细介绍,在此我直接给出解决方案:

引用 win.graphics 库后写入如下代码:

  1. winform.wndproc = function(hwnd,message,wparam,lparam) {
  2.     if (message == 0xF/*_WM_PAINT*/) {
  3.         var cvs = win.graphics.canvas();
  4.         cvs.fromWindow(winform);
  5.         cvs.beginPaint();
  6.         var g = gdip.graphics(cvs.handle);
  7.         var img = gdip.image("icon.png");
  8.         g.drawImageRect(img, 0, 0, 128, 128);
  9.         img.dispose();
  10.         cvs.endPaint();
  11.         cvs.destroy();
  12.         return 0;
  13.     }

我们可以看到我们改了几处,首先将前面的三行代码放入了窗口的 WM_PAINT 消息中,窗体要重画的时候,系统会给窗体发送这个消息。

然后我们创建了一个 win.graphics.canvas 实例,这也是一块画板,然后让这块画板从我们的 winform 创建,也就是代替了一开始我们 gdip.graphics 所做的事情。

接着,我们调用了其 beginPaint 方法,beginPaint 和 endPaint 方法是用来告诉系统窗体的绘制由我们自己来,您老可以休息休息。那有人会问,要是不加还能画上吗?回答是肯定的,但是你可以尝试一下,若是去掉了这两行,系统会不停地发送 WM_PAINT 消息,因为系统并不知道你已经画好了。

再有,我们将 gdip.graphics 的第一个参数改为了 cvs 的句柄,关于这点我们可以看 gdip.graphics 的智能提示。

其次,我们加入了 img.dispose() 来释放 img 的资源。这里可能有人要问了,那为什么 g 不用释放呢?这点我们看一下 g.dispose() 的智能提示就明白了。

最后,我们加入了 return 0,这句表明我们已经处理了这个消息,不需要系统再处理了。

最终截图:

最终截图
 
 
在文章的结尾,祝大家新年快乐!