Tools Links Login

Updated - 27 VB Hints and Tricks you should know

Just a bunch of VB6 hints and tricks I thought I could share with you.
Many new hints and tricks you should know in VB6.
How to add events to Windows Application log
How to add controls in run time
VB6 and the 2GB File limit - Be aware
How to hide your application from task manager
ASM Subclassing - Moving back is the safest way
How to check for non-Modal permitions
How to implement DIR$ correctly in your application.
Convert ByteArrays to String and vice versa
And more...

Original Author: Filipe Lage

Code

VB Hints:


Give description to your print jobs:



Before printing set APP.TITLE to the description of
the print job.

This way, the description of the document being printer will appear in the
printer job window instead of your application

name.

Ex:



app.title = "Invoice #1234"



[do the printing code and enddoc]



Quickly get data from a separated string



Let's consider



dim a as string

dim atmp() as string

a="Text1;Text2;Text3;Text4"

atmp=split(a,";")

Test = a(3)



Now let's look at...



dim a as string

a="Text1;Text2;Text3;Text4"

Test = split(a,";")(3)



This way you can get the "Text4" string directly
from split instead of mapping a temporary string (previous example).

It's actually faster too ;)



Naturally, this also applies to tab delimited files. Example, Create a file
in excel and export as TXT (Tab delimited)

You can get the cell from the respective row and column after reading
contents to memory



function CellData(data as string, row as
integer, column as integer) as variant

CellData = split(split(data,vbcrlf)(Row),vbtab)(Column)

end function





Quickly get rounding of a number the right way:



Since VB rounds fail in mathematical functions (ex:
Round(2.5) results in 2 instead of 3)

we can avoid that by creating a new Round Function in VB



function MathRound(value as Double,
optional lngDecimals as Long = 0) as double

MathRound = CDbl(Format$(value * 10^lngDecimals, "0")) / 10^lngDecimals

end function



This function also supports negative decimal places.

Ex: MathRound(1100,-3)=1000



There's a faster function (also created by me) available on the net if you
prefer speed over simplicity.

Check it at

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=61414&lngWId=1



Immediate window



In case you don't know, you can use "?" to replace "debug.print"
in the immediate window

Ex:

Go to immediate window and type:



? 1+1



It will appear: 2 (naturally)

It's useful to test functions or parts of code parsing the output value to
the immediate window, or simply to check variables.

Ex:



? a=3

False



BTW, if type it in your VB code itself, the "?" will
be replaced to "Print" just after you press enter.

Ex:



me.? "test"



will be automatically replaced to:



Me.Print test




Use mouseweelfix



VB6 doesn't support mousewheel natively, so you
can't scroll up and down with your mouse.

But there's a fix... actually, it's an addon for VB that scrolls the text
and implements that so-much-needed function.

You can find it in microsoft here: http://support.microsoft.com/?id=837910



How to register an ActiveX in code.



Just make a declaration such as:



Private Declare Function REGISTER_MYDLL
Lib "MYDLL.DLL" _

  Alias "DllRegisterServer" () As Long

Private Declare Function UNREGISTER_MYDLL Lib "MYDLL.DLL" _

  Alias "DllUnregisterServer" () As
Long

Private Const ERROR_SUCCESS = &H0



Then, simply call



REGISTER_DLL



or



UNREGISTER_DLL



in your code to register or unregister the dll.



There are more advanced functions that enable you to specify the DLL to get
registered on code instead of

mapping the actual DLL file in the declaration. But if you know your DLL's,
then simply include the declarations in the EXE

and add

an option to Fix components by calling the respectivefunctions

This also works for OCX files.



XCOPY Install?



YES! That is, if you only use OCX files...

In case your EXE requires external OCX files, and you put them in the same
path as the EXE, they are loaded without any

problems! :)

Doesn't work for dll's though. You still have to register them using
regsvr32 or using the previous hint.

If you want to make sure your app works even without VB6 Runtimes, simply
include MSVBVM60.DLL to your EXE path, but don't

register it.

But if you want to run your application even though you're not sure if the
target system has VB6 runtimes, just include

the MSVBVM60.DLL in the same path as the EXE... it works :).

Note for "Virgin" Win95/98:

Must have DCOM previous installed (it is installed with IE 4.5 anyway and
MDAC's, and other updates)



How to enable/disable all controls in a form/container



to disable:



on error resume next

for each o in me.controls: o.enabled = False: next



to enable:



on error resume next

for each o in me.controls: o.enabled = True: next




How to change container of an object.



Example, place a commandbutton in a form, and add a
frame next to it.

Note that both controls will have Form1 as a parent.

If you want commandbutton to be included inside the frame, but to make it
work in runtime simply add:



SET Command1.container = Frame1




Avoid using VB strings greater than 32k



VB Strings is the "Achilles's heel" of VB in terms of
speed. (ok, strings and threading/subclassing)

I recomend you use a stringhelper object (check AllocString page at http://www.xbeat.net/vbspeed/)
if you want

big strings (1MB or more) to store data. Beware of this AllocString since
the data inside the string will not be blank!


 



[Added 2006-02-02]

Read file from disk into memory (Fastest way possible without API
with low cpu usage)



I've done this function to obtain all data from an
existing file to memory. Note that if you have very large files (like 1GB)
it will take 1GB of RAM as well... It's great to read data and handle it in
memory. I get about 7MBytes/second in my P4-3000.


Public Function ReadFullFile(file As String)
As Byte()

Dim a As Long

a = FreeFile

Open file For Binary As #a

ReDim ReadFullFile(LOF(a)-1)

Get #a, , ReadFullFile

Close #a

End Function



It stores all data in a bytearray... It's better
than storing in a VB String, since all VB strings are stored in UNICODE,
meaning that for each byte in the file, it will take 2 bytes of RAM. So, if
I used a string, I would need 200MB of RAM to read a file of 100MB.


Naturally, you can convert it to string using the
code:


Dim FileData as string

FileData = StrConv(Readfullfile(file),vbUnicode)


Be careful, since you can run out of out of memory
with very large files!

You should also take in consideration, that if the file has 0 bytes or
simply doesn't exist, it will result in an error, so you should make sure
that the file being read exists and it's not 0 bytes long.


You can also change the function to read the file
directly to a string, by using


Public Function ReadFullFile(file As String)
As String

Dim a As Long

a = FreeFile

Open file For Binary As #a

ReadFullFile = Space(LOF(a)) ' You can use the VBSpeed's StringHelper to
make this faster for large files

Get #a, , ReadFullFile

Close #a

End Function




Avoid VB IDE bugs



I've used VB for several years now, and I've
discovered several bugs that many times corrupt projects and you should be
aware of that.


Lost bags

First of all, if you have an UserControl present in your EXE project,
remember that if you change the project name, all properties previously set
in your forms will be lost. To be exact, all propbag's in your user
controls become "blanks" and defaults are used.

Example:

You've added an UserControl to your project and you're using it in Form1.
One of the properties of that user control is "Caption" and you've set that
to "Hello world"... Nice, that is saved on the usercontrol's propbag... If
you change the EXE project name, and check your form again, the "Hello world"
is now gone.


Corrupt VBP's

One of the most annoying things in VB6 is that it sometimes corrupts
the VBP's by mistaking some ActiveX objects with ActiveX controls.

Example: If you have ActiveX DLL's in your project references, and you also
use external ActiveX Objects (usercontrols) in your forms, sometimes VB6
will list the object as a reference. In conclusion, when you open the VBP
once again, it will give a load error and all forms that use the "mixed up"
control will have their objects replaced with a picture box.


This happens when you open several projects in VB (ex:
EXE + DLL) and use an external OCX UserControl, compile the DLL with the other projects loaded, quit VB
and save changes. After that, just load the EXE VBP.

When this problem happens, the solution I've found is to open the VBP with
notepad and delete the "Reference" line that includes the OCX/VBP. Open the
VBP, include the OCX once again in the add controls, and re-save the project
(just the VBP). Reopen the VBP and all is well again.





[Added 2006-03-07]

Avoid using Subclassing... At least with ASM code on it

    Until recently, I've been using the ASM subclassing from (the
great)
VBAccelerator.com. The file ssubtmr6.dll to be exact.

    Unfortunatly, I had to return to the previous non-ASM code since every call crashed my application in a computer I had...


    I investigated, and I found
the reason... DEP - Data Execution Prevention...

    Naturally, when DEP is used Windows XP and 2003.NET with a
DEP compliant CPU (ex: AMD64 or the latests Intel CPU's), Windows will deny the ASM part of the subclassing
to run (since the code is stored in a variable area and not in a code execution
area)...

    Windows automatically shows a GPF when the subclassing is initialized in
this mode and the application is closed.



    There are two ways to avoid the problem:

    1) Not recomended

   
    Change the boot.ini of
the operating system (not recomended) or add your application to the DEP 'exclusion'
lists.

        Either way, it doesn't garantee a crash free operation,
and the user has to add your application to the exclusion list manually.

    2) Recomended

        Return to the previous subclassing that
doesn't use the ASM code.

        A little slower, but it's crash free with DEP compliant cpu's.


    This is my recomendation if you want to make a stable,
subclassing application to be used in Windows XP and/or 2003.NET.


 


On error resume next... Beware!

    If you want a 99% crash free app, you can always add the on
error resume next on the first line of every sub and function... I don't
recomend it, but at least it won't show any VB Runtime errors... However,
remember to set "on error goto 0" before the end of the function/sub, if not,
your code may not work at all (exits the first function calls another one
without resuming the next line if an error was raised in the second function).   




 


DIR$ - A great thing if you implement it right.

    VB has the DIR$ function so you can list folders and files,
