API programming in Visual Basic

Lesson 1:  Introduction to the Win32API

Foreword
The API programming series is a set of articles dealing with a common theme: API programming in Visual Basic. Though there are no hard and fast rules regarding the content of these articles, generally one article can be expected to contain issues related to API programming, explanation of one or more API calls with generously commented code snippets or bug reports. Depending on the subject, these code samples may expand to become a full-fledged application.
In this article we’ll look at the concept of API as applied to Win32 programming.
Note: This article is meant for absolute newbies. If you are even slightly familiar with API programming I strongly suggest that you skip this article.
So what is this API
You may be a VB programmer, a C++ programmer, a Delphi programmer or even a C programmer. But the fact is if you’ve ever developed an application for the Windows platform then you have used the Win32 API, at least indirectly. Because, quite simply, any program you write for windows uses the Windows API. Each and every line of code you write is translated into corresponding API calls which the system uses to get the tasks done.
API (Application Programming Interface) is a set of predefined Windows functions used to control the appearance and behaviour of every Windows element (from the outlook of the desktop window to the allocation of memory for a new process). Between them, these functions encapsulate the entire functionality of the Windows environment. So we can consider API as the native code of Windows. The other languages act as an attractive and often user-friendlier shell to the API promoting easier and automated access to it. An example is VB, which has replaced a sizeable portion of the API with its own functions. But every line of code written in VB is converted to its equivalent API calls.
Where does the API reside?
The bulk of the API functions are encapsulated in a set of DLLs - kernel32.dll, user32.dll, gdi32.dll, shell32.dll, etc. These DLLs form the core of the Windows OS and are present on all windows machines (At least the ones that are bootable J). So unlike when you access a function from a third-party DLL, you don’t have to ship anything with your product when you use an API function. The effect this has on the distribution size and speed of your application has to be seen to be believed.
How can we access API functions from VB?
Since these functions are encapsulated within external DLLs they are not available in VB by default. Before invoking (i.e. using) them, we must declare them. Usually this is done in the General | Declarations part of the module in which they are to be used. One important thing should be remembered while declaring API functions within a form module. VB does not allow public Declare statements within form modules. So the Declare statements should be explicitly specified as Private since all object module members are considered Public by default. But this makes them invisible outside the module in which they are defined. So the functions should be declared in every module that needs to use them. Declaring them in a separate .BAS module where they can be declared as Public and are therefore accessible to all the modules eliminates this duplication. This also permits easier maintenance.
Why use the API when I can achieve most of the things I want in VB?
First of all the features offered by (pure) VB are pretty limited when compared to what can be achieved in windows. The recent additions have alleviated this problem somewhat, but the functionality offered by VB is still woefully inadequate in many areas, especially systems programming. Using the API can help you to work around this and would be much simpler than learning a new language such as VC++.
Secondly, due to its architecture, programs written in VB run slower than their C++ or Delphi counterparts. This is the price one has to pay for easier debugging, simpler coding and a fast development cycle. API being the native interface to Windows is much faster than VB when compared to VB code and since the support files are present in all Windows installations (more about this in the Where does the API reside section) the distribution size is smaller too. So using the API in VB allows one to have the best of both worlds.

So why use VB at all?
I guess I went a bit overboard in praising the API. Because, for all its advantages, API programming does have some critical disadvantages. It is much more tougher and much less forgiving of programmer errors. Also it is child’s play to crash your application or your system with a malformed API call. And certain API calls when (im) properly used can even render your system unbootable or worse.

Conclusion
I hope I haven’t scared you with that ominous sounding previous paragraph. There is no need to be concerned. Believe me, once you tide over the initial hitches, API programming is actually fun. Just try to understand what you’re doing and how to do it properly, exercise mature prudence and lo! You’ve got yourself a slimmer, faster application doing things that’d make ordinary VB programmers go green with envy. Good luck!

P.S. I’ve tried to make this concept as clear as is possible. However if you have any doubts, questions or comments regarding this article please do not hesitate to mail me, I’ll be glad to help.


