Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all 1524 articles
Browse latest View live

Zoom Dialog

$
0
0
This is a part of file selectors, and here I made a class to be used more easily.

In example is a dialog that can be zoomed, without using any window style. So we can draw anything.

The window to zoom need to fix the scale from a most used font size. Then we can expand it without loosing width/height ratio and always fixed the scale to that font size we have choose.
We can expand to the right (optional) without scale. So with one move we can scale and expand as we wish. The dialog never loose at the minimum right expansion the form basic ratio.


New example;
Attached Files

Keep open CreateObject("ADODB.Connection")

$
0
0
I am working now changing the old DAO to ADO in my M2000 environment. I see some reduce in speed and I found why...All of my commands use the old DBEngine and workspaces...and so I was to change that to a variant
mybase= CreateObject("ADODB.Connection")
But in DAO the opening and close of Workspace has no delays. So I thinking about and my solution is easy to follow... All we have is to save the object and reused it and at the end we can delete all together.
Why we have a solution here which uses a collection and not use one or more variants variables and do the same thing at the end of program?
For simple programs the easy way is to use simple variables. But in more complicated, when we can't figure how many open connection we have, this collection is useful. We can expand the use of it if we pass to the index of it a number indicating the number of open connection (not as ordinal but as an autoincrement number)

So, when we need to set a mybase with SET mybase= CreateObject("ADODB.Connection")
we can see if exist and if exist we can use that or if not we make one.

We need to set that in the same module as with the functions included in the thread
Dim conCollection As Collection
Dim init As Boolean


If Not getone(base, myBase) Then

Set myBase = CreateObject("ADODB.Connection")
' it is better to use the default CursorLocation. So do not change it
' With CursorLocation=3 I can't read an mdb file written with DAO..but with CursorLocation=2 I can..

Set.Open ....the known string here.., 3, 4

end if

now we can open and close recordsets easy and fast.

So before we close the program e say just CloseAllConnections
CloseAllConnections



Code:

Dim conCollection As Collection
Dim init As Boolean

Sub PushOne(conname As String, v As Variant)
On Error Resume Next
conCollection.Add v, conname
Set v = conCollection(conname)
End Sub

Sub CloseAllConnections()
Dim v As Variant, BB As Boolean
On Error Resume Next
If Not init Then Exit Sub
If conCollection.Count > 0 Then
Dim i As Long
Err.clear
For i = conCollection.Count To 1 Step -1
On Error Resume Next
BB = conCollection(i).connectionstring <> ""
If Err.Number = 0 Then
        If conCollection(i).ActiveConnection <> "" Then conCollection(i).Close       
End If
conCollection.Remove i
Err.clear
Next i
Set conCollection = New Collection
End If
Err.clear
End Sub
Function getone(conname As String, this As Variant) As Boolean
On Error Resume Next
Dim v As Variant
InitMe
Err.clear
Set v = conCollection(conname)
If Err.Number = 0 Then getone = True: Set this = v
Err.clear
End Function

Sub InitMe()
If init Then Exit Sub
Set conCollection = New Collection
init = True
End Sub

Zcreenshot (translucent selection-box seamless screenshot application)

$
0
0
Thought I'd share this awesome little open-source app with tons of useful code examples with VBForums. I've won 2 awards for code of the month over at PlanetSourceCode, and this was one of them.

Fully operational screenshot application that is activated with a set of hot-keys of your choice, that when activated changes your mouse cursor to the selection-cross to let you know you can now click and drag a translucent selection box across any part of your desktop, and when the mouse is released, it will be saved to a folder with only the area selected. JPEG compression is available for saving the image, or standard raw bitmap. The appearance of the selection box is fully customizable (as far as translucency, border color, and background color) As well as saving all preferences in an INI file, such as which compression to use, running on start-up, it also features the ability to easily access the application through use of the Windows tray area; you may also access the screenshot folder where the images are saved to from the tray icon for ease of use. As well demonstrating quite a large number of API calls in relation to I/O and GDI+/other graphic operations, this also demonstrates the basics of making an application that runs on start up and is easily available from tray area. Great, fairly simple application to learn a lot of the basics to make headway to becoming an advanced programmer.
:check:Zcreenshot.zip
Name:  PIC201382023235054.jpg
Views: 4
Size:  73.4 KB
Attached Images
 
Attached Files

OptionButtonEx (grouping without frames, Unicode at runtime, & lightweight)

$
0
0
Here's what I'm calling OptionButtonEx. It has two features that the regular OptionButton doesn't have:

1) There's a GroupNum property that allows grouping of sets of them without the need for creating extra containers (frames, etc). The default is group zero, which will link all new option buttons together, but you can create as many groups (sets of option buttons) as you like.

2) There is a CaptionUnicode property. This property is available only at runtime, but it allows the setting (and getting) of a Unicode caption (using a standard VB6 string). This isn't available at design time because it would make this control too heavy (requiring a RichTextBox). I've previously posted a Unicode Option Button which is Unicode editable at design time for those who want that functionality.

This control is almost as lightweight as the regular option button, and has these two new features.

Enjoy.

OptionButtonEx.zip
Attached Files

[VB6] MS Office (MODI) OCR - OCR "for free"

$
0
0
This may already have been posted, but a search turned nothing up here in the CodeBank.


If you have an appropriate version of Microsoft Office you can use MODI to do OCR on images. The obvious candidates are 32-bit Office 2003 and 2007, but supposedly this can be made to work in 32-bit Office 2010 as well.

As far as I can tell there is no way to feed images to MODI.Document except by having it load them from disk. But you could always "dump" images to a temporary folder as required, so that isn't a nasty restriction.


Requirements

