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

Unicode aware VB6 functions replacement

$
0
0
Hi,

here is W replacement for several native VB6 functions / properties:

- Dir -> DirW()
- MkDir -> MkDirW()
- Environ -> EnvironW()
- App.Path -> AppPathW()
- App.ExeName -> AppExeNameW()
- App.Major, Minor, Revision -> AppVersionW()

All functions packed on archive as separate projects, available under the post below.

1) DirW

Prototype is: Dir$(Path with mask or backslash at the end, opt_mask of allowed attributes, opt_return folders? )

Difference to original VB6 Dir$():

Fixed bug, when Dir cannot handle attribute: read only (vbReadOnly)
Added attributes:
- reparse points (symlinks / junctions) (vbReparse)
- all file objects (vbAll)
- vbFile (files only, without folders)

Enum VbFileAttribute "overloaded" by own: I removed all superfluous attributes, which original VB6 dir() are still not used in any way; I leave meaningful attributes only.

+ 3-rd optional argument (FoldersOnly); if true, it will filter files and leave folders only in output.
Function also automatically filter folders-aliases "." и ".."

Code based on earlier VB6() Dir$ reversing by @The Trick.

2) MkDirW()

Prototype is: MkDirW(Path to folder to create, opt_LastComponentIsFile as boolean) as boolean

LastComponentIsFile - true, if you plan to specify filename as a last part of path component
Return value: true, if successfully created or if folder is already exist

3) EnvironW()

Prototype: EnvironW$( "%Environment variable(s)%" )

Difference to original VB6 Environ():

- support several env. var-s on one line, like EnvironW("%UserName% - %UserDomain%")
- require %var%, i.e. each environment variable should be surrounded by % signs.
- automatically correct and "right" (in the sense, like if we wanted to do so from a 64-bit application) to expand under WOW64 such env. variables as:
- %PROGRAMFILES%
- %COMMONPROGRAMFILES%
and get on 64-bit OS, respectively:
- C:\Program Files, but not C:\Program Files (x86)
- C:\Program Files\Common Files, but not C:\Program Files (x86)\Common Files

4,5) AppPathW(), AppExeNameW()

Prototypes are:
- AppPathW$(opt_bGetFullPath as boolean)
- AppExeNameW$(opt_WithExtension As Boolean)

Self-explained:
Code:

    Debug.Print AppPathW()                          'Folder
    Debug.Print AppPathW(bGetFullPath:=True)        'Folder\FileName.extension
    Debug.Print AppExeNameW()                      'FileName
    Debug.Print AppExeNameW(WithExtension:=True)    'FileName.extension

6) AppVersionW()

Prototype is: AppVersionW$()

# require AppPathW(), AppExeNameW()

Just append unicode-char to your exe-name /and-or path (e.g. ALT + 3333) and you'll understand why you may need this function replacement.

Returns: String, version of your program in format: Major.Minor.Build.Revision
___________________

Best wishes,
Alex.
Attached Files

Here's a better way to generate random nums than using Rnd

$
0
0
Using Rnd always gives you the same set of numbers, whenever you start the program. Even if you use Randomize first to set a random number seed at the start of the program, it will eventually cycle through all the numbers (plus there are certain patterns of numbers that you can see under certain situations). You can get a much better random number generator (in fact, cryptographically secure level of randomness) if you used the crypto API functions. Here's a simple program I made to demonstrate how to use the crypto API to generate random numbers.

Code:

Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptGenRandom Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwLen As Long, ByRef pbBuffer As Any) As Long

Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)

Dim hProv As Long
Dim Quit As Boolean

Private Sub Form_Load()
    Dim a As Long
    CryptAcquireContext hProv, vbNullString, vbNullString, 1, 0
   
    If hProv = 0 Then
        Unload Me
        Exit Sub
    End If
   
    Show
    Do Until Quit
        CryptGenRandom hProv, 4, a
        Cls
        Print a
        Sleep 100
        DoEvents
    Loop

End Sub

Private Sub Form_Unload(Cancel As Integer)
    Quit = True
    If hProv Then CryptReleaseContext hProv, 0
End Sub