Contributed by Sreejath S. Warrier

Lesson 2:  Using the Win32 API in VB

Foreword
The API programming series is a set of articles dealing with a common theme: API programming in Visual Basic. Though there are no hard and fast rules regarding the content of these articles, generally one article can be expected to contain issues related to API programming, explanation of one or more API calls with generously commented code snippets or bug reports. Depending on the subject, these code samples may expand to become a full-fledged application.
In this article we’ll see how to access the Win32 API from the Visual Basic environment. We’ll start with the basics of declaring and using an API function. From there we’ll move on to discussing parameter passing, passing by value, passing by reference, aliasing etc. in the course of this we develop a small utility that displays the computer name in a message box.

First step: Declaring the API
As discussed in Article#1, the API functions are declared in DLLs located in the Windows System directory. You can type in the declaration of an API just as you do with any other function exported from a DLL, but there is an easier way to do it. Microsoft ships an application called API Text Viewer along with VB. This was available as a standalone application in VB5. In VB6 this can be run as a standalone app or as an addin.
To have some API declared in your project, just launch API Text Viewer, open Win32Api.txt (or .MDB if you have converted it into a database to speed it up), choose Declares, find the function, and click Add and then Copy. Go to your project and paste it in. Do the same to have a predefined constant or type. This saves quite lot of typing. Also it eliminates the errors caused due to mistyping. Note: The first time you do this, the Application may suggest that you convert the text file to a database file. If so, accept the suggestion as this enables faster access to the data.
However, you need to watch out for these common glitches:
1. If you copy the declarations right from the API Text Viewer, the scope of the function is not specified. Since the scope is Public by default, the function has public scope. But VB does not allow public Declare statements within form modules. So if we are copying the Declare statements into a form module, they should be explicitly specified as Private.
2. This strategy has its own problems as this makes the declarations invisible outside the module in which they are defined. So the functions should be declared in every module that needs to use them. Declaring them in a separate .BAS module where they can be declared as Public and are therefore accessible to all the modules eliminates this duplication. This also permits easier maintenance.
3. Another common error is the Ambiguous Name detected error. Put simply this means that the module contains more than one function or constant having the same name, causing the ambiguity. Since most of the functions are Aliased, they are referred to by different names. In such cases we can change the function name at the declaration and invocation points and the code will work fine.
4. There is one more error that you need to keep a really sharp eye out for, mainly because it comes from an unexpected source. The Win32api.txt file supplied by Microsoft contains some errors, which can cause you endless hours of frustration. Since we copy it from the API Text Viewer, the Declaration would be the last place we’d expect an error to arise, especially as the file itself is a Microsoft product. But sadly this file contains a number of errors that are particularly hard to track down. There’s nothing much you can do about it, except of course to correct any that come to your attention and consult a good API guide or SDK documentation when things don’t seem to go as expected.
Example:
Now we’ll see a simple declaration and invocation example. For this purpose let us build an application that finds out your computer name, i.e. the name you have given your computer. Ready? OK, API gods, here we come ready or not!

Code:
First, load VB and create a new standard EXE project. A form should have been added to the project by default. In the General | Declarations section of the form add the following code:

Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal sBuffer As String, lSize As Long) As Long

‘Now add the following code to an appropriate procedure. Here I’ve used the
‘Form_Load event
Private Sub Form_Load ()
Dim strString As String
"Create a buffer
strString = String(255, Chr$(0))
"Get the computer name
GetComputerName strString, 255
"Remove the unnecessary Chr$(0)
strString = Left$(strString, InStr(1, strString, Chr$(0)) - 1)
"Show the computer name
MsgBox strString
End Sub