VB6 development tools. Of course the logic can be trivially ported to Office VBA or even a WSH or MSHTA script written in VBScript.

A version of 32-bit Office supporting MODI.


Notes

This program uses early binding against Microsoft Office Document Imaging 11.0 Type Library (Office 2003). This is used to give us easy access to MODI.Document's OnOCRProgress event and the predefined constant miLANG_ENGLISH in Enum MiLANGUAGES.

To use this code with Office 2007 you'd need to change the reference to Microsoft Office Document Imaging 12.0 Type Library and recompile.

You could also use late binding, but then you would either have to give up using WithEvents (not valid for As Object) and the OnOCRProgress event entirely... or else use additional code or a C++ helper DLL to bind to the event.

MODI was removed in Office 2010, but you might look at:



Attached Demo

The attachment is large because of included image files.

The program just grabs the file names from a hard-coded folder, then loads and OCRs them one by one and displays the resulting text in a RichTextBox. A status line reports progress on each image as it works.

A Timer control is used to work through the queue of images, primarily to help avoid the program being marked unresponsive by Windows.

The demo helps illustrate the "garbage in, garbage out" nature of OCR: the quality of the results depends on what you feed into it.
Attached Files

[VB6] Code Tip: Toggle Button with Image and Text (Vista+, ComCtl6)

$
0
0
NOTE: I will make a sample project, but since I had deleted this content and there was a 'please delete me' filler I wanted to repost as soon as possible. What happened was, I tried the code I posted, it seemed to work, so I posted it. I don't know if something in my system changed, or if I was hallucinating, or what, but the next minute I look and this method is not working. I came up with a fix, but it turns this from a code snippet into something fairly complicated. So standby for a sample project, but I wanted to get the post back up.


Problem: A regular CommandButton can have its image set with BM_SETIMAGE, but making it into a pushbutton (toggle button) by setting its style to BS_PUSHLIKE does not work. Conversely, a checkbox can be made into a pushbutton, but then you can't set its picture with BM_SETIMAGE and also have text.

Solution: A workable solution is to simply mimic the behavior of a pushbutton using BM_SETSTATE- which toggles whether the button is in its mousedown appearance. It stays depressed when focus is lost and when left clicked, and as far as I can tell behaves no different than a BS_PUSHLIKE button. The only trick is preventing a change to the state when focus is lost.

This code assumes you already have a project using modern common controls; see other threads for info about that.

On Form_Load, set the icon and whatever other styles you need for the button; e.g.

Code:

hBtn = Command1.hWnd
Call SendMessage(Command1.hWnd, BM_SETIMAGE, 1&, ByVal hIcon1)
SetButtonStyle Command1.hWnd, BS_NOTIFY Or BS_LEFT

hBtn is a Public Long. BS_NOTIFY is required; BS_LEFT I just added because it looks better, you can omit it or change it as long as the notify style remains. Do NOT set BS_PUSHLIKE.
Then you can toggle it on and off like this:

Code:

Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If bFlag Then
    ToggleButtonState Command1.hWnd, 0
    bFlag = False
Else
    ToggleButtonState Command1.hWnd, 1
    bFlag = True
End If
End Sub


Public Sub ToggleButtonState(hWnd As Long, lState As Long)
Call SendMessage(hWnd, BM_SETSTATE, lState, ByVal 0&)
End Sub

bFlag is a project level setting you're tracking with the button state.

The big problem, and initial issue with this post, is that the button seems to lose the effect when focus is lost. Further complicating the issue, the Command_LostFocus is only fired when you click some controls and not others in VB (but the effect is lost on all), so your main form has to be subclassed to intercept the BN_KILLFOCUS message (the button itself need not be subclassed).

Code:

Public Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

'[...other subclass code]
    Case WM_COMMAND
        Dim lCode As Long
        lCode = HiWord(wParam)
        Select Case lCode
            Case BN_KILLFOCUS
                If lParam = hBtn Then
                    If bFlag Then
                        Call SendMessage(hBtn, BM_SETSTATE, 1&, ByVal 0&)
                    End If
                End If
                WndProc = 1
                Exit Function
'[...other subclass code


I know this is rather trivial, but when I came across the problem I saw lots of people asking and no adequate solutions. In modern UI's there's lots of places I prefer toggle buttons to checkboxes, so figured someone else might come across the same issue one day.


Declares and Supports
Code:

Public Const BM_SETIMAGE = &HF7
Public Const BM_SETSTATE = &HF3
Public Const BS_LEFT = &H100&
Public Const BS_NOTIFY = &H4000&
Public Const BN_KILLFOCUS = 7&
Public Const WM_COMMAND = &H111

Public Const GWL_STYLE = (-16)
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
                                                                    Source As Any, _
                                                                    ByVal Length As Long)

Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, _
                                                                      ByVal wMsg As Long, _
                                                                      ByVal wParam As Long, _
                                                                      lParam As Any) As Long

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, _
                                                                          ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, _
                                                                          ByVal nIndex As Long, _
                                                                          ByVal dwNewLong As Long) As Long
Public Function SetButtonStyle(hWnd As Long, dwNewStyle As Long, Optional bAdd As Boolean = True) As Long
Dim dwStyle As Long
If bAdd Then
    dwStyle = GetWindowLong(hWnd, GWL_STYLE)
End If
dwStyle = dwStyle Or dwNewStyle
SetButtonStyle = SetWindowLong(hWnd, GWL_STYLE, dwStyle)
End Function

Public Function HiWord(dwValue As Long) As Integer
  CopyMemory HiWord, ByVal VarPtr(dwValue) + 2, 2
End Function

How to make a new Ctrl-Break key.

