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 app.title = "Invoice #1234" [do the printing code and enddoc] Quickly get data from a separated string Let's consider dim a as string Now let's look at... dim a as string This way you can get the "Text4" string directly function CellData(data as string, row as Quickly get rounding of a number the right way: Since VB rounds fail in mathematical functions (ex: function MathRound(value as Double, This function also supports negative decimal places. Immediate window In case you don't know, you can use "?" to replace "debug.print" ? 1+1 It will appear: 2 (naturally) ? a=3 BTW, if type it in your VB code itself, the "?" will me.? "test" will be automatically replaced to: Me.Print test Use mouseweelfix VB6 doesn't support mousewheel natively, so you How to register an ActiveX in code. Just make a declaration such as: Private Declare Function REGISTER_MYDLL Then, simply call REGISTER_DLL or UNREGISTER_DLL in your code to register or unregister the dll. XCOPY Install? YES! That is, if you only use OCX files... How to enable/disable all controls in a form/container to disable: on error resume next to enable: on error resume next How to change container of an object. Example, place a commandbutton in a form, and add a SET Command1.container = Frame1 Avoid using VB strings greater than 32k VB Strings is the "Achilles's heel" of VB in terms of [Added 2006-02-02] I've done this function to obtain all data from an Public Function ReadFullFile(file As String) It stores all data in a bytearray... It's better Naturally, you can convert it to string using the Dim FileData as string Be careful, since you can run out of out of memory You can also change the function to read the file Public Function ReadFullFile(file As String) Avoid VB IDE bugs I've used VB for several years now, and I've Lost bags Corrupt VBP's This happens when you open several projects in VB (ex: This is my recomendation if you want to make a stable, On error resume next... Beware! DIR$ - A great thing if you implement it right. Beyond 2GB files with VB Use VB's Application LogEvent to track your Some functions that most people are unware of How to convert a string to a byte How to add controls to your forms in How can you check the number of forms How to unload all forms in a MDI Check if you can show a non-Modal How to hide your application from the Cheers
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:
dim atmp() as string
a="Text1;Text2;Text3;Text4"
atmp=split(a,";")
Test = a(3)
a="Text1;Text2;Text3;Text4"
Test = split(a,";")(3)
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
integer, column as integer) as variant
CellData = split(split(data,vbcrlf)(Row),vbtab)(Column)
end function
Round(2.5) results in 2 instead of 3)
we can avoid that by creating a new Round Function in VB
optional lngDecimals as Long = 0) as double
MathRound = CDbl(Format$(value * 10^lngDecimals, "0")) / 10^lngDecimals
end function
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
in the immediate window
Ex:
Go to immediate window and type:
It's useful to test functions or parts of code parsing the output value to
the immediate window, or simply to check variables.
Ex:
False
be replaced to "Print" just after you press enter.
Ex:
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
Lib "MYDLL.DLL" _
Alias "DllRegisterServer" () As Long
Private Declare Function UNREGISTER_MYDLL Lib "MYDLL.DLL" _
Alias "DllUnregisterServer" () As
Long
Private Const ERROR_SUCCESS = &H0
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.
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)
for each o in me.controls: o.enabled = False: next
for each o in me.controls: o.enabled = True: next
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:
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!
Read file from disk into memory (Fastest way possible without API
with low cpu usage)
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.
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
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.
code:
FileData = StrConv(Readfullfile(file),vbUnicode)
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.
directly to a string, by using
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
discovered several bugs that many times corrupt projects and you should be
aware of that.
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.
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.
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.
subclassing application to be used in Windows XP and/or 2003.NET.
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).
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.
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.
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.
How to convert a byte array to a string:
MyString = strconv(MyByteArray, vbUnicode)
array:
MyByteArray = StrConv(MyString, vbFromUnicode)
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.
currently loaded:
NumberOfFormsLoaded = vb.Forms.Count
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.
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.
Task Manager's "Applications" tab (however it will be visible in the "Processes"
tab):
App.TaskVisible = False
// FCLage
2006-03-07
Loading Comments ...
Comments
No comments have been added for this post.
You must be logged in to make a comment.