Please examine the Declaration part carefully. Straightaway, we can notice several things. First of all we see that the scope of the Declaration is private. This is because VB does not allow Public Declare statements in object modules. Next we see that this is the declaration for a Function and that the name by which the function is referred in this program is GetComputerName. This is NOT the real name of the function as will become clear when we discuss aliasing in a short while. The next two words are interesting.
Lib “kernel32”
Lib “kernel32” means that the specified API function is found in the kernel32.dll file. Strictly speaking, it should be “kernel32.dll” but the extension name can be skipped. Also, the path can be skipped since the file is located in the System folder.
Aliasing
Aliasing is a technique used to call a function with a different name than its original name as defined in the DLL to avoid naming problems ambiguities etc. Occasionally, a DLL procedure has a name that is not a legal identifier. It might have an invalid character (such as a hyphen), or the name might be the same as a Visual Basic keyword (such as GetObject). When this is the case, use the Alias keyword to specify a new, legal name for the procedure with the illegal name. I.e. For example, some procedures in the operating environment DLLs begin with an underscore character. While you can use an underscore in a Visual Basic identifier, you cannot begin an identifier with an underscore. To use one of these procedures, you first declare the function with a legal name, then use the Alias clause to reference the procedure"s real name.
We can also use the Alias clause to change a procedure name whenever it"s convenient. Say, to remove the ambiguity problem discussed earlier in this article. If you do substitute your own names for procedures, make sure that you thoroughly document the changes so that your code can be maintained at a later date.
In our example therefore, “GetComputerNameA” is the name of the function and GetComputerName is its alias. This could be confusing the first time around. Don’t worry; it’s simple once you get the hang of it.
Arguments
This function takes two arguments. The first argument is a string and is passed ByVal. The second argument is a long value and is passed ByRef. Wait a minute! What are these ByVal and ByRef arguments and what is their significance? We’ll see that in a minute. Now let us see the argument list:
lpBuffer - Points to a buffer to receive the null-terminated character string containing the computer name.
nSize - Points to a variable that specifies the maximum size, in characters, of the buffer. This value should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.

ByVal and ByRef
If you do API programming for any length of time, it is impossible to avoid these two terms. They refer to two methods used to pass arguments to functions. ByVal means that the argument is passed by value. I.e. a copy of the argument is made and this copy is passed to the function. Any changes that the function makes to its own copy of the data are not reflected to the original value. ByRef means that the address of the variable (i.e. a pointer to the variable as it is known in nerd lingo) is passed as argument to the function. So any changes the function makes to the argument is immediately reflected in the original variable. In passing arguments to API functions, ByRef is the default, whereas if you need to pass an argument ByVal, it needs to be explicitly specified.
Now let us analyse the rest of the code.
In the Form_Load event procedure we first create a string buffer, strString. Then we pre-size (or stuff) it with enough Chr$(0) (space) so that it is larger than the maximum length that the computer name can have.
Warning: If you skip the previous step, you may get back an empty string as the result. And though it has never occurred to me, Microsoft warns that you may even crash the program if you fail to pre-size the buffer.
After that, we pass the pointer to the buffer and an integer value, which denotes the length of the buffer to the GetComputerName function. The strString buffer now contains the computer name and trailing spaces. In the final step we lop off the spaces to get the computer name, which we display, using the MsgBox function.
That is all there is to it! And I guess the time has come for me to say goodbye.
If you have any doubts, comments or questions, do feel free to mail me.
Happy coding!


Contributed by Sreejath S. Warrier

Lesson 3:  Bring a Window to Top

Foreword
The API programming series is a set of articles dealing with a common theme: API programming in Visual Basic. Though there are no hard and fast rules regarding the content of these articles, generally one article can be expected to contain issues related to API programming, explanation of one or more API calls with generously commented code snippets or bug reports. Depending on the subject, these code samples may expand to become a full-fledged application.
In this article we see how to bring a window to the top of all other currently active windows.
As usual we start with the API declaration.

Create a new VB Standard EXE project.
When you created the project, a form Form1 should have been added to the project by default. Add another form to the project. Since this is only an example to illustrate the above API call, we’ll not change the properties of the forms. So now we have two forms named Form1 and Form2 in the project. Add a command button each to both the forms. Leave their names as Command1 itself.
In the General | Declarations section of both the forms, type in the following code

Private Declare Function BringWindowToTop Lib "user32" Alias "BringWindowToTop" (ByVal hwnd As Long) As Long

In the Click event procedure of the button on Form1 add the following code:

Private Sub Command1_Click ()
BringWindowToTop Form2.hwnd
End Sub

In the Click event procedure of the button on Form2 add the following code:

Private Sub Command1_Click ()
BringWindowToTop Form1.hwnd
End Sub

Now in the load event of Form1 (which should be the default form of the project add the following code.

Private Sub Form_Load ()
Form2.Show
End Sub

Now if we press the command button on Form1, Form2 will be brought to top and vice versa.
Explanation
Let us see how this works.
The API function BringWindowToTop is encapsulated in the user32.dll file located in the System directory. But how does this function identify the Window that is to be brought on top? Fortunately, it so happens that Windows (the OS) assigns each currently loaded window a unique ID called its handle abbreviated as hwnd. Our function accepts the hwnd of the window that is to be brought on top as its parameter. Once invoked, it brings the specified window to the top of the Z order. If the window is a top-level window, it is activated. If the window is a child window, the top-level parent window associated with the child window is activated. But wait a minute what is this Z-order? Z-order is the order in which the various windows are “stacked” on the screen, so to speak. The lower the Z-order number, the higher up the window is. To understand this, consider the monitor as a Cartesian system with the origin at the top left corner. Now downwards from that corner is the positive X axis, rightwards is the positive Y axis and inwards is the positive Z axis. So if we consider the three dimensional model, a window at the top has its Z value zero and those below have positive Z values which go on increasing as the “depth” increases. From this model came the concept of Z-order. This concept might be a bit tricky to grasp, so if you have any doubts do contact me.
While adequate for the purpose of explaining the function, the above example is rather trivial in nature. I.e. it doesn’t achieve anything practical. So what would be a practical application for this? Hmmm… Say, you’ve got a long process running in a window. Naturally you can expect your users to switch to other windows during this period. However, once the process is complete you may want to put this window on top. In such a case this code can be put to use.
This can be done as follows:
It is only natural to expect that the abovementioned long-running process will raise an event once it is complete. Let us call it Process_Complete event. Then adding the following code to this event will bring the application window to top once the process is complete.

Public Sub Process_Complete()
BringWindowToTop Form1.hwnd
End Sub
In fact, this is a standard technique implemented by most windows apps. To see this in action, perform the following steps:
Run a windows application, say Notepad.exe.
Now load a reasonably “heavy” application like say MSWord or Access and immediately switch back to notepad. Once the loading process is complete, the Word window will be brought on top. In fact this occurs many times during the loading process. Just check. The Windows environment automatically implements this using this same API call. In special cases such as those mentioned above, we can use the BringWindowToTop API call to do this explicitly.
As always if you have any doubts, questions or comments, please do not hesitate to mail me.
That’s it for now. Until next time it is good luck, good-bye and happy coding.


Contributed by Sreejath S. Warrier

Lesson 4:  Hiding your Application from the Alt-Ctrl-Del list

Foreword
The API programming series is a set of articles dealing with a common theme: API programming in Visual Basic. Though there are no hard and fast rules regarding the content of these articles, generally one article can be expected to contain explanation of one or more API programming issues or API calls with generously commented code snippets. Depending on the subject, these code samples may expand to become a full-fledged application.
This article deals with hiding an Application from the Windows task list.

As developers, we often feel the need to run certain applications that provide support services to another application. In such cases it is desirable that this support application doesn’t show up in the Alt-Ctrl-Del list (also called the “hit-list”) as this may enable the user to kill it causing an application/system crash. In this article we’ll discuss how to achieve this in a VB application using API programming.

Here the key concept to be understood is this: The task list, while showing the currently running “tasks” on a machine, does not display those registered as services. So to prevent a task from appearing in the task list, register it as a service. And to make the task appear in the task list again, unregister it. Simple!

Let’s get on with the code.
As always, start up Visual Basic and create a new Standard EXE project.
A form should have been added to the project by default.
Copy this code into the declarations section of the form:

Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function RegisterServiceProcess Lib "kernel32" (ByVal dwProcessID As Long, _
ByVal dwType As Long) As Long

Private Const RSP_SIMPLE_SERVICE = 1
Private Const RSP_UNREGISTER_SERVICE = 0

Create a new procedure to the form, called "MakeMeService".
Add the following code to this procedure:

Dim pid As Long
Dim regserv As Long
pid = GetCurrentProcessId()
regserv = RegisterServiceProcess(pid, RSP_SIMPLE_SERVICE)

To remove your program from the Ctrl+Alt+Delete add this code to call the procedure:

Call MakeMeService

This can be called from any procedure in the form.
To make your program appear in the task list again:
Create a new procedure to the form, called "UnMakeMeService".
Add the following code to this procedure:
Dim pid As Long
Dim regserv As Long
pid = GetCurrentProcessId()
regserv = RegisterServiceProcess(pid, RSP_UNREGISTER_SERVICE)

To unregister your application as a service (and therefore show the program in the Ctrl+Alt+Delete task list), add this code to call the procedure:

Call UnMakeMeService

Analysis

Let us try to understand what we’ve been doing here.
First we declared the necessary API calls. (For more information re: how to declare and use API functions, see Article#2- Using API in VB. For more information regarding API Programming see Article#1 What is Windows API?)
Here we need three API calls.
1) GetCurrentProcessId - This call, which doesn’t accept any parameters, returns the ProcessID of the current process. The ProcessID is a unique Long value that Windows assigns to a process.
2) GetCurrentProcess - This call returns a handle to the current process and is used by the GetCurrentProcessId function in determining the ProcessID.
3) RegisterServiceProcess - This call accepts the ProcessID of a process and a type parameter. It then registers/unregisters the process (whose ID is given) as a service depending on the value of the type parameter. The type parameter can be either RSP_SIMPLE_SERVICE(= 1) in which case the process is registered as a simple service (it no longer appears in the task list) or RSP_UNREGISTER_SERVICE (= 0), in which case the process is unregistered as a service (appears in the task list). Both these constants are declared in the General | Declarations section.
All the three are encapsulated in the kernel32.dll file located in the System directory.
Now, whenever we want to register a service as a process, we retrieve its ProcessID; pass it to the RegisterServiceProcess along with the dwType argument set to RSP_SIMPLE_SERVICE. And when we want to unregister it, do the same thing but this time set the dwType parameter to RSP_UNREGISTER_SERVICE. (ProcessID is a unique ID assigned to all currently running processes by the Windows)
For convenience, we can put all the necessary code in two separate procedures and call these procedures as necessary as we have done here.
That’s all for now. As always, mail me if you have any doubts, questions or comments.
Good-bye, Good luck and happy coding!