$
0
0
My new Win 8.1 system keyboard doesn't have a Ctrl-Break key, and I found that extremely annoying when working with Visual Basic. So with some research, I located some info on how to disable the Caps Lock key. In the registry locate the key, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout
and add a binary value:
"Scancode Map" = 00 00 00 00 00 00 00 00 02 00 00 00 00 00 3a 00 00 00 00 00
The first 8 bytes are always zero.
The next 4 bytes are one more than the number of keys being mapped.
The next 2 bytes are the key code that you want to map to (in this case 00 00).
the next 2 bytes are the key code that you want to change (Caps Lock = 3A 00).
The last 4 bytes are always zero.
I decided to use the Ctrl-F12 key as a Ctrl-Break, and finding the key codes for those was a little more difficult.
"Scancode Map" = 00 00 00 00 00 00 00 00 02 00 00 00 46 e0 58 00 00 00 00 00
Reboot the system for the changes to take effect, and you have a new Ctrl-Break key.

J.A. Coutts
Attached Images
 

VB6 Dual-Pivot-QuickSort

$
0
0
Just to throw something new (for VB6) into the ring of competing Sort-Algos...

I've just finished porting (from Java-SourceCode) the relative new (Sep. 2009) Dual-Pivot-Algorithm, invented by
Vladimir Yaroslavskiy, who has tuned good old QuickSort significantly, leaving over next to zero disadvantages.

Here his posting, which finally led to the inclusion of this new algorithm into the official Java-SDK (used in Java.Array)
http://permalink.gmane.org/gmane.com...ibs.devel/2628

The source for this new Algo is contained in the attached Demo-Zip.

Here's a Screenshot, which shows its performance with different kinds of Input-Data:
With normal (random) Data it shows no disadvantages to a Standard-QuickSort -
but offers huge improvements over "naive Quicksorts" when fed with "inconvenient data".

As a side-note:
HeapSort is outperformed in all tests quite significantly by the DualPivot-Algo...
HeapSort is also beaten by the naive QuickSort in all tests, except the one with constant Data.



Olaf
Attached Files

Fix for SSTab not correctly handling focus and comboboxes

$
0
0
Make a Class module out of the following code, create an object with it for any form that uses the SSTab control and follow directions in comments.

Code:

'
' ****************************************************************
' ****************************************************************
' ****************************************************************
' This program is free software: you can redistribute it and/or
' modify it under the terms of the GNU General Public License
' version 3 as published my the Free Software Foundation:
' http://www.gnu.org/licenses/gpl.html
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
'
' This software was originally written by Elroy Sullivan, PhD in
' cooperation with Shriners Hospitals for Children, Houston.
' Dr. Sullivan can be reached at elroysullivan@gmail.com.
' ****************************************************************
' ****************************************************************
' ****************************************************************
'
Option Explicit
'
Dim WithEvents tabCtl As SSTab
Dim frm As Form
Dim TabStops() As Boolean
'
' A primary purpose of this fix is to correctly control the tab stops.
' To make the appearance of tabs, the SSTab control simply moves the controls out of view.
' An artifact of this approach is that the controls are still able to get the focus when the
' user uses the TAB key.  The following code corrects this problem by appropriately turning
' on and off the TabStop properties of the controls as the user tabs from one tab to another.
'
' Another problem has to do with ComboBoxes.  When changing to a new tab, dropdown comboboxes
' will have their text selected.  The combobox will not have the focus, but their text will be
' selected.  The primary problem with this is that it right-justifies the text when there is more
' text than will fit in the textbox portion of the combobox, and this is confusing to users.
' This problem is corrected in the following code.
'

Friend Sub SetTabControl(TheTabControl As SSTab, TheForm As Form)
    ' Call this in the form load event.
    Dim ctl As Control
    Dim ptr As Long
    '
    Set tabCtl = TheTabControl
    Set frm = TheForm
    '
    ' Store the true value of the TabStops.
    ReDim TabStops(0 To frm.Controls.Count - 1)
    ' Not all controls have TabStop property, so we must set error trapping.
    On Error Resume Next
    For ptr = 0 To frm.Controls.Count - 1
        TabStops(ptr) = frm.Controls(ptr).TabStop
    Next ptr
    On Error GoTo 0
End Sub

Friend Sub SetTabStopsAccordingly()
    ' Call this in the form activate event.
    ' After this first call, it will automatically be called when the tabs change.
    Dim ctl As Control
    Dim ctlTheControlOrContainer As Control
    Dim ItsOnTheTabControl As Boolean
    Dim ptr As Long
    '
    For ptr = 0 To frm.Controls.Count - 1
        Set ctl = frm.Controls(ptr)
        Set ctlTheControlOrContainer = ctl ' The control might be on a container that's on the SSTab, rather than directly on the SSTab.
        Do
            Select Case True
            Case TypeOf ctlTheControlOrContainer.Container Is SSTab
                ItsOnTheTabControl = True
                Exit Do ' The way out.
            Case TypeOf ctlTheControlOrContainer.Container Is Form
                ItsOnTheTabControl = False
                Exit Do ' The way out.
            End Select
            Set ctlTheControlOrContainer = ctlTheControlOrContainer.Container ' Must deal with controls nested deeper than the SSTab control.
        Loop
        If ItsOnTheTabControl Then
            ' Not all controls have TabStop property, so we must set error trapping.
            On Error Resume Next
            If ctlTheControlOrContainer.Left >= 0 Then
                ctl.TabStop = TabStops(ptr) ' If it's showing, restore the original TabStop value.
                ' Must also fix the problem with combo boxes having an internal focus set.
                ctl.SelStart = 0
                ctl.SelLength = 0
            Else
                ctl.TabStop = False
            End If
            On Error GoTo 0
        End If
    Next ptr
