Don't write that declare!
When you use the Windows API, you should never need to write your own Declare statement. The API Text Viewer utility loads in a text file (WIN31API.TXT for 16-bit, and WIN32API.TXT for 32-bit) and lets you copy declares, global constants, and user-defined types. You can also convert the text file to an Access database for faster searching.
Dragging items from one list to another
Here's a way that you can let users drag items from one list and drop them in another one.
Create two lists (lstDraggedItems, lstDroppedItems) and a text box (txtItem) in a form (frmTip).
Put the following code in the load event of your form.
Private Sub Form_Load() ' Set the visible property of txtItem to false txtItem.Visible = False 'Add items to list1 (lstDraggedItems) lstDraggedItems.AddItem "Apple" lstDraggedItems.AddItem "Orange" lstDraggedItems.AddItem "Grape" lstDraggedItems.AddItem "Banana" lstDraggedItems.AddItem "Lemon" ' End Sub
In the mouseDown event of the list lstDraggedItems put the following code:
Private Sub lstDraggedItems_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) ' txtItem.Text = lstDraggedItems.Text txtItem.Top = Y + lstDraggedItems.Top txtItem.Left = X + lstDraggedItems.Left txtItem.Drag ' End Sub
In the dragDrop event of the list lstDroppedItems put the following code:
Private Sub lstDroppedItems_DragDrop(Source As Control, X As Single, Y As Single) ' If lstDraggedItems.ItemData(lstDraggedItems.ListIndex) = 9 Then Exit Sub End If ' To make sure that this item will not be selected again lstDraggedItems.ItemData(lstDraggedItems.ListIndex) = 9 lstDroppedItems.AddItem txtItem.Text ' End Sub
Now you can drag items from lstDraggedItems and drop them in LstDroppedItems.
Note that you cannot drag from the second list to the first. Also, the dragged item remains in the first list. You'll have to address those limitations yourself.
Quick Custom Dialogs for DBGrid Cells
It's easy to add custom input dialogs to al the cells in the Microsoft Data Bound Grid control.
First, add a DBGrid control and Data control to your form. Next, set the DatabaseName and RecordSource properties of the data control to a valid database and table ("biblio.mdb" and "Publishers" for example). Then set the DataSource property of the DBGrid control to Data1 (the data control).
Now add the following code to your form.
' general declaration area Dim strDBGridCell As String Private Sub DBGrid1_AfterColEdit(ByVal ColIndex As Integer) ' DBGrid1.Columns(ColIndex) = strDBGridCell ' End Sub Private Sub DBGrid1_BeforeColEdit(ByVal ColIndex As Integer, ByVal KeyAscii As Integer, Cancel As Integer) ' strDBGridCell = InputBox("Edit DBGrid Cell:", , DBGrid1.Columns(ColIndex)) ' End Sub
Now whenever you attempt to edit any cell in the DBGrid, you'll see the InputBox prompt you for input. You can replace the InputBox with any other custom dialog you wish to build.
Using the Alias Option to Prevent API Crashes
A number of Windows APIs have parameters that can be more than one data type. For example, the WinHelp API call can accept the last parameter as a Long or String data type depending on the service requested.
Visual Basic allows you to declare this data type as "Any" in the API call, but this can lead to type mismatch errors or even system crashes if the value is not the proper form.
You can prevent the errors and improve the run-time type checking by declaring multiple versions of the same API function in your program. By adding a function declaration for each possible parameter type, you can continue to use strong data type checking.
To illustrate this technique, add the following APIs and constants to a Visual Basic form. Notice that the two API declarations differ only in their initial name ("WinHelp" and "WinHelpSearch") and the type declaration of the last parameter ("dwData as Long" and "dwData as String").
' WinHelp APIs Private Declare Function WinHelp Lib "user32" Alias "WinHelpA" (ByVal hwnd As Long, ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal dwData As Long) As Long Private Declare Function WinHelpSearch Lib "user32" Alias "WinHelpA" (ByVal hwnd As Long, ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal dwData As String) As Long ' Private Const HELP_PARTIALKEY = &H105& Private Const HELP_HELPONHELP = &H4 Private Const HelpFile = "c:\program files\devstudio\vb5\help\vb5.hlp"
Now add two command buttons to your form (cmdHelpAbout and cmdHelpSearch) and place the following code behind the buttons. Be sure to edit the location of the help file to match your installation of Visual Basic.
Private Sub cmdHelpAbout_Click() ' WinHelp Me.hwnd, HelpFile, HELP_HELPONHELP, &H0 ' End Sub Private Sub cmdHelpSearch_Click() ' WinHelpSearch Me.hwnd, HelpFile, HELP_PARTIALKEY, "option" ' End Sub
When you press on the HelpAbout button, you'll see help about using the help system. When you press on the HelpSearch button, you'll see a list of help entries on the "option" topic.
Add Dithered Backgrounds to your VB Forms
Ever wonder how the SETUP.EXE screen gets its cool shaded background coloring? This color shading is called dithering, and you can easily incorporate it into your forms. Add the following routine to a form:
Sub Dither(vForm As Form) Dim intLoop As Integer vForm.DrawStyle = vbInsideSolid vForm.DrawMode = vbCopyPen vForm.ScaleMode = vbPixels vForm.DrawWidth = 2 vForm.ScaleHeight = 256 For intLoop = 0 To 255 vForm.Line (0, intLoop)-(Screen.Width, intLoop - 1), RGB(0, 0, 255 -intLoop), B Next intLoop End Sub
Now, add to the Form_Activate event the line:
Dither ME
This version creates a fading blue background by adjusting the blue value in the RGB function. (RGB stands for Red-Green-Blue.) You can create a fading red background by changing the RGB call to:
RGB(255 - intLoop, 0, 0).
Use FreeFile to Prevent File Open Conflicts
Both Access and VB let you hard code the file numbers when using the File Open statement. For example:
Open "myfile.txt" for Append as #1 Print #1,"a line of text" Close #1
The problem with this method of coding is that you never know which file numbers may be in use somewhere else in your program. If you attempt to use a file number already occupied, you'll get a file error. To prevent this problem, you should always use the FreeFile function. This function will return the next available file number for your use. For example:
IntFile=FreeFile() Open "myfile.txt" for Append as #intFile Print #intFile,"a line of text" Close #intFile
Confirm Screen Resolution
Here's a great way to stop the user from running your application in the wrong screen resolution. First, create a function called CheckRez:
Public Function CheckRez(pixelWidth As Long, pixelHeight As Long) As Boolean ' Dim lngTwipsX As Long Dim lngTwipsY As Long ' ' convert pixels to twips lngTwipsX = pixelWidth * 15 lngTwipsY = pixelHeight * 15 ' ' check against current settings If lngTwipsX <> Screen.Width Then CheckRez = False Else If lngTwipsY <> Screen.Height Then CheckRez = False Else CheckRez = True End If End If ' End Function
Next, run the following code at the start of the program:
If CheckRez(640, 480) = False Then MsgBox "Incorrect screen size!" Else MsgBox "Screen Resolution Matches!" End If
Quick Text Select On GotFocus
When working with data entry controls, the current value in the control often needs to be selected when the control received focus. This allows the user to immediately begin typing over any previous value. Here's a quick subroutine to do just that:
Public Sub FocusMe(ctlName As Control) ' With ctlName .SelStart = 0 .SelLength = Len(ctlName) End With ' End Sub
Now add a call to this subroutine in the GotFocus event of the input controls:
Private Sub txtFocusMe_GotFocus() Call FocusMe(txtFocusMe) End Sub