Just paste the above code into your Form1, and make sure that its AutoRedraw property is set to True. Then run the program, it will generate a new random number every tenth of a second (that's what "Sleep 100" is for). I have it doing that instead of running at max speed, so as not to max out your CPU cycles and cause unnecessary heating of your computer if you leave it running for a while. If you don't intend to have it running for a long time, you can remove the Sleep 100 line of code, so it can run at maximum speed (limited only by your CPU speed). Just close the Form1 window to end the program (make sure you DON'T use the stop button in the VB6 IDE, or the Unload event won't fire, and it won't run the required cleanup function CryptReleaseContext.

CryptGenRandom will NEVER repeat a set of numbers, and will NEVER produce any visible pattern of numbers.

[VB6] Convert CSV to Excel Using ADO

$
0
0
A piece of code I thought might be useful to some. Caveat first... Won't be the ideal solution for everyone.

Having Microsoft Excel on the computer is not a requirement. Including an ADO reference is. This code was tested using both ADO Library versions 2.8 and 6.1. The ADO dependency could be removed if code tweaked to use late-binding CreateObject() like VB scripts do.

This is unicode-friendly regarding file names. There are comments in the code should anyone want to tweak it to handle unicode file content. The routine will default to the more modern versions of Excel and can be forced to use the lower versions as desired.

A few common options are provided as function parameters and a schema.ini file would likely be needed for more complex options. Comments in the code talk a bit about that.

The code is really simple and allows ADO to do 100% of the work. Most of the routine below consists of sanity checks along with dealing with various options. The guts is an ADO connection to the csv file and an SQL execution on that connection to create the Excel file, create the tab/sheet, and copy the csv content to that sheet -- all done in that one execution.

Code:

' API used to check if file exists
Private Declare Function GetFileAttributes Lib "kernel32.dll" Alias "GetFileAttributesW" (ByVal lpFileName As Long) As Long

Private Function ConvertCSVtoExcel(CsvFile As String, _
                            Optional CsvHasHeaders As Boolean = True, _
                            Optional ExcelSheetName As String = "Sheet1", _
                            Optional ByVal ExcelVersion8 As Boolean = False, _
                            Optional DestinationPath As String = vbNullString, _
                            Optional ReturnedErrorString As String) As String

    ' Function will return full Excel file path & name if no errors & ReturnedErrorString will be null
    '  else function returns vbNullString and ReturnedErrorString contains error description
    '  Converted file name will be the same as the CSV except having an Excel extension
   
    ' Unicode. Handles unicode file names & sheet names.
    ' For those that want to also handle unicode CSV data, you will want to pass a new parameter and
    '  modify this routine. Key google term: CharacterSet=Unicode
   
    ' ensure CsvFile exists before calling this function
    ' ensure DestinationPath has write-access. By default this path is same as CsvFile path
    ' ExcelVersion8 can be accessed by most versions of Excel except very, very old versions
    '  if absolutely needed, you may want to rework this to pass an exact version, i.e., 5, 8, 12, etc
    '  If parameter is False, v12 (xlsx extension) will be attempted & falls back to v8 if needed
    '  Version 12 driver can be found here & requires at least Win7
    '  https://www.microsoft.com/en-us/download/details.aspx?id=13255
   
    ' Last but not least, some additional info
    '  many delimited file options can be used, but require a schema.ini file & no changes in this routine
    '      i.e., other delimiter than comma, specifying column data types, different column header names, etc
    '      https://docs.microsoft.com/en-us/sql/odbc/microsoft/schema-ini-file-text-file-driver
    '  if you need to play with xlsb (binary files) vs xlsx files, remove the XML from the v12 connection string

    Static v12ProviderAbsent As Boolean
    Const E_NOPROVIDER As Long = 3706&

    Dim cn As ADODB.Connection, p As Long
    Dim sSrcFile As String, sSrcPath As String
    Dim sSQL As String, sDest As String
    Dim sHDRprop As String, sVersion As String
   
    ' sanity checks and prep
    p = InStrRev(CsvFile, "\")
    sSrcFile = Mid$(CsvFile, p + 1)
    sSrcPath = Left$(CsvFile, p)
    If DestinationPath = vbNullString Then
        sDest = sSrcPath
    ElseIf Right$(DestinationPath, 1) <> "\" Then
        sDest = DestinationPath & "\"
    Else
        sDest = DestinationPath
    End If
    If v12ProviderAbsent = True Then ExcelVersion8 = True
    p = InStrRev(sSrcFile, ".")
    If p = 0 Then sDest = sDest & "." Else sDest = sDest & Left$(sSrcFile, p)
    If ExcelVersion8 Then sDest = sDest & "xls" Else sDest = sDest & "xlsx"
    If ExcelSheetName = vbNullString Then ExcelSheetName = "Data"
    If CsvHasHeaders Then sHDRprop = "Yes" Else sHDRprop = "No"
   
    ' prevent overwriting existing file; Excel file creation fails if file/sheet already exists
    Do
        If GetFileAttributes(StrPtr(sDest)) = -1& Then Exit Do
        If ExcelVersion8 Then sDest = sDest & ".xls" Else sDest = sDest & ".xlsx"
    Loop
   
    ' verify we can open the csv
    On Error Resume Next
    Set cn = New ADODB.Connection
    cn.CursorLocation = adUseClient
    If Not ExcelVersion8 Then
        cn.ConnectionString = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=" & _
            sSrcPath & ";Extended Properties='text;HDR=" & sHDRprop & ";FMT=CSVDelimited'"
        cn.Open
        If Err Then ' failure. Either version 12 not installed or O/S less than Win7
            If Err.Number = E_NOPROVIDER Then v12ProviderAbsent = True
            ExcelVersion8 = True                ' try again using lower Excel version
            sDest = Left$(sDest, Len(sDest) - 1)
            Err.Clear
        Else
            sVersion = "12.0 XML"
        End If
    End If
    If ExcelVersion8 Then
        cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
            sSrcPath & ";Extended Properties='text;HDR=" & sHDRprop & ";FMT=CSVDelimited'"
        cn.Open
        If Err Then ' can't be done via this routine
            ReturnedErrorString = Err.Description
            Err.Clear
            GoTo ExitRoutine
        End If
        sVersion = "8.0"
    End If
   
    ' create the excel file, sheet, & import data in one call
    sSQL = "SELECT * INTO [" & ExcelSheetName & "] IN '' [Excel " & sVersion & _
            ";Database=" & sDest & "] FROM [" & sSrcFile & "]"
    cn.Execute sSQL
    If Err Then
        ReturnedErrorString = Err.Description
        Err.Clear
    Else
        ReturnedErrorString = vbNullString
        ConvertCSVtoExcel = sDest
    End If
   
ExitRoutine:
    If cn.State Then cn.Close
    Set cn = Nothing
End Function

Edited: A specific scenario has yet to be resolved. If the CSV file name (excluding the path) is unicode, the routine fails when the actual data is not unicode (i.e., ASCII); just the file name is. For full unicode support, including actual CSV data in unicode, the CharacterSet=Unicode extended property on the connection string should work well in most cases.

[VB6] VB6.tlb - Passing a ParamArray without Copying

$
0
0
The Issue: How do you access a ParamArray, and pass it to another function,
without copying it.
The Answer: Pointer magic. ParamArrays are really just a
Variant Array - managed by the runtime. For whatever reason though - the
runtime / ide doesn't allow you to get at it's address easily, or even pass it
to another function without making a copy

This particular technique I believe was first pioneered by Matt Curland.
Originally Curland used assembly to get the stack pointer,
add a hard coded offset (depending on the function parameters passed before
the ParamArray) to calculate where the SAFEARRAY** is on the stack, then
return the dereferenced pointer. Then you can safely swap the SAFEARRAY
reference with another SAFEARRAY.

edit: After a a good amount of fumbling, I using Curland's proven methods, with my own self modfying code.
I usually avoid assembly, and dislike mixing it with VB - but here's the cleaned up routines.

just include MParamArray.bas in a project, and you can use the GetParams function.
GetParams takes a single Parameter Offset, and returns a Variant Array, that you can use to pass to other functions.
GetParams steals the Array reference off the stack, without copying the original Array.

Code:

' SomeForm.frm or Class1.cls
Private Sub Func1(ParamArray Params())
    ' NOTE: offset calculation from Frame Pointer in a Class Module (.cls) or Form (.frm)
    ' saved ebp (4) + return address (4) + this ptr (4) + No Params before ParamArray (0)
    OtherFunc GetParams(12)
End Sub

Code:

' StandardModule.bas
Private Sub Func2(ParamArray Params())
    ' NOTE: offset calculation from Frame Pointer (ebp) in a Standard Module (.bas)
    ' saved ebp (4) + return address (4) + no other params on stack before ParamArray (0)
    Dim ParamOffset As Long: ParamOffset = 4 + 4 + 0
    If InIDE Then ParamOffset = ParamOffset + 4 ' Standard Module Functions need an extra 4 bytes when debugging

    'If you need to pass the array as a ParamArray, to allow modification of ByRef paramaters, Use CallPtr
    CallPtr AddressOf Module1.OtherFunc, vbEmpty, RefAry(GetParams(ParamOffset))
End Sub

Attached Files

Possible fix to the improved random generator technique I previously described

$
0
0
In this thread http://www.vbforums.com/showthread.p...than-using-Rnd I mentioned gave a description of how to use CryptGenRandom to generate completely secure random numbers. However one person there said it didn't work for them. I have finally figured out how to fix the problem (I think, as I can't duplicate the problem they had, on my own computer). I posted an explanation in that thread, saying how to fix it, but not a single reply even acknowledging that I had posted a fix. None at all, it's like the method for fixing it is being ignored by the very person who was asking for a fix.

Therefore, I've created this new thread, and posted this complete fixed copy of the code in this thread (not merely instructions on how to fix it). Again, copy and paste this code into your form, and make sure that your form's AutoRedraw property is set to True.

Code:

Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptGenRandom Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwLen As Long, ByRef pbBuffer As Any) As Long

Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)

Private Const BaseProvider As String = "Microsoft Base Cryptographic Provider v1.0"
Private Const EnhancedProvider As String = "Microsoft Enhanced Cryptographic Provider v1.0"
Private Const StrongProvider As String = "Microsoft Strong Cryptographic Provider"

Private Const CRYPT_VERIFYCONTEXT As Long = &HF0000000



Dim hProv As Long
Dim Quit As Boolean

Private Sub Form_Load()
    Dim a As Long
    CryptAcquireContext hProv, vbNullString, vbNullString, 1, CRYPT_VERIFYCONTEXT
   
    If hProv = 0 Then
        Unload Me
        Exit Sub
    End If
   
    Show
    Do Until Quit
        CryptGenRandom hProv, 4, a
        Cls
        Print a
        Sleep 100
        DoEvents
    Loop

End Sub

Private Sub Form_Unload(Cancel As Integer)
    Quit = True
    If hProv Then CryptReleaseContext hProv, 0
End Sub

The key here is that the dwFlags argument in the CryptGenRandom function has been set to CRYPT_VERIFYCONTEXT this time (rather than 0).
Again the pszProvider argument of the function is set to vbNullString, to use the default provider. And also again, if the default doesn't work, use one of the constants BaseProvider, EnhancedProvider, or StrongProvider for the pszProvider argument.

If NONE of these still work. Try starting VB6 as an administrator (not a standard user), and again repeat the above procedures for testing it.

If after all of this still does not work, I can't figure out what is wrong, because I believe I have exhausted all possible fixes.

In that case, I would recommend a shortcut for using the random number generator in the crypto API. That shortcut is to use RtlGenRandom, which is declared in the code box below.
Code:

Private Declare Function RtlGenRandom Lib "advapi32.dll" Alias "SystemFunction036" (ByRef RandomBuffer As Any, ByVal RandomBufferLength As Long) As Long
It does not require a crypto provider handle (hProv) like CryptGenRandom does, so if you are having problems with CryptAcquireContext, RtlGenRandom will still work. However, that is an absolute last resort, as the MSDN documentation for RtlGenRandom https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx says that there is absolutely no guaranty that RtlGenRandom will be kept in future versions of Windows, and that one should instead use CryptGenRandom. That is why I am not suggesting you just switch over to using RtlGenRandom, but am instead trying to fix the code for using CryptGenRandom, and would suggest that RtlGenRandom be used ONLY if ALL ELSE fails.

[VB6] FIRENZE LABEL - label control with so many functions

$
0
0
FIRENZE LABEL
version 1.1.1

last actualization: 26.3.2017


Created by Martin Vartiak, powered by Cairo Graphics and vbRichClient-Framework.
LICENSE: http://creativecommons.org/licenses/...1.0/fi/deed.en




1. Shortly about the project Firenze Label

All starts simply as always. I was looking for a simple anti-aliasing solution for VB6 because I was never satisfied with original one. Found some examples on the web, but as a graphic designer I was still very disappointed with results. After further search I found very interesting .dll library for graphic use of Cairo Graphics. At the first sight all was so complicated for me. I started to play with that library and decide to make very simple ActiveX component just for me. As I started to add more and more functions it becomes very user friendly component. And now i want to share it with you.



2. What makes Firenze Label so special?

Imagine me or you as a graphic designer and now remeber to basic VB6 Label component. Practically you can do nothing special with it, there are missing even some basic functions as a Vertical Alignment. I will try to describe most of the functions of the Firenze Label and you can imagine the endless possibilities of it use. With these properties and functions you can possibly achieve most of the modern design functions.

Custom Properties:
BackColor - ordinary back color
BackColorOpacity - back color with opacity (0-100)
Border - draws a border around the component
BorderColorOpacity - opacity of border (0-100)
BorderCorner - you can apply a mask for corners (i.e. you can mask only top corners for a tab strip)
BorderPosition - position of border
BorderRadius - border radius
BorderSmoothEdge - property for a better and smoother border in some cases
Border Width - border width
Caption - main text
CaptionAlignmentH - horizontal alignment of caption (left/center/right)
CaptionAlignmentV - vertical alignment of caption (top/middle/bottom)
CaptionPadding - padding for a caption
Cursor - you can choose between arrow and hand cursor (as on the website)
Font - don’t affraid to use all of the modern fonts with proper antialiasing
FontAwesome - if you lazy downloading custom icons, you can use hex codes of FontAwesome and get so many scalable icons so fast
ForeColor - simple ForeColor property
ForeColorOpacity - opacity for ForeColor (0-100)
Gradient - turn on if you like gradient background
GradientAngle - determines in which angle should gradient be drawn (0-360)
GradientColor1 - gradient color 1
GradientColor1Opacity - opacity for gradient color 1
GradientColor2 - gradient color 2
GradientColor2Opacity - opacity for gradient color 2
ParentControl - child control shares all functionality of the parent control
Picture - you like modern .png or .svg pictures? (path to the picture)
PictureAlignmentH - horizontal aligment of picture
PictureAlignmentV - vertical alignment of picture
PictureOpacity - picture opacity (0-100)
PicturePadding - picture padding
PictureSVGScale - after you load .svg picture, you can scale it up or down
WordWrap - wordwrap, because why not

Custom events:
MouseEnter
MouseLeave


Practically you can use opacity on everything. You can use Firenze Label just to show .png or .svg picture if you want. Possibilities are endless.



3. Next developement

I have sooo many ideas for the next developement. Possibly I can “hire” someone for a optimalization of code and make it even more fast and pixel perfect.

Main goals to achieve:
- add all planned functions
- custom website
- custom installation file
- complete documentation
- more examples and sample codes



4. Showcase

Showtime :)
Working examples you can download.

