首页 > 开发 > .Net > 正文

Visual Basic.NET和GDI+共创图标编辑器

2020-02-03 15:59:21
字体:
来源:转载
供稿:网友
如果想自己设计一个个性独特的ico图片,然后让它成为如"我的电脑","回收站"这样的图标该怎么做?就只有用一些专门的画图工具。因为windows的的画图程序无法创建ico文件。于是本人利用.net和gdi+就编写了一个这样的画图工具。虽然现在有很多文章都介绍了gdi+技术,但都只是纯粹的gdi+的简单应用的介绍,至少我还没有看见一篇利用gdi+开发一个完整软件或程序片段的文章。

  这个程序实现了以下的功能:将bmp、jpg、jpeg、gif、.png、.tiff文件转化成ico文件,可以对转化后的文件进行编辑;创建并编辑一个新的ico文件;对已有的ico文件进行编辑。所有被编辑的文件都保存为ico文件,可以在任何可使用ico文件的地方使用它们。

  我先说明一下什么是gdi+。gdi+ 是gdi(windows 早期版本提供的图形设备接口)的后续版本,是microsoft windows xp操作系统即后续版本的图形显示技术。它已经集成到了.net开发环境中,所以不管你的os是什么版本,只要安装了.net框架,就有了gdi+(注意:是.net框架,而不是.net开发环境,所以win98中也可以使用gdi+)。当然它也提供了传统的api,可以由.net或非.net开发工具调用它。由于他和gdi的使用有很大的差别,所以要使用gdi+就必须从头学。gdi+要比gdi简单得多。

  现在就来看一下如何实现这个软件:先添加picturebox,0penfiledialog,savefiledialog,colordialog,domainupdown,label控件;然后添加两个菜单即它们的子菜单,添加的菜单如下"文件"菜单包括"新建","打开","保存","退出","功能"菜单包括"直线","选择颜色"代码如下,在代码后给出程序说明:

public class form1
inherits system.windows.forms.form
public imagepen, newbit, changiamge, mpen 'movepen,moveb,,grh,filenames,endpen
dim xd, yd, xu, yu, pk, ps

private sub menuitem9_click(byval sender as system.object,
byval e as system.eventargs) 'handles menuitem9.click
'新建一个ico文件,即"新建"菜单

 picturebox1.image = nothing
 dim bitnew as new system.drawing.bitmap(32, 32,
 drawing.imaging.pixelformat.format32bppargb)'建立一个bitmap对象,以便在它上面画图
 dim x, y
 for x = 0 to 31
  for y = 0 to 31
   bitnew.setpixel(x, y, color.transparent)'将bitmap的背景设置为透明
  next
 next

 newbit = bitnew
 menuitem3.enabled = false'"选择颜色"菜单不可用
 menuitem2.enabled = true'"直线"菜单可用
end sub

private sub menuitem6_click(byval sender as system.object,
byval e as system.eventargs)' handles menuitem6.click
'打开图片文件即"打开"菜单"

 openfiledialog1.filter = "ico文件(*.ico)|*.ico|图像文件
(*.bmp;*.jpg;*.jpeg;*.gif;*.png;*.tiff)|*.bmp;*.jpg;*.jpeg;*.gif;*.png;*.tiff"

 openfiledialog1.filterindex = 2
 openfiledialog1.showdialog()
 openfiledialog1.filename = ""

end sub

private sub menuitem8_click(byval sender as system.object,
byval e as system.eventargs) 'handles menuitem8.click

 me.close()'退出

end sub

