top
Loading...
VisualBasic.NET和GDI+共創圖標編輯器

如果想自己設計一個個性獨特的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代碼就夠了。

運行如圖:



更換后的"我的電腦"圖標


作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