Name:  admin.jpg
Views: 168
Size:  18.8 KB
Name:  einstein.jpg
Views: 166
Size:  99.0 KB


What you can achieve with Firenze Label. (Sorry, there are lot of more but this post can have only 5 attachements)

Name:  calendar.jpg
Views: 165
Size:  22.7 KB Name:  icerikdashh.jpg
Views: 163
Size:  19.9 KB


5. Download

IMPORTANT NOTICE:
you have to add project reference vbRichClient5 (download from http://www.vbrichclient.com/#/en/Downloads.htm)
icons from the examples are not pictures but windows font FontAwesome, you need to download and install it first (download from http://fontawesome.io/).


DOWNLOAD Firenze Label source code:
FirenzeLabel.zip



PROJECT IS IN DEVELOPEMENT.
Ask freely if you don't understand to something. I realize I didn't make it well documented for now, but I don't want to spam here a lot of text and explanations. For more questions or explanations send me PM or write here. Enjoy!


Matt
Attached Images
    
Attached Files

FontAwesome-SVG-Resources (per vbRichClient5)

$
0
0
Posted, due to a request in this related thread here (the nice Firenze-Label-Project by porkynet):
http://www.vbforums.com/showthread.p...many-functions

Those who are doing some Web-Development (besides writing VB6-Apps) might already be familiar
with the FontAwesome-Project (which encapsulates about 700 Flat-Icons inside a Font-Resource).
http://fontawesome.io/icons/

Encapsulating these Icons in a (downloadable Web-)Font-Resource eases some pain, e.g. when it comes to
defining CSS-classes or -contents or when dealing with a lot of Flat-Icons in JavaScript whilst writing Browser-Apps.
(mostly by avoiding the somewhat more complicated fiddling with Image- or SVG-resources, which when hosted
*separately* on a WebServer behind an /img/-folder also increases download-time of the whole WebApp into the Browser).

That much as an explanation, on why these 700 Icons are sitting within a Font-Resource (which one has to download into the Browser only once).

Though the "Image-Paths" (the Vector-definitions as "curves" or "outlines") of these Flat-Icons are also available as SVGs -
hosted on a GitHub-Project-Space here:
https://github.com/encharm/Font-Awesome-SVG-PNG (the license being MIT, which is also a bit more generous than
the one used for the FontFiles-downloads from http://fontawesome.io).

Since the RC5 comes with SVG-rendering-support, one can use these Icons also "directly from an SVG" -
thus avoiding to have to install a FontFile in the Windows-Fonts-Folder, which requires Admin-Rights (avoiding
an additional hurdle for "regfree deployment of an Application").

Instead all the SVGs are "bundled" within a compressed RC5-Resource-Archive (usually given the file-ending *.wac) -
and the contents of such *.wac-files can of course also be embedded directly into the *.exe of *.dll as normal "ByteArray-resources".
This way an Application can make use of FontAwesome-Icons whilst remaining "XCopy-deployable".

The Demo itself is not complicated - the Code in a normal VB6-Form quite lean:
Code:

Option Explicit

Private FA As New cFontAwesomeSVG, WithEvents ColorChooser As cwColorChooser

Private Sub Form_Load()
  Set ColorChooser = ucPanel1.Widgets.Add(New cwColorChooser, "ColorChooser", 0, 0, 258, 258)
 
  Dim Key
  For Each Key In Split(FA.KeyList, vbCrLf): lstKeys.AddItem Key: Next
 
  lstKeys.ListIndex = 0
End Sub

Private Sub ColorChooser_ColorChanged()
  RenderCurrentSymbol 'force a refresh
End Sub
Private Sub lstKeys_Click()
  RenderCurrentSymbol 'force a refresh
End Sub

Private Sub RenderCurrentSymbol()
  Set picPreview.Picture = FA.GetPicture(lstKeys.Text, ColorChooser.Color, 256, 256)
End Sub

Private Sub Form_Terminate()
  If Forms.Count = 0 Then New_c.CleanupRichClientDll
End Sub

Producing this output:


The work in the above code is done by an accompanying little Helper-Class, which is able to hand
out all the "Friendly-Name-Keys" which are contained in the _FontAwesomeSVGs.wac Resource-Archive
(in the ScreenShot above these Keys were filled into a normal VB-ListBox).

And then in the List_Click()-Event one can directly render any of these Icon-Symbols per:
Code:

  Set picPreview.Picture = FA.GetPicture(lstKeys.Text, ColorChooser.Color, 256, 256)
or alternatively (when there's an interest in keeping the Alpha-Channel) also per:
Code:

  FA.GetSurface( strSomeSymbolKey, SomeForeColor, DesiredWidth, DesiredHeight)
The above FA is an instance of the already mentioned Helper-Class cFontAwesomeSVG,
which deals with loading the Resource-Archive into Memory - and offering access to the contained Images.

What the Demo also shows at the occasion is, how to use RC5-WidgetClasses within the realm of a
"normal VB6-Form" (instead of hosting these new Control-Classes on a cWidgetForm-Class, as in other RC5-Demos).

The Demo-Widget-Class which is used as a vehicle to demonstrate that (in conjunction with a generic ucPanel.ctl)
is cwColorChooser (the circular Color-Selector-Control in the BottomRIght-Corner of the ScreenShot).

Well, that was it already with regards to an easy way to use FontAwesome-Symbols (or other SVGs)
from within a single compressed Resource-Archive.


Here is the Zipped Demo-Project (including the 126KB FontAwesome-Archive along with its MIT-license-file):
FontAwesomeSVG.zip
(note that these SVGs require a vbRichClient5-version >= 5.0.59 to be rendered correctly, so download and
update your RC5-Baselibs-Folder accordingly before running the project).


Have fun,

Olaf
Attached Files

[VB6] Manifest Creator II

$
0
0
This is the second version of this application. The previous version will no longer be maintained.

The project simply creates application-manifests that can be written to disk, clipboard, or VB resource files. The project includes a default/dummy manifest with all known options, as of this date. You would select whichever manifest options you want to include and modify those option values as needed. If you wish to view or replace an existing manifest file, you can import it into the project via the clipboard, disk, or VB resource file. The tool will attempt to parse VB vbp project files and create a new manifest, filling in the Identity element from that file.

The major reasons for revision are several
- Previous version was create only. This version can also edit existing manifests.
- Use Microsoft XML in the background to create and modify the XML
- Use XML stylesheets to help transform the manifest based on export options
- More intuitive design and more modular to assist with future updates by you or me
- Will no longer ignore hand-jammed manifests within VB resource files, i.e., #24 custom entries
- Offers ability to update unrecognized (future) manifest entries imported from elsewhere

The manifest is designed to make use of XML qualified names, internally, and is the default mode. However, when exporting the manifest, you can opt to convert to traditional name spaces if you choose.

Caveat: Not 100% of the manifest options available have been fully tested. Some options can't be tested by me because I don't have the system(s) to perform the desired tests. However, all the options should be technically correct and in accordance with the Microsoft schema for application manifests.

Comments, bug reports, and suggested enhancements are always welcomed.

Name:  screenshot.jpg
Views: 160
Size:  48.9 KB

Update History
9 Apr 17: Realigned several elements to their correct namespace
10 Apr 17: Three minor mods
1) Fixed error noted in post #5 below
2) Fixed logic flaw that would only allow max of one <file> element imported
3) Added more detailed help when editing some attribute values via InputBox()
Attached Images
 
