VB12
VB12
VB12
With rsholder
If eCurLoc = 0 Then
.CursorLocation = adUseClient
Else
.CursorLocation = eCurLoc
End If
If eCurType = 0 Then
.CursorType = adOpenStatic
Else
.CursorType = eCurType
End If
Using it is very simple. If you supply no paramters, you get a client side, static cursor with minimal
locking:
The function uses the same enumerated values as the recordset properties, so the choices will pop up as
they do when you type in object.property =
A1 = Text1.Text
A2 = Text2.Text
iWorkDays = A2 - A1 + 1 - Int((A2 - A1 + 1) / 7) * 2 - _
IIf(Int((A2 - A1 + 1) / 7) = (A2 - A1 + 1) / 7, 0, _
IIf(WeekDay(A2) < WeekDay(A1), 2, 0)) - _
IIf((WeekDay(A1) = 1 Or WeekDay(A2) = 7), 1, 0)
Label1.Caption = iWorkDays
End Sub
Often, an application needs a special window without a title bar, the horizontal
bar at the top of a window that contains the title of the window. For instance, a splash
screen or a custom context sensitive menu are nothing more than VB forms without title
bars. To make a form appear without a title bar set the following design-time and run-time
properties.
This involves using the SetWindowLong API function with the following parameters, GWL_EXSTYLE
and WS_EX_TRANSPARENT as constants.
this will make the form referenced by me.hwnd transparent so that the background can be seen but the
controls can still be accessed.
command1.caption = &SetOnTop
command2.caption = &Make Normal
End Sub
lngontop = SetWindowPos =
(me.hwnd,HWND_NOTOPMOST,0,0,0,0,(SWP_NOMOVE or SWP_NOSIZE))
End Sub
The Command1 button set the Always On Top behaviour of the form, while Command2 sets it back to
normal.
Excel=A2-A1+INT((A2-A1+1)/7*2-IF(INT((A2-A1+1)/7)=(A2-A1+1/7,0,IF
WEEKDAY(A2)<WEEKDAY(A1),2,0))-IF(OR(WEEKDAY(A1)=1, pre <
lblDays.Caption="intDaysBetween" 0) 1, WeekDay(EndDate)="7)," Or IIf((WeekDay(StartDate)="1" - _
0)) 2, WeekDay(StartDate), IIf(WeekDay(EndDate) 0, 7, 1) + StartDate 7)="(EndDate" IIf(Int((EndDate 2
* 7 Int(EndDate 1 intDaysBetween Date As EndDate Dim Integer VB WEEKDAY(A2)="7),1,0)"
As you can see i had to replace all the IF's with IIf's (implicit If's). The first part
determines the number of days between the 2 dates. The next part determines the number of whole weeks
between because of the Saturdays & Sundays. Then the last part determines if the dates spanned a
weekend where the start date day would be smaller that the end date day.
I have seen that many programmers face this problem and to solve this problem VB 6.0 has introduced a
Validate event also.
Place two text boxes on the form and see that the initial text property is blank.
And now run the application. Type some value in text1 and do a lostfocus and everything will work fine.
Now change the code and do a setfocus after the message is displayed on the lostfocus of both the text
boxes.
That is change the code to :
Now run the application.Type some value in the first text box and perform a lostfocus and you will see
that everything goes in a loop and the only solution is to perform an abnormal termination of the
application..
Hence the trick is that if any validation is to be done and you need to place the control back on the text
box then perform a setfocus before the Message is displayed instead of performing it after the message is
displayed.
I really think VBers will like this little application. It answers several questions:
How can I map a networked Drive Letter
'add code to retrieve information from the recordset and assign it to the retval
retvaltype = VarType(retval)
if retvaltype = 2 then
retval = "" ' or you could put a 0(zero) if it is a numeric field
else
reval = retval
end if
This should be done only with small amount of variables declared as variant as it take more overhead to
delcare a variant, however if you need a fast way to solve this problem it works.
Name Message
DataBindingBehavior 0-VBNone
DataSourceBehavior 0-VBNone
Instancing 5-Multiuse
MTSTransactionMode 0-NotAnMTSObject
Persistable 0-NonPersistable
There are four public proceudres for message dialogue box. You can write any type of procedure or
function, but for simplicity I wrote procdures that only display message boxes.
Public Sub information(details, title)
MsgBox details, vbInformation, title
End Sub
Option Explicit
Private mess As New message
End Sub
Now write some text in description box and the title text in title text box and also choose the message type
and press the command button and u will see the appropriate message coming through the dll file.
End If
End If
'================
Dagnummer$ = ""
zat$ = ""
bij$ = ""
Dagnummer1$ = ""
Dagnummer2$ = ""
Rekendagen$ = ""
Verschil$ = ""
weken$ = ""
Overdagen$ = ""
aww$ = ""
odb$ = ""
Weekdagen$ = ""
awr$ = ""
aftel$ = ""
Werkdagen = ""
aww$ = Format$(Val(weken$) * 5)
awr$ = Format$(Val(aww$) + Val(Weekdagen$))
'========
If Val(Dagnummer$) = 6 Then
odb$ = Format$(Val(Overdagen$) - 1)
aftel$ = "1"
ElseIf Val(Dagnummer$) = 7 Then
odb$ = Format$(Val(Overdagen$) - 0)
aftel$ = "0"
Else
odb$ = Format$(Val(Overdagen$) - 2)
End If
'==========
If Val(Dagnummer2$) = 6 Then
zat$ = "-1"
Else
zat$ = "0"
End If
'==================
End Sub
Counter = 1
TmpInt = 0
Option Explicit
Dim Cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim ii As Long
Dim oo As Integer
ii = 0
For oo = 0 To 24
DBGrid1.TextMatrix(ii, oo) = rs.Fields(oo)
Next oo
ii = ii + 1
rs.MoveNext
Wend
End Sub
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
Unload Me
End Sub
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
All entries under these three keys are started during the bootup process and your application should be
listed under one of them. The "Run" key names applications to run every time, as does the "RunServices"
key. The difference is when they start during the boot process. You probably want to use the Run key, but
you can try both and see what the difference is. The RunOnce key will run the next time Win95 starts, but
is then purged. This is a good place to put applications that complete a setup process or a cleanup.
List Box To List Box - VB5 Professional
Here is another way to move data from one list box to another and back. The four buttons ( ADD, ADD
ALL, REMOVE and REMOVE ALL) are a control array and the subroutine FourButtons handles all
List1.AddItem List2.Text
List2.RemoveItem List2.ListIndex
End Select
Screen.MousePointer = 0
End Sub
SCRNSAVE: name
The 'name' part will appear on the list of available screen savers in the control panel. Note that
this is not the title of the form, it is the application title and must be set in the project properties.
When you compile the program use .SCR for the extension instead of .EXE as normal. Place the
compiled code in the Windows\System directory (it can also go in Windows, but System is
preferred)
When your application starts check for a previous instance and stop if one is found:
Sub Form_Load()
If App.PrevInstance Then
Unload Me ' NEVER use END!
Exit Sub
End If
End Sub
If the screen saver is to run normally use the following to tell Windows that you are taking over as a
screen saver (this will disable ALT-TAB and CTRL-ALT-DEL and prevent more instances from
being started):
For more information, including sample code that handles password protected screen savers
check http://www.arcatapet.com/vb.html or http://www.tiac.net/users/lvasseur/
To prevent an 'invalid use of null' error occurring when reading data from a database use the following
syntax:
Text fields:
Form1.text1.text = "" & myRecordset("TextName")
Numeric fields:
Form1.Option1.Value = 0 & myRecordset("NumricField")
Both Windows95 and WindowsNT have that neat new feature called the system tray where you can place
your application. This is easily done via the Windows API called "Shell_NotifyIcon" which manages the
Taskbar which the system tray is part of.
There are a couple of tricky things that you need to keep in mind when using this function. First, the
application needs to be visible (but not necessarily seen--you can set its Top & Left to -10000) and you
also need to know how to handle callback functions. If your not sure what a callback function is then stop
here (you should learn about callback functions before proceeding).
First, place the declares into a bas module:
' These tell you what is happening in the system tray (over your icon)
Public Const WM_MOUSEISMOVING = &H200 ' Mouse is moving
Public Const WM_LBUTTONDOWN = &H201 'Button down
Public Const WM_LBUTTONUP = &H202 'Button up
Public Const WM_LBUTTONDBLCLK = &H203 'Double-click
Public Const WM_RBUTTONDOWN = &H204 'Button down
Public Const WM_RBUTTONUP = &H205 'Button up
Public Const WM_RBUTTONDBLCLK = &H206 'Double-click
Public Const WM_SETHOTKEY = &H32
With nidProgramData
.cbSize = Len(nidProgramData)
.hwnd = Me.hwnd
.uId = vbNull
.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
' This is the event that will trigger when stuff happens
.uCallbackMessage = WM_MOUSEMOVE
.hIcon = Me.Icon
.szTip = "Lock Your System" & vbNullChar
End With
End Sub
' This procedure receives the callbacks from the System Tray icon.
Dim Result As Long
Dim msg As Long
' The value of X will vary depending upon the scalemode setting
If Me.ScaleMode = vbPixels Then
msg = X
Else
msg = X / Screen.TwipsPerPixelX
End If
Case WM_LBUTTONDBLCLK
' Process double click on your icon
Case WM_RBUTTONUP
' Usually display popup menu
Case WM_MOUSEISMOVING
' Do Somthing...
End Select
Exit Sub
Form_MouseMove_err:
' Your Error handler goes here!
End Sub
When your Application executes, it will head right into the System Tray. It is up to you to program in the
context menus and to process the callback messages.
First, the Command Button style property is set 1(Graphic) and the shape of the image can be changed
according that the user presses the mouse button up or down. However, the images should be placed at a
fixed position, and both images and texts can't be displayed. Second, we can put the PictureBox which has
the Enabled property False on the Command Button control. In this case, we can't make use of a function
of the PictureBox. That is, we can't change the BorderStyle according that the mouse pointer is in the
PictureBox or out of the PictureBox. If PostMessage Windows API is used, we can solve this problem.
Suppose there are two bitmap files, button.bmp and camera.bmp.
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Sub Timer1_Timer()
Label1.Top =3D thetop
thetop =3D thetop - 1
If thetop < -p1hgt Then
Timer1.Enabled =3D False
I hope this will be of some use to somebody someday, I know that I was surprised when I discovered the
lack of a ScrollPos Member.
The "AlwaysOnTop" property.
By Joe LeVasseur
[email protected]
Simply paste the code below into the form that you need to have the "AlwaysOnTop" property. Syntax
would be like this-[FormName].AlwaysOnTop= True Note the commented code in the Resize event, the
form loses the "AlwaysOnTop" property if it is minimized. I think that under most circumstances a
"AlwaysOnTop" window would probably be a fixed dialog and therefore not minimizable. One other
caveat- this code may or may not work in the IDE. (I've seen both.)
__________snip____________________________________
Option Explicit
'------------------
' Paste this into a form and you
' will have a new property-AlwaysOnTop.
Do
...
...
MyDynaset.MoveNext
Loop Until MyDynaset.EOF
MyDynaset.MoveLast
j = MyDynaset.RecordCount
MyDynaset.MoveFirst
For k = 1 to j
...
...
MyDynaset.MoveNext
Next
you should notice is 30% speed increase from the first code. I tried this code with a MDB file with
17000 records, and with a MDB file with 500 records. They both work well. The reason? Of course
because the second code does not check the EOF condition every iteration (even if it must go to the last
record and then to the first record)! Maybe, if the recordset is small you may not notice any
improvement, but in this case, processing time is short anyway. I found this code does not improve
processing time in Delphi. I think it's because Delphi EXE is compiled and not p-code.
' Special Subroutine to move selected items from one listbox to another
Public Sub List_Refresh(SourceList As Control, TargetList As Control)
Dim N As Integer
Dim I As Integer
ReDim Remove(0 To SourceList.ListCount - 1) As Boolean 'Items to remove
For N = 0 To (SourceList.ListCount - 1) ' If selected, then , add to Target List
If SourceList.Selected(N) = True Then
TargetList.AddItem SourceList.List(N)
Remove(N) = True ' Sets item for removal from Source list
End If
Next N
"This method is meant to work best when the multi-select feature of the listboxes is enabled"
TestValues = "02468"
TmpChar = Right$(Trim(Str$(TestInt)), 1)
Answer = InStr(1, TestValues, TmpChar)
IsEven = Answer
End Function
Tip supplied by James Johnston [email protected]
Accessing Databases
This tip is on accessing databases. For performing an operation in every record of a Table or RecordSet
(for example you could want to update some fields, or retrieve some information), generally this code is
used.
Do
...
...
MyDynaset.MoveNext
Loop Until MyDynaset.EOF
MyDynaset.MoveLast
j = MyDynaset.RecordCount
MyDynaset.MoveFirst
For k = 1 to j
...
...
MyDynaset.MoveNext
Next
you should notice is 30% speed increase from the first code. I tried this code with a MDB file with 17000
records, and with a MDB file with 500 records. They both work well. The reason? Of course because the
second code does not check the EOF condition every iteration (even if it must go to the last record and
then to the first record)! Maybe, if the recordset is small you may not notice any improvement, but in this
case, processing time is short anyway. I found this code does not improve processing time in Delphi. I
think it's because Delphi EXE is compiled and not p-code.
1 Why does CommonDialog control show error "No Fonts Installed" when ShowFont method is called ?
The possible reason could be invalid value assignment for Flags property of CommonDialog Control.
Try assigning cdlCFBoth to Flags property. This will inform the Control to use the installed fonts.
3 How can i add the application to SysTray in windows ? Can you please help me out ?
Dear Hansal, It's possible to add your VB form to System Tray in 32-bit windows. Yu can fidn the
code for this with detailed explanation in the 'Downloads Section' of VB Forum on this site. Thank you for
your query.
4 Is it possible to create our own setup programs (customized) for installing VB Applications ? If so how
can we do it ? Do we need to know VC++ or SDK ?
Hi Anwar and Ramesh, You need to know only VB, Application Package and Deployment Wizard for
preparing a customized installation program. A VB App Installer package will have two major files
firstly, setup.exe and secondly, setup1.exe. The former one installs VB Runtime Environment and the
later installs the actual application. So it's always possible to modify (customize) Setup1.exe file. It's
nothing but a VB Project.
5 Sir as we will be using forms with similar properties like BorderStyle, WindowState, StartUp position,
Font, BackColor, ForeColor and sometimes even startup code, Can't we make templates and use this form
as a VB Form ? [ Srinath, Sripad, Manjunath, Harry and Monica ]
Hello, The query sent by all of you was very similar. It'll be very usefull while developing big
applications. It's possible to create your own templates. What all you ahve to do is, Open a new form set
all the properties add any code required and save it in <VB-HOME>\Template\Forms\ Folder. After this
you can see the new form in the VB Add Form Dialog itself. Thank you.
6 Is it possible to allow the user to Cut or Copy the contents of a password field (Text Box) ?
Hi Again Anwar, Well by default you are not allowed to copy or cut the contents of a password field
but it's possible to provide this feature by writing few lines of code in the KeyDown or KeyUp Events of
the password field. The following code demonstrates the same. [ To run the following code open a
StandardEXE Project and add a TextBoxby name Text1 and set it's PasswordChar field to * or # etc... ]
Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer) 'For Cut [ Ctrl + X ] If Shift =
vbCtrlMask And KeyCode = vbKeyX Then Clipboard.SetText Text1.Text Text1.Text = "" End If 'For
Copy [ Ctrl + C ] If Shift = vbCtrlMask And KeyCode = vbKeyC Then Clipboard.SetText Text1.Text
End If End Sub
7 Sir, Actual Problem that i have is Can we Create control like DataGrid which contains
combobox,CheckBox. Means when we call addnew method then user must be able to select apprppriate
type from combobox as well as check for his status with check box. [ Mahesh Shinde
<mailto:[email protected]> ]
Dear Mahesh, What i understood from your query is, you wanna integrate ComboBox and CheckBox
sort of controls with DataGrid so the user can choose a value from a list or check rather than typing. It's
possible. Either you can create a new control or soemtiems you can prepare a floating control. Anyways i
suggest yout o gor for the later as the former one would take more time and you need to be carefull while
designing such a control as it may kill available resources.
8 I am doing a final year project at the mement and wan't to know how to control the Com1(or 2) ports
using VB, to Tx & Rx data from a hand unit. any suggestions welcome. [ Sweeney
<mailto:[email protected]> ]
9 sir i would like to know the code to disable the default rightclick menu that pops up when we right clik
on a text box (when appl is running) except for this all other aspects for the textbox must be enabled I was
unable to find any such refrence in the site. [ Deepa Iyer <mailto:[email protected]> ]
Hi Deepa, The best possible way of doing it is using SubClassing. You have to use few APIs for this.
Please download THIS <zipz/Q_9_VID104.zip> file. It has both the source code and some docs about
subclassing. Hope this will solve your problem.
Go to the Tools|Custom Controls menu choice. Remove ALL check marks or all that it lets you. Then go
to the Tolls|Reference menu choice. Remove all of these it lets you. You should be left with most of the
controls your programs need. Most of the rest of the controls your program might need are probably in
Windows Common Controls(Go back to Tools|Custom Controls and check this if you need this). This
makes a HUGE difference in many parts of your program. Loading it when run and when edited in VB is
faster. The needed files list in the Setup Wizard is cut in half almost.
Use Labels instead of TextBoxes, unless the user needs to type into the TextBox. If you like the look of the
TextBox you can reproduce it by setting a Labels border to Single.
Use control arrays for any related controls, especially with Label controls that just display text and do
nothing else. Also this works really well with Option Controls contained in a Frame.
Unless you have pictures that are updated often, you can set the Autoredraw to False and as long as you
placed controls correctly, no overlapping, set the Clip Controls option to False.
Sub Form_Load ()
' Don't want two copies of the program running at the same time
If AnotherInstance() Then End
' Note: that this routine will not work if the application's title changes
' (showing file names in the title bar for example).
End Sub
15. I would like to create masks for date and time input. I have heard of
the MaskedEdit control but don`t know how to use it.
Ans. Keyword: MaskedBox control, Mask property.
Example: To input a date in a MaskedEditBox, set its mask to "##/##/####". When
you run the app, the box will show "__/__/____" and you will be able to type
numbers in its prompt area.
16. I am writing a VB5 program to interface with a MS Access
database...it will add and delete records and scroll through all the
records currently entered. I need to be able to add a Find function to this
application. I tried the FindFirst and FindNext methods but...it didn`t
work. I need it to display the record that matches the given search
string.
A: You want to Search the Given data in a Table...Let me give you an
example for this. Suppose You want to Search for CustomerName in
Customer Table of CustomerDetails Database. The text you want to
search is in "Text1.Text" box.
VSearch = "CustomerName="+Text1.Text
CustomerDetails.Recordset.FindFirst VSearch
Yogesh
The number one problem with FindNext, etc. methods and SQL is in
handling the quotes. Note the Chr$(34)`s. They are quotation marks.
Beyond that, note that the routine cleans up after itself by checking
for a match. If no match, the data control`s recordset is set back to
the record that was current prior to the FindNext.
Function Find_Record_By_Item#()
Dim Notice As String
Dim Msg As String
Dim Buttons As Integer
Dim Title As String
Dim Number As String
Dim Number2 As Integer
start:
Msg = "Enter an item number to look up and press enter." _
& Chr(13) & Chr(13) & "To cancel this operation press escape."
Title = "Item Number Look up"
Number = InputBox(Msg, Title)
If Number <> "" Then
DoCmd.FindRecord Number, acEntire, False, acSearchAll, True, acAll, True
Screen.ActiveForm![txtItem_Number].SetFocus
Number2 = Screen.ActiveForm![txtItem_Number].Text
If Number <> Number2 Then
Msg = "The item number you entered was not found." & Chr(13) _
& "Please enter another one."
Title = "Invalid Item Number"
Buttons = 48
Notice = MsgBox(Msg, Buttons, Title)
GoTo start
End If
Else
Screen.ActiveForm![txtItem_Number].SetFocus
End If
If Screen.ActiveForm![txtItem_Number].Locked = True Then
Screen.ActiveForm![txtDate_of_Sale].SetFocus
End If
End Function
A. Add a picture box, and then the scroll box to the form. Have the scroll bar move the picture box up and
down on the form. Put all of the controls on the "scrollable form" inside the picture box. Make sure the
picture box has no border.
If Combo1.ListIndex = -1 Then
SendKeys "{F4}{Down}"
Else
SendKeys "{F4}"
End If
This will make it dropdown and select first item if nothing is selected or just drop down if there is an item
already selected.
19. How to activate cancel button in dialog box?
How do I assign the cancel property to the cancel button of a simple dialog box? I`ve written a macro in
Excel using VB and use dialog box inputs to get user data. However, hitting the cancel button during
data entry has no effect.
This means that if the user presses Cancel it causes an error - so then you set up an error trap to do what
ever you want when the error happens. Look in the help file to get the exact syntax but it is something like
this:
'Pseudo code
on error goto errortrap ... ... ...
'all your stuff here ... ... ...
exit sub
errortrap:
if err=32755 then
'that might not be the right value, you can look up the error
'codes in the help file.
end if
end sub
21. I`m trying to write some code where clicking a radio button on form
#1 makes
a command button visible on form #2. I know how to do this within one form, but I don`t know how to do
this with two forms.
A. This is an easy one. You just have to include Form2`s name in front of the button`s name. Example:
The above is a brief example of the control your code can have over
keyboard input. The code fragment simply filters out any characters
that are not upper case. If the character received is lower case, it is
converted to caps, otherwise the character is zeroed out. Setting the
keystroke value to zero will be interpreted by most controls as a null
character and will therefore be ignored. You can also set the
keystroke to some other default value depending on the control
receiving the keystroke.
New Tips
Dollar sign Functions--what are they?
Ever wonder about those functions ending in a dollar sign? If you are running VB5 or VB6, you might not
even see them mentioned in VB Help.
In VB, there are a number of functions that have a dollar sign version---such as Left$, Right$ and Case$
Yes---if there's a possibility that the function will encounter a Null character in its argument string, you
need to use the non-dollar sign version--otherwise the function will bomb. For instance, in this code
Form1.Print Left(string1, 1)
Form1.Print Left$(string1, 1)
both Left and Left$ will return the left-most character of the string. However, if string1 contains a Null
character, Left$ will bomb---however, Left will work fine.
'-------------------------------------------
Visual Basic programs need to have the Visual Basic runtime DLL installed on the PC also---plus some
other support files.
The easiest way to do this is to run the Package and Deployment Wizard in Visual Basic to create a Setup
package.
Then all you need to do is give the diskette(s) to your friend, and have them run the Setup program found
on Disk 1---the same they would do for any other Windows program.
This way both your executable, and the Visual Basic runtime DLL and support files are installed.
'-------------------------------------------
Looking for a free version of VB?
Microsoft made a free version of VB5 called the Control Creation Edition available for download from
their website.
There is no free version of Visual Basic 6 available from Microsoft. However, there are several Visual
Basic books (including my first book, Learn to Program with Visual Basic 6) on the market that come
with
the Visual Basic Working Model Edition--which is a surprisingly full featured version of Visual Basic
(no,
you can't compile programs with it).
These tips were extracted from the June 2000 issue of the Visual Basic Explorer
newsletter and were submitted by John Smiley. Be sure to check out John's other
tutorials in the tutorials section or check out his website here <http://www.johnsmiley.com>.
'-------------------------------------------
Where have you gone Crystal Reports?
Crystal Reports, the leading third party Report Writer for Visual Basic, was previously packaged with VB
in versions 4 and 5 and appeared as an Add-in off of the Visual Basic menu.
VB6 users were disappointed to find that Crystal Reports apparently was not shipped with VB6---most
likely, it was believe, because Microsoft decided to include a Report Writer of its own called the Microsoft
Data Report designer.
For those of you still yearning for Crystal Reports, take heart--you can still find it on your Visual Basic
installation CD-ROM, provided, that is, you purchase Visual Basic Pro or Enterprise.
\Common\Tools\CryReports
For instance, if you have a Command Button whose caption is OK, to designate a hot key combination of
Alternate+O for the Command Button, you specify
&OK
The user can click on the textbox or tab to it, but wouldn't it be great to be able to get to a Textbox by
pressing the Alternate key plus a character?
The secret is to place a label control next to a textbox, and then designate a hot key combination for the
label control using the ampersand character in the Caption property of the label control.
For instance, if
you have a textbox sitting next to a label control whose Caption Property is &Name, if the user presses
Alternate+N, focus will move to the textbox adjacent to the label control.
Just one word of warning. In order for this to work, the Textbox's TabIndex property must be immediately
after the TabIndex Property of the Label Control. If the Label Control's TabIndex property is 15, for
instance, the Textbox must be 16.
'-------------------------------------------
Textbox selection goes away
Have you noticed that if the user selects text in a textbox, and then moves focus off of the textbox, that the
text is no longer selected.
This is because the HideSelect property of the textbox is by default set to True.
If you would prefer to keep the text selected when the user moves `off` of the textbox, then just set the
HideSelect property of the Textbox to False.
'-------------------------------------------
Password Char
Have a textbox into which you want the user to type an entry, but don't want anyone looking over their
shoulder to see it.
Just set the PasswordChar Property of the textbox to something other than its default blank character.
'-------------------------------------------
The Click event requires both the Mouse Down and Mouse Up over the
control
Just a reminder that in order for the Click event procedure of a control to take place, the user must both
click and then release the mouse button over the control. If, after clicking the mouse over the control they
then move it over the form or over another control before releasing it, the click event procedure never
takes place.
'-------------------------------------------
Entries in a Listbox
Many beginners are confounded with the List Property of a Listbox, which is where the programmer can,
at design time, place items that are to appear in a Listbox.
Because when they type an item into the Listbox, invariably they hit the ENTER key, and the List
Property in the Properties Window closes. They select it again, make a second entry, and then hit ENTER
again. Once again, the List property closes. This continues on and on until they have finished adding all
of the items (experienced programmers use the AddItem Method of the Listbox at runtime.).
If you want to add items to a Listbox at design time using the List property, after making your first entry,
type the
Ctrl+N
combination instead of the hitting the ENTER key. This will advance the carriage return to the next line
in the List property, and enable you to more quickly add the items to the Listbox.
Each icon in the tray is 16 by 16 pixels large -- the same as a control menu icon. Any icon can be used,
but if you use a 32 by 32 pixel icon, it will be re-sized to fit the space. If you want to create a separate icon
Message = X / Screen.TwipsPerPixelX
If RR = False Then
RR = True
Select Case Message
' Left double click (This should bring up a dialog box)
Case WM_LBUTTONDBLCLK
Me.Show
' Right button up (This should bring up a menu)
Case WM_RBUTTONUP
Me.PopupMenu mnuPump
End Select
RR = False
End If
End Sub
This looks for one of two things. If the user double clicks on the icon, it displays it's form. If they right
click on the icon, a popup menu is displayed that gives the user a list of options. The menu needs to reside
on the controlling form, but the top-most level must be hidden.
Ready to go? Before ending your program, you should always remove the icon, therefore, place this in
QueryUnload to remove the icon:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
TrayIcon.cbSize = Len(TrayIcon)
TrayIcon.hWnd = Me.hWnd
The following example demonstrates creating a toolbar for an MDI application; the
procedure for creating a toolbar on a standard form is basically the same.
The width of the picture box automatically stretches to fill the width of the MDI
form's workspace. The workspace is the area inside a form's borders, not including
the title bar, menu bar, or any toolbars, status bars, or scroll bars that may be on
the form.
Note You can place only those controls that support the Align property directly
on an MDI form (the picture box is the only standard control that supports this
property).
2. Inside the picture box, place any controls you want to display on the toolbar.
Typically, you create buttons for the toolbar using command buttons or image
controls. To add a control inside a picture box, click the control button in the
toolbox, and then draw it inside the picture box.
Note When an MDI form contains a picture box, the internal area of the MDI
form does not include the area of the picture box. For example, the ScaleHeight
property of the MDI form returns the internal height of the MDI form, which does
not include the height of the picture box.
3. Set design-time properties.
One advantage of using a toolbar is that you can present the user with a graphical
representation of a command. The image control is a good choice as a toolbar
button because you can use it to display a bitmap. Set its Picture property at design
time to display a bitmap; this provides the user with a visual cue of the command
performed when the button is clicked. You can also use ToolTips, which display
Because toolbar buttons are frequently used to provide easy access to other
commands, most of the time you call other procedures, such as a corresponding
menu command, from within each button's Click event.
Tip You can use controls that are invisible at run time (such as the timer control) with an
MDI form without displaying a toolbar. To do this, place a picture box on the MDI form,
place the control in the picture box, and set the picture box's Visible property to False.
Writing Code for Toolbars
Toolbars are used to provide the user with a quick way to access some of the
application's commands. There are now three places in the MDI NotePad sample
application where the user can request a new file:
• On the MDI form (New on the MDI form File menu)
Rather than duplicate this code three times, you can take the original code from the child
form's mnuFileNew_Click event and place it in a public procedure in the child form. You
can call this procedure from any of the preceding event procedures. Here's an example:
' This module is in a public procedure.
Public Sub FileNew ()
Dim frmNewPad As New frmNotePad
frmNewPad.Show
End Sub
' The user chooses New on the child form File menu.
Private Sub mnuchildFileNew_Click ()
FileNew
End Sub
' The user chooses New on the MDI form File menu.
Private Sub mnumdiFileNew_Click ()
frmNotePad.FileNew
End Sub
' The user clicks the File New button on the toolbar.
Private Sub btnFileNew_Click ()
frmNotePad.FileNew
End Sub
It’s important to distinguish between the events received by your UserControl object (or
by the controls it contains) and the events your control raises. Events your control
receives are opportunities for you to do something interesting; events your control raises
provide opportunities for the developer who uses your control to do something
interesting.
There are many events that might be of interest to the user of the ShapeLabel control. The
Visual Basic Label control raises a Click event, and ShapeLabel is just a fancy label, so the
following procedure will add a Click event. To make the event more interesting, it will be
raised only if the user clicks on the oval background.
Being compatible with other controls of the same type is an important reason to add a
particular event to your control. Other criteria for choosing what events to raise can be
found in "Raising Events from Controls," in "Building ActiveX Controls."
Note This topic is part of a series that walks you through creating a sample ActiveX
control. It begins with the topic Creating an ActiveX Control.
2. In the Object box, select (General). In the Procedure box, select (Declarations) to position
yourself at the top of the code module. Add the following code:
3. Option Explicit
4. ' Declare a public Click event with no arguments.
5. Public Event Click()
6. In the Object box, select lblCaption. In the Procedure box, select the Click event for the label
control. Add the following code to the lblCaption_Click event procedure:
7. Private Sub lblCaption_Click()
8. ' Raise a Click event whenever the user clicks
9. ' on the label.
10. RaiseEvent Click
11. End Sub
The code above raises a Click event only if the user clicks on the constituent
control lblCaption. It will seem more natural to users to be able to click anywhere
on ShapeLabel’s oval background, so the next step shows how to raise the click
event if the user clicks on the colored oval.
12. In the Object box, select UserControl. In the Procedure box, select the UserControl’s
MouseUp event. Add the following code to the UserControl_MouseUp event procedure:
13. Private Sub UserControl_MouseUp(Button As Integer, _
14. Shift As Integer, X As Single, Y As Single)
15. ' Raise a Click event only if the color of the
You might expect to put the hit test code in the shpBack_Click event procedure,
because shpBack is always resized to cover the entire surface of the ShapeLabel
control. However, Shape controls don’t receive Click events. Instead, the Click
event is received by the object that contains the Shape — in this case, the
UserControl object.
24. In the Object box, select one of the ShapeLabel controls you added to Form1. In the Procedure
box, select the Click event.
Note If the Click event does not appear, make sure the ShapeLabel designer is
closed.
You can click the arrow on the Procedure box to view all of the events for the
ShapeLabel control. In addition to your Click event, there are four events —
DragDrop, DragOver, GotFocus, and LostFocus — that are automatically
provided for you by the container, Form1.
25. On the toolbar, click the Start button, or press CTRL+F5 to run TestCtlDemo. Try clicking
various places on the form and on the ShapeLabel control, to verify that the Click event is being
raised only when you click inside the oval background.
26. There’s a subtle bug in the hit testing for ShapeLabel’s click event. To see this, press the mouse
button while the mouse pointer is in the lower half of the red oval. Holding the mouse button
The hit test code in the MouseUp event works if the mouse button is released over
the red background that shows through lblCaption’s transparent background, but
not if the button is released over the white foreground color of the text. (If the
button is released outside ShapeLabel, the Point function returns -1, so releasing
the mouse button over some random red spot will not raise the Click event.)
Fixing this bug is left as an exercise for the reader. (Hint: Moving the hit test to the
Click event of the UserControl won’t help, because the Click event doesn’t occur
when the MouseUp event is over a different object from the MouseDown.)
The Visual Basic Package and Deployment Wizard makes it easy for you to create the
necessary .cab files and setup programs for your application. Like other wizards, the
Package and Deployment Wizard prompts you for information so that it can create the
exact configuration you want.
There are three ways you can start the Package and Deployment Wizard:
• You can run it from within Visual Basic as an add-in. If you run the wizard as an add-in, you
must first set the necessary references in the Add-In Manager to load the wizard. When you use
the wizard as an add-in, Visual Basic assumes that you want to work with the project you
currently have open. If you want to work with another project, you must either open that project
before starting the add-in, or use the wizard as a stand-alone component.
• You can run it as a stand-alone component from outside the development environment. When
you run the wizard as a stand-alone component, you are prompted to choose the project on which
you want to work.
• You can start it in silent mode by launching it from a command prompt. See "Running the
Wizard in Silent Mode" in this topic for more information.
After you start the wizard, a series of screens prompt you for information about your
project and let you choose options for the package. Each screen explains how it is to be
used, including which information is optional, and what information must be entered
Note You should save and compile your project before running the Package and
Deployment Wizard.
In most cases, the Package and Deployment Wizard is all you need to create a package
that is ready for deployment. However, if you want to customize your packaging process
further or provide functionality not supported by the Package and Deployment Wizard,
you can modify the Setup Toolkit Project.
To start the Package and Deployment Wizard from within Visual Basic
1. Open the project you want to package or deploy using the wizard.
Note If you are working in a project group or have multiple projects loaded,
make sure that the project you want to package or deploy is the current project
before starting the wizard.
2. Use the Add-In Manager to load the Package and Deployment Wizard, if necessary: Select Add-
In Manager from the Add-Ins menu, select Package and Deployment Wizard from the list,
then click OK.
3. Select Package and Deployment Wizard from the Add-Ins menu to launch the wizard.
• If you want to create a standard package, Internet package, or dependency file for the
project, click Package.
For an introduction to these options, see "The Package and Deployment Wizard."
5. Proceed through the wizard screens.
2. Click the Start button, and then click Package and Deployment Wizard from the Visual Basic
submenu.
3. In the Project list on the initial screen, choose the project you want to package.
Note You can click Browse if your project is not in the list.
4. On the main screen, select one of the following options:
Silent mode is especially useful if you are packaging and deploying as part of a batch
process. For example, early in the development of your project, you may use the Package
and Deployment Wizard to package your project and deploy it to a test location. You can
later create a batch file to perform the same packaging and deployment steps periodically
as you update your project.
2. Type the name of the wizard executable, pdcmdln.exe, followed by the path and file name of your
Visual Basic project, and the appropriate command line arguments, as shown in the following
example:
3. PDCmdLn.exe C:\Project1\Project1.vbp /p "Internet Package"
4. /d Deployment1 /l "C:\Project1\Silent Mode.log"
Note You can perform packaging and deployment in a single silent session by
specifying both the /p and the /d arguments, as shown in the example above.
Otherwise, use either /p or /d.
Argument Description
/p packagingscript Type /p followed by the name of a previously saved packaging
script to package the project silently according to the specified
script.
/d deploymentscript Type /d followed by the name of a previously saved deployment
script to deploy the project silently according to the specified
script.
/l path Specifies that the wizard should store all output from the wizard,
such as error messages and success reports, to a file rather than
displaying them on the screen.
Type /l followed by the path and file name of a file in
which output should be stored. If the file does not exist,
the wizard creates it.
Note Any file or script name that includes spaces should be enclosed in quotation marks,
as shown in the example above.
You can combine variables of several different types to create user-defined types (known
as structs in the C programming language). User-defined types are useful when you want
to create a single variable that records several related pieces of information.
You create a user-defined type with the Type statement, which must be placed in the
Declarations section of a module. User-defined types can be declared as Private or Public
with the appropriate keyword. For example:
Private Type MyDataType
-or-
Public Type MyDataType
For example, you could create a user-defined type that records information about a
computer system:
' Declarations (of a standard module).
Private Type SystemInfo
CPU As Variant
Memory As Long
VideoColors As Integer
Cost As Currency
PurchaseDate As Variant
End Type
Declaring Variables of a User-Defined Type
You can declare local, private module-level, or public module-level variables of the same
user-defined type:
Dim MySystem As SystemInfo, YourSystem As SystemInfo
Note If declared using the Dim keyword, user-defined types in Standard or Class
modules will default to Public. If you intend a user-defined type to be private, make sure
you declare it using the Private keyword.
Assigning and Retrieving Values
Assigning and retrieving values from the elements of this variable is similar to setting and
getting properties:
MySystem.CPU = "486"
If MySystem.PurchaseDate > #1/1/92# Then
You can also assign one variable to another if they are both of the same user-defined type.
This assigns all the elements of one variable to the same elements in the other variable.
YourSystem = MySystem
User-Defined Types that Contain Arrays
A user-defined type can contain an ordinary (fixed-size) array. For example:
Type SystemInfo
CPU As Variant
Memory As Long
DiskDrives(25) As String ' Fixed-size array.
VideoColors As Integer
Cost As Currency
PurchaseDate As Variant
End Type
It can also contain a dynamic array.
Type SystemInfo
CPU As Variant
Memory As Long
DiskDrives() As String ' Dynamic array.
VideoColors As Integer
Cost As Currency
PurchaseDate As Variant
End Type
You can access the values in an array within a user-defined type in the same way that you
access the property of an object.
Dim MySystem As SystemInfo
ReDim MySystem.DiskDrives(3)
MySystem.DiskDrives(0) = "1.44 MB"
You can return user-defined types from functions, and you can pass a user-defined type
variable to a procedure as one of the arguments. User-defined types are always passed by
reference, so the procedure can modify the argument and return it to the calling
procedure, as illustrated in the previous example.
Note Because user-defined types are always passed by reference, all of the data
contained in the user-defined type will be passed to and returned from the procedure. For
user-defined types that contain large arrays, this could result in poor performance,
especially in client/server applications where a procedure may be running on a remote
machine. In such a situation, it is better to extract and pass only the necessary data from
the user-defined type.
For More Information To read more about passing by reference, see "Passing
Arguments to Procedures" in "Programming Fundamentals."
User-Defined Types that Contain Objects
User-defined types can also contain objects.
Private Type AccountPack
frmInput as Form
dbPayRollAccount as Database
End Type
Because the Variant data type can store many different types of data, a Variant array can
be used in many situations where you might expect to use a user-defined type. A Variant
array is actually more flexible than a user-defined type, because you can change the type of
data you store in each element at any time, and you can make the array dynamic so that
you can change its size as necessary. However, a Variant array always uses more memory
than an equivalent user-defined type.
Type SystemInfo
CPU As Variant
Memory As Long
DiskDrives(26) As DriveInfo
Cost As Currency
PurchaseDate As Variant
End Type
The Setup Toolkit is a project installed with Visual Basic that is used by the Package and
Deployment Wizard when it creates a setup program. The Setup Toolkit project contains
the forms and code that the application's setup program uses to install files onto the user's
computer. When you use the Package and Deployment Wizard, the wizard includes the
setup1.exe file that the Setup Toolkit project creates. This file is used as the application's
main installation file.
Note There are two setup programs involved in the installation process — setup.exe and
setup1.exe. The setup.exe program performs pre-installation processing on the user's
computer, including installing the setup1.exe program and any other files needed for the
main installation program to run. Only setup1.exe is customizable through the Setup
Toolkit.
In addition to playing a supporting role in the process of creating a setup program, the
Setup Toolkit can be used to modify the screens seen in the installation process, or to
create a setup program directly. You might create a custom setup program if you need to
add additional functionality not supported by the wizard to your installation sequence.
Caution The files in this project are the same files used by the output of the Package and
Deployment Wizard. Do not modify them without making a backup copy in another
You use the Setup Toolkit by loading the Setup1.vbp file into Visual Basic and making
modifications to the appearance or functionality of the project. In doing so, you may need
to manually go through the steps that the Package and Deployment Wizard would
otherwise do for you. The following sections describe steps in the process and explain
how to determine which files you need to include in your setup, how to create a Setup.lst,
how to create distribution media, and how to test your setup.
Overall Steps to Modify the Package and Deployment Wizard
When you modify the Setup Toolkit with the intention of changing the output created by
the Package and Deployment Wizard, you follow these steps:
1. Modify the Setup Toolkit project to contain any new prompts, screens, functions, code, or other
information you want to include. When you are finished, compile the project to create setup1.exe.
2. Run the Package and Deployment Wizard, following the prompts on each screen, to create your
distribution media.
Overall Steps to Create a Custom Setup Program
When you create a setup program manually using the Setup Toolkit rather than the
Package and Deployment Wizard, you must follow these steps:
1. If necessary, modify the Setup Toolkit project to contain any new prompts, screens, functions,
code, or other information you want to include.
2. Determine the files you want to distribute, including all run-time, setup, and dependency files.
4. Manually create your Setup.lst file to reflect the names and installation locations of all files that
must be included for your project.
6. Create the .cab files for your project using the Makecab utility.
You can use the Package and Deployment Wizard to create your .cab files, then modify
the .cab files manually. When the wizard creates your .cab files, it creates a .ddf file and a
batch file in the \Support subdirectory of your project directory. To modify the .cab files,
edit the .ddf file, then run the batch file provided. The batch file in turn will run
Makecab.exe to recreate your .cab files.
7. Create the setup1.exe for your project by compiling the Setup Toolkit project with your changes.
8. Copy your files to the distribution media, or manually publish your files to the Web site using the
Web Publishing Wizard, available in the ActiveX SDK.
Any SQL statement can include multiple SELECT statements or stored procedures that
invoke one or more SELECT statements. Each SELECT statement generates a result set
that must be processed by your code or discarded before the RDO resources are released
and the next result set is made available.
Action queries also generate row-less result sets that must also be processed — this is
another type of multiple result set query. In many cases, when you execute a stored
procedure, it might return more than one result set. It is often difficult to determine if a
stored procedure will return more than one result set because a stored procedure might
call another procedure.
For example, if you submit a query that includes four SELECT queries to populate four
local ListBox controls and a stored procedure that updates a table, your code must deal
with at least five result sets. Because you might not know how many result sets can be
generated by a stored procedure, your code must be prepared to process n sets of results.
There are two approaches to executing queries with multiple result sets:
• Execute the OpenResultset method directly against a connection.
Both are processed in similar ways, but if you use the rdoQuery, you can examine the
RowsAffected property to determine the number of rows affected by action queries. While
it is possible to execute a multiple result set query using the Execute method, it is not
possible to retrieve the rows affected from individual statements, and a trappable error
results if any of the queries returns rows.
Using Server-Side Cursor Libraries with Multiple Result Sets
Not all cursor drivers support the ability to process queries that contain more than one set
of results — the SQL Server server-side cursor driver is an example. However, if you
request a cursorless result set by using the rdOpenForwardOnly, rdConcurReadOnly
options and by setting the RowsetSize property to 1, you can execute queries with
multiple result sets using server-side cursors. You can also set these options for all result
sets by setting the CursorDriver property to rdUseNone.
Whenever you use the concatenation operator "&" to build SQL queries, be sure to
include white space (such as spaces or tabs) between the operators on separate lines.
1. Create your SQL statement and place it in a string variable — for instance, MySQL. For SQL
Server, multiple statements must be separated by semi-colons.
2. Dim MySQL As String
3. MySQL = "Select Name from Authors Where ID = 5; " _
4. & " Select City from Publishers; " _
5. & " Update MyTable " _
6. & " Set Age = 18 Where Name = 'Fred'"
7. Next, create a new rdoQuery and set a variable declared as rdoQuery and multiple result sets to
this object — in this case, MyQy. The example assumes an rdoConnection object (Cn) already
exists. There are a number of other ways to instantiate and initialize rdoQuery objects; this
example illustrates only one of these ways.
8. Dim MyQy As rdoQuery
9. Set MyQy = Cn.CreateQuery("MyQy1", "")
10. MyQy.SQL = MySQL
11. Execute the query by using the OpenResultset method against the rdoQuery object. If you do not
need the extra properties and the ability to pass parameters to the query, you can use the
OpenResultset method directly against the rdoConnection object. The arguments you use here
affect all result sets fetched from this query. For example, if you need to use a cursor on the
second result set, you must specify a cursor type when the first result set is opened.
12. Dim MyRs As rdoResultset
13. Set MyRs = MyQy.OpenResultset(rdOpenForwardOnly, _
14. rdConcurReadOnly)
15. You are now ready to process the first result set. Note that the rdAsyncEnable options argument
was not set. Because of this, control is not returned to the application until the first row of the
first result set is ready for processing. If the current rdoResultset contains rows, the RowCount
property is set to a value > 0, and the EOF and BOF properties are both False. If no rows were
returned, the RowCount property returns either –1 to indicate that the number of rows is not
available, or 0, depending on the driver and data source.
The following example fills a ListBox control called NameList1 with the results of
the query.
While Not MyRs.EOF ' Loop through all rows.
' Use the first column.
NameList1.AddItem = MyRs(0)
MyRs.MoveNext ' Position to the next row
' in the result set.
Wend
16. The first result set is now at end-of-file (MyRs.EOF = True). Use the MoreResults method to
activate the next result set. Once you execute MoreResults, the first set of rows is no longer
available — even if you used one of the cursor options to create it.
17. ' Activate the next set of results.
18. If (MyRs.MoreResults) Then ...
The TabStrip control is used to create dialog boxes which contain a number of tabs. Each
tab usually has some relationship to a larger theme, and is therefore related to other tabs in
the same dialog box. In this scenario, we create a tabbed dialog box which sets the fonts,
and indents of a RichTextBox.
5. Use the Move method in the Load event to position the Frame controls.
6. In the TabStrip control's Click event, use the SelectedItem property to determine the Index of the
clicked Tab.
7. Use the Index with the ZOrder method to bring the right Frame to the front.
Create two Forms, One Named "frmRTF" to Contain the RichTextbox, and a Second
Named "frmTab" to Contain the TabStrip Control
This scenario requires two forms: the first is named "frmRTF," and contains the
RichTextBox control, the second, named "frmTab", contains the TabStrip control.
2. Double-click the Standard EXE Project icon, and a new form named Form1 will be created for
you.
Note You must have the RichTextBox (RichTx32.ocx) loaded into the Toolbox.
See "Loading ActiveX Controls" for more information.
6. On the Properties page window, click the Name box and type "rtfData"
8. Double-click the Form icon to insert another form into the project.
9. On the Properties window, click the name box and type "frmTab."
You must also have some code that shows the second form. A quick way to do this would
be to place a Show method in the DblClick event of the first Form object (frmRTF), as
shown below:
Private Sub Form_DblClick()
frmTab.Show
End Sub
At Design time, Create Two Tab Objects on the TabStrip Control
You can create Tab objects at design time and at run time. In this scenario, you should
create the two tabs at design time. Right-click on the TabStrip control and click Properties
to display the Property Pages dialog box. Then click the Tabs tab and click Insert Tab
twice. Be sure to give the tabs appropriate captions — "Fonts," and "Indents."
Create a Control Array Named "fraTab" on frmTab
A TabStrip control functions by managing Tab objects. Each Tab object is associated with
a container control that appears in the tab's client area. It's most efficient to use a control
array to create the container controls. In this scenario, draw a Frame control on the same
form as the TabStrip control, and name it "fraTab."
2. Click the Name box on the Properties window and type "fraTab."
3. Click the Frame control and copy it to the clipboard by either pressing CTRL+C or clicking
Copy from the Edit menu.
4. Paste the same control back on the form by pressing CTRL+V. A dialog box will ask you if you
want to create a control array. Click Yes.
Draw the ComboBox on fraTab(0) and Two OptionButton controls on fraTab(1)
On the control named fraTab(0), draw a ComboBox control, and name it "cmbFonts." To
populate the ComboBox with all available fonts on your system, use the following code:
Private Sub Form_Load()
Dim i ' Declare variable.
' Determine number of fonts.
For i = 0 To Printer.FontCount - 1
' Put each font into list box.
cmbFonts.AddItem Printer.Fonts(I)
cmbFonts.ListIndex = 0
End Sub
Because they're visible to the user, forms and controls have a different life cycle than other
objects. For example, a form will not close just because you've released all your references
to it. Visual Basic maintains a global collection of all forms in your project, and only
removes a form from that collection when you unload the form.
In similar fashion, Visual Basic maintains a collection of controls on each form. You can
load and unload controls from control arrays, but simply releasing all references to a
control is not sufficient to destroy it.
For More Information The Forms and Controls collections are discussed in
"Collections in Visual Basic" earlier in this chapter.
States a Visual Basic Form Passes Through
A Visual Basic form normally passes through four states in its lifetime:
1. Created, but not loaded.
3. Shown.
There's a fifth state a form can get into under certain circumstances: Unloaded and
unreferenced while a control is still referenced.
This topic describes these states, and the transitions between them.
Created, But Not Loaded
The beginning of this state is marked by the Initialize event. Code you place in the
Form_Initialize event procedure is therefore the first code that gets executed when a form
is created.
In this state, the form exists as an object, but it has no window. None of its controls exist
yet. A form always passes through this state, although its stay there may be brief.
For example, if you execute Form1.Show, the form will be created, and Form_Initialize will
execute; as soon as Form_Initialize is complete, the form will be loaded, which is the next
state.
Note You can cause your form to load from within Form_Initialize, by calling its Show
method or by invoking its built-in properties and methods, as described below.
Remaining Created, But Not Loaded
By contrast, the following code creates an instance of Form1 without advancing the form
to the loaded state:
Dim frm As Form1
Set frm = New Form1
Once Form_Initialize has ended, the only procedures you can execute without forcing the
form to load are Sub, Function, and Property procedures you've added to the form's code
window. For example, you might add the following method to Form1:
Public Sub ANewMethod()
Debug.Print "Executing ANewMethod"
End Sub
You could call this method using the variable frm (that is, frm.ANewMethod) without forcing
the form on to the next state. In similar fashion, you could call ANewMethod in order to
create the form:
Dim frm As New Form1
frm.ANewMethod
Because frm is declared As New, the form is not created until the first time the variable is
used in code — in this case, when ANewMethod is invoked. After the code above is
executed, the form remains created, but not loaded.
Note Executing Form1.ANewMethod, without declaring a form variable, has the same effect
as the example above. As explained in "Customizing Form Classes," Visual Basic creates a
hidden global variable for each form class. This variable has the same name as the class;
it's as though Visual Basic had declared Public Form1 As New Form1.
You can execute as many custom properties and methods as you like without forcing the
form to load. However, the moment you access one of the form's built-in properties, or
any control on the form, the form enters the next state.
Note You may find it helpful to think of a form as having two parts, a code part and a
visual part. Before the form is loaded, only the code part is in memory. You can call as
many procedures as you like in the code part without loading the visual part of the form.
The Only State All Forms Pass Through
Created, But Not Loaded is the only state all forms pass through. If the variable frm in the
examples above is set to Nothing, as shown here, the form will be destroyed before
entering the next state:
When the Form_Load event procedure begins, the controls on the form have all been
created and loaded, and the form has a window — complete with window handle (hWnd)
and device context (hDC) — although that window has not yet been shown.
Many forms pass automatically from the Created, But Not Loaded state into the Loaded,
but Not Shown state. A form will be loaded automatically if:
• The form has been specified as the Startup Object, on the General tab of the Project Properties
dialog box.
• The Show method is the first property or method of the form to be invoked, as for example
Form1.Show.
• The first property or method of the form to be invoked is one of the form's built-in members, as
for example the Move method.
Note This case includes any controls on the form, because each control defines a
property of the form; that is, in order to access the Caption property of
Command1, you must go through the form's Command1 property:
Command1.Caption.
• The Load statement is used to load the form, without first using New or As New to create the
form, as described earlier.
It has long been common coding practice in Visual Basic to load a form but never show it.
This might be done for several reasons:
• To use the Timer control to generate timed events.
• To use controls for their functionality, rather than their user interface — for example, for serial
communications or access to the file system.
Note With the Professional or Enterprise edition, you can create ActiveX components
(formerly called OLE servers), which are often better at providing code-only functionality
than controls are. See Creating ActiveX Components in the Component Tools Guide.
Always Coming Home
Forms return from the visible state to the loaded state whenever they're hidden. Returning
to the loaded state does not re-execute the Load event, however. Form_Load is executed
only once in a form's life.
Shown
Once a form becomes visible, the user can interact with it. Thereafter, the form may be
hidden and shown as many times as you like before finally being unloaded.
Interlude: Preparing to Unload
A form may be either hidden or visible when it's unloaded. If not explicitly hidden, it
remains visible until unloaded.
The last event the form gets before unloading is the Unload event. Before this event
occurs, however, you get a very important event called QueryUnload. QueryUnload is
your chance to stop the form from unloading. If there's data the user might like to save,
this is the time to prompt the user to save or discard changes.
Important Setting the Cancel argument of the QueryUnload to True will stop the form
from unloading, negating an Unload statement.
One of most powerful features of this event is that it tells you how the impending unload
was caused: By the user clicking the Close button; by your program executing the Unload
statement; by the application closing; or by Windows closing. Thus QueryUnload allows
you to offer the user a chance to cancel closing the form, while still letting you close the
form from code when you need to.
Important Under certain circumstances, a form will not receive a QueryUnload event: If
you use the End statement to terminate your program, or if you click the End button (or
select End from the Run menu) in the development environment.
If you kept a reference to the form in a variable somewhere, such as the hidden global
variable described in "Customizing Form Classes," then the form returns to the Created,
But Not Loaded state. The form no longer has a window, and its controls no longer exist.
You can use that reference you've been keeping to call the methods and properties that
you added to the form, but if you invoke the form's built-in members, or access its
controls, the form will load again, and Form_Load will execute.
Memory and Resources Completely Reclaimed
The only way to release all memory and resources is to unload the form and then set all
references to Nothing. The reference most commonly overlooked when doing this is the
hidden global variable mentioned earlier. If at any time you have referred to the form by its
class name (as shown in the Properties Window by the Name property), you've used the
hidden global variable. To free the form's memory, you must set this variable to Nothing.
For example:
Set Form1 = Nothing
Your form will receive its Terminate event just before it is destroyed.
Tip Many professional programmers avoid the use of the hidden global variable,
preferring to declare their own form variables (for example, Dim dlgAbout As New
frmAboutBox) to manage form lifetime.
Note Executing the End statement unloads all forms and sets all object variables in your
program to Nothing. However, this is a very abrupt way to terminate your program. None
of your forms will get their QueryUnload, Unload, or Terminate events, and objects
you've created will not get their Terminate events.
Unloaded and Unreferenced, But a Control Is Still Referenced
To get into this odd state, you have to unload and free the form while keeping a reference
to one of its controls. If this sounds like a silly thing to do, rest assured that it is.
Dim frm As New Form1
Dim obj As Object
frm.Show vbModal
' When the modal form is dismissed, save a
' reference to one of its controls.
Set obj = frm.Command1
Unload frm
Set frm = Nothing
The form has been unloaded, and all references to it released. However, you still have a
reference to one of its controls, and this will keep the code part of the form from releasing
the memory it's using. If you invoke any of the properties or methods of this control, the
form will be reloaded:
obj.Caption = "Back to life"
The values in module-level variables will still be preserved, but the property values of all
the controls will be set back to their defaults, as if the form were being loaded for the first
time. Form_Load will execute.
Note Not all forms behave as Visual Basic forms do. For example, the Microsoft Forms
provided in Microsoft Office don't have Load and Unload events; when these forms
receive their Initialize events, all their controls exist and are ready to use.
For More Information Forms are discussed in "Designing a Form" in "Forms, Controls,
and Menus" and in "More About Forms" in "Creating a User Interface."
Data Limitations
If you define a procedure that has more than 64K of local variables defined, you get the
error "Too many local nonstatic variables."
If you define a module that has more than 64K of module-level variables defined, or if you
define a User-Defined Type larger than 64K, you get the error "Fixed or static data can't
be larger than 64K."
If you encounter this error, you can avoid it by breaking extremely large procedures into
several smaller procedures, or by moving module-level declarations into another module.
An array declared as a variable doesn't contribute to the entire size of the array; only the
array descriptor counts toward the 64K limit. So it is acceptable, for example, to have a
declaration such as Dim x(1000000) As Byte either in a procedure or at module level. Out of
memory problems occur, however, if you declare a large, fixed-size array in a record, then
declare instances of those records as variables.
Visual Basic itself uses some of the stack for its own purposes, such as storing
intermediate values when evaluating expressions.
Total available stack size for Visual Basic is one megabyte (1MB) per thread. A stack may
grow beyond this, however, if there is adjacent free memory.
Visual Basic Concepts
• When the program halts, test the values of important variables and properties. Use Quick Watch
or set watch expressions to monitor these values. Use the Immediate window to examine
variables and expressions.
• Use the Break on All Errors option to determine where an error occurred. To temporarily change
this option, select Toggle from the Code window context menu, then toggle the option from the
submenu. Step through your code, using watch expressions and the Locals window to monitor
how values change as the code runs.
• If an error occurs in a loop, define a break expression to determine where the problem occurs.
Use the Immediate window together with Set Next Statement to re-execute the loop after making
corrections.
• If you determine that a variable or property is causing problems in your application, use a
Debug.Assert statement to halt execution when the wrong value is assigned to the variable or
property.
• To set the error trapping state that Visual Basic defaults to at the beginning of any debugging
session, open the Options dialog box (available from the Tools menu), select the General tab, and
Occasionally you may encounter a bug that’s especially difficult to track down. Don’t
panic – here are some things that you can do:
• First and foremost, make a backup. This is the point at which even experienced programmers
frequently lose many hours of work. When you experiment, it is far too easy to accidentally
overwrite or delete necessary sections of code.
• Use the debugging facilities built in to Visual Basic. Attempt to identify the line or lines of code
generating the error. Isolate the code. If you can isolate the problem to one block of code, try to
reproduce the same problem with this block of code separated from the rest of your program.
Select the code, copy it, start a new project, paste the code into the new project, run the new
project, and see if the error still occurs.
• Create a log file. If you cannot isolate the code or if the problem is erratic or if the problem only
happens when compiled, then the debugging facility of Visual Basic will be less effective. In
these situations you can create a log file which records the activity of your program. This will
allow you to progressively isolate the location of the suspect code. Call the following procedure
from various points in your program. You should pass in a string of text which indicates the
current location of the code executing in your program.
• Sub LogFile (Message As String)
• Dim LogFile As Integer
• LogFile = FreeFile
• Open "C:\VB\LogFile.Log" For Append As #LogFile
• Print #LogFile, Message
• Close #LogFile
• End Sub
•
• Sub Sub1 ()
• '...
• Call LogFile("Here I am in Sub1")
• '...
• End Sub
• Simplify the problem. If possible, remove any third party controls and custom controls from your
project. Replace them with Visual Basic standard controls. Eliminate any code that does not seem
to relate to the problem.
• Reduce the search space. If you cannot resolve the problem with any of the above methods, then
it is time to eliminate all other non-Visual Basic causes from the problem search space. Copy
your AUTOEXEC.BAT and CONFIG.SYS files to backup files. Comment out any and all drivers
and programs from these two files that are not absolutely essential to running your program
under Windows. Change your Windows video driver to the standard Windows VGA driver. Shut
down Windows and reboot your machine. This will eliminate the possibility that there is some
other program or driver which is interfering with your program.
• If you cannot locate a solution and are unable to isolate or resolve the problem with any of these
methods, it's time to look for help. See the technical support documentation.
The way you handle focus for your control depends on which model you're using to
develop your control. Models for building ActiveX controls are discussed in "Three Ways
to Build ActiveX Controls," earlier in this chapter.
Important If you're authoring a control that can be a container for other controls, as
described in "Allowing Developers to Put Controls on Your Control," note that the
material in this topic does not apply to controls a developer places on an instance of your
control. These contained controls will receive focus independent of your control and its
constituent controls.
User-Drawn Controls
If you're authoring a user-drawn control, there won't be any constituent controls on your
UserControl. If you don't want your control to be able to receive the focus, set the
CanGetFocus property of the UserControl object to False. CanGetFocus is True by
default.
If your user-drawn control can receive the focus, the UserControl object will receive
GotFocus and LostFocus events when your control receives and loses the focus. A user-
drawn control is responsible for drawing its own focus rectangle when it has the focus, as
described in "User-Drawn Controls," in this chapter.
This is the only function your UserControl's GotFocus and LostFocus events need to fulfill
for a user-drawn control. You don't need to raise GotFocus or LostFocus events for the
user of your control, because the container's extender provides these events if the
CanGetFocus property is True.
Note The UserControl object of a user-drawn control will also receive a EnterFocus
event prior to GotFocus, and an ExitFocus event after LostFocus. You don't need to put
any code in the event procedures of these event, and in fact it is recommended that you
not do so.
User-drawn controls can respond to access keys, as described later in this topic.
Controls That Use Constituent Controls
If you're authoring a control that enhances a single constituent control, or is an assembly
of constituent controls, your UserControl object will be unable to receive the focus,
If no constituent controls can receive the focus, and CanGetFocus is True, then your
UserControl object will receive the same events a user-drawn control receives. The only
thing you need to do with these events is provide a visual indication that your control has
the focus.
How Constituent Controls Are Affected by CanGetFocus
If your control contains at least one constituent control that can receive the focus, the
CanGetFocus property of the UserControl object must be set to True. If you attempt to
set CanGetFocus to False on a UserControl that has constituent controls that can receive
focus, an error will occur.
Visual Basic will not allow a constituent control that can receive focus to be placed on a
UserControl whose CanGetFocus property is False: Icons of controls that can receive
focus are disabled in the Toolbox when the UserControl's design window is active.
EnterFocus and ExitFocus
When the focus moves from outside your control to any of your control's constituent
controls, the UserControl object will receive an EnterFocus event. The GotFocus event
for the constituent control that receives the focus will be raised after the
UserControl_EnterFocus event procedure.
As long as the focus remains within your control, the UserControl object's focus-related
events will not be raised. As the focus moves from one constituent control to another,
however, the appropriate GotFocus and LostFocus events of the constituent controls will
be raised.
When the focus moves back outside your control, the last constituent control that had the
focus will receive its LostFocus event. When the event procedure returns, the UserControl
object will receive its ExitFocus event.
You can use the EnterFocus event to change which constituent control receives the focus.
You may wish to do this in order to restore the focus to the constituent control that last
had it, rather than simply allowing the first constituent control in your UserControl's tab
order to receive the focus, which is the default behavior.
Tip If your control is complex — as for example an Address control with multiple
constituent controls — you may be tempted to validate the data in the ExitFocus event.
Don't. The user of your control can put code in the Validate event of the user control to
handle data validation as they see fit. If it's absolutely necessary to validate data inside the
control, use the Validate events in combination with the CausesValidation properties of
the constituent controls. Be aware that you can't always count on the Validate event for
constituent controls, as is discussed in "Handling the Validate Event" below.
"Allowing Developers to Set Access Keys for Your Control," later in this chapter,
discusses how you can give the user of your control the ability to set access keys on
instances of your control.
Forwarding Focus to the Next Control in the Tab Order
If your control cannot receive the focus itself, and has no constituent controls that can
receive the focus, you can give your control the same behavior displayed by Label
controls. That is, when the access key for your control is pressed, the focus is forwarded
to the next control in the tab order.
To enable this behavior, set the ForwardFocus property of the UserControl object to
True.
Handling the Validate Event
The Validate event and CausesValidation property for a user control behave exactly like
they do for any other control, but the behavior of Validate and CausesValidation for
constituent controls may not yield the expected results. Let's review the standard behavior.
When a control loses focus, its Validation event is fired before its LostFocus event — but
only if the control about to receive the focus has its CausesValidation property set to
True. This allows you to handle data validation before the control loses focus.
A user control exposes a Validate event and, via the Extender object, exposes a
CausesValidation property. Code in the Validate event is executed when the focus is
shifted from the user control to any control that had its CausesValidation property set to
True; setting the CausesValidation property of the user control to True will enable the
Validation event for any control passing focus to the user control.
The Validate event and CausesValidation property for constituent controls work as
expected as long as the focus remains inside the user control. When the focus is shifted
outside of the user control, the Validate event for the constituent control isn't fired. For
that reason, it's best to avoid trying to handle validation within a user control.
When you define an input mask using the Mask property, each character position in the
MaskedEdit control maps to a placeholder of a specified type, or to a literal character.
Literal characters, or literals, give visual cues about the type of data being used. For
example, the parentheses surrounding the area code of a telephone number are literals:
(206).
The input mask prevents users from entering invalid characters into the control. If the user
attempts to enter a character that conflicts with the input mask, the control generates a
ValidationError event.
The MaskedEdit control is a bound control and can be used with a data control to display
or update field values in a data set.
Possible Uses
• To prompt for date/time, number, or currency information.
• To prompt for custom mask formats such as a telephone number or any other input that follows a
pattern.
• To work with a data control to display and update field values in a data set.
The Mask Property
The Mask property determines the type of information that is input into the MaskedEdit
control. The Mask property uses characters such as the pound sign (#), backslash (\),
comma (,), and ampersand (&) as placeholders that define the type of input. The following
table lists all the characters you can use to set the Mask property:
Mask Description
character
# Digit placeholder.
. Decimal placeholder. The actual character used is the one specified as the decimal
placeholder in your international settings. This character is treated as a literal for
masking purposes.
, Thousands separator. The actual character used is the one specified as the thousands
separator in your international settings. This character is treated as a literal for
masking purposes.
: Time separator. The actual character used is the one specified as the time separator
in your international settings. This character is treated as a literal for masking
purposes.
/ Date separator. The actual character used is the one specified as the date separator in
To create an input mask, you combine mask characters with literal characters. Literal
characters are characters which rather than representing some data type or format, are
used as themselves. For example, to create an input mask for a phone number you define
the Mask property as follows:
MaskEdBox1.Mask = (###) - ### - ####
The pound sign (a digit placeholder) is used with the left and right parentheses and the
hyphen (literal characters). At run time, the MaskedEdit control would look like the
following:
When you define an input mask, the insertion point automatically skips over literals as you
enter data or move the insertion point.
The Text and ClipText Properties
All data entered in the MaskedEdit control is contained in and can be retrieved from the
Text property. This is a run time only property and includes all the literal and prompt
characters of the input mask. For instance, retrieving data from the Text property of the
example above returns the string "(555) - 555 - 5555" – the phone number that was
entered.
The ClipText property also returns data entered in the MaskedEdit control, but without
the literal and prompt characters. Using the example above, retrieving data from the
ClipText property returns the string "5555555555". The ClipText property is available
only at run time.
You can also change the underline input character to a different character by using the
PromptChar property. For example, to change the underline (_) character to the asterisk
(*) character, you simply redefine the value of the PromptChar property:
MaskEdBox1.PromptChar = "*"
Using Mask Characters as Literals
If you want to use a mask character as a literal, you can precede the mask character with a
backslash (\). For example, if you want the pound sign (#) to display, you set the mask as
follows:
MaskEdBox1.Mask = "\##"
This would produce a mask that displays a pound sign (#) followed by a blank space for
entering a number.
The Format Property
You can modify how the MaskedEdit control is displayed and printed using the Format
property. The Format property provides you with standard formats for displaying number,
currency, and date/time information.
The following table lists the standard formats you can use with the Format property:
Data type Value Description
Number (Default) Empty string General Numeric format. Displays as entered.
Number $#,##0.00;($#,##0.00) Currency format. Uses thousands separator; displays
negative numbers enclosed in parentheses.
Number 0 Fixed number format. Displays at least one digit.
Number #,##0 Commas format. Uses commas as thousands
separator.
Number 0% Percent format. Multiplies value by 100 and appends
a percent sign.
Number 0.00E+00 Scientific format. Uses standard scientific notation.
Date/Time (Default) c General Date and Time format. Displays date ,
time, or both.
Date/Time Dddddd Long Date format. Same as the Long Date setting in
the International section of the Microsoft Windows
Control Panel. Example: Tuesday, May 26, 1992.
Date/Time dd-mmm-yy Medium Date format. Example: 26-May-92.
Date/Time Ddddd Short Date format. Same as the Short Date setting in
the International section of the Microsoft Windows
Control Panel. Example: 5/26/92.
Date/Time Ttttt Long Time format. Same as the Time setting in the
International section of the Microsoft Windows
You use the Format property with the Mask property. For example, to create a mask that
prompts for a Short Date input that displays in the Long Date format, you set the Mask
and Format properties as follows:
MaskEdBox1.Mask = "##-##-##"
MaskEdBox1.Format = "dddddd"
When the user enters the date in the short format (06-27-96, for instance), the MaskedEdit
control verifies that the entered data is valid, and then, when the focus passes to the next
control, it is displayed as "Thursday, June 27, 1996".
Note To automatically shift the focus to the next control when the data has been verified
as valid, set the AutoTab property of the MaskedEdit control to True.
The Format property also allows you to specify custom formatting using the same format
expressions defined by the Visual Basic Format function.
You enter the mask and format patterns as in the run time examples above. The Format
drop down list allows you to select any of the predefined standard formats shown above.
This dialog box also allows you to easily set such properties as PromptChar, ClipMode,
and MaxLength.
The ClipMode property specifies whether or not literal characters are included when doing
a cut or copy command. By default, when a selection in the MaskedEdit control is copied
to the Clipboard, the entire selection, including the literals, is transferred. To limit the copy
operation to only the data entered by the user, set the ClipMode property to True.
The ValidationError Event
The ValidationError event occurs when the MaskedEdit control receives invalid input, as
determined by the input mask. For example, if you've defined an input mask that prompts
for numbers, a ValidationError event will occur if the user attempts to enter a letter.
Unless you write an event handler to respond to the ValidationError event, the
Mask characters are validated as they are entered and the insertion point is shifted to the
right. When a character is entered or deleted out of sequence (when a digit is inserted or
deleted after the phone number has been entered, for example), all nonliteral characters
shift either to the right or left. When the shift occurs, if an invalid character replaces the
position of a valid character, the ValidationError event is triggered.
For example, suppose the Mask property is defined as "?###", and the current value of the
Text property is "A12." If you attempt to insert the letter "B" before the letter "A," the
"A" would shift to the right. Since the second value of the input mask requires a number,
the letter "A" would cause the control to generate a ValidationError event.
The MaskedEdit control also validates the values of the Text property at run time. If the
Text property settings conflict with the input mask, the control generates a run-time error.
You can select text in the same way you would with a standard text box control. When
selected text is deleted, the control attempts to shift the remaining characters to the right
of the selection. However, any remaining character that might cause a validation error
during this shift is deleted, and no ValidationError event is generated.
Using MaskedEdit as a Bound Control
The MaskedEdit control is a bound control. This means that it can be linked to a data
control and display field values for the current record in a data set. The MaskedEdit
control can also write out values to a data set.
Note When the value of the field referenced by the DataField property is read, it is
converted to a Text property string, if possible. If the recordset is updatable, the string is
converted to the data type of the field.
The MaskedEdit control has three bound properties: DataChanged, DataField, and
DataSource.
With rsholder
If eCurLoc = 0 Then
.CursorLocation = adUseClient
Else
.CursorLocation = eCurLoc
End If
If eCurType = 0 Then
.CursorType = adOpenStatic
Else
.CursorType = eCurType
End If
If eLockType = 0 Then
End Function
Using it is very simple. If you supply no paramters, you get a client side, static cursor with
minimal locking:
set rs = GetRSTemplate()
end sub
The function uses the same enumerated values as the recordset properties, so the choices
will pop up as they do when you type in object.property =
Determines the number of workdays within a date range.
By Bill Mosca
[email protected]
I used implicit If Statements (IIF) because they take less lines of code, and this procedure
is convoluted enough without making is bigger! In case you aren't familiar with them, they
are a hold-over from VBA. The first argument is the expression, the second is what to do
if it's true, the third is what to do if it's false.
The first part determines the number of days between 2 dates. The second part determines
the number of whole weeks because each whole week has a Saturday & a Sunday in it.
The last part determines if the range spanned a weekend but not a whole week so it can
subtract the weekend out.
Private Sub FindWorkDays()
Dim A1 As Date
Dim A2 As Date
Dim iWorkDays As Integer
A1 = Text1.Text
A2 = Text2.Text
iWorkDays = A2 - A1 + 1 - Int((A2 - A1 + 1) / 7) * 2 - _
IIf(Int((A2 - A1 + 1) / 7) = (A2 - A1 + 1) / 7, 0, _
IIf(WeekDay(A2) < WeekDay(A1), 2, 0)) - _
IIf((WeekDay(A1) = 1 Or WeekDay(A2) = 7), 1, 0)
Label1.Caption = iWorkDays
this will make the form referenced by me.hwnd transparent so that the background can be
seen but the controls can still be accessed.
Making a form stay on top.
By Nigel Pierre
[email protected]
This one is for VB programmers who enjoy VB but are new to Visual Basic.
Create a Module called ontop.bas in this module put the following constants.
command1.caption = &SetOnTop
command2.caption = &Make Normal
End Sub
lngontop = SetWindowPos =
(me.hwnd,HWND_NOTOPMOST,0,0,0,0,(SWP_NOMOVE or SWP_NOSIZE))
End Sub
The Command1 button set the Always On Top behaviour of the form, while Command2
sets it back to normal.
Number of Workdays between two dates.
By Bill Mosca.
[email protected]
After stumbling around with case statements, tons of if statements I finally found the code
to get the number of Workdays between two dates, & it only takes a few lines of code.
Anyway, here is the code that Excel uses for its NetWorkdays function, and the code i
modified to fit VB:
Excel
=A2-A1+INT((A2-A1+1)/7*2-IF(INT((A2-A1+1)/7)=(A2-A1+1/7,0,IF
WEEKDAY(A2)<WEEKDAY(A1),2,0))-IF(OR(WEEKDAY(A1)=1, pre <
lblDays.Caption="intDaysBetween" 0) 1, WeekDay(EndDate)="7)," Or IIf((WeekDay(StartDate)="1" - _
0)) 2, WeekDay(StartDate), IIf(WeekDay(EndDate) 0, 7, 1) + StartDate 7)="(EndDate" IIf(Int((EndDate 2
* 7 Int(EndDate 1 intDaysBetween Date As EndDate Dim Integer VB WEEKDAY(A2)="7),1,0)"
As you can see i had to replace all the IF's with IIf's (implicit If's). The
first part determines the number of days between the 2 dates. The next part
I have seen that many programmers face this problem and to solve this problem VB 6.0 has introduced a
Validate event also.
But as i have been using VB 4.0 from a long time i have found a simpler trick to handle this problem,
which works on VB 4.0 and VB 6.0
Place two text boxes on the form and see that the initial text property is blank.
'add code to retrieve information from the recordset and assign it to the retval
retvaltype = VarType(retval)
if retvaltype = 2 then
retval = "" ' or you could put a 0(zero) if it is a numeric field
else
reval = retval
end if
This should be done only with small amount of variables declared as variant as it take more overhead to
delcare a variant, however if you need a fast way to solve this problem it works.
How to create dll files using Visual Basic.
By Ahmed Zulfiqar.
[email protected]
Intermediate level of VB knowledge required. VB4/5/6
It is always said that the only language for creating dll is C or C++, but VB is also very powerful and easy
to use for the creation of dll files. Here is a sample of how u can create a small message dll file and then
call it in your program, the way you call windows dll.
Open a new ActiveXDll project from New Project Menu in VB. change the name of class1 to message and
set the following properties as
Properties of class Message
Name Message
DataBindingBehavior 0-VBNone
DataSourceBehavior 0-VBNone
Option Explicit
Private mess As New message
End Sub
Now write some text in description box and the title text in title text box and also choose the message type
and press the command button and u will see the appropriate message coming through the dll file.
Find the number of workdays between two dates.
By High Tree Soft - Warnsveld, The Nteherlands.
[email protected]
Like Bill Mosca, I had to find the number of workdays between two dates. This solution doesn’t have
rules, the starting day may be any day of the week. Workdays are Monday through Friday
Put two textboxes and a command button on a form, and call them;
End If
End If
'================
Dagnummer$ = ""
zat$ = ""
bij$ = ""
Dagnummer1$ = ""
Dagnummer2$ = ""
Rekendagen$ = ""
Verschil$ = ""
weken$ = ""
Overdagen$ = ""
aww$ = ""
odb$ = ""
Weekdagen$ = ""
awr$ = ""
aftel$ = ""
Werkdagen = ""
aww$ = Format$(Val(weken$) * 5)
awr$ = Format$(Val(aww$) + Val(Weekdagen$))
'========
If Val(Dagnummer2$) = 6 Then
zat$ = "-1"
Else
zat$ = "0"
End If
'==================
End Sub
This function checks the validity of a credit card number.
By James Johnston
[email protected]
Returns 'True' If the number is in a valid format.
Returns 'False' If the number is in an invalid format.
Description:
This algorithm should work with all credit cards.
If a card validates with this code it doesn't mean that the card is actually good, it just means that the
numbers are arranged in a valid format. If they don't validate then you've saved some time because you
don't have to process the card to find out that it is defiantely bad. I use this function in CGI forms that
process credit card orders.
Function CheckCard(CCNumber As String) As Boolean
Dim Counter As Integer, TmpInt As Integer
Dim Answer As Integer
Counter = 1
TmpInt = 0
Option Explicit
Dim Cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim ii As Long
Dim oo As Integer
ii = 0
' Loop for the column, we just used 25 columns for display!
For oo = 0 To 24
DBGrid1.TextMatrix(ii, oo) = rs.Fields(oo)
Next oo
ii = ii + 1
rs.MoveNext
Wend
End Sub
rs.Close
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
All entries under these three keys are started during the bootup process and your application should be
listed under one of them. The "Run" key names applications to run every time, as does the "RunServices"
key. The difference is when they start during the boot process. You probably want to use the Run key, but
you can try both and see what the difference is. The RunOnce key will run the next time Win95 starts, but
is then purged. This is a good place to put applications that complete a setup process or a cleanup.
List Box To List Box - VB5 Professional
By Peter Nunez
[email protected]
Here is another way to move data from one list box to another and back. The four buttons ( ADD, ADD
ALL, REMOVE and REMOVE ALL) are a control array and the subroutine FourButtons handles all
movements between the two list boxes. I tried to use the least amount of code. This app is an unattended
bulk printing app.
List1.AddItem List2.Text
List2.RemoveItem List2.ListIndex
End Select
Screen.MousePointer = 0
End Sub
How to write a Screen Saver.
By Bob Butler
[email protected]
The basic requirements for creating a screen saver are:
In the properties for your application set the title to:
The 'name' part will appear on the list of available screen savers in the control panel. Note that
this is not the title of the form, it is the application title and must be set in the project properties.
When you compile the program use .SCR for the extension instead of .EXE as normal. Place the
compiled code in the Windows\System directory (it can also go in Windows, but System is
preferred)
When your application starts check for a previous instance and stop if one is found:
Sub Form_Load()
If App.PrevInstance Then
Unload Me ' NEVER use END!
Exit Sub
End If
End Sub
If the screen saver is to run normally use the following to tell Windows that you are taking over as a
screen saver (this will disable ALT-TAB and CTRL-ALT-DEL and prevent more instances from
being started):
For more information, including sample code that handles password protected screen savers
check http://www.arcatapet.com/vb.html or http://www.tiac.net/users/lvasseur/
reading data from a database to display on a form is null fields.
By Martin Woodward
[email protected]
To prevent an 'invalid use of null' error occurring when reading data from a database use the following
syntax:
Text fields:
Form1.text1.text = "" & myRecordset("TextName")
Numeric fields:
Form1.Option1.Value = 0 & myRecordset("NumricField")
With nidProgramData
.cbSize = Len(nidProgramData)
.hwnd = Me.hwnd
.uId = vbNull
.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
' This is the event that will trigger when stuff happens
.uCallbackMessage = WM_MOUSEMOVE
.hIcon = Me.Icon
.szTip = "Lock Your System" & vbNullChar
End With
End Sub
' This procedure receives the callbacks from the System Tray icon.
Dim Result As Long
Dim msg As Long
' The value of X will vary depending upon the scalemode setting
If Me.ScaleMode = vbPixels Then
msg = X
Else
Case WM_LBUTTONDBLCLK
' Process double click on your icon
Case WM_RBUTTONUP
' Usually display popup menu
Case WM_MOUSEISMOVING
' Do Somthing...
End Select
Exit Sub
Form_MouseMove_err:
' Your Error handler goes here!
End Sub
When your Application executes, it will head right into the System Tray. It is up to you to program in the
context menus and to process the callback messages.
Attaching and manipulating PictureBox and TextBox on the Command
Button.
By JungHwan Kim
[email protected]
When images are needed to be inserted at the Command Button control, there are two ways.
First, the Command Button style property is set 1(Graphic) and the hape of the image can be changed
according that the user presses the mouse button up or down. However, the images should be placed at a
fixed position, and both images and texts can't be displayed. Second, we can put the PictureBox which has
the Enabled property False on the Command Button control. In this case, we can't make use of a function
of the PictureBox. That is, we can't change the BorderStyle according that the mouse pointer is in the
PictureBox or out of the PictureBox. If PostMessage Windows API is used, we can solve this problem.
Suppose there are two bitmap files, button.bmp and camera.bmp.
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Sub Timer1_Timer()
Label1.Top =3D thetop
thetop =3D thetop - 1
If thetop < -p1hgt Then
Timer1.Enabled =3D False
Txt$ =3D "Finished With Scrolling"
CurrentY =3D ScaleHeight / 2
CurrentX =3D (ScaleWidth - TextWidth(Txt$)) / 2
Print Txt$
End If
End Sub
No Listbox.ScrollPos member?
By Dave Wilson
[email protected]
Whilst working on a current project the requirement to scroll an array of listboxes simultaneously cropped
up. I was surprised to discover that there is no Listbox.ScrollPos member of the ListBox control and so
had to resort to the windows API to overcome this oversight. The results of which are included below.
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd
As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
I hope this will be of some use to somebody someday, I know that I was surprised when I discovered the
lack of a ScrollPos Member.
The "AlwaysOnTop" property.
By Joe LeVasseur
[email protected]
Simply paste the code below into the form that you need to have the "AlwaysOnTop" property. Syntax
would be like this-[FormName].AlwaysOnTop= True Note the commented code in the Resize event, the
form loses the "AlwaysOnTop" property if it is minimized. I think that under most circumstances a
"AlwaysOnTop" window would probably be a fixed dialog and therefore not minimizable. One other
caveat- this code may or may not work in the IDE. (I've seen both.)
__________snip____________________________________
Option Explicit
'------------------
' Paste this into a form and you
' will have a new property-AlwaysOnTop.
' You then can use it like any other
' property- [FormName].AlwaysOnTop= True
' Joe LeVasseur
'------------------
Private Const HWND_TOPMOST = -&H1
Private Const HWND_NOTOPMOST = -&H2
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
'------------------
Private Declare Sub SetWindowPos Lib "user32" (ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _
ByVal wFlags As Long)
'------------------
Private bOnTopState As Boolean
Public Property Let AlwaysOnTop(bState As Boolean)
Dim lFlag As Long
On Error Resume Next
If bState = True Then
lFlag = HWND_TOPMOST
Else
lFlag = HWND_NOTOPMOST
End If
bOnTopState = bState
Do
...
...
MyDynaset.MoveNext
Loop Until MyDynaset.EOF
MyDynaset.MoveLast
j = MyDynaset.RecordCount
MyDynaset.MoveFirst
For k = 1 to j
...
...
MyDynaset.MoveNext
Next
' Special Subroutine to move selected items from one listbox to another
Public Sub List_Refresh(SourceList As Control, TargetList As Control)
Dim N As Integer
Dim I As Integer
ReDim Remove(0 To SourceList.ListCount - 1) As Boolean 'Items to remove
For N = 0 To (SourceList.ListCount - 1) ' If selected, then , add to Target List
"This method is meant to work best when the multi-select feature of the listboxes is enabled"
Check a DOB against a valid age
Author: James Johnston
Email : [email protected]
Description: This function checks a DOB against a valid age.
Returns 'True' if the DOB is valid for the specified age.
Returns 'False' if the DOB is not valid for the specified age.
I've used this in CGI programs that need DOB validation.
Function CheckDOB(TestDOB As String, ValidAGE As Integer) As Boolean
Dim TmpInt As Long
End Function
Tip supplied by James Johnston [email protected]
Tells whether a number is even or odd.
Returns 'True' if even.
Returns 'False' if odd.
Function IsEven(TestInt As Integer) As Boolean
Dim TestValues As String, TmpChar As String, Answer As Integer
TestValues = "02468"
TmpChar = Right$(Trim(Str$(TestInt)), 1)
Answer = InStr(1, TestValues, TmpChar)
End Function
Tip supplied by James Johnston [email protected]
Accessing Databases
This tip is on accessing databases. For performing an operation in every record of a Table or RecordSet
(for example you could want to update some fields, or retrieve some information), generally this code is
used.
Do
...
...
MyDynaset.MoveNext
Loop Until MyDynaset.EOF
MyDynaset.MoveLast
j = MyDynaset.RecordCount
MyDynaset.MoveFirst
For k = 1 to j
...
...
MyDynaset.MoveNext
Next
you should notice is 30% speed increase from the first code. I tried this code with a MDB file with 17000
records, and with a MDB file with 500 records. They both work well. The reason? Of course because the
second code does not check the EOF condition every iteration (even if it must go to the last record and
then to the first record)! Maybe, if the recordset is small you may not notice any improvement, but in this
case, processing time is short anyway. I found this code does not improve processing time in Delphi. I
think it's because Delphi EXE is compiled and not p-code.