Visual Basic Q&A

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries Tagged ‘window’

How To Create a Form That Always Stays on Top

Symptoms
Microsoft Visual Basic does not offer a property or method to make a formthe topmost window. This behavior can be achieved using the SetWindowPosWin32 API.
This article demonstrates how to set a form as the topmost window using theSetWindowPos Win32 API.
Resolution
The sample code below uses a function called SetTopMostWindow. TheSetTopMostWindow function sets a window as a topmost Window or as a normalWindow, based on the two parameters, hwnd and Topmost, passed to it.
The hwnd parameter specifies the handle of the window to be set as topmostor as normal.
The Topmost parameter specifies whether to set the form as topmost or asnormal. If the value is true, the function sets the form to always remainon top. If the value is false, the function sets the form as a normalwindow.
Step-by-Step ExampleStart a new Standard EXE project. Form1 is created by default.Add two command buttons (Command1 and Command2) to Form1.Set the caption property of Command1 to “Always on top.”Set the caption property of Command2 to “Normal.”Put the following code in the Form1 Declaration section:

Option ExplicitPrivate Sub Command1_Click()Dim lR As LonglR = SetTopMostWindow(Form1.hwnd, True)End SubPrivate Sub Command2_Click()Dim lR As LonglR = SetTopMostWindow(Form1.hwnd, False)End Sub On the Project menu, click Add Module, to add a new module to theproject.Add the following code to the new module:

Option ExplicitPublic Const SWP_NOMOVE = 2Public Const SWP_NOSIZE = 1Public Const FLAGS = SWP_NOMOVE Or SWP_NOSIZEPublic Const HWND_TOPMOST = -1Public Const HWND_NOTOPMOST = -2Declare 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 LongPublic Function SetTopMostWindow(hwnd As Long, Topmost As Boolean) _As LongIf Topmost = True Then ‘Make the window topmostSetTopMostWindow = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, _0, FLAGS)ElseSetTopMostWindow = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, _0, 0,FLAGS)SetTopMostWindow = FalseEnd IfEnd Function
NOTE: In the above sample code, an underscore (_) at the end of a line isused as a line-continuation character.
Press F5 to run the project.If you click the “Always on top” command button, your form becomes thetopmost window and remains on top of every window; you cannot move anyother window on top of it. If you click the “Normal” button, the formbehaves normally (you can move other windows on top of it).

PRB: RDC/ODBC Password Display Inconsistencies

Symptoms
When setting the password property of the RemoteData Control (RDC) atdesign time in the Property Window, asterisks are not substituted for thepassword characters. When the ODBC dialog box is displayed, the password isconverted into asterisks.
Resolution
The RDC does not control the edit field in the Property Window, andtherefore cannot force asterisks to be displayed. An OLE custom controldoes not have direct control over the Property window supplied by theVisual Basic design environment. The Remote Data control does correctly useasterisks in its own Property page.

BUG: Font Changes After Open Stored Procedure in Data View

Symptoms
When you open a Data View Stored Procedure Design window, the font of theData View window changes to the font of the Code window.
Resolution
To restore the font, you have to exit Visual Basic and restart.

HOWTO: Subclass a UserControl

Symptoms
In Windows programming terminology, subclassing is the process of creatinga message handling procedure to intercept messages for a given window,handling those messages, and passing any remaining messages to the window’soriginal message handler.
This article demonstrates how to subclass a UserControl in Visual Basicusing the AddressOf operator.
Resolution
WARNING: One or more of the following functions are discussed in this article; VarPtr, VarPtrArray, VarPtrStringArray, StrPtr, ObjPtr. These functions are not supported by Microsoft Technical Support. They are not documented in the Visual Basic documentation and are provided in this Knowledge Base article “as is.” Microsoft does not guarantee that they will be available in future releases of Visual Basic.
In Visual Basic, the AddressOf operator is used to specify whichfunction in a code module (.BAS file) will be the message handlingprocedure. The subclass procedure is basically a message filter thatperforms non-default processing for a few key messages, and passes othermessages to a default window procedure using CallWindowProc API. TheCallWindowProc API function passes a message to the Windows system, which,in turn, sends the message to the specified window procedure.
When subclassing a UserControl with the AddressOf operator, you must takeinto account that multiple instances of the control utilize the same codemodule and its functions. In order for the UserControl to maintain its”own” message handling function, the common procedure in the module needsto forward the messages to the proper instance of the UserControl.
To implement a function for each instance of a UserControl, you need tocreate a function in the UserControl to process the messages. The currentrequirement of Visual Basic is that the AddressOf operator can only beused for functions residing in a .BAS module. Therefore, the function inthe .BAS module must forward the message to the correct instance of theUserControl.