private sub menuitem7_click(byval sender as system.object,
byval e as system.eventargs)

 'handles menuitem7.click
 '保存文件,即"保存"对话筐

 picturebox1.cursor = system.windows.forms.cursors.default
 savefiledialog1.filter = "ico文件(*.ico)|*.ico"'设置要保存的文件后缀
 savefiledialog1.showdialog()
 if savefiledialog1.filename <> "" then
  if not savefiledialog1.showdialog.cancel then
   dim bmp as new system.drawing.bitmap(picturebox1.image,
32,32)'从picturebox1.image初始化bitmap,设置保存为图片的大小,标准ico图由
32*32和16*16两种格式组成,此处为32*32,你也可以设置为16*16

   dim ico as system.drawing.icon = ico.fromhandle(bmp.gethicon())
   '用bitmap的句柄,初始化icon,他是专门处理ico文件的类
   dim file as new system.io.filestream(savefiledialog1.filename(),
   io.filemode.create)'创建文件流
   ico.save(file)'保存为ico文件
   file.close()'关闭流
  end if
 end if
end sub

public sub menuitem2_click(byval sender as system.object,
byval e as system.eventargs)

 'handles menuitem2.click
 '是用直线在新建的ico中画图

 picturebox1.cursor =system.windows.forms.cursors.cross
 '在picturebox1中鼠标的样式

 colordialog1.showdialog()
 dim pen as new pen(colordialog1.color, domainupdown1.text())'创建画笔
 imagepen = pen

end sub

private sub picturebox1_mousedown(byval sender as system.object,
byval e as system.windows.forms.mouseeventargs)

 'handles picturebox1.mousedown
 '当按下鼠标左键时获取直线的起点

 if e.button = mousebuttons.left then
  xd = e.x / 8 : yd = e.y / 8
 end if

end sub

private sub picturebox1_mouseup(byval sender as system.object,
byval e as system.windows.forms.mouseeventargs)

 'handles picturebox1.mouseup
 '画出直线
 if picturebox1.cursor is system.windows.forms.cursors.cross and ps <> 1 then
  xu = e.x : yu = e.y
  me.k(1, imagepen, yu / 8, xu / 8, xd, yd)
 else
  if openfiledialog1.filterindex = 1 then
   xu = e.x : yu = e.y
   me.k(2, mpen, yu / 8, xu / 8, xd, yd)
  end if
 end if
end sub

public sub k(byval k as integer, byval drawtool as object,
byval x as integer, byval y as integer, byval xs as integer,
byval ys as integer)

 if k = 1 then
  picturebox1.sizemode = pictureboxsizemode.stretchimage'自动容纳图片
  picturebox1.image = newbit
  dim graphic as graphics
  graphic = graphic.fromimage(me.picturebox1.image)'在picturebox1上画图
  graphic.smoothingmode = drawing.drawing2d.smoothingmode.antialias'锯齿削边
  graphic.drawline(drawtool, y, x, xs, ys)'画线
 end if
  if k = 2 then
   picturebox1.sizemode = pictureboxsizemode.stretchimage
   picturebox1.image = changiamge
   dim graphic as graphics
   graphic = graphic.fromimage(me.picturebox1.image)
   graphic.smoothingmode = drawing.drawing2d.smoothingmode.antialias
   graphic.drawline(drawtool, y, x, xs, ys)
  end if
end sub

private sub menuitem3_click(byval sender as system.object,
byval e as system.eventargs)

 'handles menuitem3.click
 '对打开的ico文件用直线画图

 colordialog1.showdialog()
 dim m3pen as new pen(colordialog1.color, domainupdown1.text())'建立画笔
 mpen = m3pen

end sub

private sub openfiledialog1_fileok(byval sender as object, byval e as
system.componentmodel.canceleventargs)

 'handles openfiledialog1.fileok
 '打开文件

 if openfiledialog1.filterindex = 1 then
  dim m3pen as new pen(color.black, domainupdown1.text())
  mpen = m3pen
  menuitem2.enabled = false
  menuitem3.enabled = true
 else
  menuitem3.enabled = false
  menuitem2.enabled = false
 end if

 if openfiledialog1.filename <> "" then
  picturebox1.cursor = system.windows.forms.cursors.default
  dim images as new system.drawing.bitmap(openfiledialog1.filename)
  changiamge = images
  picturebox1.sizemode = pictureboxsizemode.stretchimage
  picturebox1.image = images
  me.text = openfiledialog1.filename
 end if