Attached Files

Drag form by any "gray" space rather than just the title-bar

$
0
0
A special thanks to LaVolpe for coming up with the best idea on doing this.

Sure, most of us know how to drag a form around by the form's own "gray" space. But what if we also want labels to drag it, and we also want any containers to work as well. Sure, we don't want Buttons, TextBoxes, ComboBoxes, and other "active" controls to work, but we do want the inactive controls to work. That's where these routines come to the rescue.

Let me also say that this may not be a perfect solution for everyone, especially if you use labels and containers in a more "active" way than I do. But I thought it was pretty cool, so I posted it.

Also, just as an FYI, it also works with the SSTab container, which I tend to use often.

Start by looking at the code in Form1 to see how to use it. It should be fairly self-explanatory. The whole objective was to make the amount of code in your form be at a minimum. The other modules should just be "drop ins" for you.

Sure, we could do this by monitoring the mouse-events of all the places we'd like to drag, but these procedures hopefully makes the whole thing easier. Also, my objective was to do all of this without sub-classing so we could still use all the glory of the IDE. Labels in control arrays don't slow it down either.

Enjoy,
Elroy
Attached Files

Xor Cipher - Revisited

$
0
0
Beginners are often attracted to the simple XOR cipher. Besides having serious limitations as ciphers go, they usually try to approach it ignoring many important topics.

