設為首頁收藏本站Access中國

Office中國論壇/Access中國論壇

 找回密碼
 注冊

QQ登錄

只需一步,快速開始

tag 標簽: Freebasic基礎

相關帖子

版塊 作者 回復/查看 最后發(fā)表

沒有相關內容

相關日志

分享 freebasic菜鳥初學Freebasic基礎教程十一:使用afx庫有關字符串的函數(shù)和類
ganlinlao 2017-5-12 21:00
freebasic菜鳥初學Freebasic基礎教程十一:使用afx庫有關字符串的函數(shù)和類
'冬瓜湯編寫整理 字符串處理,對于大部分語言來說,都是一件麻煩的事,ansi,unicode,utf-8……,我前面已經(jīng)說過了,F(xiàn)B對于unicode支持不是特別的好,也就是wstring只能是指針或固定長度,而不是動態(tài)不定長的字符串,這非常麻煩。雖然wstr()可以快速將string字符串轉變成wstring字符串,但其實很多場合下的使用,還是非常不方便。afx的CWstr類就是專門處理unicode字符串,其實用它可以處理ansi,unicode,utf-8,Bstr(vbstring),非常方便,不管是網(wǎng)絡上常用的utf-8,還是com的BSTR,都挺方便的。 一、len(),和sizeof()對字符串的影響 在FB中,len()用來判斷一個字符串的大小, 對于string和zstring來說,len返回的是字節(jié)大小。對于unicode來說,len()返回的是字符數(shù)。uniocde字符串的字節(jié)大小,是len(unicode)*2 。 而sizeof()是用來判斷一個變量,對象內存占用多少。 這是一個測試例子: #include once "afx/cwindow.inc" Dim As String anStr,anStrEN dim anStrU as string dim unStr as wstring*20 '這里直接用固定長度20個unicode字符 anStrEn = "FB is new basic" unstr = "FB是語言" anstr = "FB是語言" anStrU = wstr(anstr) afxmsg "ansi的Len大。" Len( anstr) chr(13) _ "ansi的sizeof大小:" sizeof(anstr) chr(13) _ "ansi純英文的Len大。" Len( anstrEn) chr(13) _ "ansi純英文的sizeof大。" sizeof(anstrEn) chr(13) _ "unicode的Len大。" len(unStr) chr(13) _ "uniocde的sizeof大。" sizeof(unStr) chr(13) _ "an轉Un的len大小:" len(anStrU) chr(13) _ "an轉Un的sizeof大。" sizeof(anStrU) chr(13) _ "wstr()返回值的Len大。" len(wstr(anstr)) chr(13) _ "wstr()返回值的sizeof大。" sizeof(wstr(anStr)) 在這里我們會發(fā)現(xiàn)sizeof對于string不起作用,總是返回大小12,這我無法解釋,只能把它理解成因為string是一個動態(tài)不定長的字符串數(shù)組,sizeof返回的實際上是一個數(shù)組結構的字節(jié)大小。如果用64位編譯,你會發(fā)現(xiàn)sizeof總是返回24。 (2)wstr(string)賦值給一個string類型的變量,不會發(fā)現(xiàn)任何變化。 (3) sizeof(wstr())總是返回0,估計是一個Null值。 所以在實際使用中如果要預先分配內存的話,千萬要小心不要誤以為sizeof(string)能返回總字節(jié)大小。 '冬瓜湯整理編寫 二、使用afx的字符串函數(shù) #include once "afx/CWSTR.inc" #include once "afx/afxStr.inc" using afx ' 所有的afx庫,都處在同一個命名空間afx里,F(xiàn)B的命名空間規(guī)則和c#/vb.net是一樣的。 '我不喜歡using這個關鍵詞,我更喜歡Imports,但沒辦法 import在FB很早以前就是一個關鍵字了。 '判斷是否是數(shù)字 Dim inNumeric As boolean=afxIsNumeric("-1395.43") '同left的用法 Dim As cwstr strLeft=afxstrClipLeft("這是一個Freebasic測試",9) '同mid的用法 Dim As cwstr strMid=afxstrClipMid("這是一個Freebasic測試",4,5) '同Right用法 Dim As cwstr strRight=afxstrClipRight("這是一個Freebasic測試",2) '左右嵌入空格或指定的符號 Dim As cwstr strCset=afxstrCset("單身狗",11,"*") '返回 ****單身狗**** '刪除指定數(shù)量的子字符串 Dim As cwstr strDelete=afxstrDelete("這是一個Freebasic測試",4,9) '從主字符串提取匹配指定字符的字符串,但不包括指定字符本身 Dim As cwstr strExtract=afxstrExtract(1,"誰是單身狗,不是單身貓","狗") ' Dim As cwstr strExtractAny=afxstrExtractAny(1,"誰是單身狗,不是單身貓","貓狗") '從指定位置插入子字符串 Dim As cwstr strInsert=afxstrInsert("01032547891","—",3) '從第三個位置之后插入子字符串 '同join用法 Dim cwsa As cwstrArray=cwstrArray(4,1) '建一個4行1列的數(shù)組 cwsa.Item(1) = "One" cwsa.Item(2) = "Two" cwsa.Item(3) = "Three" cwsa.item(4)="Four" DIM strJoinAS CWSTR = AfxStrJoin(cwsa, ",") '用法和vb的join一樣 '左邊加入指定數(shù)量的空格或指定符號 DIM strLset AS CWSTR = AfxStrLSet("FreeBasic", 20, "#") '解析帶分隔符的字符串,分隔符可以多種混用 DIM cws AS CWSTR = AfxStrParse("one,two,three", 2) ' Returns "two" DIM cws AS CWSTR = AfxStrParseAny("1;2,3", 2, ",;") ' Returns "2" '解析帶分隔符的字符串,并返回數(shù)量 DIM nCount AS LONG = AfxStrParseCount("one,two,three", ",") ' Returns 3 DIM nCount AS LONG = AfxStrParseCountAny("1;2,3", ",;") ' Returns 3 '返回子字符串第一次出現(xiàn)在主字符串位置之前的那部分字符串,可以指定搜索位置從哪里開始,默認從1 DIM cws AS CWSTR = AfxStrRemain("Brevity is the soul of wit", "is ") ' Returns "the soul of wit" DIM cws AS CWSTR = AfxStrRemainAny("I think, therefore I am", ",") ' Returns "therefore I am" '從主字符串移除子符串 DIM cws AS CWSTR = AfxStrRemove(" ", "[]") ' Returns "Hello" DIM cws AS CWSTR = AfxStrRemoveAny("abacadabra", "bac") ' Returns "dr" '替換,同Replace() DIM cws AS CWSTR = AfxStrReplace("Hello World", "World", "Earth") ' Returns "Hello Earth" DIM cws AS CWSTR = AfxStrReplaceAny("abacadabra", "bac", "*") ' Returns "*****d**r* '去掉主字符串不匹配指定的子符串的那部分,只返回匹配的子符串或子符串組 DIM cws AS CWSTR = AfxStrRetain("abacadabra","b") ' Returns "bb" DIM cws AS CWSTR = AfxStrRetainAny("1234567890ak;lk;l1234567890", ";/p") ' Returns ";;" '反轉字符串 DIM cws AS CWSTR = AfxStrReverse("garden") ' Returns "nedrag" '右邊添加指定數(shù)量的空格或指定符號 DIM cws AS CWSTR = AfxStrRSet("FreeBasic", 20, "*") '將帶各種不規(guī)范分隔符的字符串,整理成一種規(guī)范的字符串 DIM cws AS CWSTR = AfxStrShrink(",,, one , two three, four,", " ,")' Returns "one two three four" '同split DIM cws AS CWSTR = "- This, a sample string." DIM cwsa AS CWstrArray = AfxStrSplit(cws, " ,.-") FOR i AS LONG = cwsa.LBound TO cwsa.UBound PRINT cwsa.Item(i) NEXT '統(tǒng)計子符串在主子符串出現(xiàn)的次數(shù) DIM nCount AS LONG = AfxStrTally("abacadabra", "ab") ' Returns 2 DIM nCount AS LONG = AfxStrTallyAny("abacadabra", "bac") ' Returns 8 '在開頭和結尾,刪除成對的字符符號 AfxStrUnWrap("Paul", "", "") results Paul AfxStrUnWrap("'Paul'", "'") results Paul '確定主字符串是否包含指定子符串中任一一個字符 DIM nCount AS LONG = AfxStrVerify(5, "123.65,22.5", "0123456789") ' Returns 7 '在字符串開頭和結尾添加 成對的字符 AfxStrWrap('保羅',"", "")結果保羅 ……還有一些函數(shù),具體看幫助文檔 ########################################################### 三、使用BSTR 為了方便使用,我將Cbstr類和Cwstr類合并在同一個文件cwstr.inc中 #include once "afx/Cwstr.inc" using afx Dim myBstr as CBSTR myBstr="這是一個測試" 用 Cbstr類,主要是為了能夠自動釋放vbstring指針。忘記釋放bstr指針,是非常容易犯的錯。所以一遇到任何傳進來的bstr字符串 就立即用cbstr進行接收。
個人分類: FreeBasic|4301 次閱讀|0 個評論
分享 Freebasic菜鳥初學Freebasic基礎教程九:了解com數(shù)據(jù)類型
ganlinlao 2017-5-11 10:34
FB在windows上使用,有兩種東西是無法回避的,一種是api,一種是com,這是幾乎所有在windows上使用的語言都必須用到的。 這是引用自csdn上的博客內容: 了解一下com數(shù)據(jù)類型,有助于在FB中使用com。 BSTR、 BSTR到底是什么。 BSTR是COM中的數(shù)據(jù)類型,在COM編程時,接口中定義的字符串類型都是BSTR類型, 而使用BSTR類型是極其容易出錯的,同時,一不小心就有可能造成內存泄露。所以有如下建議: 在對接口進行實現(xiàn)時,從接口參數(shù)中傳遞過來的BSTR類型的變量,一定要在第一時刻將BSTR類型轉變成_bstr_t類型的變量,就是因為 BSTR有隱藏的危險 ,同時當使用BSTR出現(xiàn)bug時,而這種bug而不一定好找; 在對接口進行實現(xiàn)時,接口中的BSTR字符串參數(shù)是out時,在接口實現(xiàn)的內部不要定義BSTR類型變量,而是定義_bstr_t類型的變量,進行操作,操作完成以后,然后在轉為BSTR類型的變量傳出去。 既然是這樣,就有人要問了,那么BSTR存在的必要是什么? 這個是由COM決定的,由于COM是跨系統(tǒng)及不同開發(fā)語言間實現(xiàn)互操作的技術,常規(guī)以NULL結尾的簡單字符串在COM組件間傳遞不太方便。 所以,BSTR就這么出現(xiàn)了。 BSTR作為指針類型,標準的BSTR是一個有長度前綴和NULL結束符的OLECHAR數(shù)組。BSTR的前4個字節(jié)是一個 表示字符串長度的前綴。BSTR長度域的值是字符串的字節(jié)數(shù),但不包括字符串結束符。BSTR實際上包含的是Unicode串, 所以字符數(shù)是字節(jié)數(shù)的一半。 所以,在能不使用BSTR的情況下,就盡量不要使用BSTR類型,而是使用對應的_bstr_t類型。為了處理BSTR,Microsoft提供了以下API供使用: BSTR SysAllocString ( const OLECHAR * psz ); INT SysReAllocString ( BSTR * pbstr , const OLECHAR * psz ); BSTR SysAllocStringLen ( const OLECHAR * strIn , UINTui ); INT SysReAllocStringLen ( BSTR * pbstr , constOLECHAR * psz , unsignedintlen ); void SysFreeString ( BSTR bstrString ); UINT SysStringLen ( BSTR ); UINT SysStringByteLen ( BSTR bstr ); BSTR SysAllocStringByteLen ( LPCSTRpsz , UINTlen ); 現(xiàn)在對以上的 API 逐一的進行講解和應用,大家可以結合著 MSDN ,看這篇博文,至少 MSDN 講的比我這里更詳細。 SysAllocString 分配內存,并創(chuàng)建 BSTR 字符串; SysReAllocString 重新分配內存,并將第二個參數(shù)指定的 OLECHAR 同時放入新開辟的的內存中; SysAllocStringLen 分配內存,將第一個參數(shù)指定的字符串的前 ui (第二個參數(shù)指定的字符個數(shù))個數(shù)放入開辟的內存中; SysReAllocStringLen ,經(jīng)過上面兩個 API 的講解,這個 API 的就不需要更多的講解了; SysFreeString 釋放由以上的 API 函數(shù)開辟的內存; SysStringLen 表示的是 BSTR 的字符個數(shù); SysStringByteLen 獲得 BSTR 字符串表示的字節(jié)數(shù),也就是 BSTR 的前 4 個字節(jié)表示的內容; SysAllocStringByteLen 使用的是 ANSI string 進行創(chuàng)建 BSTR 對象,盡量少用該 API 。 VARIANT VARIANT結構體主要是使用在COM(組件對象模型)中用于傳遞參數(shù)使用, 它的存在主要是為了保持一個在COM參數(shù)傳遞方法的統(tǒng)一性,它幾乎包含了所有普通常用類型的數(shù)據(jù)類型的傳遞, 如整型,浮點型,布爾型等等,以及相應類型的指針類型,如整型指針。 它的使用也比較方便。先來看看這個結構體它的結構: typedef struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONGLONG llVal; LONG lVal; BYTE bVal; SHORT iVal; FLOAT fltVal; DOUBLE dblVal; VARIANT_BOOL boolVal; _VARIANT_BOOL bool; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown *punkVal; IDispatch *pdispVal; SAFEARRAY *parray; BYTE *pbVal; SHORT *piVal; LONG *plVal; LONGLONG *pllVal; FLOAT *pfltVal; DOUBLE *pdblVal; VARIANT_BOOL *pboolVal; _VARIANT_BOOL *pbool; SCODE *pscode; CY *pcyVal; DATE *pdate; BSTR *pbstrVal; IUnknown **ppunkVal; IDispatch **ppdispVal; SAFEARRAY **pparray; VARIANT *pvarVal; PVOID byref; CHAR cVal; USHORT uiVal; ULONG ulVal; ULONGLONG ullVal; INT intVal; UINT uintVal; DECIMAL *pdecVal; CHAR *pcVal; USHORT *puiVal; ULONG *pulVal; ULONGLONG *pullVal; INT *pintVal; UINT *puintVal; struct __tagBRECORD { PVOID pvRecord; IRecordInfo *pRecInfo; } __VARIANT_NAME_4; } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; } VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG; 這個結構體呢,有5個成員,分別是 VARTYPE vt ,WORD wReserved1,WORD wReserved2,WORD wReserved3,和最后一個共用體。 其中vt用以指明最后一個共用體中哪一個成員有效,wReserved1,wReserved2,wReserved3,這三個我們使用的時候不用管,系統(tǒng)保留, 最后一個共用體根據(jù)vt的提示,對相應的成員進行值的存儲。我們從兩個不同的角度來理解,首先是使用VARIANT來存儲參數(shù), 首先是聲明一個這個結構體的對象,然后對對象的vt進行賦值,它可接受的值是一個枚舉值,也就說只能在枚舉這個范圍內取值, 比如我要用VARIANT傳遞一個整數(shù),現(xiàn)在我對vt的賦值為VT_INT,這樣就說明了我要使用這個結構體中共用體的整型變量, 接著對INT變量進行賦值,賦我們要傳遞的值。這樣就完成VARIANT的傳遞,F(xiàn)在我們從另外一個角度來理解VARIANT, 剛才是我們對VARIANT對象進行賦值傳遞,現(xiàn)在我們是這個VARIANT對象的接收者,我們從參數(shù)中獲得這個對象之后, 我們首先檢查這個結構體的vt成員,看它哪個類型的變量有效,比如就這個例子而言,檢查到vt的值是VT_INT, 因此,我直接去獲取這個結構體中VT_INT所對應的變量,獲取它的值。這樣,我們從傳遞到使用兩個角度來理解了VARIANT結構體, 概括起來說,就是vt指明了我要傳遞的變量的類型,結構體中共用體的成員用來存儲vt指明的類型的值。 下面來看看具體VARIANT結構體是如何使用賦值的,首先是第一種方法: 首先我們聲明一個VARIANT結構體的對象vr1,然后使用VariantInit函數(shù)對其進行初始化,它的作用就是對vt賦VT_EMPTY, 對別的變量值附空,否則就是一個隨機值,這個過程和我們聲明一個int變量一樣,如果聲明的時候不初始化,就是一個隨機值。 編程過程中,不管是指針還是什么變量,都應該在聲明之后對其進行初始化。接著就是我賦VT_INT給vt, 這里的V_VT就是代表要對vr1結構體中的vt成員進行幅值,接著對vr1中的INT成員賦值,這里的V_INT就是表示要對INT賦值, 因此這里有一個規(guī)律,就是V_,它的后面加成員類型就可以對相應的成員賦值,而這里的成員類型有一個對照表,在文章的最后給出, 比如,我要對BSTR成員賦值,我就用V_BSTR。這時候,就可以使用vr1了,使用完成之后,我們應該調用VariantClear函數(shù), 這個函數(shù)的作用就是將vt賦值為VT_EMPTY,以及釋放使用這個結構體中的內存中的內容,如果是com對象,該函數(shù)是不會進行對象的release操作的, 不管怎么樣,我們都應該在使用完了VARIANT結構體之后,調用這個函數(shù)。 下面是第二種方法,原理和過程和地中方法類似,有一點微小的區(qū)別, 就是VARIANT結構體的賦值上面來說,有點不同,如下: 接下來是字符串的操作,BSTR,我們不能直接將字符串傳遞一個VARIANT結構體對象,而是要用到函數(shù)SysAllocString, 它的返回值就是一個BSTR,由它分配一個字符串,供VARIANT,對于為什么要這么做,可以自己查看MSDN COM的Automation那部分: 完成之后,我們還應該調用SysFreeString來釋放由SysAllocString分配的內存。 另外,我們可以在類型與變量的對照表中發(fā)現(xiàn),同一類型,對應了兩種不同的變量,如,INT對應了變量有intVal和pintVal,其實這很簡單,后者是指針性,如果要使用,說明我們賦值的對象是一個指針,如下: 最后給出類型與變量的對照表,如果是使用地中方法用V_加類型,就直接使用下表中VT_后的名稱就可以了: Member name Description VT_EMPTY Indicates that a value was not specified. VT_NULL Indicates a null value, similar to a null value in SQL. VT_I2 Indicates ashortinteger. VT_I4 Indicates alonginteger. VT_R4 Indicates afloatvalue. VT_R8 Indicates adoublevalue. VT_CY Indicates a currency value. VT_DATE Indicates a DATE value. VT_BSTR Indicates a BSTR string. VT_DISPATCH Indicates anIDispatchpointer. VT_ERROR Indicates an SCODE. VT_BOOL Indicates a Boolean value. VT_VARIANT Indicates a VARIANTfarpointer. VT_UNKNOWN Indicates anIUnknownpointer. VT_DECIMAL Indicates adecimalvalue. VT_I1 Indicates acharvalue. VT_UI1 Indicates abyte. VT_UI2 Indicates anunsignedshort. VT_UI4 Indicates anunsignedlong. VT_I8 Indicates a 64-bit integer. VT_UI8 Indicates an 64-bit unsigned integer. VT_INT Indicates an integer value. VT_UINT Indicates anunsignedinteger value. VT_VOID Indicates a C stylevoid. VT_HRESULT Indicates an HRESULT. VT_PTR Indicates a pointer type. VT_SAFEARRAY Indicates a SAFEARRAY. Not valid in a VARIANT. VT_CARRAY Indicates a C style array. VT_USERDEFINED Indicates a user defined type. VT_LPSTR Indicates a null-terminated string. VT_LPWSTR Indicates a wide string terminated bynullNothingnullptra null reference (Nothing in Visual Basic). VT_RECORD Indicates a user defined type. VT_FILETIME Indicates a FILETIME value. VT_BLOB Indicates length prefixed bytes. VT_STREAM Indicates that the name of a stream follows. VT_STORAGE Indicates that the name of a storage follows. VT_STREAMED_OBJECT Indicates that a stream contains an object. VT_STORED_OBJECT Indicates that a storage contains an object. VT_BLOB_OBJECT Indicates that a blob contains an object. VT_CF Indicates the clipboard format. VT_CLSID Indicates a class ID. VT_VECTOR Indicates a simple, counted array. VT_ARRAY Indicates aSAFEARRAYpointer. VT_BYREF Indicates that a value is a reference. VARIANT使用起來是很簡單的,但是有些問題,我們還必須要去注意: 建立VARIANT變量時,必須使用VariantInit進行初始化 ; 對于VT_UI1, VT_I2, VT_I4, VT_R4, VT_R8, VT_BOOL, VT_ERROR, VT_CY, VT_DECIMAL, 和VT_DATE這些類型, 數(shù)據(jù)的值是直接儲存在VARIANT結構中的,當VARIANT的類型發(fā)生變化時,指向這些數(shù)據(jù)的指針會變得無效。 例如: VARIANT varParam ; :: VariantInit ( varParam ); short iVal = 20 ; varParam . vt = VT_I2 ; varParam . iVal = iVal ; short * pVal = varParam . iVal ; varParam . vt = VT_I4 ; varParam . lVal = 200 ; 此時,*pVal指向的值與你期望的可能是不一樣的。 對于VT_BYREF | any type數(shù)據(jù)類型,而VARIANT只是擁有這些數(shù)據(jù)指向內存的指針,而內存的釋放需要由函數(shù)的調用者負責。 例如: VARIANT varParam ; :: VariantInit ( varParam ); int * p = new int ; * p = 10 ; varParam . vt = VT_BYREF | VT_I4 ; varParam . plVal = ( long *) p ; delete p ; // If you donnot delete the memory, this may cause memory leak 對于VT_BSTR類型,在VARIANT中的字符串必須要用SysAllocString進行分配內存,當釋放時,或者VARIANT的類型發(fā)生改變時, 都需要調用SysFreeString進行內存釋放,否則就會發(fā)生內存泄露; 對于VT_ARRAY | any type類型,這個規(guī)則和VT_BSTR是類似的,在VARIANT中的數(shù)組必須使用SafeArrayCreate進行開辟內存空間, 然后必須使用SafeArrayDestroy進行內存空間的釋放; 對于VT_DISPATCH和VT_UNKNOWN,我們考慮的更多的就是引用計數(shù)器的增加與減少了, 是的,在進行賦值時需要進行引用計數(shù)的增加,釋放時,則需要對應的減少。 SAFEARRAY的使用 SAFEARRAY的主要目的是用于automation中的數(shù)組型參數(shù)的傳遞,我們都知道,在網(wǎng)絡環(huán)境中,數(shù)組是不能直接傳遞的, 所以我們必須將數(shù)組封裝成SAFEARRAY類型,這樣才能進行傳遞,在COM編程時,SAFEARRAY類型是可以存放在VARIANT類型中, 指定vt為VT_ARRAY|*或者VT_BYREF|VT_ARRAY。對于SAFEARRAY,說白了,就是普通的數(shù)組,添加了一些額外的說明, 當我第一次遇到這個類型時,也是有點恐懼的,后來,用慣了,也就無所謂了。SAFEARRAY單獨用的時候很少,就像我前面說的, 一般都是搭配著VARIANT一起使用,指定vt類型以后,parray成員就是指向SAFEARRAY的指針。SAFEARRAY中元素的類型可以 是VARIANT能封裝的任何類型,包括VARIANT類型本身。 訪問SAFEARRAY 訪問SAFEARRAY的方法大體上有兩種: 使用SafeArrayAccessData方法; 使用SafeArrayGetElement和SafeArrayPutElement方法。 關于這兩種方法,在上面的例子中都有涉及。 HRESULT 函數(shù)返回值 每個人在做程序設計的時候,都有他們各自的哲學思想。拿函數(shù)返回值來說,就有好多種形式。 函數(shù) 返回值 返回值信息 double sin(double) 浮點數(shù)值 計算正玄值 BOOL DeleteFile(LPCTSTR) 布爾值 文件刪除是否成功。如失敗,需要GetLastError()才能取得失敗原因 void * malloc(size_t) 內存指針 內存申請,如果失敗,返回空指針 NULL LONG RegDeleteKey(HKEY,LPCTSTR) 整數(shù) 刪除注冊表項。0表示成功,非0失敗,同時這個值就反映了失敗的原因 UINT DragQueryFile(HDROP,UINT,LPTSTR,UINT) 整數(shù) 取得拖放文件信息。以不同的參數(shù)調用,則返回不同的含義: 一會兒表示文件個數(shù),一會兒表示文件名長度,一會兒表示字符長度 ...... ...... ... ...... ...... 如此紛繁復雜的返回值,如此含義多變的返回值,使得大家在學習和使用的過程中,增加了額外的困難。好了,COM 的設計規(guī)范終于對他們進行了統(tǒng)一。組件API及接口指針中,除了IUnknown::AddRef()和IUnknown::Release()兩個函數(shù)外,其它所有的函數(shù),都以 HRESULT 作為返回值。大家想象一個組件的接口函數(shù)比如叫Add(),完成2個整數(shù)的加法運算,在 C語言 中,我們可以如下定義: view plain copy print ? long Add( long n1, long n2) { return n1+n2; } 還記得剛才我們說的原則嗎? COM 組件是運行在分布式環(huán)境中的 。也就是說,這個函數(shù)可能運行在“地球另一邊”的計算機上,既然運行在那么遙遠的地方,就有可能出現(xiàn)服務器關機、網(wǎng)絡掉線、運行超時、對方不在服務區(qū)......等異常。于是,這個加法函數(shù),除了需要返回運算結果以外,還應該返回一個值------函數(shù)是否被正常執(zhí)行了。 view plain copy print ? HRESULT Add( long n1, long n2, long *pSum) { 3*pSum=n1+n2; return S_OK; } 如果函數(shù)正常執(zhí)行,則返回 S_OK,同時真正的函數(shù)運行結果則通過參數(shù)指針返回。如果遇到了異常情況,則COM系統(tǒng)經(jīng)過判斷,會返回相應的錯誤值。常見的返回值有: HRESULT 值 含義 S_OK 0x00000000 成功 S_FALSE 0x00000001 函數(shù)成功執(zhí)行完成,但返回時出現(xiàn)錯誤 E_INVALIDARG 0x80070057 參數(shù)有錯誤 E_OUTOFMEMORY 0x8007000E 內存申請錯誤 E_UNEXPECTED 0x8000FFFF 未知的異常 E_NOTIMPL 0x80004001 未實現(xiàn)功能 E_FAIL 0x80004005 沒有詳細說明的錯誤。一般需要取得 Rich Error 錯誤信息(注1) E_POINTER 0x80004003 無效的指針 E_HANDLE 0x80070006 無效的句柄 E_ABORT 0x80004004 終止操作 E_ACCESSDENIED 0x80070005 訪問被拒絕 E_NOINTERFACE 0x80004002 不支持接口 圖一、HRESULT 的結構 HRESULT 其實是一個雙字節(jié)的值,其最高位(bit)如果是0表示成功,1表示錯誤。具體參見 MSDN 之"Structure of COM Error Codes"說明。我們在程序中如果需要判斷返回值,則可以使用比較運算符號;switch開關語句;也可以使用VC提供的宏: view plain copy print ? HRESULT hr=調用組件函數(shù); if (SUCCEEDED(hr)){...} //如果成功 ...... if (FAILED(hr)){...} //如果失敗 ......
個人分類: FreeBasic|4226 次閱讀|0 個評論

QQ|站長郵箱|小黑屋|手機版|Office中國/Access中國 ( 粵ICP備10043721號-1 )  

GMT+8, 2025-7-13 07:51 , Processed in 0.064722 second(s), 14 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回頂部