End Sub

Private Sub tabCtl_Click(PreviousTab As Integer)
    SetTabStopsAccordingly
End Sub

Private Sub tabCtl_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    ' This allows other controls to close up when user click off.
    ' The problem is that clicking into the body of the tab control does NOT cause change in focus.
    ' The control with the focus keeps it, and it may not close up as typically happens when clicking on dead space of a form.
    ' You may also want to consider placing this "SetFocus" code on the labels on the tabs.  This is NOT automatically done
    ' because the programmer may want to use a label click for other purposes.
    tabCtl.SetFocus
End Sub

Simple Bingo Engine

$
0
0
Hey guys, I made this Bingo Engine, in case any of you guys need ideas on how to make one or need one, there you go. I have also included a small demo project.
Attached Files

Random number generator

$
0
0
Here is a small program that demonstrate a random number generator. There are two buttons and a listbox. We can see the frequencies of each of 100 numbers (from 0 to 99). We produce 2000000 random numbers. With the left button is mine generator the other is the vb generator. In Ide vb generetor is faster, but in compiled code mine generator is 2 times quicker. Why? First I would like more span to the frequencies, and the function give a number form 0 to 9999. In mine computer needed 1 seconds for 2 million random numbers, and 2 seconds using the vb function.
Attached Files

[VB6] Call Functions By Pointer

$
0
0
I was recently made aware that a function I've used from time to time for calling virtual functions of COM objects was perfectly adept at calling functions from just about any standard DLL out there. So, I whipped up a 'generic' class that can call both standard DLL functions & COM VTable functions. No thunks are used, just a couple of supporting API calls in the main class, including the low-level core API function: DispCallFunc

What does this mean for you? Well, it does allow you to call DLL functions from nearly 10 different calling conventions, including CDecl. It also allows you to call virtual functions from COM objects.

I'd consider this topic advanced for one reason only. This is very low level. If you provide incorrect parameter information to the class, your project is likely to crash. For advanced coders, we have no problem doing the research to understand what parameter information is required, be it variable type, a pointer, a pointer to a pointer, function return types, etc, etc. Not-so-advanced coders just want to plug in values & play, but when playing at such a low level, that usually results in crashes, in frustration.

The attachment includes very simple examples of calling DLL functions and calling a COM virtual function. You will notice that the form has no API function declarations, though several DLL functions are called & executed correctly.

For DLL calls, the class takes the DLL name and function name to be called. Technically, you aren't passing the function pointer to the class. However, the class does make the call to the pointer, not via declared API functions. Just thought I'd throw this comment in, should someone suggest we aren't really calling functions by pointer. The class is, the user calling the class is not, but can be if inclined to modify the code a bit.

Tip: If you really like this class, you may want to instantiate one for each DLL you will be calling quite often. This could speed things up a bit when making subsequent calls. As is, the class will load the requested DLL into memory if it isn't already. Once class is called again, for a different DLL, then the previous DLL is unloaded if needed & the new DLL loaded as needed. So, if you created cUser32, cShell32, cKernel32 instances, less code is executed in the class if it doesn't have to drop & load DLLs.
Code:

' top of form
Private cUser32 As cUniversalDLLCalls
Private cKernel32 As cUniversalDLLCalls
Private cShell32 As cUniversalDLLCalls
' in form load
Set cUser32 = New cUniversalDLLCalls
Set cKernel32 = New cUniversalDLLCalls
Set cShell32 = New cUniversalDLLCalls
' now use cUser32 for all user32.dll calls, cKernel32 for kernel32, cShell32 for shell32, etc

Attached Files

[VB6] Lickety - an alternative to Slurp'n'Split

$
0
0
We're in a time of PCs with vast amounts of RAM and little going on in the background, despite money being spent on multi-core CPUs. What was once considered a crude and naive practice of slurping entire text files into a String and then calling Split() to make an array is now actually touted by many programmers.

But much as the practice of Slurp'n'Split was impractical when far smaller amounts of RAM were available, it can break down when you deal with large files.

First you have the problem of an ANSI text file doubling in size in RAM as soon as your slurp it. Then you double that again by calling the Split() function, at least until you discard the original intact String. Both of these together conspire against you for the maximum file size you can process no matter how much RAM you bought on Mommy's credit card: VB6 programs can only use just so much due to 32-bit and other design limitations.

To add insult to injury, Split() was taken over almost without modification from VBScript and never designed for high performance on large amounts of data. That just wasn't one of its design goals.


So What's A Slurp'n'Splitter To Do?

VB5 didn't get a Split() function, and this led the fans at VBspeed to create several alternative equivalents. And of course being VBspeed they worked out some clever optimizations.


Lickety Class

My Lickety.cls was based on some of those Split() alternatives, adding in the reading of the file in chunks for better memory efficiency.

The performance is pretty good, and as soon as your input file is much over 10KB of ANSI text it quickly overtakes a Split() call in both performance and memory requirements. This advantage just grows with the size of the input file.

It has options to read ANSI or Unicode (UTF-16LE) files, optionally skip the Unicode BOM, and whatever line delimiter you choose.

It also takes care of discarding the "dangler" empty line at the end of the file, unlike a Split() call.

I haven't looked it over to be sure but it may work in VB5 as well if you work around the returning of the array (VB5 can't have array-valued functions).


Demo

The demo runs through several rounds of using Lickety and Split() to load the text lines from files of several record lengths and record counts, reporting elapsed time for each test.

Name:  sshot.png
Views: 3
Size:  7.7 KB

Your mileage may vary.
Attached Images
 
Attached Files

