vbpjtip5 面向VisualBasic程序员的杂志 第5版.docx
WelcometotheFifthEditionoftheVBPJTechnicaltipsSupplement!ThesetipsandtricksweresubmittedbyprofessionaldevelopersusingVisualBasic3.0,VisualBasic4.0,VisualBasic5.0,VisualBasicforApplications,andVisualBasicScript.ThetipswerecompiledbytheeditorsatVisualBasicProgrammer,sJournal.SpecialthankstoVBPJTechnicalReviewBoardmembersFrancescoBalenaandPhilWeberfortestingallthecode.Ifyou'dliketosubmitatiptoVisualBasicProgrammer,sJournal,pleasesendittoUsertips,FawcetteTechnicalPublications,209HamiltonAvenue,PaloAlto,California,USA,94301-2500.Youcanalsofaxitto415-853-0230orsenditelectronicallytoVbpjeditQor74774.3050CompuS.Pleaseincludeaclearexplanationofwhatthetechniquedoesandwhyitisuseful,indicateifit,sforVBA,VBS,VB3zVB416-or32-bitzorVB5.Pleasetrytolimitcodelengthto20lines.Don'tforgettoincludeyoure-mailandmailingaddress.We,11payyou$25ifwepublishyourtipVB3,VB416/321.evel:BeginningCOMBOBOXEVENTHAND1.INGTwoproblemscanarisewhenaconfuseduserscrollsupordownwiththemouseandthenmakesaselectionwiththeEnterKey.First,thedownarrowfirestwoevents:ChangeandClick.Second,theEnterkeymovesfocustothenexttabstop,whilethemouseclickdoesn,tcausealossoffocusfromthecombobox.Therefore,ifyouplaceyouractioncodeintheChangeevent,anUporDownarrowwillfireit,whichyoudon,twant.Onthecontrary,ifyouplaceyouractioncodeonlyinthe1.ostFocuseventandtheuserclicksonaselection,focuswon,tmovefromthecombobox,andtheuserisleftstaringattheselectedtextinthecomboboxandwonderingwhynoactionoccurred.ThissolutionfiltersoutClickeventsgeneratedwitharrowkeys,andforcesthecontroltolosefocus.IntheDeclarationssectionoftheform,enterthiscode:Note:UseanIntegerflagvariablein,VB3DimbNoiseasBoolean,TruedenotesaNoiseEventwhichisto,beignoredEnterthiscodeintheForm_1.oadevent:bNoise=FalseEnterthiscodeinthecomboboxKeyDownevent:PrivateSubcbTest_KeyDown(KeyCodeAs_Integer,ShiftAsInteger),Iftheuserisbrowsingwiththe,arrows,ignoretheClickEventsIfKeyCode=VbKeyDownOrKeyCode_=VbKeyUpThenbNoise=TrueEndSubevent:EnterthiscodeinthecomboboxClickPrivateSubcbTest_Click()IfbNoiseThen,IgnoreNoiseevents,(upordownarrow)bNoise=FalseElse'ForcelossoffocusSendKeys”TAB”,TrueEndIfEndSubWritecodethatreactstoanewuserselectioninthecombobox1.ostFocusevent.Don,tsendaTabkeystrokebecausefocushasalreadyshifted,andthecombobox,sbehaviorisconsistentregardlessofhowtheuserselectsanewvalue.-1.esSmith,Concord,NorthCarolinaVB51.evel:BeginningCOMMENTANDUNCOMMENTB1.OCKSOFCODEVisualBasic5.0letsyoucommentablockofcodeinasnapanduncommentitlater.Thisfeatureisusefulinthedebugphase,whenyoudon,twanttoexecuteanumberofstatements,butyoudon,twanttophysicallydeletethemeither.However,theComment/Uncommentcommandpairisn,tpresentinanymenuoftheenvironment,andyoucanonlyreachitbyenablingtheEdittoolbar.Todothisquickly,right-clickonanytoolbarintheenvironmentandselecttheEditcommand.-FrancescoBalena,Bari,ItalyVB51.evel:BeginningDEFAU1.TVA1.UESFOROPTIONA1.PARAMETERSIfyoueverprogrammedunderVB4,youprobablytookadvantageofthepowerfulOptionalparameters.VB5enhancedtheminseveralways:theycanbeofanytypenow(notonlyVariants),andtheycanappearinPropertyprocedures.Interestingly,youcannowstateadefaultvalueforthem:PropertyGetValue_(OptionalindexAs1.ong=1)EndPropertyYoucandothiswithoutanexplicit(andslower)IsMissingtest:PropertyGetValue_(OptionalindexAs1.ong)IfIsMissing(index)Thenindex=1EndProperty-FrancescoBalena,Bari,ItalyDON*TCREATEA1.IASEDVARIAB1.ESNeverpassaglobalvariableasanargumenttoaprocedurethatalsoaccessesthevariabledirectly.Ifyou,re100percentsureyouadheredtothisrulewithinyourapplication,checktheAssumeNoAliasingoptionintheAdvancedOptimizationsdialogthatyouinvokefromtheCompiletaboftheProjectPropertiesdialog.Ifthenativecodecompilerknowsnoaliasedvariablesexist,itcanfreelycachevariablevaluesintofasterCPUregisters,andstorethembacktoRAMmemoryonlywhenleavingtheprocedure.Thisimprovestheexecutionspeedofcompiledprograms.-FrancescoBalena,Bari,ItalyVB51.evel:BeginningCENTERFORMSONSCREENApopularcodesnippetletsyoucenteranyformonthescreen,regardlessofthecurrentscreenresolution.YounowcanreachthesameresultbysimplyassigningthevalueVbStartUpScreen(=2)totheform'sStartUpPositionnewproperty.YoucanevencenteraformwithinitsparentwindowbyassigningtheVbStartUpOwner(=1)value.YoucansetthispropertyfromthePropertywindow.Whenaformissupposedtobecenteredwithinitsparentwindow,remembertoaddasecondargumenttotheShowmethod:Form2.ShowVbModalzMe-FrancescoBalena,Bari,Italy0N¾-E16aDON,TAUTO-OPTIMIZEFORFASTCODEIfyoutakealookatVB,snativecodeoptimizationoptionsforthefirsttime,youmightbetemptedtoclick,on"OptimizeforFastCode"rightaway.Strangeasitmaysound,though,thisdoesnotalwaysguaranteethebestperformance.Applicationsoptimizedforperformancegenerallydon,trunthatmuchfaster,butdohavealargermemoryfootprint.Thiscausesthemtoloadslower,especiallyonmemory-constrainedmachines,givingtheusertheimpressionthatyourappisactuallyslowerthanoneoptimizedforcompactcode.Forthesamereason,considerleavingyourapplicationscompiledasp-codeanyway.Especiallyforlarge,UI-anddatabase-intensiveapplications,theperformancegainofcompilingtonativecodewon,toutweightheincreaseinapplicationsize.Todetermineexactlywhichcompilationoptionisrightforyou,usetheVBApplicationPerformanceExplorer(APE)includedonyourVBCD.-MichieldeBruijn,Rotterdam,TheNetherlandsVBA51.evel:BeginningNOTA1.1.TEMP1.ATESARECREATEDEQUA1.UnliketemplatesinotherOffice97products,Word97templatesprovideabusiness-applicationenginethatremainsseparatefromthedocumentsthatusethatengine.TemplatebasedExcelworkbooksandPowerPointpresentationsincludeacopyofthatengine.Inpractice,allWorddocumentstwoVBAprojects:thefirstprojectisfromtheunderlyingtemplate),templateandthedocumentitself.On(allWorddocumentsarebasedonasecondprojectbelongstotheWordtheotherhand,ExcelworkbooksandPowerPointpresentationsbasedonatemplatehaveonlyoneVBAproject.Everyfilecontainsitsowncopyoftheprojectintheoriginaltemplate.Changesmadetothiscopydon,taffecttheunderlyingtemplate.InExcel,PowerPoint,andAccess,add-insprovidecodeenginesthatremainseparatefromtheworkbooksandpresentationsthatusethoseengines.TocreateanExcelorPowerPointadd-in,usetheSaveAscommandontheFilemenuandsavethefileasaspecifictype:thenAdd-in11type.Eachproductusesaspecific"Add-in"extension(X1.AforExcel,PPAforPowerPoint,andMDAforAccess).There,snocanonicallocationforstoringadd-ins,buttoloadadd-insautomaticallywhenyoulaunchanOfficeproduct,storethemintheX1.StartfolderorintheStartUpfolder.Youcanloadadd-insmanuallywiththeAdd-inscommandontheToolsmenu,oryoucanautomatetheprocessincode.TocreateanAccessadd-in,usethecommand"MakeMDEfile"availablethroughtheDatabaseUtilitiescommandontheToolsmenu.-ChristineSolomon,NewYork,NewYorkVB51.evel:BeginningCUSTOMIZEVBTOO1.BARSHereareafewsimplewaysyoucancustomizeyourVB5IDE:?AddtabstothecustomcontroltoolboxbyrightclickingontheGeneralbuttonandselectingtheAddTabcommand.Youcanalsomovetabsaroundanddeletethem,aswellasmovecontroliconsfromonetabtotheotherusingthedrag-and-dropmethod.?CreatetoolbarbuttonsforanymenucommandbyrightclickingonanytoolbarandselectingtheCustomizecommand.MovetotheCommandstab,selectthemenucommandintheright-mostlistbox,anddragitontothetoolbarwhereyouwanttomoveit.GoodcandidatesforthisprocedurearetheProject-References,Project-Properties,andTools-AddProcedurecommands.?CreateabrandnewtoolbarintheToolbarstaboftheCustomizedialogbox.Afteryoudefineatoolbar,addbuttonsusingtheprocedureoutlinedabove.WhentheCustomizedialogboxisactive,right-clickonanytoolbarbuttontochangeitsimage,createagroupdivider,show/hidetext,andmore.-FrancescoBalena,Bari,ItalyHIDEA1.1.PROJECTWINDOWSWhenworkingwithmultipleprojects,it'seasytogetconfusedbythemanywindowsactiveonthescreenatthesametime.However,youcantemporarilyhideallthewindowsrelatedtoagivenprojectbysimplycollapsingtheprojectitemintheProjectExplorerwindow.YoucandisablethisfeatureintheGeneraltaboftheTools-Optionsdialogbox.-FrancescoBalena,Bari,ItalyVB51.evel:IntermediateFRIEND1.YENUMERATEDVA1.UESIfyoubuildanActiveXcontrolthatexposesanenumeratedproperty,youshoulddefineaPublicEnumstructurethatgathersallthepossiblevaluesforthatproperty.DoingthishelpsthedeveloperthatusesyourcontrolbecausetheenumeratedvalueswillbelistedinacomboboxinthePropertywindow.However,atfirstglance,itseemsimpossibletoachievethesamebehaviorasmostofVB,sintrinsiccontrols,whichexposeenumeratedpropertieswithshortdescriptionsandembeddedspaces.Evenifthey*renotdocumentedinthelanguagemanuals,youcancreateenumerateditemsthatembedspacesbysimplyenclosingtheirnameswithinsquarebrackets:PublicEnumDrawModeConstantsBlackness=1NotMergePen)MaskNotPenNotCopyPenEndEnumThenaddaDrawModeConstantspropertycontrol.AlltheenumeratedvaluesappeartotheActiveXwindowoftheVBIDE,withoutthesquarebracketsallthespacesyouincluded.Usethistechniqueotherotherwiseforbiddencharacters,suchasinthePropertyandwithtoembedmathorpunctuationsymbols.-FrancescoBalena,Bari,ItalyVB416/32,VB51.evel:AdvancedIMP1.EMENTATIONOFPUB1.ICFORMANDC1.ASSVARIAB1.ESTheimplementationofPublicvariablesinformsandclasseschangedwithVisualBasic5.0.VB4implementspublicvariablesinformsandclassmodulesasifthey,reregularvariables,usingpointerstodatainmemory.InVB5zpublicvariablesaremorecorrectlyimplementedasapairofhiddenGet/1.etpropertyprocedures.ThisapproachslowsdownthesepropertieswhentheprogramisportedfromVB4toVB5.Moreimportantly,thischangelikelybreaksanycodethatreliesonpassingsuchvariablestoproceduresasByRefargumentsandexpectsthattheproceduremodifiesthem.Infact,underVB5zthey'repassedbyvalue,andtheoriginalpropertyisneveraffected.Formoreinformationonthisissue,seearticleQ166928intheMicrosoftKnowledgeBase.-FrancescoBalenazBari,ItalyVB416/32,VB5(EnterpriseEdition)1.evel:IntermediateSTANDA1.ONETYPE1.IBRARIESIfyoucreateout-of-processO1.Eservers,VisualBasicembedsthecompaniontypelibraryintotheEXEfileandgeneratesnoT1.Bfile.However,ifyouowntheEnterpriseEditionofVB4orVB5,youcanflagtheRemoteServerFilecheckboxtohaveVisualBasiccreateastandalonetypelibrary.InVB5zyoucanfindthisoptionintheComponenttaboftheProject-Propertiesdialogbox.-FrancescoBalena,Bari,ItalyVB51.evel:IntermediateUSEOBJECTBROWSERTODISCOVERUNDOCUMENTEDFEATURESIfyouright-clickontheright-mostpaneoftheObjectBrowser,youcanissuetheShowHiddenMemberscommand.Fromthispointon,theObjectBrowsershowsallhiddenpropertiesandmethodsinanylibrary,andyoucanuseittoexploreallobjectlibrariesinmoredetail.Forinstance,theVBAlibraryexposesahiddenclass,appropriatelynamed*'_HiddenModule,whichincludesmanywell-knownVBAfunctionsplusthreeundocumentedones:ObjPtrzStrPtrzandVarPtr.ObjPtrreturnstheaddressoftheprivateareaofanobjectinstance,StrPtrreturnstheaddressofthefirstcharacterinastring,andVarPtrreturnstheaddressofavariableorastringdescriptor,ifyoupassitastringvariable.-FrancescoBalena,BarizItalyVB416/321.evel:AdvancedTHEADDRESSOFAVARIAB1.EVB5includesabuilt-inVarPtrfunction(seetipuUsetheObjectBrowsertoDiscoverUndocumentedFeatures*),butthisfunctionisn,tavailableinVB4.TheVB4runtimelibrarydoesincludethisfunction,butyoumustdeclareitfirst:#IfWinlThenDeclareFunction"VB40016.D1.1."As1.ong#ElseDeclareFunction"VB40032.D1.1."As1.ong#EndIfVarPtr1.ib_(variableAsAny)VarPtr1.ib_(variableAsAny)ThisfunctionisusefulwhenpassinganexternalAPIroutineaTypestructure,addressofanothervariableandoneofitsfieldsistheorrecord.-FrancescoBalenazBari,ItalyVB416/32,VB51.evel:IntermediateCROSSMIDNIGHTBENCHMARKSTraditionally,VBprogrammersbenchmarktheircodeusingtheTimerfunction.However,ifyourprocessmightterminateonthefollowingday,youmusttakeintoaccountthatthevaluereturnedbythatfunctionisresetatmidnight.Ifyou,resatisfiedwithone-secondprecision,youcansimplifyyourcodeusingtheNowfunction:DimStartTimeAsDateStartTime=Now,thecodetobebenchmarkedIPrint"elapsedSeCondS="&Format5_(Now-StartTime)*86400z"#")YouneedtheFormat$functiontoroundtheresulttothenearestInteger.-FrancescoBalena,Bari,ItalyVB51.evel:IntermediateAPP.PATHMIGHTRETURNUNCPATHSPECIFICATIONSUnlikeVB4,VB5,sApp.PathpropertymightreturnaUNCpath,suchas,serverrograms.")zundercertaincircumstances,dependingonhowtheprogramstartedandifit'sinterpretedintheVBIDEorcompiledasastandaloneEXE.ThischangelikelyaffectsallapplicationsthatuseApp.Pathtosetthecurrentdirectorywhentheprogramstarts:ChDriveApp.PathChDirApp.PathInfact,becauseChDrivecannothandleUNCpaths,thecodemightraiseafatalruntimeerror,andshouldbeprotectedusinganOnErrorResumeNextstatement.Thisfixzhowever,doesn'tprotectyouundereverypossiblecondition.Thebestapproachistogivetheenduserthecapabilitytosettheapplicationdirectoryatruntime,thensavetheenteredvalueintheregistryorinanINIfile.Formoreinformationonthisproblemanditspossiblesolutions,seearticleQ167167intheMicrosoftKnowledgeBase.-FrancescoBalena,Bari,ItalyVB416/32,VB51.evel:AdvancedMOREVERSATI1.EARRAYPARAMETERSYoucanwriteasingleprocedurethatacceptsanytypeofarrayasanargumentbyusingavariantparameter.Withintheprocedure,addressthearrayusingtheusualsyntax:,returnthenumberofitemsFunctionItemCount(anArrayAsVariant)As1.ongItemCount=UBound(anArray)-_1.Bound(anArray)+1,thefirstelementis,anArray(1.Bound(anArray)EndFunctionYoucanevenpassamatrixwithanynumberofdimensions;inordertounderstandhowmanydimensions,youmustiterateontheUBoundor1.Boundfunctionsuntilanerroroccurs:FunctionItemCount(anArrayAsVariant)As1.ongDimitemsAs1.ong,iAsIntegerOnErrorResumeNextitems=UBound(anArray)-1.Bound(anArray)+1Fori=2to999items=items*(UBound(anArray,i)-1.BoundfanArray,i)+1)IfErrThenExitForNextItemCount=itemsEndFunction-FrancescoBalena,BarizItaly11¾-E1OAVB416/32,VB51.evel:IntermediateCOMPACTYOURCODEUSINGIIFANDSWITCHYoucanoftenreplaceanIf.Then.ElseblockwithamorecompactIIffunction:,returnsthemaxoftwovaluesmaxValue=IIf(first>=second,first,second)Switchisararelyusedfunction,yetinmanycasesitprovesratherusefulasasubstituteforalengthyIf.ElseIfblock:,is,x11negative,positiveornull?PrintSwitch(x<Oz"negative",x>O,"positive*1,True,"Null11)NotethelasttestisTrue,becausethethreeconditionsaremutuallyexclusiveandexhaustive.-FrancescoBalena,Bari,ItalyVB51.evel:AdvancedPROPERTIESTHATBEHAVE1.IKETEXTANDCAPTIONIfyoubuildanActiveXcontrolthatexposesaText-orCaption-Iikeproperty,evenunderdifferentnames,youshouldmodifyitsattributesintheProcedureAttributedialogboxafterexpandingitusingtheAdvancedbutton.Thisway,theProcedureIDissettoTextorCaptionrespectively.ThiscausesyourpropertytobehavelikestandardTextorCaptionproperties.WhentheusermodifiesitsvalueinthePropertywindow,theeffectofeachnewcharacterisimmediatelyreflectedontheActiveXcontrolitself.-FrancescoBalena,Bari,ItalyVB51.evel:AdvancedCOMBINEDEFAU1.TWITHOTHERATTRIBUTESWhenbuildinganActiveXcontrol,youcansetadefaultpropertyormethodusingtheProcedureAttributesdialogbox,afterclickingontheAdvancedbutton