(1).使用DllImport特征類來申明Windows API函數(shù):
員工經(jīng)過長(zhǎng)期磨合與沉淀,具備了協(xié)作精神,得以通過團(tuán)隊(duì)的力量開發(fā)出優(yōu)質(zhì)的產(chǎn)品。創(chuàng)新互聯(lián)堅(jiān)持“專注、創(chuàng)新、易用”的產(chǎn)品理念,因?yàn)椤皩W⑺詫I(yè)、創(chuàng)新互聯(lián)網(wǎng)站所以易用所以簡(jiǎn)單”。公司專注于為企業(yè)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、電商網(wǎng)站開發(fā),微信小程序定制開發(fā),軟件按需規(guī)劃網(wǎng)站等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。
下面是在Visual Basic .Net中使用DllImport特征類申明二個(gè)Windows API函數(shù)的具體示例:
'函數(shù)ExtractIcon,其功能是是從指定文件的指定位置導(dǎo)出圖標(biāo)的Windows句柄。
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'函數(shù)Icon_Num,其功能是獲得指定文件中的圖標(biāo)數(shù)目
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
Icon_Num ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
End Function
在使用DllImport特征類申明Windows API函數(shù)時(shí),如果申明的函數(shù)名稱和函數(shù)的入口點(diǎn)相同,則可以在申明Windows API函數(shù)時(shí),省略定義函數(shù)入口點(diǎn)對(duì)應(yīng)的代碼,即EntryPoint對(duì)象字段對(duì)應(yīng)的代碼,這樣聲明ExtractIcon函數(shù)的代碼也可以簡(jiǎn)化為如下所示:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
(2).使用“Declare”語句來申明Windows API函數(shù):
使用“Declare”語句的確比使用DllImport特征類要簡(jiǎn)單了許多,下面是在Visual Basic .Net中使用“Declare”語句來聲明上述二個(gè)Windows API函數(shù)的具體方法:
Declare Auto Function ExtractIcon Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
'聲明ExtractIcon函數(shù)
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
'聲明Icon_Num函數(shù)
在Visual Basic .Net中聲明Windows API函數(shù)時(shí),“Declare”語句中Alias關(guān)鍵字的作用相當(dāng)于使用DllImport特征類中的EntryPoint對(duì)象字段。同樣在使用“Declare”語句聲明Windows API函數(shù)時(shí),如果聲明的函數(shù)和函數(shù)的入口點(diǎn)相同,也可以省略Alias關(guān)鍵字對(duì)應(yīng)的代碼,所以ExtractIcon函數(shù)也可以簡(jiǎn)化為如下:
Declare Auto Function ExtractIcon Lib "Shell32.dll" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
success = WritePrivateProfileStringA改成success = WritePrivateProfileString 另外vc6里的long在vc.net里要換成integer,你這樣調(diào)用會(huì)出錯(cuò)的
現(xiàn)在我用我所知道的為樓主介紹VB.NET的API調(diào)用,請(qǐng)樓主瀏覽一下,看看行不行。
Windows API就是Windows系統(tǒng)的API函數(shù)簡(jiǎn)稱(Application Program Interface,即:應(yīng)用程序接口函數(shù)),它是Windows操作系統(tǒng)提供給各種開發(fā)基于Windows平臺(tái)應(yīng)用軟件的開發(fā)語言的一些公用的函數(shù),這些函數(shù)一般都比較底層,所以當(dāng)各種開發(fā)語言使用自帶的函數(shù)或類庫已無法解決問題時(shí),調(diào)用Windows API函數(shù)往往是一種非常直接、有效的解決方法。但由于在程序中調(diào)用Windows API函數(shù)一般都很復(fù)雜,所以對(duì)于程序員來說,是否能夠靈活的使用Windows API函數(shù),往往也是其水平高低的一個(gè)重要標(biāo)志。但自從微軟推出.Net框架以后,各種開發(fā)基于.Net平臺(tái)下的程序語言,如Visual Basic .Net、Visual C#等卻很少使用Windows API函數(shù),并且微軟公司也不像以前那樣,提倡在這些.Net開發(fā)語言中使用Windows API函數(shù),其主要的原因如下:
1. .Net框架所附帶的類庫.Net FrameWork SDK是一個(gè)內(nèi)容豐富、功能強(qiáng)大的軟件開發(fā)包,各種Windows API函數(shù)所實(shí)現(xiàn)的各種功能幾乎都可以在這個(gè)軟件開發(fā)包中找到與之對(duì)應(yīng)的部分。
2. 微軟Visual Basic .Net、Visual C#等目的是編寫跨平臺(tái)的應(yīng)用程序,如果在Visual Basic .Net、Visual C#等中使用Windows API函數(shù),這也就注定了編寫出的程序只能運(yùn)行于Windows平臺(tái)之下,而弱化了.NET的跨平臺(tái)能力。這也就是為什么微軟不提倡在.Net平臺(tái)調(diào)用Windows API函數(shù)的原因。
雖然微軟并不提倡在Visual Basic .Net、Visual C#中調(diào)用Windows API函數(shù),但由于目前.Net 框架推出時(shí)間較短,.Net FrameWork SDK中提供的類庫還并不足以完全替換Windows API函數(shù)的所有功能,所以在某些時(shí)候,.Net開發(fā)語言還是必須要調(diào)用Windows API函數(shù)。
一.平臺(tái)調(diào)用、托管DLL、非托管DLL簡(jiǎn)介:
托管DLL就是能夠在公共語言運(yùn)行庫(Common Language Runtime,簡(jiǎn)稱CLR)中能夠直接引用的,并且擴(kuò)展名為“DLL”的文件。具體所指就是封裝各種命名空間所在的DLL文件,如System.dll等。非托管DLL就是平常所的動(dòng)態(tài)鏈接庫等,其中就包括了封裝所有Windows API函數(shù)的DLL文件。各種非托管DLL中的函數(shù)在公共語言運(yùn)行庫中不能直接被調(diào)用,而需要經(jīng)過.Net框架提供的“平臺(tái)調(diào)用”服務(wù)后才可以。
“平臺(tái)調(diào)用”是.Net框架為Visual Basic .Net、Visual C#等.Net開發(fā)語言提供的一種服務(wù),用以在托管代碼中引入各種非托管DLL中封裝的函數(shù)(其中包括Windows API函數(shù))?!捌脚_(tái)調(diào)用”依賴于元數(shù)據(jù)在運(yùn)行時(shí)查找導(dǎo)出函數(shù)并封裝其參數(shù)。圖01公共語言運(yùn)行庫利用“平臺(tái)服務(wù)”調(diào)用非托管DLL中的函數(shù)的流程圖:
圖01:“平臺(tái)服務(wù)”的調(diào)用非托管函數(shù)的流程圖
在托管代碼中使用“平臺(tái)調(diào)用”服務(wù)調(diào)用非托管DLL中封裝的函數(shù)時(shí),“平臺(tái)服務(wù)”將依次執(zhí)行以下操作:
1. 查找包含該函數(shù)所在的DLL文件。
2. 如果找到,則將該DLL文件 加載到內(nèi)存中。
3. 查找函數(shù)在內(nèi)存中的地址并將其參數(shù)推到堆棧上,并封送所需的數(shù)據(jù)。
4. 將控制權(quán)轉(zhuǎn)移給非托管函數(shù)。 這樣整個(gè)函數(shù)調(diào)用完成。
在Visual Basic .Net中使用“平臺(tái)調(diào)用”服務(wù),申明Windows API函數(shù)主要有二種具體的實(shí)現(xiàn)方法:
1. 使用DllImport特征類來申明Windows API函數(shù)。
2. 使用“Declare”語句來申明Windows API函數(shù)。
這二種方法雖有異曲同工之效,但在繁簡(jiǎn)上卻有很大差異,第一種方法申明過程比較復(fù)雜,很容易在申明Windows API函數(shù)時(shí)出錯(cuò),所以并不提倡。而第二種方法相對(duì)簡(jiǎn)單,并且又保存了以前Visual Basic中的很多語法,所以在平常時(shí)大都使用這種方法來申明Windows API函數(shù)。
二.VB.Net查看文件中圖標(biāo)的函數(shù)及申明Windows API的方法:
Visual Basic .Net要實(shí)現(xiàn)查看文件中的圖標(biāo),目前只使用.Net FrameWork SDK是無法實(shí)現(xiàn)這種功能的,正如前面所說,主要是由于.Net FrameWork SDK推出的時(shí)間較短,其功能還不可能面面俱到。解決問題的關(guān)鍵是正確使用Windows API函數(shù),其中所涉及到的Windows API函數(shù)主要有二個(gè):其一是獲得指定文件中的圖標(biāo)數(shù)目;其二是從指定文件的指定位置導(dǎo)出圖標(biāo)的Windows句柄。這二個(gè)函數(shù)都位于“Shell32.dll”文件中,并且函數(shù)的入口點(diǎn)都為“ExtractIcon”。下面是在Visual Basic .Net中分別使用DllImport特征類和“Declare”語句申明這二個(gè)Windows API函數(shù)的具體方法。
(1).使用DllImport特征類來申明Windows API函數(shù):
下面是在Visual Basic .Net中使用DllImport特征類申明二個(gè)Windows API函數(shù)的具體示例:
'函數(shù)ExtractIcon,其功能是是從指定文件的指定位置導(dǎo)出圖標(biāo)的Windows句柄。
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'函數(shù)Icon_Num,其功能是獲得指定文件中的圖標(biāo)數(shù)目
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
Icon_Num ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
End Function
在使用DllImport特征類申明Windows API函數(shù)時(shí),如果申明的函數(shù)名稱和函數(shù)的入口點(diǎn)相同,則可以在申明Windows API函數(shù)時(shí),省略定義函數(shù)入口點(diǎn)對(duì)應(yīng)的代碼,即EntryPoint對(duì)象字段對(duì)應(yīng)的代碼,這樣聲明ExtractIcon函數(shù)的代碼也可以簡(jiǎn)化為如下所示:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
(2).使用“Declare”語句來申明Windows API函數(shù):
使用“Declare”語句的確比使用DllImport特征類要簡(jiǎn)單了許多,下面是在Visual Basic .Net中使用“Declare”語句來聲明上述二個(gè)Windows API函數(shù)的具體方法:
Declare Auto Function ExtractIcon Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
'聲明ExtractIcon函數(shù)
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
'聲明Icon_Num函數(shù)
在Visual Basic .Net中聲明Windows API函數(shù)時(shí),“Declare”語句中Alias關(guān)鍵字的作用相當(dāng)于使用DllImport特征類中的EntryPoint對(duì)象字段。同樣在使用“Declare”語句聲明Windows API函數(shù)時(shí),如果聲明的函數(shù)和函數(shù)的入口點(diǎn)相同,也可以省略Alias關(guān)鍵字對(duì)應(yīng)的代碼,所以ExtractIcon函數(shù)也可以簡(jiǎn)化為如下:
Declare Auto Function ExtractIcon Lib "Shell32.dll" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
下面就結(jié)合一個(gè)示例的編寫過程來掌握的這二個(gè)Windows API函數(shù)的具體使用方法,這個(gè)示例的作用就是讀取指定文件中的圖標(biāo)數(shù)目,并顯示文件中的圖標(biāo)。
三.本文中程序的編寫、調(diào)試和運(yùn)行環(huán)境:
(1).視窗2000高級(jí)服務(wù)器版。
(2).Visual Studio .Net 2003企業(yè)結(jié)構(gòu)設(shè)計(jì)版,.Net FrameWork SDK版本號(hào)4322。
四.Visual Basic .Net讀取文件中的圖標(biāo)的實(shí)現(xiàn)步驟:
下面介紹的示例,其功能讀取指定文件中包含的圖標(biāo)數(shù)目,并把這些圖標(biāo)全部顯示出來。下面是這個(gè)示例的實(shí)現(xiàn)步驟:
1. 啟動(dòng)Visual Studio .Net。
2. 選擇菜單【文件】|【新建】|【項(xiàng)目】后,彈出【新建項(xiàng)目】對(duì)話框。
3. 將【項(xiàng)目類型】設(shè)置為【Visual Basic項(xiàng)目】。
4. 將【模板】設(shè)置為【W(wǎng)indows應(yīng)用程序】。
5. 在【名稱】文本框中輸入【Visual Basic .Net查看文件中的圖標(biāo)】。
6. 在【位置】的文本框中輸入【E:\VS.NET項(xiàng)目】,然后單擊【確定】按鈕,這樣在【E:\VS.NET項(xiàng)目】目錄中就產(chǎn)生了名稱為【Visual Basic .Net查看文件中的圖標(biāo)】文件夾,里面存放著【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目的所有文件。具體如圖02所示:
圖02:【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目的【新建項(xiàng)目】對(duì)話框
7. 選擇菜單【項(xiàng)目】|【添加新項(xiàng)】,在彈出的對(duì)話框中的【模板】設(shè)置為【模塊】,【名稱】文本框設(shè)置為【Module1.vb】后。單擊【打開】按鈕,則在項(xiàng)目中增加了一個(gè)模板文件,名稱為【Module1.vb】。
8. 把Visual Stuido .Net的當(dāng)前窗口切換到Module1.vb的代碼編輯窗口,并在其Module1的代碼區(qū)中添加下列代碼,下列代碼是用二種方式聲明二個(gè)Windows API函數(shù):
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'聲明ExtractIcon函數(shù)
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As Integer ) As Integer
9. 把Visual Studio .Net的當(dāng)前窗口切換到Form1窗體的設(shè)計(jì)查看,并從【工具箱】中的【W(wǎng)indows窗體】選項(xiàng)卡中拖入下列組件到Form1窗體:
四個(gè)Label組件,其中二個(gè)用以顯示提示信息,另外二個(gè)分別用以顯示選擇的文件名稱和這個(gè)文件中包含的圖標(biāo)數(shù)目。
一個(gè)ListView組件,利用其顯示大圖標(biāo)的屬性用以顯示選定文件中的圖標(biāo)。
一個(gè)OpenFileDialog組件,用以選擇要查看圖標(biāo)的文件名稱。
一個(gè)ImageList組件,它起的是橋梁的作用,首先把從文件中導(dǎo)出的圖標(biāo)存放到這里,然后再提供ListView組件顯示出來。
一個(gè)Button組件。
10. 按照表01中數(shù)值來設(shè)定設(shè)定組件的主要屬性:
組件類型 組件名稱 屬性 設(shè)置結(jié)果
Form Form1 Text VB.NET查看文件中的圖標(biāo)
Form1 MaximizeBox False
Form1 MinimizeBox False
Form1 FormBorderStyle FixedSingle
ListView ListView1 ImageList1 LargeImageList
ListView1 MultiSelect False
ListView1 Size Size ( 380 , 208 )
Button Button1 Text 選擇文件
Button1 FlatStyle Flat
ImageList ImageList1 Size Size ( 32 , 32 )
ImageList1 TransparentColor Color.Transparent
Label Label1 Text 文件名稱:
Label2 Text 圖標(biāo)數(shù)目:
Label3 Text ""
Label4 Text "0"
表01:【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目窗體中各組件的主要屬性設(shè)定數(shù)值表
并按照?qǐng)D02中各組件的位置、大小和排列方式來調(diào)整窗體中各個(gè)組件:
圖02:【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目的設(shè)計(jì)界面
11. 把Visual Studio .Net當(dāng)前窗口切換到Form.vb的代碼編輯窗口,并用下列代碼替換Form1.vb中的Button1組件的Click事件的處理代碼,下列代碼是在Button1組件的Click事件中處理查看文件中圖標(biāo)的功能,具體如下:
Private Sub Button1_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button1.Click
If OpenFileDialog1.ShowDialog ( ) = DialogResult.OK Then
'清除組件中的所有項(xiàng)目
ListView1.Items.Clear ( )
ImageList1.Images.Clear ( )
Dim sfName As String = OpenFileDialog1.FileName
Label3.Text = sfName
Dim iIcon_Num As Integer = Icon_Num ( IntPtr.Zero , sfName , -1 )
'顯示文件中的圖標(biāo)數(shù)目
Label4.Text = iIcon_Num.ToString ( )
Dim i As Integer
For i = 0 To iIcon_Num - 1 Step 1
'強(qiáng)制實(shí)現(xiàn)int到uint類型轉(zhuǎn)換
Dim j As UInt32
j = System.Convert.ToUInt32 ( i )
Dim hIcon As System.IntPtr = ExtractIcon ( IntPtr.Zero , sfName , j )
'在imageList1組件中加入當(dāng)然提取的圖標(biāo)
ImageList1.Images.Add ( Icon.FromHandle ( hIcon ).ToBitmap ( ) )
'在ListView組件中加入一個(gè)項(xiàng)目
ListView1.Items.Add ( "第" + ( i + 1 ).ToString ( ) + "個(gè)圖標(biāo)" )
'把加入項(xiàng)目的圖象索引指向剛才加入圖標(biāo)在imagList1組件中的索引,從而顯示圖標(biāo)
ListView1.Items ( i ).ImageIndex = i
Next i
End If
End Sub
12. 至此,在上述步驟都正確執(zhí)行后,【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目的全部工作就完成了。單擊快捷鍵F5就可以運(yùn)行程序,此時(shí)單擊【選擇文件】按鈕選擇文件后,程序就能夠讀取這個(gè)文件中的圖標(biāo)及其數(shù)目,并顯示出來了。具體如圖03所示:
圖03:【Visual Basic .Net查看文件中的圖標(biāo)】項(xiàng)目的運(yùn)行界面
五.總結(jié):
解決Visual Basic .Net查看文件中的圖標(biāo)的關(guān)鍵并非是使用.Net框架中提供的類庫,而是使用Windows的API函數(shù)。雖然這與利用Visual Basic .Net開發(fā)跨平臺(tái)程序的初衷相違背,但的確不失為一種解決問題的方法。有些時(shí)候通過Windows API函數(shù)能夠快捷、方便的解決實(shí)際問題,而這往往是只使用.Net FrameWork SDK所望塵莫及的,但隨著.Net FrameWork SDK內(nèi)容的不斷豐富,各種新的組成部分和新的功能不斷加入,可以預(yù)見的是,在未來的.Net FrameWork SDK中必將擁有可以替換本文中介紹的二個(gè)Windows API函數(shù)的組成部分。
1.Windows的API有兩個(gè)版本的,比如ANSI的FindWindowA(),Unicode的FindWindowW()
2.兩種聲明的方式
DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="FindWindow") _
Shared Function FindWindow(ByVal className As String, ByVal windowName As String) As IntPtr
End Function
Declare Auto Function FindWindow Lib "user32.dll" Alias "FindWindow" (ByVal className As String, ByVal windowName As String) As IntPtr