[VB6] Call Functions By Pointer (Universall DLL Calls)

$
0
0
I was recently made aware that a function I've used from time to time for calling virtual functions of COM objects was perfectly adept at calling functions from just about any standard DLL out there. So, I whipped up a 'generic' class that can call both standard DLL functions & COM VTable functions. No thunks are used, just a couple of supporting API calls in the main class, including the low-level core API function: DispCallFunc

What does this mean for you? Well, it does allow you to call DLL functions from nearly 10 different calling conventions, including the two most common: StdCall & CDecl. It also allows you to call virtual functions from COM objects.

I'd consider this topic advanced for one reason only. This is very low level. If you provide incorrect parameter information to the class, your project is likely to crash. For advanced coders, we have no problem doing the research to understand what parameter information is required, be it variable type, a pointer, a pointer to a pointer, function return types, etc, etc. Not-so-advanced coders just want to plug in values & play, but when playing at such a low level, that usually results in crashes, frustration.

The attachment includes very simple examples of calling DLL functions and calling a COM virtual function. You will notice that the form has no API function declarations, though several DLL functions are called & executed correctly.

For DLL calls, the class takes the DLL name and function name to be called. Technically, you aren't passing the function pointer to the class. However, the class does make the call to the pointer, not via declared API functions. Just thought I'd throw this comment in, should someone suggest we aren't really calling functions by pointer. The class is, the user calling the class is not, but can be if inclined to modify the code a bit.

Tip: If you really like this class, you may want to instantiate one for each DLL you will be calling quite often. This could speed things up a bit when making subsequent calls. As is, the class will load the requested DLL into memory if it isn't already. Once class is called again, for a different DLL, then the previous DLL is unloaded if needed & the new DLL loaded as needed. So, if you created cUser32, cShell32, cKernel32 instances, less code is executed in the class if it doesn't have to drop & load DLLs.
vb Code:
  1. ' top of form
  2. Private cUser32 As cUniversalDLLCalls
  3. Private cKernel32 As cUniversalDLLCalls
  4. Private cShell32 As cUniversalDLLCalls
  5.  
  6. ' in form load
  7. Set cUser32 = New cUniversalDLLCalls
  8. Set cKernel32 = New cUniversalDLLCalls
  9. Set cShell32 = New cUniversalDLLCalls
  10. ' now use cUser32 for all user32.dll calls, cKernel32 for kernel32, cShell32 for shell32, etc
Tip: When using the STR_ANSI flag to indicate the passed parameters include string values destined for ANSI functions, the class will convert the passed string to ANSI before calling the function. Doing so, default Locale is used for string conversion. If this is a problem, you should ensure you convert the string(s) to ANSI before passing it to the class. If you do this conversion, use STR_NONE & pass the string via StrPtr(). FYI: strings used strictly as a buffer for return values should always be passed via StrPtr() and the flag STR_NONE used; regardless if destined for ANSI or unicode functions.
vb Code:
  1. ' how to have a VB string contain ANSI vs Unicode
  2. myString = StrConv(myString, vbFromUnicode, [Locale ID])
  3. ' how to convert the returned ANSI string to a proper VB string
  4. myString = StrConv(myString, vbUnicode, [Locale ID])
Attached Files

[VB6] Clipboard/DataObject Extension Class

$
0
0
The attached class extends VB's Clipboard and Data objects. Change its extension from .txt to .cls after downloading.

1) Support for dragging and pasting virtual files. Virtual files exist in Windows compressed folders. They also can be transfered from any application that wishes to use the registered clipboard format. Outlook, for example, uses it when dragging emails & attachments. VB does not natively support this format

2) Support for unicode file names. The clipboard's & data object's Files collection is not unicode compatible. This class replicates the Files collection that is unicode compatible.

3) Adding custom formats and standard formats to the clipboard that VB does not support natively. This class offers two methods to add data to the clipboard and data object.

The attached class also includes, for convenience, all the methods of VB's clipboard and data objects. If you use this class, you should not need to call some methods from it and some methods from VB's objects. However, you are not prevented from using VB's methods for its objects.

Virtual files used here, do not refer to files dragged out of a WinZip file. WinZip extracts the file to a temporary folder and then provides the full path/file name of the file. The dragged data was unzipped and written to file and the file(s) are accessible to VB normally. Windows compressed folders do not do this when dropping on your form.

How does the class enable virtual file access? It uses a low-level API to communicate with VB's IDataObject. That object allows us to ask the source for specific information that VB doesn't expose. No existing APIs, that I'm aware of, expose that data either. With this IDataObject, we have full control for retrieval of anything pasted to the clipboard or dropped via OLE.

One more note about virtual files. As mentioned above, don't think of these as actual files. Think of them as simply blobs of data. The file names provided by the source application should be considered for information only. Do not consider those actual file names, they may not be. Could be an Outlook attachment name. Do not assume they do not contain invalid file name characters. To view or save these data blobs, the class includes methods for saving the blobs to file or array.

Examples of a few "file names" dragged out of a Windows compressed folder follows. Notice there is no qualified path. These are not traditional files, just blobs of data.
Code:

license.txt
readme.txt
inc\jpegdecoder.h  << sub-folder items in compressed folder
inc\jpegdecoder.inl
inc\main.h

And here's an email dragged out of Outlook Express:
Code:

Welcome to Outlook Express 6.eml
Will update the class from time to time to repair errors and/or enhance.

The code is well commented. Take the time to read thru the comments at the top of the class and those comments provided with the public methods/properties.
Attached Files

mistaken post

$
0
0
please save my sorry dumb butt from this and allow us to delete our own threads

VB6 Mercator-Projection (or - how to handle lots of small objects on a Picturebox)