The first one is that most ciphers don't really apply to text at all. Sure, there are some that do but these are mostly obsolete and of little but historical interest. So when using most ciphers today, including simple Xor, you want to combine the plaintext and the key as arrays of bytes:

Code:

Private Function XorCipher(ByRef Bytes() As Byte, ByRef PassBytes() As Byte) As Byte()
    Dim Temp() As Byte
    Dim Length As Long
    Dim I As Long

    ReDim Temp(UBound(Bytes))
    'Assumes LBound() = 0 for both arrays passed to us:
    Length = UBound(PassBytes) + 1
    For I = 0 To UBound(Bytes)
        Temp(I) = Bytes(I) Xor PassBytes(I Mod Length)
    Next I
    XorCipher = Temp
End Function

But how to get those bytes?

Typically people start off with String values for both "inputs" and to get them as Byte arrays they'll either just slop them in and get lots of zero bytes or much worse they'll convert the String to ANSI.

Converting to ANSI is ok as long as you enforce the use of the 7-bit ASCII subset. But if you don't do that you can run into serious portability problems. ANSI is not ANSI, but a family of ANSI encodings that differ for different language alphabets. And you can also run into Double Byte Character Set issues in many Asian alphabets.

See the classic:

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Or perhaps the newer take on the subject:

What every programmer absolutely, positively needs to know about encodings and character sets to work with text


Text in VB6

First you need some grasp of text in VB6. String values in VB6 are normally 16-bit Windows Unicode UTF-16LE characters. Yes, a String variable can hold other things such as ASCII, ANSI, DBCS, even UTF-8 and UTF-7. However this is rarely done and you'd want to a good handle on the subject before you attempt it.

So one can almost say VB6 Strings are always Unicode (UTF-16LE).

This can get confusing because to help bridge the gap from MS-DOS and earlier versions of VB, VB6 "helps" you. Most text I/O operations and many controls do implicit conversion to and from ANSI using the current session codepage. This means that in many ways VB6 is "Unicode on the inside and ANSI on the outside."

People also get confused because 7-bit US-ASCII is a proper subset of every ANSI encoding as well. Then the somewhat misleading notion of "extended 8-bit ASCII" came along in the MS-DOS era.

Once again see the links above for some conceptual help.


Demo

So here is a demo that attempts to address some of these things.

It uses the Text Object Model (TOM) interface of the Win32 RichEdit control which VB6's RichTextBox control wraps to get us some Unicode capabilities. This should work on Windows 2000 or later.

A small helper class RtbTom.cls wraps an API call to grab ITextDocument references for our RichTextBox controls.

It converts Unicode text to UTF-8 text in Byte arrays to operate upon them. UTF-8 is a multibyte character set, though be careful. The 7-bit ASCII subset uses one byte per character so people often get mislead into thinking things are that simple. Other characters get encoded as 2 to 4 bytes instead of just one. Still, at least with UTF-8 you can compress out most of the zero bytes you'd have using "Unicode" (UTF-16LE).

After applying the XorCipher() function above, it encodes the ciphertext bytes in Base64. Base64 is relatively compact compared to hex, etc. and it uses only "safe" characters - safe for ASCII, ANSI, almost anything.

We don't have much character encoding support in VB6, so the helper class TextCodec.cls wraps a few API calls to accomplish this.

Then the cipher is reversed by converting the Base64 back to bytes, applying XorCipher() once more using the same passphrase, and finally converts the resulting UTF-8 back to "Unicode."

Name:  sshot.png
Views: 109
Size:  12.6 KB

When the program starts it reads the data from PlainTextIn.txt into rtbPlainText1 (a RichTextBox). The file is Unicode, so we bring in lots of characters from various alphabets. You can type over this or leave it as-is.

When you type a passphrase into rtbPass it enables cmdEncrypt allowing you to click on it.

Clicking that does the encryption and displays the results in rtbCipherText and also saves it to disk as a 7-bit ASCII file Encrypted.txt.

Then it enables cmdDecrypt.

Clicking on that reverses the encryption process. Results are written into rtbPlainText2 and also saves it to disk as a Unicode file PlainTextOut.txt.


Requirements

VB6, Windows 2000 or later.


Summary

Xor Cipher is simple though limited, but using it effectively can be trickier than new programmers expect.

In order to avoid corrupting your data in the process you need to be aware of character encodings and make some choices about which ones to use and how to use them.

We could have skipped encoding as UTF-8 but we'd produce a far larger "encrypted" ciphertext in most cases, with a lot of "dead air" zero bytes. Don't rely on ANSI conversion though, it can be a trap.

The ciphertext itself is not "text" as such, but binary data. If you need to represent this as actual text you should encode it using Base64, hex, or something similar. Web and email do tons of this very thing under the covers and most people aren't aware of it.

There is a lot here that can be intimidating and confusing, but these are good concepts to understand.
Attached Images
 
Attached Files

Visual Basic Classic - My VB6 fork

$
0
0
Hello, I am new in this forum. I want to present a project that I am doing, using the same VB6 RAID and adding new functions as support for new Windows styles.

Name:  VBC_Example.png
Views: 62
Size:  48.9 KB

Name:  compare_forms.jpg
Views: 58
Size:  20.1 KB

Name:  VBDesign.jpg
Views: 61
Size:  52.9 KB


This is the project page
Attached Images
   

[VB6] SizeGrip without StatusBar

$
0
0
Some controls will get this for you automatically. For example when ScrollBars join at the lower-right corner of the Form, or you have a StatusBar, etc.

However when you don't have or want these but your Form is sizable you may want the sizing grip because in the post-Win7 world you no longer get fat borders. Actually they still are fat, but the fat part is transparent making them look thin to the user.

It turns out that you can turn a VB6 intrinsic ScrollBar control into a sizing grip fairly easily. It works both with and without Common Controls 6.0 UxTheming, and it is a real sizing grip visible as such to Windows Accessibility unlike funky hacks like sticking a Label or something in the corner and capturing the mouse when hovered over and clicked.


Name:  sshot.png
Views: 104
Size:  8.6 KB


Code:

Private Sub Form_Load()
    With hsbSizeGrip
        'Turn the HScrollBar into a Sizing Grip:
        SetWindowLong .hWnd, _
                      GWL_STYLE, _
                      GetWindowLong(.hWnd, GWL_STYLE) Or SBS_SIZEGRIP
        'Size the Sizing Grip to the system dimensions for such things.  This
        'is not automatic:
        MoveWindow .hWnd, _
                  0, _
                  0, _
                  GetSystemMetrics(SM_CXVSCROLL), _
                  GetSystemMetrics(SM_CYHSCROLL), _
                  True
        'Set the MousePointer to system lower-right resize arrows:
        .MousePointer = vbSizeNWSE
    End With
End Sub

However you do still have to position it in your Resize event handler, because it doesn't get docked/aligned automagically:

Code:

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        'Position the Sizing Grip.  It is not automatically anchored to the
        'corner of the Form:
        With hsbSizeGrip
            .Move ScaleWidth - .Width, ScaleHeight - .Height
        End With
    End If
End Sub

Of course the attached demo moves and sizes a few more controls in its Resize handler. ;)
Attached Images
 
Attached Files

VB6 - ClientDNS

$
0
0
ClientDNS is a utility program designed and intended to give you full access to the DNS packets returned from the requested server. DNS packets are very compact and highly cryptic, and because of that, command line utilities like "NSLookUP" will display incomplete interpreted results. ClientDNS returns all the results on separate tabs.

Internet standards require DNS servers to accept both UDP and TCP requests. TCP is very seldom used however, and some servers do not accept them due to firewall restrictions on port 53. ClientDNS does not support TCP.

Some modern recursive DNS servers use EDNS (Extended Domain Name Service) to support DNSSEC. ClientDNS does not support EDNS.

There are numerous Web pages available that explain the DNS packet structure. What is not very well covered is the use of Compression Pointers, so a brief explanation would seem to be in order. The Header and Question sections are common to the both the outgoing query and the server response (see included image below).

There is a lot of information in the header. First of all, it tells us that this is not an authoritative answer (Authoritative Answer = False). That is because this server does not host this particular domain, and recursion was requested and utilized to find the answer. It also tells us that there were no errors and 1 Question (QDCount=1), 1 Answer (ANCount=1), 2 Nameserver (NSCount=2), and 1 Additional (ARCount=1) records received.

To see how Compression Pointers are used, we will examine the response for an MX record.
Code:

Answer:
00 02 85 00 00 01 00 01 00 00 00 01 0A 79 65 6C
6C 6F 77 68 65 61 64 03 63 6F 6D 00 00 0F 00 01
C0 0C 00 0F 00 01 00 0D 2E C4 00 0B 00 0A 06 6E
6F 6D 61 69 6C C0 0C C0 2E C0 0C 00 01 00 0D 2E
C4 00 04 60 35 60 32

The first 12 bytes are for the Header, and the Question occupies the next 16 bytes (variable). Notice that the question has a length byte (0A/10) in front of the Domain Name (yellowhead). This takes us up to where the dot separator would normally exist. There we find the length (03) of the high level domain (com). All questions will end in a NULL character (00). 00 0F is the Question Type (15), and 00 01 is the Question Class (IN). The next Record is the Answer Record, and here we find an unknown character (C0). The top 2 bits of this byte (192) tell us that compression is used, and the next 6 bits and the following byte tell us where to find those compression characters (0C/12). Wait a minute; the question starts at byte 13. That is true, but we are using zero based counters, which corresponds to the Question Name just discussed. The 2 bytes (C0 0C) will return the Record Name, followed by the Record Type (00 0F) and Record Class (00 01). After that comes the suggested TTL in seconds (00 0D 2E C4), the Record Data Length (00 0B), and MX Priority (00 0A). That brings us to the Record Data itself. It starts with a 6 character Name followed by the Compression characters (C0 0C). When combined, it results in "nomail.yellowhead.com".

The last Record is an Additional Record. It starts with a C0 2E. This Compression Pointer points to byte 46, which is the name just recovered above. It is followed by Record Type (00 01), which is an "A" record, and Class (00 01), which is the Internet Class. Following that is the TTL (00 0D 2E C4), the Record Length (00 04), and finally the IP address (60 35 60 32).

Using this technique, you can see how they manage to squeeze 27 root servers into very limited space.

The original version of ClientDNS utilized MS Winsock. Version 2 utilized cSocket2 and supported IPv4 and IPv6 using string data. Version 3 utilizes SimpleSock, which enabled the use of binary information via byte arrays. ClientDNS V3.0 has been tested on Windows Vista and Windows 8.1. IPv6 has not been fully tested because of the lack of a native IPv6 network (tested with Teredo Tunnel).

How to use ClientDNS is demonstrated in the following web page.
http://www.yellowhead.com/DNS_How.htm
It should be noted that you do not have to enter the correct format for PTR requests (ie. 117.178.26.52.in-addr.arpa). You simply enter the IP address (ie. 52.26.178.117), and ClientDNS will reformat it for you. Clicking on any field will display it on the bottom bar, and double clicking will copy it to the clipboard.

J.A> Coutts
Attached Images
 
Attached Files

[VB6] "Attribution" - a web link control

$
0
0
There are useful or fun RESTful Web Services that we can easily use in VB6 programs. Many are free or offer a free tier of use, but may require attribution and a link to "terms of service" or their home page. Some do not require this but it might be good manners to do so.

Easy enough for a web mashup, but more effort in a desktop application. This Attribution control shows how such a thing might be accomplished.

Here is an example of such an API: TheySaidSo Famous Quotes API

Free usage is limited to 10 requests per hour, and they ask for attribution. That's possible but clunky in VB6. We could make a small browser window but here is an alternative: Attribution.cls.

This Attribution control supports "hover highlighting" though not perfectly. If you want better mouseout detection there are alternatives you can use instead of the simplistic technique used here. Edit: altered this to use the SetCapture/ReleaseCapture API approach.

It has properties covering their ImgSrc, HRef, displayed Text, and of course ToolTipText can be used for their "powered by" title text.


Requirements

VB6 to compile the Project.

Windows Vista or later. Windows XP SP1 or later could be used if the redist version of WIA 2.0 has been previously installed.


Interaction with the API provider

When an instance of Attribution.ctl loads it:

  • Requests the image at ImgSrc if this property is not empty.
  • When the image is received, it is composited onto backgrounds to produce NormalImage and HighlightImage.
  • NormalImage is displayed initially on the Attribution instance.


When the Form loads it:

  • Makes a "categories" request.
  • When received successfully, it displays them in a ListBox for the user to optionally choose one from.
  • The "Get quote" button is enabled.


When the user clicks the "Get quote" button the Form:

  • Makes a Quote Of The Day request, with or without a specified "category" depending on whether the user chose a category from the ListBox by selecting it.
  • When received successfully, it extracts several value from the response including a background picture URL.
  • Then it makes another request for the background picture.
  • When the background picture is received it paints that into a PictureBox, and then it draws the text of the quote and related information extracted from the QOD response.


If the users clicks on Attribution a link to the API provider's site is opened in the user's default web browser.


This was more of a "concept" Project rather than something "real." There is a lot of random stuff in this program. Maybe you can find some of it useful.
Attached Images
 
Attached Files

OS Version information class

$
0
0
WinAPI based.

Can show such information, like:

OS Name: Windows 7
Service Pack ver.: 1
Bitness: x64
Edition: Ultimate
Family: Vista
Suite mask: SingleUserTS
ProductType: Workstation
OS - Vista or newer? True
Major: 6
Minor: 1
Major + Minor: 6,1
Build: 7601
ReleaseId: 0
Language in dialogues: 1049 RU Russian
Language of OS inslallation: 1049 RU Russian
Language for non-Unicode programs: 1049 RU Russian
Process integrity level: Medium
Elevated process? False
User group: Administrator
Safe boot? False (Normal)
OEM Codepage: 866 (c_866.nls)
ANSI Codepage: 1251 (c_1251.nls)

You should add manifest with compatiblity section in your program to properly handle version of Windows 8.1 and higher (included in example attached).
If program run from IDE, Win version will be extracted via WMI, so IDE-mode doesn't depend on the manifest.
Attached Files

[VB6] Another Method for Loading/Drawing PNG