end sub

private sub form1_load(byval sender as object, byval e as system.eventargs)

  'handles mybase.load
  '由于刚运行次程序时,没有打开的ico文件和新建立的ico对象所以不可以创建画图工具对象

  menuitem3.enabled = false
  menuitem2.enabled = false

end sub
end class

  程序说明:

  1. 如何新建ico文件:先初始化bitmap,然后在"功能"-》"直线"菜单代码中创建画笔,就可以开始画了。此时只是创建的一个bitmap对象,是我们在picturebox中画。画完后将bitmap对象保存到文件,就完成了新建ico的文件。

  2.如何打开已有的ico文件,并修改后保存它:判断打开的文件是否是ico,如果不是就只显示他,如果是就显示并且初始化一个画笔,通过"功能"-》"选择颜色"来改变画出直线的颜色和宽度,然后保存,就完成了对原来ico文件的修改。

  3.保存文件和对非ico文件转化为ico文件:通过打开文件,将非ico文件显示在picturebox中,在用picturebox.image初始化bitmap对象,此句的实际作用是将当前的picturebox.image内容附给bitmap。用bitmap的句柄初始icon对象(处理ico文件的对象),作用是将非ico文件转化为ico文件,建立文件流对象,在其中指定新文件名,和访问方法(文件流是save方法的参数)使用icon对象的save保存,最后关闭文件流。

  4.如何画:当完成1或2后,就可以开始画图,画图是由sub k过程,mouse-down,mouse-up来实现的。此时调用mouse-down获得直线的起点,在mouse-up中获得直线终点,接着在mouse-up 中调用sub k过中程绑定bitmap对象到picturebox的image属性,他的作用类似于有了一张可以画画的纸,并在sub k中用graphic.fromimage(me.picturebox1.image)语句创建graphics对象,表示是在picturebox1.image的bitmap对象中画,而不是在picturebox1上画,他们的区别在于前者是可以保存画画结果的,后者不可以。k的值表示是在新建的ico文件中画还是修改以有的ico文件(k=2是表示修改已有的ico文件)

  5.一些语句说明:dim pen …是指用钢笔来画,object.rawline(….)表示画直线,

  6.文件格式的转换问题:你可以使用image对象的save的方法来转换图象的格式,但是我发现虽然他提供了icon格式,但转化后不是ico文件,而是png文件。从网上的资料显示这是.net的本身问题。顺便提一下image对象无构造函数,他虽然标为必须继承才可使用,但实际上不行,如要使用它要用他的fromfile或fromstream方法来构造它。

  7.关于k的问题:当你看懂这篇文章后你一定会提出为什么在每条分支中的picturebox1.sizemode = pictureboxsizemode.stretchimage,picturebox1.image = changiamge这两句代码不可以与它后面的代码分开放在其他地方,如k=1时放在"新建"菜单中的代码部分,k=2是放在mouseup中的else后的if语句中!其实这两句就是我在编写这个程序时遇到的最大的难题,我用了两个小时才的出这两句代码要放在了现在的位置。最后看资料并与朋友探讨后得出3个结论:

  1. .net本身问题。

  2.如果分开使picturebox1.image对象丢失(picturebox1.image返回的是bitmap对象),无法绑定到graphics。

  3. picturebox1.image对象在sub k中不可见。虽然我不知道那个结论是对的,但我将它写了出来,仅供参考。

  对于程序中的0penfiledialog,savefiledialog,colordialog,domainupdown,文件流的使用请见msdn。这5个只是为了辅助这个程序而使用的,如果要在这里讲清楚那这片文章就太长了,而且这些的使用很简单。我在程序中使用的画图工具是钢笔,画出的图形是直线,这队ico文件已经够有了,如果你想使用其他工具,画其他图形,只要修改"功能"中的子菜单,和sub k代码就够了。

  运行如图:



  更换后的"我的电脑"图标




发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表