$
0
0
Just a small Demo, which demonstrates a Mapping for Latitude/Longitude based Coords into
a Mercator-Projected MapImage (the Background-image of a VB-PictureBox).

What's often preferred (in case one has to handle a lot of "Sub-Objects" or "Sub-Regions"
on such a Container-Control) - is normal VB-Labels or VB-Shape-Objects - usually "inherited"
from an Index-Zero Member of VBs Control-Arrays.

Though Control-Arrays behave a bit clumsy as far as dynamic removing/adding in-between
an existing List of Objects goes... so - that's the reason why I made this post, to break a lance
for a Collection-based approach which takes up and holds the instances of small alternative
ShapeClasses (any of VBs Shape-Like Controls can be replaced by a Class and a few Drawing-Commands).

Here's the complete Class-Code for the alternative Label-Shape which is used in the Demo.
Code:

Option Explicit

Private Declare Function Rectangle& Lib "gdi32" (ByVal hDC&, ByVal X1&, ByVal Y1&, ByVal X2&, ByVal Y2&)

Public Key As String                          'a unique Key for identification (we are added into a Collection under it)
Public Longitude As Single, Latitude As Single 'centerpoint of the Label in Lat/Lng-coords
Public cx As Single, cy As Single              'Pixel-centerpoint of the Label on the PicBox
Public Radius As Long, Color As Long, ToolTipText As String, Hovered As Boolean

Friend Sub Init(Key, cx, cy, Lat, Lng, Optional ByVal Radius& = 3, Optional ByVal Color&, Optional ToolTipText$)
  Me.Key = Key
  Me.cx = cx: Longitude = Lng
  Me.cy = cy: Latitude = Lat
 
  Me.Radius = Radius
  Me.Color = Color
  Me.ToolTipText = ToolTipText
End Sub

Public Sub DrawOn(Cont As PictureBox)
  Cont.ForeColor = vbYellow
  Cont.FillColor = IIf(Hovered, vbCyan, Color)
  Rectangle Cont.hDC, cx - Radius, cy - Radius, cx + Radius, cy + Radius 'GDI is a bit faster than VBs Line-Method
End Sub

The approach in the Zip below is fast, behaves flickerfree - it reports the current MousePos
in both Coord-Systems (Pixels - and Lat/Lng) - it supports hovered highlighting of the current
Shape-Object under the Cursor - as well as dynamic ToolTips for each of the Shape-Objects separately.

It does that in a quite small CodeBase, so for those who have Label-based approaches out there -
compare carefully if that's not something to switch over - even if it's a bit out of your comfort-zone. ;)


Mercator.zip

Olaf
Attached Files

VB6 Render PDF-Files directly (and generate a Preview from the same DrawingRoutine)

$
0
0
Since the PDF-Printing-Topic comes up occasionally - sometimes with recommendations and links to
VB-Modules which try to write a PDF-file directly - the PDF-support of the cairo-lib (wrapped conveniently
in vbRichClient5.dll) is "miles ahead" of all these approaches in terms of functionality (the supported
Drawing-Commands) - and reliability (correctness of the generated PDF-Output).

So here's a small VB6-Demo which shows how to use a vbRichClient5.cCairoSurface instance, which
can also be created as "being of cairo-SurfaceType PDF" instead of the usual "ImgSurface-Type" which
is pixelbased and used for OnScreen-Output (BTW, another true VectorSurface-type is e.g. SVG,
which other than PDF can not only be written directly, but also read).

Anyways, in the end we are able to perform the very same Drawing-Commands against a CairoSurface
of type PDF, the same way as we are wont, when we take a CairoSurface of Type "Image" (which then
just renders antialiased against a Pixel-area to bring out the results of the VectorDrawing-Commands).

That transparently usable multi-surface-support of Cairo is one of the greatest advantages of this library IMO.

The demo will print two Pages (only the first one is currently rendered and shown as an OnScreen-Preview) -
but in the PDF-Document we will end up with a Portrait-Page - followed by a Landscape-Page with somewhat
different (simpler) content ( just wanted to show how to handle the swapping of Page-Orientations "on the go",
so that's the purpose of the simpler Landscape-Page).

Ok, here's the Demo-Code (which references the vbRichClient5 dependency, you will
have to download and install first, to be able to run the Example... from vbRichClient.com).
SimplePDF.zip

And here's a ScreenShot of the VB-OnScreen-Preview of the first Page - accompanied to the right
with the Preview of the PDF-Viewer (adjusted to show the two contained PDF-Document-Pages).



Edit: added a missing info to the RichClient-Library, this PDF-Demo depends on.

Olaf
Attached Files

VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

$
0
0
Think, that this topic is an important one - and deserves its own article.

Hmm, how to begin...

Once there was a time,
in the dark ages,
long before "Manifestos" became available to human beings,
that VB-Developers fought all kinds of Dll-Hell...


Erm, all of them? ...No... ;)

So this is about an approach which is an alternative to the Manifest-triggered SxS-Services
we can use today, reliably and succesfully in usage for nearly two decades now (it was working
already on Win95/Win98 - and still works up to the recent Win8.1 or Win10).

It is IMO the more flexible approach - and relative easy to incorporate into your Apps,
by dropping-in a simple *.bas Module which can remain constant, codewise (no Manifests
to keep in sync with your COM-Dlls TypeLib-informations, in case one recompiles these
Dlls without Binary-Compatibility).

Ok, let's come to the point:
(will try to roll this out a bit, in a style which is hopefully more Newbie-friendly to read).

You plan, to ship your own 'MyActiveX.dll' alongside your 'MyApp.exe' -
in addition to 'ForeignActiveX.dll', which you made use of in your App too.

