设为首页收藏本站language 语言切换
查看: 1630|回复: 0
收起左侧

.net和gdi+共创ico图标编辑器

[复制链接]
发表于 2010-2-25 10:25:54 | 显示全部楼层 |阅读模式
<p >ico文件是一种图片类型,在windows中应用广泛,用在窗口,桌面,资源管理器等地方。如果想自己画一张图片,然后让它成为如"我的电脑","回首站"的图片该怎么做?就只有用一些专门的画图工具。因为windows的的画图程序无法创建ico文件。于是本人利用.net和gdi+就编写了一个这样的画图工具。同时也希望大家可以更深入的掌握gdi+和.net。虽然现在有很多文章都介绍了gdi+技术,但都只是纯粹的gdi+的简单应用的介绍,至少我还没有看见一篇利用gdi+开发一个完整软件或程序片段的文章。<p >这个程序利用gdi+和.net实现了以下的功能:将BMP;JPG;jpeg;GIF;.png;.tiff文件转化成ico文件,可以对转化后的文件进行编辑;创建一个新的ico文件,并可以编辑它;对以有的ico文件编辑。所有被编辑的文件都保存为ico文件,可以在任何可使用ico文件的地方使用它们。<p >我先说明一下什么是gdi+。GDI+ 是GDI(Windows 早期版本提供的图形设备接口)的后续版本,是Microsoft Windows xp操作系统即后续版本的图形显示技术。它已经集成到了.net开发环境中,所以不管你的os是什么版本,只要安装了.net框架,就有了gdi+(注意:是.net框架,而不是.net开发环境,所以win98中也可以使用gdi+)。当然它也提供了传统的api,可以由.net或非.net开发工具调用它。由于他和gdi的使用有很大的差别,所以要使用gid+就必须从头学。gdi+要比gdi简单得多。<p >现在就来看一下如何实现这个软件:先添加picturebox,0penfiledialog,savefiledialog,colordialog,domainupdown,label控件;然后添加两个菜单即它们的子菜单,添加的菜单如下"文件"菜单包括"新建","打开","保存","退出","功能"菜单包括"直线","选择颜色"代码如下,在代码后给出程序说明:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>ublic Class Form1    Inherits System.Windows.Forms.FormPublic 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文件,即&quot;新建&quot;菜单        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'&quot;选择颜色&quot;菜单不可用        MenuItem2.Enabled = True'&quot;直线&quot;菜单可用    End Sub    Private Sub MenuItem6_Click(ByVal sender As System.Object,    ByVal e As System.EventArgs) Handles MenuItem6.Click        '打开图片文件即&quot;打开&quot;菜单&quot;              OpenFileDialog1.Filter = &quot;ico文件(*.ico)|*.ico|图像文件 (*.BMP;*.JPG;*.jpeg;*.GIF;*.png;*.tiff)|*.BMP;*.JPG;*.jpeg;*.GIF;*.png;*.tiff&quot;        OpenFileDialog1.FilterIndex = 2        OpenFileDialog1.ShowDialog()        OpenFileDialog1.FileName = &quot;&quot;    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        '保存文件,即&quot;保存&quot;对话筐        PictureBox1.Cursor = System.Windows.Forms.Cursors.Default        SaveFileDialog1.Filter = &quot;ico文件(*.ico)|*.ico&quot;'设置要保存的文件后缀        SaveFileDialog1.ShowDialog()        If SaveFileDialog1.FileName &lt;&gt; &quot;&quot; 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 &lt;&gt; 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 &lt;&gt; &quot;&quot; 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 SubEnd Class</ccid_code></pre></td></tr></table></ccid_nobr><p ><b>程序说明:</b><p >1.        如何新建ico文件:先初始化bitmap,然后在"功能"-》"直线"菜单代码中创建画笔,就可以开始画了。此时只是创建的一个bitmap对象,是我们在picturebox中画。画完后将bitmap对象保存到文件,就完成了新建ico的文件。<p >2.如何打开已有的ico文件,并修改后保存它:判断打开的文件是否是ico,如果不是就只显示他,如果是就显示并且初始化一个画笔,通过"功能"-》"选择颜色"来改变画出直线的颜色和宽度,然后保存,就完成了对原来ico文件的修改。<p >3.保存文件和对非ico文件转化为ico文件:通过打开文件,将非ico文件显示在picturebox中,在用picturebox.image初始化bitmap对象,此句的实际作用是将当前的picturebox.image内容附给bitmap。用bitmap的句柄初始icon对象(处理ico文件的对象),作用是将非ico文件转化为ico文件,建立文件流对象,在其中指定新文件名,和访问方法(文件流是save方法的参数)使用icon对象的save保存,最后关闭文件流。<p >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文件)<p >5.一些语句说明:dim pen …是指用钢笔来画,object.rawline(….)表示画直线,<p >6.文件格式的转换问题:你可以使用image对象的save的方法来转换图象的格式,但是我发现虽然他提供了icon格式,但转化后不是ico文件,而是png文件。从网上的资料显示这是.net的本身问题。顺便提一下image对象无构造函数,他虽然标为必须继承才可使用,但实际上不行,如要使用它要用他的fromfile或fromstream方法来构造它。<p >7.Sub k中的问题:当你看懂这篇文章后你一定会提出为什么在每条分支中的PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage,PictureBox1.Image = changiamge这两句代码不可以与它后面的代码分开放在其他地方,如k=1时放在"新建"菜单中的代码部分,k=2是放在mouseup中的else后的if中!其实这两句就是我在编写这个程序时遇到的最大的难题,我用了两个小时才的出这两句代码要放在了现在的位置。最后看资料并和别人讨论的出3个结论:<p >1. .net本身问题。<p >2.如果分开使PictureBox1.Image对象丢失(PictureBox1.Image返回的是bitmap对象),无法绑定到Graphics。<p >3. PictureBox1.Image对象在sub k中不可见。虽然我不知道那个结论是对的,但我将它写了出来,仅供参考。<p >对于程序中的0penfiledialog,savefiledialog,colordialog,domainupdown,文件流的使用请见msdn。这5个只是为了辅助这个程序而使用的,如果要在这里讲清楚那这片文章就太长了,而且这些的使用很简单。我在程序中使用的画图工具是钢笔,画出的图形是直线,这队ico文件已经够有了,如果你想使用其他工具,画其他图形,只要修改"功能"中的子菜单,和sub k代码就够了。<p >运行如图:<p ><center><img  src="http://www.hh010.com/upload_files/article/244/9_k49bju37666.jpg"></center><p >更换后的"我的电脑"图标<p ><img  src="http://www.hh010.com/upload_files/article/244/9_9cdvle37669.jpg"><p >在vb.net和win2000中通过。<p >(Sunny</ccid_nobr>)                                 <p align="center"></p></p>
您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-4-12 01:11 , Processed in 0.077728 second(s), 23 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表