[图像] 在窗体上绘制png图片
- 日期:2011-01-30
- 点击:
picturebox 是不支持 png 图片的,png 图片有一个很好的特性——支持半透明,我们可能看见有许多 png 图片都非常好看,那怎么显示在我们的窗体上呢?那就要用到 GDI+ 了。
今天我就给大家一个非常简单的例子,希望大家有所收获。介于新年即将到来,我们就使用下面这张 png 图片作为资源吧:


GDI+ 在别的编程语言中调用起来可能不容易,但是在快手中已经有现成的封装好的库了,几句代码即可。我们要用到的就是 gdip 库。下面跟着我一起做吧。
新建一个窗体设计器,保存为 NewYear.aau(记得与刚才同文件夹哦),并切换到代码视图(Ctrl+U)
首先在头部加入对 gdip 库的引用:
- import gdip;
有点感觉了吧,我们要操作 png 就得用这个库。接着,我们看看快手中有没有帮助文档,暂时没有。没关系,我们有万能的智能提示,我们知道,要画图,得有一块画板吧?画什么上去,那总得有一张图片吧?
我们尝试在代码编辑器中输入 gdip.,这点刚输完,智能提示就出来了,我们来研究一下:

- var g = gdip.graphics(winform);
很好,现在 g 这个变量就是一块画板了,同样的方法,我们创建一幅图像:
- var img = gdip.image("icon.png");
我们即使完全不会 GDI+ 也没关系,因为我们知道 image 是图片的意思,看智能提示也知道这就能创建一个图片对象。
接下来我们就可以使用 g.drawImageRect() 来绘制了。注意:现在 gdip 库的智能提示还没有完善,因此这个方法不会显示在智能提示中,但是我们可以通过库的源代码来找到这个方法,记得,快手库的源代码也是一个很好的文档。这里就补充一下 drawImageRect 的函数原型:
| drawImageRect(img,x1,y1,width,height) |
- g.drawImageRect(img, 0, 0, 128, 128);
我们就大功告成了。但你会说:“我运行的时候,窗口上什么都没有呀!”
是的,但是当我们将这些代码写到按钮的 oncommand 中,按下按钮是不是又会出现了?
这就涉及到了系统是怎样绘制窗体的,以及 Windows 的消息机制,这些部分我们将在以后的文章中详细介绍,在此我直接给出解决方案:
引用 win.graphics 库后写入如下代码:
- winform.wndproc = function(hwnd,message,wparam,lparam) {
- if (message == 0xF/*_WM_PAINT*/) {
- var cvs = win.graphics.canvas();
- cvs.fromWindow(winform);
- cvs.beginPaint();
- var g = gdip.graphics(cvs.handle);
- var img = gdip.image("icon.png");
- g.drawImageRect(img, 0, 0, 128, 128);
- img.dispose();
- cvs.endPaint();
- cvs.destroy();
- return 0;
- }
- }
我们可以看到我们改了几处,首先将前面的三行代码放入了窗口的 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,这句表明我们已经处理了这个消息,不需要系统再处理了。
最终截图:
