- Joined
- Mar 31, 2007
- Messages
- 276
- Reaction score
- 0
ABOUT TUTORIAL - PREFACE!
First, you all should know that vb6 executables and programs that you make take up alot of memory... Now people may say... so what i got 1 gig of ram! and 2.63 gigahertz! lol... you obviously dont know much if u think that... no matter how much ram or herts you got, a program which takes up alot of memory will drag your computer down, now you may also think... big deal? it will be a little slow? it is a big deal... slowness leads exceptions(errors that the program catchs) and exceptions lead to the program either shutting down, or straight up freezing. Above all that, the bigger your program is, the more memory it will take when running, and when compiling(by compiling i mean program size, whether its 70 kylobites, or 600 k/b)
BY THE WAY IM SURE SOME OF YOU ARE THINKING, YEA RIGHT, I KNOW EVERYTHING ABOUT VB... TRUST ME YOU DONT... I BEEN PROGRAMMIN VB FOR 7 YEARS, AND READ OVER 8 BOOKS ON IT, AND I STILL DONT UNDERSTAND/KNOW EVERYTHING
Did you know if u made a program that was 600 k/b i can make the same program with the same buttons and looking identical taking up only 200 k/b? lol... How? Simple, this tutorial will teach you how to fully compress and manage memory management functions that most vb programmers(not only vb6 but vb.net and vb5 as well) do not understand or maybe they do but do not bother using it. Also on the side the tutorial will teach/explain some keywords we will be using in this tutorial, so i guess you get a vocabulary lession too.
VOCABULARY TO KNOW
This tutorial will go in order, first i will start by introducing Control Creation at Runtime(CCR) to you, and giving a small example then i will give u 2 more examples, then we will move on to the API part of the tutorial, followed by the subclassing and creating functions for your controls part. and that will conclude our tutorial.
Creating controls at runtime -I
Many times we are faced with a situation where we want to create controls such as TextBox , CommandButton, Label at runtime in Visual Basic . Say u wanted to create a textBox or an array of Option Buttons but you don't know how many u might need at that point in the program . Creating controls at runtime allows you the flexibility to do this and more. You can create and use all the common controls that u see in your toolbar very easily. The first step in creating a
control at runtime involves declaring a variable which will 'hold' the control.
1. Declaration:
It is always better to declare this variable in the general declaration section of a form so that
it can be used through out the form or declare it globally in a module(.bas file), if u have a
module added to your project. A good idea here is to name the variable using standard conventions.
Using the
txt prefix for a TextBox
cmd prefix for a CommandButton
lbl prefix for a Lable
chk prefix for a CheckBox
opt prefix for an OptionButton
and so on. For e.g.
Dim txtInput
Dim cmdInput
Dim lblInput
The Next Step involves setting the variable to a particular control like TextBox or a
CommandButton
2. Preparing the variable to hold the control:
This is the most important step while creating a control at runtime. The common format for
creating a control is as follows
Set varname=frmName.Controls.Add(Control Type,Control Name,frmName)
Here varname is the variable to which you want to set the control to ,frmName is the form name to
which you want to add the control, Control Type is the type of control i.e "VB.TextBox" for a text
box,"VB.CommandButton" for a command button and so on .Control Name can be the same as the
variable name or any name.
So if u wanted to create a textbox txtInput you would have to do it this way
Set txtInput=frmTest.Controls.Add("VB.TextBox","txtInput",frmTest)
To create a CommandButton
Set cmdInput=frmTest.Controls.Add("VB.CommandButton","cmdInput",frmTest)
To create a Label
Set lblInput=frmTest.Controls.Add("VB.Label","lblInput",frmTest)
To create a CheckBox
Set chkInput=frmTest.Controls.Add("VB.CheckBox","chkInput",frmTest)
To create an OptionButton
Set optInput=frmTest.Controls.Add("VB.OptionButton","chkInput",frmTest)
Similarly you can add a ListBox,ComboBox,PictureBox etc
3. Setting the properties of the control.
Well now that you have created the control ,you want it to be displayed, visible.You will need to
set a few properties before you can display the control. The 2 most important properties are the
controlname.Left and controlname.Top properites. These 2 properties determine where your control
will be placed on the form. It is generally a very good idea to set these properties with respect
to the form on which they are present. For ex
txtInput.Left=frmTest.Left + 100Or
txtInput.Left=frmTest.Left/2
and
txtInput.Top=frmTest.Top + 100Or
txtInput.Top=frmTest.Top/2
There are 2 more properites which are equally important.They are the controlname.Width and
controlname.Height properites.
txtInput.Height=25
txtInput.Width=50
In addition you may set any properties that u might need.
4. Displaying the control.
This is the last step where you have got to set the .Visible property to true in order to display
the control.
Eg
txtInput.Visible=True
cmdInput.Visible=True
The final code should look something like this if u want to add a textbox at runtime
In the General Declaration
Dim txtInput
And in any event like the form_load event or command_click event for e.g. put this
Set txtInput=frmTest.Controls.Add("VB.TextBox","txtInput",frmTest)
txtInput.Left=frmTest.Left/2
txtInput.Top=frmTest.Top/2
txtInput.Height=25
txtInput.Width=50
txtInput.Visible=True
After you have created the controls you can use them as you use your controls normally. You can set the caption, get the text inputted just as you you would do for any control created at design time.
EXAMPLE ONE CREATING A NEW COMMAND BUTTON AT RUNTIME:
'Create a new project.
'Add a command button.
'Name the button...
' Command1(0)
'As if it were an array.
'Its sometimes easyier to create
'an aray to begin with. If you do
'be sure to delete all button except
'Command1(0).
'The Code...
Private Sub Command1_Click(Index As Integer)
Static I As Integer
I = I + 1
Load Command1(I)
Command1(I).Left = Command1(I - 1).Left + 200
Command1(I).Top = Command1(I - 1).Top + 600
Command1(I).Caption = "New Button !"
Command1(I).Visible = True
End Sub
'At runtime this will create a new
'command button.
'To add additional function you could ad
' d
'an IF statement. As follows...
Private Sub Command1_Click(Index As Integer)
On Error Goto Handler1
'Create new button
Static I As Integer
I = I + 1
Load Command(I)
Command(I).Left = 2460
Command(I).Top = 5520
Command(I).Caption = "For Real This Time" ' change the caption
Command(I).Visible = True
' Code to unload the form when the new b
' utton is clicked
If Command(1) Then
Unload Me
End If
Handler1:
End Sub
EXAMPLE TWO CREATING A RANDOM CONTROL AT RUNTIME!:
'Make a command1, try to make it smal &
' it the bottom right hand corner for best
' results.
Private WithEvents txtDynamic As TextBox
Private Sub Command1_Click()
On Error Resume Next
Dim RandomControl(1 To 18) As String
Dim i As Integer
Randomize
RandomControl(1) = "VB.TextBox"
RandomControl(2) = "VB.CommandButton"
RandomControl(3) = "VB.Shape"
RandomControl(4) = "VB.Label"
RandomControl(5) = "VB.ListBox"
RandomControl(6) = "VB.PictureBox"
RandomControl(7) = "VB.Frame"
RandomControl(8) = "VB.HScrollBar"
RandomControl(9) = "VB.VScrollBar"
RandomControl(10) = "VB.Image"
RandomControl(11) = "VB.Line"
RandomControl(12) = "VB.DirListBox"
RandomControl(13) = "VB.DriveListBox"
RandomControl(14) = "VB.FileListBox"
RandomControl(15) = "VB.Timer"
RandomControl(16) = "VB.ComboBox"
RandomControl(17) = "VB.OptionButton"
RandomControl(18) = "VB.CheckBox"
i = Int((18 * Rnd) + 1)
RandomTop = Int(Rnd * Me.Height)
RandomLeft = Int(Rnd * Me.Width)
RandomWidth = Int(Rnd * Me.Height)
RandomText = Int(Rnd * 3200)
Set RandDynamic = Controls.Add(RandomControl(i), "Rand" & RandomText)
With RandDynamic
.Visible = True
.Text = "The Unknown"
.Caption = "The Unknown"
.BackColor = vbRed
.Width = RandomWidth
.Top = RandomTop
.Left = RandomLeft
End With
End Sub
Now, alot of you may think ok, i created a control at runtime, now how do i set the code that will be executed when for instance the commandbutton i created at runtime is clicked? Well thats wat we will discuss now, before before we get to that, Lets review our API a little bit, ppl who dont know api, this is the best tutorial for you to learn from =)
What is an API???
API-stands for Application Programming Interface. If you look at the Windows System directory, typically \Windows\System under Window 95/98 and \Winnt\System32 under Windows NT, you will find a number of Dynamic Link Library (.DLL) files. These files contain functions that are used to run the windows os(operating system). These files make up the Windows API. The Windows API is a collection of routines available to the programmer. In a way, these API routines work just like Visual Basic's own internal functions. When you need to use the code in an API routine, your Visual Basic program calls that routine. When the Windows API finishes, control returns to your program so that it can continue.
Why do u need to use API???
Ever wondered how those programs got the name of your computer??,how those programs add an icon to the system tray??,how programs start as soon as windows starts??.Let's accept it ,Visual Basic has severe limitations in itself. You cannot perform the above tasks just by using plain VB.Here is where the API comes into play. So many Windows API routines exist that just about anything you can do from Windows, you can do from a Visual Basic application by calling the appropriate Windows API routine. In short "Anything any application can do ,your application can do too". You can even force a system reboot by calling the appropriate Windows API routine.
Great, Now how do I use the API???
Now Before you can use API in you application you need to define the appropriate API. For e.g. you want to force a windows logoff ,you must use the Exit Window API .The declaration for the ExitWindow API is as follows
Declare Function ExitWindows Lib "user32" Alias "ExitWindows" (ByVal dwReserved As Long, ByVal uReturnCode As Long) As Long
The function ExitWindows is defined in the user32.dll file. It requires 2 parameters ,dwReserved and uReurnCode.These 2 parameters should always be 0.
After u have declared this api function u need to call it .This is how u do it. Let's say u want to call the function when a user clicks a command button.
dim lreturn as long
Private Sub Command1_Click()
lreturn=ExitWindows(0,0)
End Sub
lreturn is the return value you get upon calling ExitWindows.If the function is successful lreturn will have a non zero value. If it fails then lreturn will have a zero value.
How can I remember all the API functions and their declarations???
You don't have to remember their declaration. Visual Studio comes with a tool called the API text viewer. You can find it in /Programs/Microsoft Visual Studio/Microsoft Visual Studio tools/API Text Viewer. All u have to do is load the win32api.txt file and voila u have all the declarations at your finger tips and all u have to do is the famous copy/paste routine.
What is a Handle???
A variable that identifies an object; an indirect reference to an operating system resource. In plain English a handle is variable of type long which uniquely identifies any object like forms,desktop,menus or in other words a handle is a unique id for each of these objects. Every window in the Windows operating system is identified by a handle. The desktop window has a handle, a Visual Basic form displayed in an application has a handle, and even the controls on a form, which are themselves actually windows, have handles. You can gather a lot of information about the windows in your application after you get the handle of the window that interests you.
In this tutorial we shall look at the various ways to get the handle of a window and hide windows using their handles. We shall use the following API's
GetActiveWindow
WindowFromPoint
GetDesktopWindow
ShowWindow
GetActiveWindow
Here is the declaration for GetActiveWindow(GAW).
Declare Function GetActiveWindow Lib "user32" () As Long
The GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue.
This might be Greek and Latin for some people .In plain English what this means is that this function will return the handle to the active window created by your application and not the window of any other application. Also this window should be capable of accepting keyboard input.
With this function declared, you can now add code to your application to call the function.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=GetActiveWindow()
End Sub
WindowFromPoint
The Declaration for WindowFromPoint(WFP).
Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
The WindowFromPoint function retrieves a handle to the window that contains the specified point. This is fairly easy to comprehend. Generally WFP is used in conjunction with another api function GetCursorPos(GCP). GCP gives us the co-ordinates of the mouse pointer at any given moment.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=WindowFromPos(125,225)
End Sub
GetDesktopWindow
The Declaration for GetDesktopWindow API is as follows
Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Long
The GetDesktopWindow API returns the handle to the desktop window. All windows which are open at any given time are CHILD windows whose parent is the Desktop Window. The function is used when for example we want a list of all windows currently running .If we GetDesktopWindow along with EnumChildWindow API we will get a list of all currently running windows.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=GetDesktopWindow()
End Sub
The GetDesktopWindow does not take any parameters.
ShowWindow
The declaration of ShowWindow is as follows
Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
The ShowWindow API is used to show/hide any window.The parameters which ShowWindow takes are the handle of the window to show/hide and the command ,0 is for hide and 1 is for show normal.
dim result as long
Private Sub Command1_Click()
result=ShowWindow(lwnhandle,0)
End Sub
The above piece of code will hide the window whose handle is lwhandle.
The SendMessage API
The SendMessage Api is one of the most powerful api functions . Before we take a look at it's uses and syntax let me give you a brief overview of how the windows os works.
The Windows Operating System is a message based operating system .By saying message based means that whenever the operating system (os) has to comunicate with applications or two applications need to communicate/send data among themselves they do so by sending messages to one another. For eg when an application is to be terminated the os sends a WM_DESTROY message to that application, also when you are adding an item to a listbox ,the application/os sends a LB_ADDSTRING message to the listbox .
While programming in VB the sendmessage api is not of much use when u want to manipulate objects controls in your own application.But say u wanted to change the title of some other application or wanted to get the text from a textbox of another application or want to terminate another application ,or set the text in a text box of another application. The uses are endless if u want to play around with your system.Also if you are planning to move over to win32 programming using c++ you just cannot escape the sendmessage api.
Let us look a the declaration of the sendmessage api
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
The SendMessage api function basically takes 4 parameters
hwnd-The handle of the window to which the message is being sent
wMsg-The message that is being sent to the window.
wParam-Parameter to be sent along with the message(depends on the message)
lParam-Parameter to be sent along with the message(depends on the message)
Example1
Let us see a practical implementation of this api . Let us assume that we want to get the *** masked text from a password textbox of a window!!! .We need to know a few things before we can do this. The first thing we need to know is the handle to the textbox window. One way of getting this is by using the windowfrompoint api.
Once we have this handle we need to send a WM_GETTEXTLENGTH message to the textbox .This message is essentially sent to query the textbox and get the length of the text string in that textbox.After we know the length of the string we have to send a WM_GETTEXT message to the textbox and the textbox will return the text as the result .This is how it is done
Along with the declaration of the sendmessage api you need to declare the 2 message constants that we are going to use
Private Const WM_GETTEXT = &HD
Private Const WM_GETTEXTLENGTH = &HE
Put the following in any event of a control .In this example we are putting it in a command click event
Private Sub command1_click()
Dim length As Long
Dim result As Long
Dim strtmp As String
length = SendMessage(hwnd, WM_GETTEXTLENGTH, ByVal 0, ByVal 0) + 1
strtmp = Space(length)
result = SendMessage(hwnd, WM_GETTEXT, ByVal length, ByVal strtmp)
End Sub
here hwnd is the handle of the password textbox.
Example 2
In this example we will try to change the title of any application ,in this case it will be a windows notepad application.
As was the case previously we have to get the handle of the notepad window .There are 2 ways to get this one is by using the windowfrompoint api and the other is by using the findwindow api.The findwindow api returns the handle of the window whose title has been specified in the function.
After we get the handle of this window we do a sendmesaage function
dim result as long
dim str1 as string
str1="tutorial"
result = SendMessage(hwnd, WM_SETTEXT, ByVal 0, ByVal str1)
Using almost the similar techniques you can also put your own text in the edit window of the notepad application.
Now that we got the API part out of the way, we may continue to figure out how to set the code that is executed when the control is used by the client... in this i will show you how to perfom this on a command button, by the way, this is called SubClassing
Put the following declarations in a .bas module, if you dont have one, make one, of course u can use ur general declarations in ur project, but i dont suggest it
To make a new module, click on new item or new, select new module
Public Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nindex As Long, ByVal dwnewlong As Long) As Long
Public Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, lParam As Long) As Long
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const GWL_WNDPROC = (-4)
Global oldWndProc As Long
The Functions SetWindowLong and CallWindowProc are used to subclass the control.
Put the following piece of code in the same event as that in which you are creating the control i.e .If you are creating the control in the form load event then put the following piece of code in that event.
oldWndProc = SetWindowLong(cmdInput.hWnd, GWL_WNDPROC, AddressOf newWndProc)
Here cmdInput is the command button which was created at runtime,newWndProc is the function which is going to handle the messages/events .
Next we write the public function in a .bas module which would process all the messages/events of the control.
Here is the function
Public Function newWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, lParam As Long) As Long
If uMsg = WM_LBUTTONDOWN Then
Form1.Text1.Text = "ok" 'the code that would have been in your msg box...
End If
newWndProc = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam)
End Function
What this function does is when the command button is clicked it prints "ok" into the textbox on form1.
So basically, say u made a command button at runtime, and when its clicked u want it to msgbox him saying ok, thats what it does, or if u want it to do something else, replace the Form1.Text1.Text = "ok" with whatever you want, remember the Form1., it is necessary most of the time.
You can modify the message i.e WM_LBUTTONDOWN to any suitable message that you wish to intercept.
Ending Notes
Now that we have gone through this tutorial, i can assure you that you are much better at visual basic 6, 5 even .NET... Now you can make a program, creating all the controls at runtime, and the code using the api statements as shown above, so ur form is blank... amazing isnt it lol, but when the form is opened, all the controls appear, TADA! u just made a 600 k/b prog into 100 k/b and it is much more optimized, remember, to make the program even better, when u dont need a control at the moment, delete it, and when its needed, create it again! the code for the control is already in the api! ahhahahaahahah!
ALSO WHEN MAKING CUSTOM CONTROLS, IN MY OPINION, THE ONLY PART THATS A TAD BIT OF A PAIN IN THE ASS, IT SETTING THEIR HEIGHT, WIDTH, AND LOCATION OF WHERE THEY ARE GOING TO BE ON THE FORM(x and y coordinates) BUT WITH THIS TIP IT WILL MAKE IT A WHOLE LOT EASIER:
in ur vb, view ur form, and put ur mouse over a spot on the form, in the top right/middle(i think) it will say two numbers like this: 1242, 8264
thats the x and y coordinates, for the height and width, make a protocol of the textbox on the form, view its properties in the properties window, and it will say its properties, or what u can do, it put all the controls on the form that ur gonna need, then type in the code to create the controls, gettin the controls x and y and height and width, then when ur ready to compile, just delete the controls, another way lol...
Need any additional help or have any questions? feel free to email me at [email protected]
EDIT NOTE: Sorry If Theres No Code TAGS Because i Copy Pasted This off Microsoft Word And I Forgot To Add The Tags
First, you all should know that vb6 executables and programs that you make take up alot of memory... Now people may say... so what i got 1 gig of ram! and 2.63 gigahertz! lol... you obviously dont know much if u think that... no matter how much ram or herts you got, a program which takes up alot of memory will drag your computer down, now you may also think... big deal? it will be a little slow? it is a big deal... slowness leads exceptions(errors that the program catchs) and exceptions lead to the program either shutting down, or straight up freezing. Above all that, the bigger your program is, the more memory it will take when running, and when compiling(by compiling i mean program size, whether its 70 kylobites, or 600 k/b)
BY THE WAY IM SURE SOME OF YOU ARE THINKING, YEA RIGHT, I KNOW EVERYTHING ABOUT VB... TRUST ME YOU DONT... I BEEN PROGRAMMIN VB FOR 7 YEARS, AND READ OVER 8 BOOKS ON IT, AND I STILL DONT UNDERSTAND/KNOW EVERYTHING
Did you know if u made a program that was 600 k/b i can make the same program with the same buttons and looking identical taking up only 200 k/b? lol... How? Simple, this tutorial will teach you how to fully compress and manage memory management functions that most vb programmers(not only vb6 but vb.net and vb5 as well) do not understand or maybe they do but do not bother using it. Also on the side the tutorial will teach/explain some keywords we will be using in this tutorial, so i guess you get a vocabulary lession too.
VOCABULARY TO KNOW
- Control - a control such as a command button
- Runtime - State when program is RUNNING(when play is pressed)
- Declare/Declaring - Setting a variables meaning/definition
- Variable - a handle for instance like Dim X As String, x is the variable
- Global - For the whole project to use
- Dim - Declaration statement, used to declare variables
- Set - Set the property of a variable(its actions/settings/or what it does)
- Property - The settings of a control or even a variable
- .BAS/Module File - File created to either hold functions or variables or both
- Static - Statically declaring an item means it will stay the same no matter what until change is requested
- For - For statement, its a loop structure... Example: For i = 0 to List1.ListCount then next line will be MSGBOX i then the next line is Next i, this will make a msg box appear for the amount of items in list1, say there are 12 items in list 1, then 12 msg boxes will appear, first saying 1, second saying 2, third saying 3 and so on.
- With - With state is so easy its hard to explain, say i write this code:
Text1.Text = "hello"
Text1.Width = 99
Text1.Text = Height
Text1.Visible = True
Text1.Multiline = True
instad of writing text1 over and over again i can simple type:
With Text1
.Text = "hello"
.Width = 00
'and so on and so forth
End With
End with statement simple says that the with statement is ending(You MUST have the end with statement) - If/End If - another looping control stucture... example:
If text1.text = "Hello" Then
msgbox "hey"
End If
End If says that the if statement has ended, its a must, the rest is self explanatory.
In an if statement you may also include Else If and Else, example:
If Text1.Text = "Hello" then
msgbox "hi"
Else If Text1.Text = "Good-Bye"
msgbox "cya later"
Else
msgbox "i do not understand, i only understand good-bye and hello!"
End If
So basically Else If is self explanatory and Else is if the If statement did not find what it was if'ing(lookin for) - Arrays - Arrays are very useful and will be used alot during this tutorial
Making an array is basically like making 10 copies of command1, Which will be
Command1(0), command1(1), Command1(2) and so on and so forth, when making a new array, default value for the array to start with is zero unless otherwise declared by the programmer.
Example: i wanna declare a integer called MYTENNUMBERS and has 10 arrays, 1 for each number
Dim MYTENNUMBERS(9) As Integer 'why 9 if i want 10? well lets count... 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 that makes 10 doesnt it =)
Now i want to assign a number to each array.
MYTENNUMBERS(0) = 12
MYTENNUMBERS(1) = 543
MYTENNUMBERS(2) = 74
MYTENNUMBERS(3) = 36
MYTENNUMBERS(4) = 74
MYTENNUMBERS(5) = 576
MYTENNUMBERS(6) = 867
MYTENNUMBERS(7) = 57
MYTENNUMBERS(8) = 98
MYTENNUMBERS(9) = 46
now if i were to type MsgBox MYTENNUMBERS(2), it would msg me saying 74
Notice how array 2 and array 4 are the same... dont worry that wont cause a problem, i coulda made all of em 10, and they would stilll be their own arrays, u can use arrays with controls too such as command buttons, go ahead try, put a cmd button on ur form, click it once just to select it, then press ctrl+ c to copy it, then press ctrl+v and vb will ask u, name take would u like to create an array, click yes, then u will have two command1 buttons Command1(0) which is the original, and Command1(1) being the newly created one, TADA!! lol
This tutorial will go in order, first i will start by introducing Control Creation at Runtime(CCR) to you, and giving a small example then i will give u 2 more examples, then we will move on to the API part of the tutorial, followed by the subclassing and creating functions for your controls part. and that will conclude our tutorial.
Creating controls at runtime -I
Many times we are faced with a situation where we want to create controls such as TextBox , CommandButton, Label at runtime in Visual Basic . Say u wanted to create a textBox or an array of Option Buttons but you don't know how many u might need at that point in the program . Creating controls at runtime allows you the flexibility to do this and more. You can create and use all the common controls that u see in your toolbar very easily. The first step in creating a
control at runtime involves declaring a variable which will 'hold' the control.
1. Declaration:
It is always better to declare this variable in the general declaration section of a form so that
it can be used through out the form or declare it globally in a module(.bas file), if u have a
module added to your project. A good idea here is to name the variable using standard conventions.
Using the
txt prefix for a TextBox
cmd prefix for a CommandButton
lbl prefix for a Lable
chk prefix for a CheckBox
opt prefix for an OptionButton
and so on. For e.g.
Dim txtInput
Dim cmdInput
Dim lblInput
The Next Step involves setting the variable to a particular control like TextBox or a
CommandButton
2. Preparing the variable to hold the control:
This is the most important step while creating a control at runtime. The common format for
creating a control is as follows
Set varname=frmName.Controls.Add(Control Type,Control Name,frmName)
Here varname is the variable to which you want to set the control to ,frmName is the form name to
which you want to add the control, Control Type is the type of control i.e "VB.TextBox" for a text
box,"VB.CommandButton" for a command button and so on .Control Name can be the same as the
variable name or any name.
So if u wanted to create a textbox txtInput you would have to do it this way
Set txtInput=frmTest.Controls.Add("VB.TextBox","txtInput",frmTest)
To create a CommandButton
Set cmdInput=frmTest.Controls.Add("VB.CommandButton","cmdInput",frmTest)
To create a Label
Set lblInput=frmTest.Controls.Add("VB.Label","lblInput",frmTest)
To create a CheckBox
Set chkInput=frmTest.Controls.Add("VB.CheckBox","chkInput",frmTest)
To create an OptionButton
Set optInput=frmTest.Controls.Add("VB.OptionButton","chkInput",frmTest)
Similarly you can add a ListBox,ComboBox,PictureBox etc
3. Setting the properties of the control.
Well now that you have created the control ,you want it to be displayed, visible.You will need to
set a few properties before you can display the control. The 2 most important properties are the
controlname.Left and controlname.Top properites. These 2 properties determine where your control
will be placed on the form. It is generally a very good idea to set these properties with respect
to the form on which they are present. For ex
txtInput.Left=frmTest.Left + 100Or
txtInput.Left=frmTest.Left/2
and
txtInput.Top=frmTest.Top + 100Or
txtInput.Top=frmTest.Top/2
There are 2 more properites which are equally important.They are the controlname.Width and
controlname.Height properites.
txtInput.Height=25
txtInput.Width=50
In addition you may set any properties that u might need.
4. Displaying the control.
This is the last step where you have got to set the .Visible property to true in order to display
the control.
Eg
txtInput.Visible=True
cmdInput.Visible=True
The final code should look something like this if u want to add a textbox at runtime
In the General Declaration
Dim txtInput
And in any event like the form_load event or command_click event for e.g. put this
Set txtInput=frmTest.Controls.Add("VB.TextBox","txtInput",frmTest)
txtInput.Left=frmTest.Left/2
txtInput.Top=frmTest.Top/2
txtInput.Height=25
txtInput.Width=50
txtInput.Visible=True
After you have created the controls you can use them as you use your controls normally. You can set the caption, get the text inputted just as you you would do for any control created at design time.
EXAMPLE ONE CREATING A NEW COMMAND BUTTON AT RUNTIME:
'Create a new project.
'Add a command button.
'Name the button...
' Command1(0)
'As if it were an array.
'Its sometimes easyier to create
'an aray to begin with. If you do
'be sure to delete all button except
'Command1(0).
'The Code...
Private Sub Command1_Click(Index As Integer)
Static I As Integer
I = I + 1
Load Command1(I)
Command1(I).Left = Command1(I - 1).Left + 200
Command1(I).Top = Command1(I - 1).Top + 600
Command1(I).Caption = "New Button !"
Command1(I).Visible = True
End Sub
'At runtime this will create a new
'command button.
'To add additional function you could ad
' d
'an IF statement. As follows...
Private Sub Command1_Click(Index As Integer)
On Error Goto Handler1
'Create new button
Static I As Integer
I = I + 1
Load Command(I)
Command(I).Left = 2460
Command(I).Top = 5520
Command(I).Caption = "For Real This Time" ' change the caption
Command(I).Visible = True
' Code to unload the form when the new b
' utton is clicked
If Command(1) Then
Unload Me
End If
Handler1:
End Sub
EXAMPLE TWO CREATING A RANDOM CONTROL AT RUNTIME!:
'Make a command1, try to make it smal &
' it the bottom right hand corner for best
' results.
Private WithEvents txtDynamic As TextBox
Private Sub Command1_Click()
On Error Resume Next
Dim RandomControl(1 To 18) As String
Dim i As Integer
Randomize
RandomControl(1) = "VB.TextBox"
RandomControl(2) = "VB.CommandButton"
RandomControl(3) = "VB.Shape"
RandomControl(4) = "VB.Label"
RandomControl(5) = "VB.ListBox"
RandomControl(6) = "VB.PictureBox"
RandomControl(7) = "VB.Frame"
RandomControl(8) = "VB.HScrollBar"
RandomControl(9) = "VB.VScrollBar"
RandomControl(10) = "VB.Image"
RandomControl(11) = "VB.Line"
RandomControl(12) = "VB.DirListBox"
RandomControl(13) = "VB.DriveListBox"
RandomControl(14) = "VB.FileListBox"
RandomControl(15) = "VB.Timer"
RandomControl(16) = "VB.ComboBox"
RandomControl(17) = "VB.OptionButton"
RandomControl(18) = "VB.CheckBox"
i = Int((18 * Rnd) + 1)
RandomTop = Int(Rnd * Me.Height)
RandomLeft = Int(Rnd * Me.Width)
RandomWidth = Int(Rnd * Me.Height)
RandomText = Int(Rnd * 3200)
Set RandDynamic = Controls.Add(RandomControl(i), "Rand" & RandomText)
With RandDynamic
.Visible = True
.Text = "The Unknown"
.Caption = "The Unknown"
.BackColor = vbRed
.Width = RandomWidth
.Top = RandomTop
.Left = RandomLeft
End With
End Sub
Now, alot of you may think ok, i created a control at runtime, now how do i set the code that will be executed when for instance the commandbutton i created at runtime is clicked? Well thats wat we will discuss now, before before we get to that, Lets review our API a little bit, ppl who dont know api, this is the best tutorial for you to learn from =)
What is an API???
API-stands for Application Programming Interface. If you look at the Windows System directory, typically \Windows\System under Window 95/98 and \Winnt\System32 under Windows NT, you will find a number of Dynamic Link Library (.DLL) files. These files contain functions that are used to run the windows os(operating system). These files make up the Windows API. The Windows API is a collection of routines available to the programmer. In a way, these API routines work just like Visual Basic's own internal functions. When you need to use the code in an API routine, your Visual Basic program calls that routine. When the Windows API finishes, control returns to your program so that it can continue.
Why do u need to use API???
Ever wondered how those programs got the name of your computer??,how those programs add an icon to the system tray??,how programs start as soon as windows starts??.Let's accept it ,Visual Basic has severe limitations in itself. You cannot perform the above tasks just by using plain VB.Here is where the API comes into play. So many Windows API routines exist that just about anything you can do from Windows, you can do from a Visual Basic application by calling the appropriate Windows API routine. In short "Anything any application can do ,your application can do too". You can even force a system reboot by calling the appropriate Windows API routine.
Great, Now how do I use the API???
Now Before you can use API in you application you need to define the appropriate API. For e.g. you want to force a windows logoff ,you must use the Exit Window API .The declaration for the ExitWindow API is as follows
Declare Function ExitWindows Lib "user32" Alias "ExitWindows" (ByVal dwReserved As Long, ByVal uReturnCode As Long) As Long
The function ExitWindows is defined in the user32.dll file. It requires 2 parameters ,dwReserved and uReurnCode.These 2 parameters should always be 0.
After u have declared this api function u need to call it .This is how u do it. Let's say u want to call the function when a user clicks a command button.
dim lreturn as long
Private Sub Command1_Click()
lreturn=ExitWindows(0,0)
End Sub
lreturn is the return value you get upon calling ExitWindows.If the function is successful lreturn will have a non zero value. If it fails then lreturn will have a zero value.
How can I remember all the API functions and their declarations???
You don't have to remember their declaration. Visual Studio comes with a tool called the API text viewer. You can find it in /Programs/Microsoft Visual Studio/Microsoft Visual Studio tools/API Text Viewer. All u have to do is load the win32api.txt file and voila u have all the declarations at your finger tips and all u have to do is the famous copy/paste routine.
What is a Handle???
A variable that identifies an object; an indirect reference to an operating system resource. In plain English a handle is variable of type long which uniquely identifies any object like forms,desktop,menus or in other words a handle is a unique id for each of these objects. Every window in the Windows operating system is identified by a handle. The desktop window has a handle, a Visual Basic form displayed in an application has a handle, and even the controls on a form, which are themselves actually windows, have handles. You can gather a lot of information about the windows in your application after you get the handle of the window that interests you.
In this tutorial we shall look at the various ways to get the handle of a window and hide windows using their handles. We shall use the following API's
GetActiveWindow
WindowFromPoint
GetDesktopWindow
ShowWindow
GetActiveWindow
Here is the declaration for GetActiveWindow(GAW).
Declare Function GetActiveWindow Lib "user32" () As Long
The GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue.
This might be Greek and Latin for some people .In plain English what this means is that this function will return the handle to the active window created by your application and not the window of any other application. Also this window should be capable of accepting keyboard input.
With this function declared, you can now add code to your application to call the function.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=GetActiveWindow()
End Sub
WindowFromPoint
The Declaration for WindowFromPoint(WFP).
Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
The WindowFromPoint function retrieves a handle to the window that contains the specified point. This is fairly easy to comprehend. Generally WFP is used in conjunction with another api function GetCursorPos(GCP). GCP gives us the co-ordinates of the mouse pointer at any given moment.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=WindowFromPos(125,225)
End Sub
GetDesktopWindow
The Declaration for GetDesktopWindow API is as follows
Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Long
The GetDesktopWindow API returns the handle to the desktop window. All windows which are open at any given time are CHILD windows whose parent is the Desktop Window. The function is used when for example we want a list of all windows currently running .If we GetDesktopWindow along with EnumChildWindow API we will get a list of all currently running windows.
dim lwnhandle as long
Private Sub Command1_Click()
lwnhandle=GetDesktopWindow()
End Sub
The GetDesktopWindow does not take any parameters.
ShowWindow
The declaration of ShowWindow is as follows
Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
The ShowWindow API is used to show/hide any window.The parameters which ShowWindow takes are the handle of the window to show/hide and the command ,0 is for hide and 1 is for show normal.
dim result as long
Private Sub Command1_Click()
result=ShowWindow(lwnhandle,0)
End Sub
The above piece of code will hide the window whose handle is lwhandle.
The SendMessage API
The SendMessage Api is one of the most powerful api functions . Before we take a look at it's uses and syntax let me give you a brief overview of how the windows os works.
The Windows Operating System is a message based operating system .By saying message based means that whenever the operating system (os) has to comunicate with applications or two applications need to communicate/send data among themselves they do so by sending messages to one another. For eg when an application is to be terminated the os sends a WM_DESTROY message to that application, also when you are adding an item to a listbox ,the application/os sends a LB_ADDSTRING message to the listbox .
While programming in VB the sendmessage api is not of much use when u want to manipulate objects controls in your own application.But say u wanted to change the title of some other application or wanted to get the text from a textbox of another application or want to terminate another application ,or set the text in a text box of another application. The uses are endless if u want to play around with your system.Also if you are planning to move over to win32 programming using c++ you just cannot escape the sendmessage api.
Let us look a the declaration of the sendmessage api
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
The SendMessage api function basically takes 4 parameters
hwnd-The handle of the window to which the message is being sent
wMsg-The message that is being sent to the window.
wParam-Parameter to be sent along with the message(depends on the message)
lParam-Parameter to be sent along with the message(depends on the message)
Example1
Let us see a practical implementation of this api . Let us assume that we want to get the *** masked text from a password textbox of a window!!! .We need to know a few things before we can do this. The first thing we need to know is the handle to the textbox window. One way of getting this is by using the windowfrompoint api.
Once we have this handle we need to send a WM_GETTEXTLENGTH message to the textbox .This message is essentially sent to query the textbox and get the length of the text string in that textbox.After we know the length of the string we have to send a WM_GETTEXT message to the textbox and the textbox will return the text as the result .This is how it is done
Along with the declaration of the sendmessage api you need to declare the 2 message constants that we are going to use
Private Const WM_GETTEXT = &HD
Private Const WM_GETTEXTLENGTH = &HE
Put the following in any event of a control .In this example we are putting it in a command click event
Private Sub command1_click()
Dim length As Long
Dim result As Long
Dim strtmp As String
length = SendMessage(hwnd, WM_GETTEXTLENGTH, ByVal 0, ByVal 0) + 1
strtmp = Space(length)
result = SendMessage(hwnd, WM_GETTEXT, ByVal length, ByVal strtmp)
End Sub
here hwnd is the handle of the password textbox.
Example 2
In this example we will try to change the title of any application ,in this case it will be a windows notepad application.
As was the case previously we have to get the handle of the notepad window .There are 2 ways to get this one is by using the windowfrompoint api and the other is by using the findwindow api.The findwindow api returns the handle of the window whose title has been specified in the function.
After we get the handle of this window we do a sendmesaage function
dim result as long
dim str1 as string
str1="tutorial"
result = SendMessage(hwnd, WM_SETTEXT, ByVal 0, ByVal str1)
Using almost the similar techniques you can also put your own text in the edit window of the notepad application.
Now that we got the API part out of the way, we may continue to figure out how to set the code that is executed when the control is used by the client... in this i will show you how to perfom this on a command button, by the way, this is called SubClassing
Put the following declarations in a .bas module, if you dont have one, make one, of course u can use ur general declarations in ur project, but i dont suggest it
To make a new module, click on new item or new, select new module
Public Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nindex As Long, ByVal dwnewlong As Long) As Long
Public Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, lParam As Long) As Long
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const GWL_WNDPROC = (-4)
Global oldWndProc As Long
The Functions SetWindowLong and CallWindowProc are used to subclass the control.
Put the following piece of code in the same event as that in which you are creating the control i.e .If you are creating the control in the form load event then put the following piece of code in that event.
oldWndProc = SetWindowLong(cmdInput.hWnd, GWL_WNDPROC, AddressOf newWndProc)
Here cmdInput is the command button which was created at runtime,newWndProc is the function which is going to handle the messages/events .
Next we write the public function in a .bas module which would process all the messages/events of the control.
Here is the function
Public Function newWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, lParam As Long) As Long
If uMsg = WM_LBUTTONDOWN Then
Form1.Text1.Text = "ok" 'the code that would have been in your msg box...
End If
newWndProc = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam)
End Function
What this function does is when the command button is clicked it prints "ok" into the textbox on form1.
So basically, say u made a command button at runtime, and when its clicked u want it to msgbox him saying ok, thats what it does, or if u want it to do something else, replace the Form1.Text1.Text = "ok" with whatever you want, remember the Form1., it is necessary most of the time.
You can modify the message i.e WM_LBUTTONDOWN to any suitable message that you wish to intercept.
Ending Notes
Now that we have gone through this tutorial, i can assure you that you are much better at visual basic 6, 5 even .NET... Now you can make a program, creating all the controls at runtime, and the code using the api statements as shown above, so ur form is blank... amazing isnt it lol, but when the form is opened, all the controls appear, TADA! u just made a 600 k/b prog into 100 k/b and it is much more optimized, remember, to make the program even better, when u dont need a control at the moment, delete it, and when its needed, create it again! the code for the control is already in the api! ahhahahaahahah!
ALSO WHEN MAKING CUSTOM CONTROLS, IN MY OPINION, THE ONLY PART THATS A TAD BIT OF A PAIN IN THE ASS, IT SETTING THEIR HEIGHT, WIDTH, AND LOCATION OF WHERE THEY ARE GOING TO BE ON THE FORM(x and y coordinates) BUT WITH THIS TIP IT WILL MAKE IT A WHOLE LOT EASIER:
in ur vb, view ur form, and put ur mouse over a spot on the form, in the top right/middle(i think) it will say two numbers like this: 1242, 8264
thats the x and y coordinates, for the height and width, make a protocol of the textbox on the form, view its properties in the properties window, and it will say its properties, or what u can do, it put all the controls on the form that ur gonna need, then type in the code to create the controls, gettin the controls x and y and height and width, then when ur ready to compile, just delete the controls, another way lol...
Need any additional help or have any questions? feel free to email me at [email protected]
EDIT NOTE: Sorry If Theres No Code TAGS Because i Copy Pasted This off Microsoft Word And I Forgot To Add The Tags