Well, first thing I would suggest when you plan to ship your App regfree is, to do it "orderly" - by
ensuring a certain Folder-Structure (in your Zip, or whatever you will use for packaging in the end).

What I usually go with is a Folder-Structure as:
\MyApp\
.... \Bin\
.... \Res\
.... MyApp.exe

Aside from MyApp.exe (and maybe a MyAppSettings.ini) not much more in the Apps Root-Folder.

This way the user (after unpacking your regfree deployed App into his own Target-Foder)
can immediately see, "where the Startup-Point is" (and what to click).

Well, forgot to congratulate you first, because when you read this article, you already did the mental step from:
"I need to compile everything into a single Executable"
to:
"I'm far more flexible, when I have certain things in my own, dedicated Dll-Binaries"
accompanied hopefully by:
"I'm also more efficient, when I re-use good work of others, avoiding re-inventions of the wheel"

So, what would reside in your relative Subfolder \Bin\ now? All the Dlls of course:
\MyApp\
.... \Bin\
........ MyActiveX.dll
........ ForeignActiveX.dll
.... \Res\
.... MyApp.exe

To make the approach I'm talking about work, what you need in addition is a Helper-Dll, which is a
Standard-Dll that needs no registering: DirectCOM.dll - so, adding it - your Folder-Structure should look then:
\MyApp\
.... \Bin\
........ DirectCOM.dll
........ MyActiveX.dll
........ ForeignActiveX.dll
.... \Res\
.... MyApp.exe

With such a Folder-Structure in place (and the Bin-Folder filled with the right Binaries),
what you need now in your App is a *.bas Module with the following content:

(in my Demo-Zip for this article, I named this Module: modRegfreeDlls.bas
Code:

'A readymade "PlugIn-Module" you can include into your Projects, to be able to load Classes from COM-Dlls
'without registering them priorily - and just to be clear - there is no "dynamic re-registering" involved -
'DirectCOM.dll will load the appropriate Class-Instances without touching the Systems Registry in any way...
'
'There's 3 Functions exposed from this Module:
'- GetInstanceFromBinFolder ... loads Classes from Dlls located in a SubFolder, relative to your Exe-Path
'- GetInstance              ... same as above - but allowing absolute Dll-Paths (anywhere in the FileSystem)
'- GetExePath              ... just a small helper, to give the correct Exe-Path, even when called from within Dlls
'
'the approach is *very* reliable (in use for nearly two decades now, it works from Win98 to Windows-10)
'So, happy regfree COM-Dll-loading... :-) (Olaf Schmidt, in Dec. 2014)

Option Explicit

'we need only two exports from the small DirectCOM.dll Helper here
Private Declare Function GetInstanceEx Lib "DirectCOM" (spFName As Long, spClassName As Long, Optional ByVal UseAlteredSearchPath As Boolean = True) As Object
Private Declare Function GETINSTANCELASTERROR Lib "DirectCOM" () As String

Private Declare Function LoadLibraryW& Lib "kernel32" (ByVal lpLibFileName&)
Private Declare Function GetModuleFileNameW& Lib "kernel32" (ByVal hMod&, ByVal lpFileName&, ByVal nSize&)
 
'a convenience-function which loads Classes from Dlls (residing in a SubFolder below your Exe-Path)
'just adjust the Optional RelBinFolderName-Param to your liking (currently specified as "Bin")
Public Function GetInstanceFromBinFolder(ByVal ShortDllFileName As String, ClassName As String, _
                                        Optional RelBinFolderName$ = "Bin") As Object
  Select Case LCase$(Right$(ShortDllFileName, 4))
    Case ".dll", ".ocx" 'all fine, nothing to do
    Case Else: ShortDllFileName = ShortDllFileName & ".dll" 'expand the ShortFileName about the proper file-ending when it was left out
  End Select

  Set GetInstanceFromBinFolder = GetInstance(GetExePath & RelBinFolderName & "\" & ShortDllFileName, ClassName)
End Function

'the generic Variant, which needs a full (user-provided), absolute Dll-PathFileName in the first Param
Public Function GetInstance(FullDllPathFileName As String, ClassName As String) As Object
  If Len(FullDllPathFileName) = 0 Or Len(ClassName) = 0 Then Err.Raise vbObjectError, , "Empty-Param(s) were passed to GetInstance"
 
  EnsureDirectCOMDllPreLoading FullDllPathFileName 'will raise an Error, when DirectCOM.dll was not found in "relative Folders"
 
  On Error Resume Next
    Set GetInstance = GetInstanceEx(StrPtr(FullDllPathFileName), StrPtr(ClassName), True)
  If Err Then
    On Error GoTo 0: Err.Raise vbObjectError, Err.Source & ".GetInstance", Err.Description
  ElseIf GetInstance Is Nothing Then
    On Error GoTo 0: Err.Raise vbObjectError, Err.Source & ".GetInstance", GETINSTANCELASTERROR()
  End If
End Function

'always returns the Path to the Executable (even when called from within COM-Dlls, which resolve App.Path to their own location)
Public Function GetExePath(Optional ExeName As String) As String
Dim S As String, Pos As Long: Const MaxPath& = 260
Static stExePath As String, stExeName As String
  If Len(stExePath) = 0 Then 'resolve it once
    S = Space$(MaxPath)
    S = Left$(S, GetModuleFileNameW(0, StrPtr(S), Len(S)))
    Pos = InStrRev(S, "\")
   
    stExeName = Mid$(S, Pos + 1)
    stExePath = Left$(S, Pos) 'preserve the BackSlash at the end
    Select Case UCase$(stExeName) 'when we run in the VB-IDE, ...
      Case "VB6.EXE", "VB5.EXE": stExePath = App.Path & "\" 'we resolve to the App.Path instead
    End Select
  End If
 
  ExeName = stExeName
  GetExePath = stExePath
End Function

Private Sub EnsureDirectCOMDllPreLoading(FullDllPathFileName As String)
Static hDirCOM As Long
  If hDirCOM Then Exit Sub  'nothing to do, DirectCOM.dll was already found and pre-loaded
  If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "DirectCOM.dll"))
  If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "Bin\DirectCOM.dll"))
  If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "RC5Bin\DirectCOM.dll"))
  If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(App.Path & "\DirectCOM.dll"))
  If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(Left$(FullDllPathFileName, InStrRev(FullDllPathFileName, "\")) & "DirectCOM.dll"))
  If hDirCOM = 0 Then Err.Raise vbObjectError, Err.Source & ".GetInstance", "Couldn't pre-load DirectCOM.dll"
End Sub

With that module in place, you have now two globally reachable (Public) Functions available:
- GetInstanceFromBinFolder(...)
- GetInstance(...)

The first one is the more conveniently usable one, because it saves you from giving
"Full explicit Paths to your Dll-Binaries", so for ActiveX-Dlls in your own Bin-Folder,
all you need to instantiate a Class from one of them is e.g.:

Code:

Dim oMyClass
Set oMyClass = GetInstanceFromBinFolder("MyActiveX", "cMyClass")
    oMyClass.DoSomething

Note, how the above Form resembles the well-known ProgID-based instancing per CreateObject:
Code:

Dim oMyClass
Set oMyClass = CreateObject("MyActiveX.cMyClass")
    oMyClass.DoSomething

And in fact, both versions accomplish the same thing - both create a new Object-Instance - just that
CreateObject needs a registered version of 'MyActiveX.dll', whilst GetInstanceFromBinFolder does not.

The second available Function from the *.bas Module (GetInstance) is just the explicit form,
which you can give a full absolute path into the FileSystem, to specify a certain Dll ...
otherwise the behaviour (and results) are the same as those from GetInstanceFromBinFolder.

Well, that's it already - a Helper-*.bas Module (in conjunction with a Helper-Dll in your Bin-Folder)
can ensure regfree loading, over a relative easy to use function (GetInstanceFromBinFolder).

You have to make sure though, that you use this Function now consequently throughout
your whole App, when it comes to the instantiation of Classes from your regfree shipped Dlls.

To ensure that, you should scan through your whole App, using a project-wide Code-search for
the String: [New ] (.... leaving out the brackets of course - but include the space-char at the end).

This will stop at all code-lines where you do an Object-Instantiation - change all New MyClass
occurences then into the appropriate GetInstanceFromBinFolder(...) replacements - of course
only for Classes which are defined in those Dlls - one doesn't need to replace the instantiation
of a normal VB-Collection - or an ADO-Recordset, since those are always available directly
(contained in the VB-Runtime or in case of ADO - coming preinstalled on a given System).

I know - if your Project is not a small one, this is quite a boring "Identify-And-Paste"-task
but not that time-consuming as one might think (I never needed more than 3-10 minutes for
those replacements, even in larger projects and with "double-checking").

So, that's it with regards to describing the usage of a regfree-alternative to SxS-Manifests.

The latest version of DirectCOM.dll is contained in the vbRichClient5-BaseDlls package on:
http://vbrichclient.com/#/en/Downloads.htm

What remains is a few words to the following Demo, in case you want to use this as a first
Code-base for your own tests:RegfreeDeployment.zip

I've tried to make it a real-world example, which involves also your own compiled ActiveX-Dll.

So, before starting the Demo Project-File: RegfreeDeploymentOfDlls.vbp ...
You should go one Folder-Deeper into: \TestDllProject\ ...
Start-up the ActiveX-Dll-Project: MyTest.vbp there ...
And compile the appropriate Dll from it into the \Bin\ Folder we already talked about above.

What this Demo shows in addition, is a scenario including some these "ForeignActiveX.dlls" which
were mentioned earlier already (using the 3 Base-Dlls of the vbRichClient-framework as an example -
since one of these Dlls, DirectCOM.dll, is needed anyways for the approach to work).

So, after downloading the vbRC5BaseDlls.zip - make sure you copy all 3 Dlls it contains:
DirectCOM.dll
vbRichClient5.dll
vb_cairo_sqlite.dll
Into the Demos \Bin\ Folder too.

So, what you will need to end up with, before starting the Main-Project: RegfreeDeploymentOfDlls.vbp
is the following FolderStructure (reusing the Schema I've introduced above):

\RegfreeDeployment\
.... \Bin\
........ DirectCOM.dll
........ MyTest.dll
........ vbRichClient5.dll
........ vb_cairo_sqlite.dll
.... \Res\
........ BackGround.jpg
........ SomeSvgIcon.svg
........ SomePngIcon.png
.... RegfreeDeploymentOfDlls.vbp
.... modRegfreeDlls.bas
.... modMain.bas
.... fTest.frm

If that above Folder-Structure is given, then you will succeed in running the Demo, which
then should come up this way:



Olaf
Attached Files

WinpkFilter VB6 Samples

$
0
0
The WinpkFilter development kit no longer includes VB6 samples. Version 3.2.3 has added support for IPv6, resulting in a number of changes to the data formats. I have taken the liberty to update the older samples to support the newer formats, and with permission, I am posting them here.

Unfortunately I still have not got the low level filter table to load, but I will post the results upon completion.

J.A. Coutts
Attached Files
Viewing all 1524 articles
Browse latest View live


Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>