$
0
0
I've known about this method for quite some time and even use it in some of my projects. But haven't seen it applied elsewhere. So, I thought I'd make it more known with an example.

We know there are plenty of examples of loading a PNG file. Those typically use GDI+, WIA, or a custom control. However, since Vista, we can do this with basically one API call. The downside is that VB still won't display these correctly if PNG has alphablending, but we can draw them flawlessly to a DC while maintaining transparency within the PNG, if any.

Requirement: Vista or better
API: CreateIconFromResourceEx. Also needed is DrawIconEx to render the PNG to DC

Edited: My comments above are a bit misleading. Only if the PNG contains alphablending will you want to use DrawIconEx to draw the image. Otherwise, just assign the returned stdPicture to any control's Picture property or even the form's Picture property. Also, see post #2 for a possible workaround.

Recommend testing on some large PNGs. I am not sure what the limit of the API may be. I believe Vista topped out around 768x768. However, never really researched it and that may have been a soft-limit. In other words, this may not be a perfect solution for all PNGs. But on Win10, for example, no problem with typical 1024x768 PNGs.

Simply get the PNG data into a zero-bound byte array (from file or via LoadResData) and pass to this function. The function creates a stdPicture object wrapped around an icon created from the PNG. You don't have to worry about destroying the icon since VB will do it when the stdPicture is released or goes out of scope.

Code:

' APIs first