Contributed by Sreejath S. Warrier

Lesson 5:  Keep your Application Window on top

The API programming series is a set of articles dealing with a common theme: API programming in Visual Basic. Though there are no hard and fast rules regarding the content of these articles, generally one article can be expected to contain issues related to API programming, explanation of one or more API calls with generously commented code snippets or bug reports. Depending on the subject, these code samples may expand to become a full-fledged application.
In this article we see how to keep our application window always on top.

As always, start up Visual Basic and create a Standard EXE project.
A form should have been added to the project by default.
Add the following code into its declarations section:

Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos"_
(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) As Long

Const SWP_NOMOVE = 2
Const SWP_NOSIZE = 1
Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2

‘To set Form1 as the topmost Windows, use this code:
Dim result as Long
result = SetWindowPos (Form1.hWnd, HWND_TOPMOST, _ 0, 0, 0, 0, FLAGS)

‘To make Form1 behave normally again, use this code:
Dim result as long
result = SetWindowPos (Form1.hWnd, HWND_NOTOPMOST, _ 0, 0, 0, 0, FLAGS)

Analysis

Let us try to understand what we’ve been doing here.
First we declared the necessary API call. (For more information re: how to declare and use API functions, see Article#2- Using API in VB. For more information regarding API Programming see Article#1 What is Windows API?)
Here we need only one API call: SetWindowPos.

Description
The SetWindowPos function is encapsulated in the user32.dll file located in the System directory.
It changes the size, position, and Z order of a child, pop-up, or top-level window. Child, pop-up, and top-level windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order. (For more info re: Z-order see Article#3.)
The declaration and the explanation of the various parameters are given below.

Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos"_
(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) As Long

hwnd
Identifies the window.

hWndInsertAfter
Identifies the window to precede the positioned window in the Z order. This parameter must be a window handle or one of the following values:
HWND_BOTTOM
Places the window at the bottom of the Z order. If the hwnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
HWND_NOTOPMOST
Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.
HWND_TOP
Places the window at the top of the Z order.
HWND_TOPMOST
Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.

X
Specifies the new position of the left side of the window.

Y
Specifies the new position of the top of the window.

cx
Specifies the new width of the window, in pixels.

cy
Specifies the new height of the window, in pixels.

uFlags
Specifies the window sizing and positioning flags. This parameter can take a number of values including combinations of individual values. A complete list of the various values that this parameter can take has been appended to this article. But for the purpose of this example we are interested in the two values given below:
SWP_NOMOVE
Retains the current position (ignores the X and Y parameters).
SWP_NOSIZE
Retains the current size (ignores the cx and cy parameters).

Now let us see how this works.
First we declare the API call. This as you may know, is necessary for invoking the function. (For more information re: how to declare and use API functions, see Article#2- Using API in VB. For more information regarding API Programming see Article#1 What is Windows API?)
After that we declare the necessary constants. We have already seen the SWP_NOMOVE and SWP_RESIZE. The FLAGS constant is used to combine both these constants (using the Or operator) prior to passing it as a parameter to the API call. This ensures that the window size and position remain unchanged as the window is brought to the top. Now that the configuration part is complete, we just need to call the SetWindowPos API call with the appropriate parameters to set the window on top or to revert to normal behaviour.


To bring the window on top:
Call the API function with hWndInsertAfter set to HWND_ONTOP. Since the wFlags parameter is set to SWP_NOMOVE Or SWP_TOPMOST the x, y, cx, cy parameters have no effect and can be set to zero.
To revert to normal window behaviour:
Call the API function with hWndInsertAfter set to HWND_NOTOPMOST. Since the wFlags parameter is set to SWP_NOMOVE Or SWP_NOSIZE the x, y, cx, cy parameters have no effect and can be set to zero.
As can be seen, the SetWindowPos function is very powerful and versatile and can be used to perform many other window related tasks. A future article will give a more comprehensive explanation with examples.
That’s it for now. If you have any doubts, questions or comments please do mail me. See you in the next article!
Until then good-bye, good luck and happy coding!
******

The complete list of values accepted by the wFlags parameter of the SetWindowPos API
SWP_DRAWFRAME
Draws a frame (defined in the window’s class description) around the window.
SWP_FRAMECHANGED
Sends a WM_NCCALCSIZE message to the window, even if the window’s size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window’s size is being changed.
SWP_HIDEWINDOW
Hides the window.
SWP_NOACTIVATE
Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
SWP_NOCOPYBITS
Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
SWP_NOMOVE
Retains the current position (ignores the X and Y parameters).
SWP_NOOWNERZORDER
Does not change the owner window’s position in the Z order.
SWP_NOREDRAW
Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the non-client area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
SWP_NOREPOSITION
Same as the SWP_NOOWNERZORDER flag.
SWP_NOSENDCHANGING
Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
SWP_NOSIZE
Retains the current size (ignores the cx and cy parameters).
SWP_NOZORDER
Retains the current Z order (ignores the hWndInsertAfter parameter).
SWP_SHOWWINDOW
Displays the window.


Contributed by Sreejath S. Warrier