however you should be aware that this function is shared across your entire
application. So, if you have one function that does something like:



    Sub ListFolder()

    mainpath = "c:windows"

    a$=Dir$(mainpath)

    do until a$=""

    b$=HowManyDirs(mainpath & "" & a$)

    a$=Dir$

    Loop



    Function HowManyDirs(f) as long

    b$=dir$(f,vbDirectory)

    do until b$=""

    HowManyDirs=HowManyDirs+1

    b$=dir$

    loop

    end function



    This code won't work at all, since the Dir$ function is
common in the entire application. If the first sub is using the Dir$, no
function should use it before the first sub finishes. You won't get the right
results if you do.


 


Beyond 2GB files with VB

    
All VB functions to get file size (LOF(x) or
FileLen(f)) are limited to longs...

    That means that you only have 31 bits (+1 bit for sign) to
store the size of the file... That gives VB a limit of 2147483648 bytes (2GB).

    Using internal functions and calls, like OPEN, SEEK, etc, you
can't get data beyond this point, so you'll need to use the API for that.

    Anyway, you should be aware of this VB6 limitation if your
project deals with very large files (ex: VOB's, MPG's, AVI's, etc) so you can
implement the necessary 64-bit functions to avoid this limitation.

    In terms of internal results (ex: a function you implement to
get the file size in 64-bits), I recomend you use the CURRENCY to get the file
size... Even though "Currency" data type isn't a full integer type, you'll have
the limit raised to 922.337.203.685.477 bytes (around 920 TeraBytes) per file
that I think is good enough for the next few years ;)



    Hint: If you're using a function to check if a file exists on
the hard disk, and your code is similar to:

   
       
Function DoesFileExist(f as string) as Boolean

             
On error resume next

             
DoesFileExist = (filelen(f)>0)

             
End Function

    You should be aware that VB's
FileLen function reports negative values when a file is bigger than 2GB, so
avoid using it unless you know what you're doing. In some cases, it can even
report that the file doesn't exist even though the file is there.


 


Use VB's Application LogEvent to track your
application status:

    VB provides a good way to log events to a file or to
Windows NT/XP Application Log.

    Note that this will only in the compiled file. No event will
be logged in IDE mode.

 

    How to log events to an external file:

        

App.StartLogging "c: est.log", vbLogToFile ' or
VbLogOverwrite

             
App.LogEvent "Hello world", vbLogEventTypeError

             
App.LogEvent "Hello world", vbLogEventTypeWarning

             
App.LogEvent "Hello world", vbLogEventTypeInformation



    How to log events to NT
Application Log:

             
App.StartLogging "My Application", vbLogToNT

             
App.LogEvent "Hello world", vbLogEventTypeError

             
App.LogEvent "Hello world", vbLogEventTypeWarning

             
App.LogEvent "Hello world", vbLogEventTypeInformation

     
One great thing about
this is that your other calls (ex: DLL's and OCX's) can use the logevent to the
same log as the main EXE file.

    This is great to debug a applications or communication
services.

    Just remember not to log TOO MUCH or else it will be filled
with irrelevent data.


 


Some functions that most people are unware of

    How to convert a byte array to a string:

       

MyString = strconv(MyByteArray, vbUnicode)


    How to convert a string to a byte
array:

       

MyByteArray = StrConv(MyString, vbFromUnicode)


    How to add controls to your forms in
run mode:

  
       
Private WithEvents Text1 As TextBox ' So you can also have events

            Sub
AddTextBox()

            Set Text1 =
Me.Controls.Add("VB.TextBox", "Text1")

            ' Now we have
the control, just as if it was added on design mode.

            Text1.Move 0,
0, 500, 100

            Text1.Visible
= True

            End With

        This also
works with other controls (ex: Winsock) as long as the control is present in
your project's VB toolbox.

        In this case you also need to remove
the check 'Remove information about unused ActiveX' in

        the VB compilation options unless if
you have at least one control present in any of your project forms.


    How can you check the number of forms
currently loaded:

       

NumberOfFormsLoaded = vb.Forms.Count


    How to unload all forms in a MDI
project safely:

  
      
do until vb.Forms.Count <=0

            unload
vb.forms(0)

            loop

        Note: if
you have in your form's QueryUnload or Unload events, the possibility of a
cancel operation this code won't work properly.


    Check if you can show a non-Modal
form before you try it to show it.

   
      
MyForm.Show (1+App.NonModalAllowed)


        This will automatically show your
form in Modal mode is a previous form is already in that mode...

        Note that if you try to show a
non-Modal form when a Modal form is visible, VB will stop the execution with a
run time error, crashing your application entirely, so this is safe to use
ensuring that no "Non-Modal" run time error occurs.


    How to hide your application from the
Task Manager's "Applications" tab (however it will be visible in the "Processes"
tab):

   
       
App.TaskVisible = False


Cheers



// FCLage


2006-03-07

About this post

Posted: 2002-06-01
By: ArchiveBot
Viewed: 308 times

Categories

Visual Basic 6

Attachments

No attachments for this post


Loading Comments ...

Comments

No comments have been added for this post.

You must be logged in to make a comment.