Private Declare Function CreateIconFromResourceEx Lib "user32.dll" (ByRef presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "OleAut32.dll" (lpPictDesc As Any, riid As Any, ByVal fPictureOwnsHandle As Long, ipic As IPicture) As Long
Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long


Public Function LoadPNGtoICO(pngData() As Byte) As IPicture
   
    Dim hIcon As Long
    Dim lpPictDesc(0 To 3) As Long, aGUID(0 To 3) As Long
   
    hIcon = CreateIconFromResourceEx(pngData(0), UBound(pngData) + 1&, 1&, &H30000, 0&, 0&, 0&)
    If hIcon Then
        lpPictDesc(0) = 16&
        lpPictDesc(1) = vbPicTypeIcon
        lpPictDesc(2) = hIcon
        ' IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}
        aGUID(0) = &H7BF80980
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        ' create stdPicture
        If OleCreatePictureIndirect(lpPictDesc(0), aGUID(0), True, LoadPNGtoICO) Then
            DestroyIcon hIcon
        End If
       
    End If
   
End Function

Example. Some error checking provided, tweak to your liking. Replace the bold blue text below with a valid file/path name of a PNG.
Code:

' DrawIconEx API:
Private Declare Function DrawIconEx Lib "user32.dll" (ByVal hDC As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long


Private Sub Command1_Click()
    Dim tPicture As StdPicture
    Dim imgData() As Byte, fnr As Integer, lSize As Long
   
    fnr = FreeFile()
    On Error Resume Next
    Open [the file] For Binary As #fnr
    If Err Then
        MsgBox Err.Description
        Exit Sub
    End If
    On Error GoTo 0
    lSize = LOF(fnr)
    If lSize = 0& Then
        MsgBox "File does not exist", vbExclamation + vbOKOnly
        Close #fnr
        Exit Sub
    End If
    ReDim imgData(0 To lSize - 1&)
    Get #fnr, 1, imgData()
    Close #fnr
   
    Set tPicture = LoadPNGtoICO(imgData())
    Erase imgData()
    If tPicture Is Nothing Then
        MsgBox "Failed to load the file. May not be valid PNG format or pre-Vista operating system.", vbExclamation + vbOKOnly
    Else
        ' change the 3rd & 4th 0& to destination width & height respectively. Zero = actual size
        DrawIconEx Me.hDC, 0&, 0&, tPicture.Handle, 0&, 0&, 0&, 0&, &H3
    End If
   
End Sub

CTimer class module with ITimer interface

$
0
0
This is a modified version of the CTimer class module from Paul Caton's "cTimer - module-less, IDE safe, machine code timer thunk".
The code has been simplified and the assembly thunk is also enhanced.

There are many class module Timers out there, so why another CTimer?

Because I was not 100% satisfied by either one. :rolleyes:
My most preferred CTimer was from Paul Caton, but were botherd because the 'lElapsedMS' parameter was not reliable as it could go negative.
The only one I know where this problem does not exist is Merri's SelfTimer class module, however there I am bothered as it is event driven and not interface driven. Also the assembly is working with private functions (ordinal address), where I have a dislike on them since I made the expierence that they can go broken in a ActiveX project after a "Binary Compatibility" compile. (means first compile works, but further ones are broken)

The benefit of interface driven "events" is that these are more efficient and it also ensures that the event will be fired. (no 'EventsFrozen' scenario)
Only downside is that this is a "two file" solution, but this is acceptable in my opinion.

So, what is the difference in this CTimer compared to the original from Paul Caton?
The original ITimer interface looks like this:
Code:

Public Sub Proc(ByVal lElapsedMS As Long, ByVal lTimerID As Long)
Whereas my is:
Code:

Public Sub Timer(ByVal Key As String, ByVal ElapsedTime As Currency)
So instead of a ID (Long), there is a Key (String) to identify multiple timers on one Owner.
Important point is that the ElapsedTime parameter is now as 'Currency' and not as 'Long' anymore to be able to represent an unsigned long integer.
So in fact the ElapsedTime value can be from 0 to 4.294.967.295. When it reaches 4.294.967.295 it wraps to 0 again.
This approach ensures that the value is never negative (important) and the timer can run 49.7 days until it wraps to 0.
Example: StartTickCount is -1 (right before GetTickCount wraps internally; unsigned value would be 4,294,967,295) and CurrentTickCount is 101 (after GetTickCount wrapped internally) the result in ElapsedTime (As Currency) will be: 102.
So that means it does not matter where GetTickCount currently is, the ElapsedTime will always work.
Only when the timer ran 49.7 days continuous, then the timer starts from 0 again. (rare case)
The assembly code was modified therefore to get the new results in the ITimer call.

Properties:
ID: Returns an internal identification of a timer. (Default value)
Interval: Returns/sets the number of milliseconds between calls to a timer event.

Functions:
Create(ByVal Owner As ITimer, Optional ByVal Key As String) As Boolean: Creates a new timer.
Terminate() As Boolean: Terminates the current timer.

There is no 'Enabled' property. To determine if the timer is running just check if 'ID' is <> 0.
The 'Interval' must be > 0, as otherwise the 'Create' function will return False and 'ID' remains 0.
To make a reset of the ElapsedTime just set 'Interval' again. (can be changed even if the timer is already created)

In the attachment is also a demo project included.
Attached Files

[VB6] Digital signature verifier (Authenticode and WHQL)

$
0
0
------------------
How to start?
Just add module 'modDigiSign.bas' to your project and look in 'Examples of using' below.
------------------

Hi,
I would like to present digital signature checker for executables and other file formats containing the code.

Purpose:
It is a well-tested module that allows you to verify things like:
- is signature legitimate (without need of internet connection)
- is driver's WHQL signature legitimate
- is signature belongs to Microsoft
- is signature embedded or external (signed by catalog)
- is signature present (by checking PE structure)

It can show info about certificates:
- validity date (begin / end period)
- issued by
- issued to (signer name)
- issued to (signer email)

Info about signature includes:
- short and extended description of verify results
- hash algoritms of signature digest and certificate's signature
- number of signatures
- timestamp (time of signing)

Demo project also contains code to check:
- is file PE EXE formatted
- is file SFC / WPF protected
Creates a report in CSV format.

Compatibility:
OS: Windows 10 / 8.1 / 8 / 7 / Vista / XP / 2000, both x32 and x64 bit, include 64-bit executables and 64-bit folders.
Hash algorithms of signature / digest: MD5, SHA1, SHA256.
Unicode aware.
Uses CryptoAPI, no other dependencies.

Requirements:
- If you are using File System Redirector in your program, make sure that it is NOT 'turned OFF' before calling functions of this module.
It is very important! If you cannot guarantee it, to ensure compatibility, you can call my wrapper "ToggleWow64FSRedirection (true / false)" from this module instead of your function.
- Do not use any sort of IDE emulations like 'compatiblity with XP' while running via IDE. It can take a negative effect on result of verifying.

License:
You can use modDigiSign.bas in your projects for free.
Full or partial re-publication of this info, attached article (including translation), projects and sources is prohibited without the direct permission of the author (me).

Examples of using:

General syntax:
Code:

Dim SignResult As SignResult_TYPE

SignVerify [File to check], [Flags], [out_SignResult]

1. Check is signature legitimate:
Code:

Dim SignResult As SignResult_TYPE

Debug.? "SignedAndVerified ? " & SignVerify("c:\path\File_to_test.exe", 0, SignResult)

Also, look in exampes / flags / tools description in posts below.
Attached Files

[VB6] StringBuilder - Fast string concatenation

$
0
0
It's well-tested class for concatenating strings like:
Code:

s = s & "one line"
s = s & "two line"
...
s = s & "N line"

but much much more faster than VB runtime do it.

Cases when it is needed sometimes:
Well, e.g., I'm using it to prepare some really huge logs of program in a single 'String' variable (e.g. up to 1 MB.) rather then writing them line by line to file (for performance acceleration purposes, if debug mode of my app. is disabled).
Don't know what else good cases. Better, don't store large data in this way, use suitable tools: arrays, databases ...

Using examples:
Code:


Private Sub Form_Load()
    'init
    Dim sb As clsStringBuilder
    Set sb = New clsStringBuilder

    'concatenation
    sb.Append "Very "
    sb.Append "many "
    sb.Append "pieces "
    sb.Append "of data"

    'result
    Debug.Print "All data: "; sb.ToString
    Debug.Print "Len of data: "; sb.length

    'removing 5 characters from position # 0
    sb.Remove 0, 5
    Debug.Print "New data: "; sb.ToString

    'inserting string in position # 0
    sb.Insert 0, "Not "
    Debug.Print "New data: "; sb.ToString

    'overwrite part of the text from position # 0 (same like MID(str,x) = "...")
    sb.Overwrite 0, "How"
    Debug.Print "New data: "; sb.ToString

    'replacing the data (same as Clear + Append)
    sb.StringData = "Anew"
    Debug.Print "New data: "; sb.ToString

    'clear all data
    sb.Clear
    Debug.Print "Len of data: "; sb.length

    'when finishing work with class
    Set sb = Nothing

    Unload Me
End Sub

Result:
Quote:

All data: Very many pieces of data
Len of data: 24
New data: many pieces of data
New data: Not many pieces of data
New data: How many pieces of data
New data: Anew
Len of data: 0
Copyrights: VolteFace (Fork by Dragokas)
Attached Files

[VB6] DPI Assistant Drop-In UserControl

$
0
0
The attached sample projects include the DPI Assistant tool. This tool is designed to help the coder prepare their projects for system DPI awareness. This tool is not designed for dynamic DPI awareness, i.e., per-monitor awareness... That's another project to create.

The tool is designed to be a drop-in, simply add it to an existing project as an uncompiled usercontrol. Do not compile the tool outside of your projects. It has features to detect IDE design and compiled host. When compiled and when in run-time, not compiled, the tool will turn some features off. The tool is strictly designed for the IDE and image scaling during runtime. It can be removed permanently after satisfied you are DPI-aware enough, as long as you are not using any of its image or control scaling options.

What does it do? It has several properties to alert you when DPI-awareness issues exist in your project. It contains several image-related functions to make it easier to scale images due to DPI changes. It can scale nearly all of your controls and allow you to override the scaling. It does not automatically scale images, but will provide the suggested new dimensions relative to current DPI. Scaling an image can be as simple as a single call to one of the tool's scaling functions.

This tool does NOT make your project DPI aware, it assists only. You still should provide multiple sizes of your icons and/or bitmaps/PNGs, etc. The scaling features use GDI+ to perform high quality scaling, but there is only so much quality that can be expected when scaling something 2 -3 times its size; hence, having multiple sizes in your resource file is a good strategy.

Along with the image scaling functions, there is also a function that will allow you to load PNG and TIFF images. However, transparency is still an issue since VB doesn't like to support that outside of icons and GIFs. But faking transparency by having the tool load the PNG over a solid background color works really nice if the image does not need to be shown over a dynamic background. There are options that will create pre-multiplied RGB bitmaps that can be used in menus on Vista and newer, load alphablended icons drawn over solid backgrounds that can be added to an ImageList for display in a TreeView or ListView control. And a few more image options.

But for any of this to help, you must declare your project DPI aware. This requires a simple manifest added to a resource file. The manifest simply tells Windows not to stretch your application when DPI changes, that your application can scale itself without much help from Windows. This is explained in more detail in post #2.

Here are some of the things that the tool will assist you with. Following are explained in more detail in posting #3.
- Image scaling
- Identifying non-TrueType fonts and alerting you so you can fix that
- Identifying known problems with VB controls that can occur when DPI changes
- Auto-scaling controls, as needed, and allowing you to prevent it (per control)
- Counter-scaling your controls when VB's DPI is different than the system

The screenshots below have been resized for upload here. In post #2 (maxed out my number of attachments on this posting) is a zip with full images, unscaled, of how atypical DPI, like at 175% DPI (as were these), can hose up your DPI-aware application if you are not prepared for it. The images below are, from top to bottom, an example of app not DPI aware, app DPI aware but failed to address VB-related problems, and a DPI aware app after addressing those problems

Name:  DPIunaware.jpg
Views: 72
Size:  53.9 KB
Name:  DPIawareNoAssist.jpg
Views: 61
Size:  64.6 KB
Name:  DPIawareAssist.jpg
Views: 59
Size:  56.6 KB

The attachments below each have the DPI Assistant tool. Just copy the .ctl & .ctx file to wherever you may want it. A good place could be your VB folder where templates are stored. That way it will show up in the list of usercontrols when you opt to add a "new" usercontrol to your project, i.e., ...VB98\Template\Userctls

I do expect changes to this code as more & more people play with it and report bugs and request enhancements. Recommend compiling each sample project and seeing how they differ in other DPIs. Always test your apps in 175% DPI. If VB breaks, it'll break there.
Attached Images
   
Attached Files
Viewing all 1321 articles
Browse latest View live


Latest Images