The following steps show how to create a UserControl that detects mouseactivation at design-time and run-time.
WARNING: ANY USE BY YOU OF THE CODE PROVIDED IN THIS ARTICLE IS AT YOUR OWNRISK. Microsoft provides this code “as is” without warranty of any kind, either express or implied, including but not limited to the impliedwarranties of merchantability and/or fitness for a particular purpose.
WARNING: Failure to unhook a window before its imminent destruction willresult in application errors, Invalid Page Faults, and data loss. This isdue the fact that the new WindowProc function being pointed to no longerexists, but the window has not been notified of the change. Always unhookthe sub-classed window upon unloading the sub-classed UserControl orexiting the application. This is especially important while debugging anapplication that uses this technique within the Microsoft Visual BasicDevelopment Environment. Pressing the End button or selecting End from theRun menu without unhooking will cause an Invalid Page Fault and closeMicrosoft Visual Basic.
Step-by-Step ExampleStart Visual Basic and create a new ActiveX Control Project.”UserControl1″ is created by default.Add the following code to the UserControl1 code module:

Option Explicit’mWndProcOrg holds the original address of the’Window Procedure for this window. This is used to’route messages to the original procedure after you’process them.Private mWndProcOrg As Long’Handle (hWnd) of the subclassed window.Private mHWndSubClassed As Long’Constant for Windows Message used in sample.Private Const WM_MOUSEACTIVATE = &H21Private Sub SubClass()’————————————————————-’Initiates the subclassing of this UserControl’s window (hwnd).’Records the original WinProc of the window in mWndProcOrg.’Places a pointer to the object in the window’s UserData area.’————————————————————-’Exit if the window is already subclassed.If mWndProcOrg Then Exit Sub’Redirect the window’s messages from this control’s default’Window Procedure to the SubWndProc function in your .BAS’module and record the address of the previous Window’Procedure for this window in mWndProcOrg.mWndProcOrg = SetWindowLong(hWnd, GWL_WNDPROC, _AddressOf SubWndProc)’Record your window handle in case SetWindowLong gave you a’new one. You will need this handle so that you can unsubclass.mHWndSubClassed = hWnd’Store a pointer to this object in the UserData section of’this window that will be used later to get the pointer to’the control based on the handle (hwnd) of the window getting’the message.Call SetWindowLong(hWnd, GWL_USERDATA, ObjPtr(Me))End SubPrivate Sub UnSubClass()’———————————————————–’Unsubclasses this UserControl’s window (hwnd), setting the’address of the Windows Procedure back to the address it was’at before it was subclassed.’———————————————————–’Ensures that you don’t try to unsubclass the window when’it is not subclassed.If mWndProcOrg = 0 Then Exit Sub’Reset the window’s function back to the original address.SetWindowLong mHWndSubClassed, GWL_WNDPROC, mWndProcOrg’0 Indicates that you are no longer subclassed.mWndProcOrg = 0End SubFriend Function WindowProc(ByVal hWnd As Long, _ByVal uMsg As Long, ByVal wParam As Long, _ByVal lParam As Long) As Long’————————————————————–’Process the window’s messages that are sent to your UserControl.’The WindowProc function is declared as a “Friend” function so’that the .BAS module can call the function but the function’cannot be seen from outside the UserControl project.’————————————————————–’Start Demo Code: Changes the color of the UserControl each’time the control is clicked in design-time from red to blue’or from blue to red.If uMsg = WM_MOUSEACTIVATE ThenIf UserControl.BackColor = vbRed ThenUserControl.BackColor = vbBlueElseUserControl.BackColor = vbRedEnd IfEnd If’End Demo Code.’Forwards the window’s messages that came in to the original’Window Procedure that handles the messages and returns’the result back to the SubWndProc function.WindowProc = CallWindowProc(mWndProcOrg, hWnd, _uMsg, wParam, ByVal lParam)End FunctionPrivate Sub UserControl_Initialize()’Occurs the first time a UserControl is placed on a container.UserControl.BackColor = vbRedSubClassEnd SubPrivate Sub UserControl_Terminate()UnSubClassEnd Sub Add new Standard Module (.BAS) to the project and add the followingcode:

Option Explicit’API Declarations used for subclassing.Public Declare Sub CopyMemory _Lib “kernel32″ Alias “RtlMoveMemory” _(pDest As Any, _pSrc As Any, _ByVal ByteLen As Long)Public Declare Function SetWindowLong _Lib “user32″ Alias “SetWindowLongA” _(ByVal hWnd As Long, _ByVal nIndex As Long, _ByVal dwNewLong As Long) As LongPublic Declare Function GetWindowLong _Lib “user32″ Alias “GetWindowLongA” _(ByVal hWnd As Long, _ByVal nIndex As Long) As LongPublic Declare Function CallWindowProc _Lib “user32″ Alias “CallWindowProcA” _(ByVal lpPrevWndFunc As Long, _ByVal hWnd As Long, _ByVal Msg As Long, _ByVal wParam As Long, _ByVal lParam As Long) As Long’Constants for GetWindowLong() and SetWindowLong() APIs.Public Const GWL_WNDPROC = (-4)Public Const GWL_USERDATA = (-21)’Used to hold a reference to the control to call its procedure.’NOTE: “UserControl1″ is the UserControl.Name Property at’design-time of the .CTL file.’(‘As Object’ or ‘As Control’ does not work)Dim ctlShadowControl As UserControl1′Used as a pointer to the UserData section of a window.Dim ptrObject As Long’The address of this function is used for subclassing.’Messages will be sent here and then forwarded to the’UserControl’s WindowProc function. The HWND determines’to which control the message is sent.Public Function SubWndProc( _ByVal hWnd As Long, _ByVal Msg As Long, _ByVal wParam As Long, _ByVal lParam As Long) As LongOn Error Resume Next’Get pointer to the control’s VTable from the’window’s UserData section. The VTable is an internal’structure that contains pointers to the methods and’properties of the control.ptrObject = GetWindowLong(hWnd, GWL_USERDATA)’Copy the memory that points to the VTable of our original’control to the shadow copy of the control you use to’call the original control’s WindowProc Function.’This way, when you call the method of the shadow control,’you are actually calling the original controls‘ method.CopyMemory ctlShadowControl, ptrObject, 4′Call the WindowProc function in the instance of the UserControl.SubWndProc = ctlShadowControl.WindowProc(hWnd, Msg, _wParam, lParam)’Destroy the Shadow Control CopyCopyMemory ctlShadowControl, 0&, 4Set ctlShadowControl = NothingEnd Function NOTE: If your UserControl is not named UserControl1, you need to changethe “Dim ctlControl As UserControl1″ line of code to indicate thecorrect name of your UserControl as specified by its Name property.
Close all the project windows that may be open and save the project.NOTE: During subclassing, you do not want to stop the executing code orit will cause an exception. Always save your project before testing anysubclassing code.
From the File menu, select “Add Project…” and add a Standard EXEproject. This will be your test project. It is named Project2 bydefault.Open the default form (Form1) of Project2 and place an instance of theUserControl on the form. It should appear as a red rectangle.Each time the mouse is clicked on the UserControl, it should toggle itscolor between red and blue.Place a second instance of the UserControl on the form. Note that thesubclassing works independently on each control, sending the messages tothe appropriate control.

BUG: Find Next Crashes After Closing a Maximized Code Window

Symptoms
Closing a maximized code window after performing a Find and Find Nextsubsequently on the code window causes Visual Basic to crash.
The possible error messages are:

An application error has occurred.
VB6.exe
Exception: Access Violation (0×00000005) Address: 0×0fb16e90
-or-

An application error has occurred.
VB5.exe
Exception: Access Violation (0×00000005) Address: 0×0fb16e90
-or-

This program has performed an illegal operation and will be shut down.
-or-

Edit: VB6.EXE Application Error
The instruction at “0×0fa76bb1″ referenced memory at “0×00000058″. The
memory could not be “read”.
-or-

Edit: VB5.EXE Application Error
The instruction at “0×0fa76bb1″ referenced memory at “0×00000058″. The
memory could not be “read”.
Resolution
This problem does not occur if the code window is not maximized.