Tải bản đầy đủ - 0 (trang)
Chapter 23. Integrating DLLs and COM

Chapter 23. Integrating DLLs and COM

Tải bản đầy đủ - 0trang

23.1.UseDLLs

Dynamiclinklibraries(DLLs)areusedeverywhereinWindows.

ManyoftheVisualBasicandExcelmembersmerely

encapsulateWindowsDLLcallsforexample,theShellfunctionis

equivalenttotheWindowsWinExecfunctioninkernel32.dllthatis

atthecoreofWindows.

There'slittlepointinusingWinExecinsteadofShell;however,

manyotherDLLfunctionsaren'tavailablefromVisualBasicor

Excel.Ingeneral,thosefunctionsgiveyouaccesstolow-level

tasksthataren'ttheusualfocusofVisualBasicorExcel.

TouseafunctionfromaDLL:

1. Findthefunctionyouwanttouse.

2. Declarethefunctionatthemodulelevel.

3. Callthefunctionwithinyourcode.



23.1.1.FindtheRightFunction

Windowsisenormous,andfindingthefunctionforaspecific

taskwithinitsforestofDLLscanbedaunting.Thebestguide

throughtheWin32APIisProgrammingWindowsbyCharles

Petzold(MicrosoftPress).Thesecond-best(andfree)guideis

theonlineMicrosoftDeveloper'sNetworkfoundat

http://msdn.microsoft.com.

YoushouldlooktoDLLsonlywhenyouhaveaspecifictaskin

mindandyou'vealreadyexhaustedpossiblesolutionsthrough

thebuilt-inmembersprovidedbyVisualBasicandExcel.Often,

programmersresorttoDLLfunctionswhenthebuilt-infeatures

ofExcelaren'tspecificenough.Forexample,theWaitmethodin



Excelhasaone-secondresolution.Ifyouwanttopausefora

fractionofasecond,youneedtoresorttotheSleepDLL

function.

OneofthebesttoolsforfindingWin32APIfunctionsistheAPI

Viewerutility(APILOAD.EXE)thatshippedwiththeVisualBasic

StandardandProfessionalEditions,Versions4.0through6.0.

TousetheAPIViewer:

1. RunAPILOAD.EXE.

2. ChooseFile



LoadTextFileandselectWIN32API.TXT.



3. ChooseDeclaresfromthedrop-downlistandbrowse

throughthelistoffunctionsortypeafewletterstofind

functionsbynameasshowninFigure23-1.



Whatifyoudon'thaveVisualBasicProfessionalorStandardEdition?

TheWIN32API.TXTfileisfreelydistributableandyoucanfinditwith

thisbook'ssamples.YoucanbrowsethatfileusingNotepadorany

othertexteditor.



23.1.2.DeclareandUseDLLFunctions

UsetheAPIViewer(Figure23-1)oropenWIN32API.TXTin

NotepadtogetthedeclarationsofDLLfunctionsyouwantto

useinVisualBasic.ThedeclarationtellsVisualBasichowtofind

thefunctionandwhatargumentsthefunctionexpects.For

example,thedeclarationfortheSleepfunctionlookslikethis:

'Modulelevel.

PublicDeclareSubSleepLib"kernel32"_

(ByValdwMillisecondsAsLong)



Figure23-1.UsetheAPIViewertohuntforDLL

functions



ThatmeanstheSleepfunctionisfoundinkernel32.dll,takesa

singlelong-integerargument,anddoesn'treturnavalue.Once

youdeclarethefunction,youcanuseitincodejustlikeany

otherprocedure:

SubPause()

'Pause1/2second.

Sleep500

EndSub



InVisualBasicterminology,SleepisaSub,notafunction.

However,mostDLLsarewritteninC,whichdoesn'tusethat

word.InC,allproceduresarefunctions;functionsthatdon't

returnvaluesarecalledvoidfunctions.

However,mostDLLfunctionsdoreturnavalue,andthatvalue

usuallyindicateswhetherthefunctionsucceeded.Ifafunction

returns0,thefunctionfailed.Anyothervalueindicatessuccess.

Forexample,thefollowingcodeplaysboing.wav;ifthesound

can'tplay,thecodedisplaysamessageintheImmediate

window:



PublicDeclareFunctionsndPlaySoundLib"winmm.dll"Alias_

"sndPlaySoundA"(ByVallpszSoundNameAsString,ByValuFlags

AsLong



SubBounce()

DimresAsLong

res=sndPlaySound("boing",0)

Ifres=0Then_

Debug.Print"Couldn'tbounce."

EndSub



23.1.3.UseFlagsandConstants

TheuFlagsargumentinsndPlaySoundisanexampleofanother

commonCconvention:youcanoftenspecifyoptionsusinga

longintegercomprisedofbitflags.Idiscussedthosebackin

Chapter3,buttheyhaven'tbeenmuchuseuptillnow.Bitflags

arenumericconstantsthatcanbecombinedintoasingle

number.Thefollowingcodedemonstratesusingbitflagstoplay



asoundoverandoveragain:



PublicDeclareFunctionsndPlaySoundLib"winmm.dll"Alias_

"sndPlaySoundA"(ByVallpszSoundNameAsString,ByValuFlags

AsLong

PublicConstSND_ASYNC=&H1'playasynchronously

PublicConstSND_LOOP=&H8'loopthesounduntilnex

PublicConstSND_SYNC=&H0'playsynchronously(defa



SubBeginBouncing()

sndPlaySound"boing",SND_ASYNCOrSND_LOOP

EndSub



SubStopBouncing()

sndPlaySound"boing",SND_SYNC

EndSub



IincludedStopBouncingbecauselisteningtoboing.wavoverand

overagaingetsreallyannoying.Youcanfindconstantsforeach

functionbysearchingforthefunctionbynameat

http://msdn.microsoft.com,thenyoucanfindthe

correspondingvaluesforthoseconstantsusingtheAPIViewer

orbysearchingWIN32API.TXT.



23.1.4.WorkwithStrings

ThequickestwaytoendyourDLLprogrammingexperienceisto

passaDLLanuninitializedstring.Forexample,thefollowing

codewillresultintheerrorshowninFigure23-2:

PublicDeclareFunctionGetTempFileNameLib"kernel32"Alias_

"GetTempFileNameA"(ByVallpszPathAsString,_

ByVallpPrefixStringAsString,ByValwUniqueAsLong,_

ByVallpTempFileNameAsString)AsLong





SubCrash()

DimfilAsString,resAsLong

res=GetTempFileName(ThisWorkbook.Path,"xl",0,fil)

Debug.Printfil

EndSub



Figure23-2.You'llcrashifyoudon'tinitialize

yourstrings



Don'tsendMicrosoftthiserrorreportitwasyourfault!Toavoid

thisproblem,fillastringwithspacesbeforeyoupassittoa

DLL.Youneedtomakethestringlongenoughtofitthepassedindata;128charactersisusuallysufficient:

FunctionCreateTempFile()AsString

DimfilAsString,resAsLong

'Initializethestring!



fil=Space(128)

'PassthestringtotheDLLfunction.

res=GetTempFileName(ThisWorkbook.Path,"xl",0,fil)

'Returnthestring.

CreateTempFile=fil

EndFunction



Figure23-2underscorestherisksofworkingwithDLLsyouareleaving

therelativelysafeworldprovidedbyExcelandareperformingwithout

asafetynet.MistakescancrashExcelandpotentiallyshutdown

Windows.SaveyourworkfrequentlywhenworkingwithDLLs.



Cstringsendwithanullcharacter(ASCII0).That'sdifferent

thanVisualBasic,whichprependseachstringwithitslength.In

somecases,liketheprecedingexample,thenullcharacteris

ignored.However,inothercases,youneedtotrimoffthe

excesscharacterswhentheDLLfunctionreturns.Inthose

cases,theDLLfunctionreturnsthelengthofthestring

argument;theGetWindowsDirectoryfunctionisagoodexample:

PublicDeclareFunctionGetWindowsDirectoryLib"kernel32"_

Alias"GetWindowsDirectoryA"(ByVallpBufferAsString,_

ByValnSizeAsLong)AsLong



FunctionGetWinDir()AsString

DimwdirAsString,resAsInteger

'Initializethestring.

wdir=Space(128)

'CalltheDLLfunction(returnslengthofresult).

res=GetWindowsDirectory(wdir,128)

'Trimoffexcessbeforereturningtheresult.

WinDir=Left(wdir,res)



EndFunction



Youcanactuallyseethenullcharacterinthestringifyouseta

breakpointatEndFunction,runtheprecedingcode,andthen

positionthemousepointeroverthewdirvariableasshownin

Figure23-3.



Figure23-3.Insomestrings,youneedtotrimoff

nulls



TheCreateTempFileandGetWinDirexamplesdemonstratehowto

createwrappersforDLLfunctions.WrappersconverttheDLL

functionsintoVisualBasicfunctionsthataremuchless

confusingtouseelsewhereincode.Itisgoodprogramming

practicetoputallofyourDLLdeclarationsinasinglemodule

andincludewrappersforeachofthosefunctions.



23.1.5.HandleExceptions

MostDLLfunctionsreturnavalueindicatingwhetherthey

succeeded.Areturnvalueof0indicatesthatthefunctiondid

notcompleteitstask.Thattypeofexceptionisdifferentfrom

theerrorinFigure23-2,whichhaltseverything.

JustaswithVisualBasicfunctions,youshouldanticipateand

handleexceptionsfromDLLfunctionsinyourcode,particularly

whenworkingwithnonmemoryresourceslikeharddisks,

printers,andotherdevices.TohandleanexceptionfromaDLL:

1. CalltheDLLfunction.

2. Checkthevaluereturnedbythefunction.

3. Ifthereturnedvalueiszero,handletheexceptionand

optionallycheckErr.LastDllErrortoidentifywhatwentwrong.

ThefollowingchangestoCreateTempFiledemonstratedetecting

andhandlingexceptionsfromaDLLfunction.Ifthecallertries

tocreateatemporaryfileataninvalidpath,GetTempFileName

returns0andthecodedisplaysamessageintheImmediate

window.Optionally,youcoulduncommenttheErrorstatement

toraiseatrappableVisualexception:



FunctionCreateTempFile(OptionalpathAsString="")AsString

DimfilAsString,resAsLong

'Initializethestring!

fil=Space(128)

Ifpath=""Thenpath=ThisWorkbook.path

'PassthestringtotheDLLfunction.

res=GetTempFileName(path,"xl",0,fil)

'Iferror,returnemptystring.

Ifres=0Then

Debug.Print"Errorcreatingtempfile:"&Err.LastDllE

'Optionally,raisecan'tCreatetemporaryfileerror.



'Error322

EndIf

'Trimtheexcessoffthestringandreturnit.

CreateTempFile=Left(fil,res)

EndFunction



TheErrobject'sLastDllErrorpropertyreturnstheerrornumber

fromtheDLLfunction.ThosenumbersarelistedasERROR_xxx

constantsinWIN32API.TXT,butitisalmostimpossibletoknow

whicherrorcodestoexpectfromaDLL.Theeasiestwayto

solvethisproblemistopassinvaluesyouknowtobeinvalid

andseewhaterrorcodeisreturned.Youcanthensearch

WIN32API.TXTtogetthedescriptiveconstant.

Forexample,typingthefollowinglineofcodeintheImmediate

windowdisplayserrorcode276:

?CreateTempFile("z:\")



AquicksearchofWIN32API.TXTfor267yieldsthisconstant:

'Thedirectorynameisinvalid.

ConstERROR_DIRECTORY=267&



Icouldusethisconstanttocreateamoredescriptivemessage,

butinrealitythere'snotmuchIcandootherthanreportthe

errorandendtheoperationasgracefullyaspossible.

Oneofthesideeffectsofreturning0whenanerroroccursis

thatLeft(fil,res)returnsanemptystringwheneverthere'san

error.That'sagoodtechniquebecauseitmakesiteasytocheck

ifthefunctionsucceededelsewhereincode,asshownhere:



SubTestCreateFile()

DimtmpAsString

'Getatemporaryfile.

tmp=CreateTempFile

Iftmp<>""Then

'Openthefileandwritesomedata

QuickWrite"Thisissomedata",tmp,True

'DisplaythefileinNotepad.

Shell"notepad.exe"&tmp

Else

Debug.Print"CreateTempFilefailed."

EndIf

EndSub



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 23. Integrating DLLs and COM

Tải bản đầy đủ ngay(0 tr)

×