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

[VB6] Friend Callback Procedures

$
0
0
The attached project below demonstrates how to set up Friend procedures inside object modules (FRM, CLS, CTL, etc.) for Windows API callback purposes. The goal of such a technique is to keep as much code as possible within the object module in order to make it as self-contained as possible and also to reduce memory consumption once the object module is unloaded. There is a possibly significant disadvantage to this approach however - the overhead of redirecting calls to procedures in an object module naturally imposes some performance penalty.

(This code has been inspired by the following post: Re: Problem with Public UDT: 'Only public user defined types......)
Attached Files

Using FileSelector class to make a compact Open File dialog.

$
0
0
This example using the latest glist4 and fileselector class for a compact file loader.
From setup menu we can change the sort type, the behavior, the performance (normal recursive 3 levels, recursive all levels). For this example the scope is to open an image file so we have a preview. We can select "multiselect" and we can fill the list on the main form with files not only from one folder but from any folder that we can open "recursive". Each file has path on it.
We can set a top folder so we can't go up beyond top folder.
It is easy to use.
Next time I make the Save File (need to take input...and I would like to finish gEditbox).

2 bug fixes. One is a logic bug, because I use internal list and external list to populate the listbox without block the logic for menus. I fixed that making the flag in selector class as a property so in a change of it, secondary changes a flag in the glist so menu parcing is blocked. So simple. The other bug is also from menu. When you select a non selected radio button and click in an other line (wrong Y position) in right X position then that click goes to the radio button and enabled. So I put an condition check and bug is over.


Programming is an art to describe your faults.
Attached Images
  
Attached Files

WIA Loader and Saver class

$
0
0
This class allows you to load and save all kinds of image files, including PNG and TIF. It is requires WIA 2.0 which is a Microsoft created DLL file called wiaaut.dll. A complete description of the capabilities of this class is included with the class as a text file. The entire thing is packaged in the ZIP file that is attached to this post, including the required DLL file. Though I don't normally package executables with my source code on the Codebank, it is an essential file, without which my class would not work, and it is an official file from Microsoft. I would usually choose to link to the Microsoft download page for the file, except that Microsoft is no longer distributing it (the page that had it before is now gone). Thus it is included in the ZIP file along with my class. Also included is Helpfile.txt (it explains in great detail, everything that my class does), License.txt (it explains how you may use, alter, distribute, etc my class file), and EULA.txt (the Microsoft EULA for the DLL file).
Attached Files

Some code to calculate the Greatest Common Divisor

$
0
0
This code sample calculates the GCD of numbers A and B, using the Euclidean algorithm (as described at https://www.khanacademy.org/computin...dean-algorithm).

Code:

Private Function CalculateGCD(ByVal A As Long, ByVal B As Long) As Long
Dim Remainder As Long

' If B is greater than A, then use the xor data swap technique.
If B > A Then
    B = A Xor B
    A = A Xor B
    B = A Xor B
End If

' Calculate the GCD.
Do Until B = 0
    Remainder = A Mod B
    A = B
    B = Remainder
Loop

CalculateGCD = A
End Function


And here's a small bit of code used to test the above function.
Code:

Private Sub Form_Load()
MsgBox CalculateGCD(100, 36)
End Sub

The output for this example should be 4.



Another thing that the GCD is useful for is to find if two given numbers are mutually prime. By definition, any two numbers are mutually prime if those numbers have a GCD of 1. The below code is a random mutual prime number pair generator. Its outputs are 31 bit numbers. It must be 31 bits, not 32, because all numbers larger than &h7FFFFFFF actually used as two's compliment negative numbers in VB6's data type. So I can't use the full 32 bit range. However, this works great for demonstrating the idea of mutually prime numbers.

Code:

Private Sub Form_Load()
Dim A As Long
Dim B As Long

Randomize

Do
    A = Int(Rnd * 256) * &H1& + Int(Rnd * 256) * &H100& + Int(Rnd * 256) * &H10000 + Int(Rnd * 128) * &H1000000
    B = Int(Rnd * 256) * &H1& + Int(Rnd * 256) * &H100& + Int(Rnd * 256) * &H10000 + Int(Rnd * 128) * &H1000000
Loop Until CalculateGCD(A, B) = 1

MsgBox "A=" & CStr(A) & " and B=" & CStr(B)
End Sub

A custom compact and resizable Open File/Save File/Folder Select.

$
0
0
This example using the latest glist4 and fileselector class for a compact file loader.
From setup menu we can change the sort type, the behavior, the performance (normal recursive 3 levels, recursive all levels). For this example the scope is to open an image file so we have a preview. We can select "multiselect" and we can fill the list on the main form with files not only from one folder but from any folder that we can open "recursive". Each file has path on it.
We can set a top folder so we can't go up beyond top folder.
It is easy to use.
Next time I make the Save File (need to take input...and I would like to finish gEditbox).

2 bug fixes. One is a logic bug, because I use internal list and external list to populate the listbox without block the logic for menus. I fixed that making the flag in selector class as a property so in a change of it, secondary changes a flag in the glist so menu parcing is blocked. So simple. The other bug is also from menu. When you select a non selected radio button and click in an other line (wrong Y position) in right X position then that click goes to the radio button and enabled. So I put an condition check and bug is over.


Programming is an art to describe your faults.

*********** Good News ******
The control is done. Now We can Save/Load/Select Folder only. Multiselection for files, tree of folders and or files, preview images (for the example). Also now glist can edit line and centered line too.
Attached Images
  
Attached Files

Kingsoft Spreadsheet and VB6

$
0
0
Reading through the forums, there seems to be some confusion on how to create an Excel Spreadsheet using the Kingsoft Spreadsheet package via Automation with Visual Basic 6.

Here is sample source code;
Code:

Dim oExcel
Dim oBook
Dim oSheet

'Start a new workbook in Kingsoft Spreadsheet
Set oExcel = CreateObject("et.Application")
Set oBook = oExcel.Workbooks.Add

'Add data to cells of the first worksheet in the new workbook
Set oSheet = oBook.Worksheets(1)
oSheet.Range("A1").Value = "Last Name"
oSheet.Range("B1").Value = "First Name"
oSheet.Range("A1:B1").Font.Bold = True
oSheet.Range("A2").Value = "Dunn"
oSheet.Range("B2").Value = "Elias"

'Save the Workbook and Quit Excel
oBook.SaveAs "C:\utils\example.xls"
oExcel.Quit
'***********END***********

The free copy of Kingsoft Spreadsheet is available from http://www.kingsoftstore.com/spreadsheets-free.html

While this code was written for use with VBScript, it works the same in Visual Basic 6.

Elias

BF Interpreter - an interpreter for a minimalist programming language

$
0
0
Attached to this thread is an interpreter for a minimalist programming language called Brain***** designed by Urban Müller. It only has eight different commands. The interpreter I made for it can load and execute files containing source code for the language.

The code for a "Hello World!" program:
Code:

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
Wikipedia has more information, but due to the language's somewhat offensive name part of the url is censored by this forum so I can't post a direct link. Just search for "Urban Müller" and you should be able to find it.
Attached Files

Connect Four/Four in a Row game

$
0
0
Here's a simple Connect Four game written in Microsoft Visual Basic 6.0. The game has the following options:

-Set who plays first. (red or yellow)
-Whether one of the players is the computer, and if so, which color it plays with.

The code should be fairly easy to customize.
Attached Files

[VB6] Color Management with GDI+

$
0
0
Updates (see post #2 for bug descriptions):
31 Aug 14: Fixed JPG related GDI+ bug

Higher quality images often have a color management profile (ICM/ICC) embedded into their file. These embedded profiles can be retrieved from GDI+ most times. Not many image formats support embedded profiles, but these do per ICC.org: png, tif, jpg & gif.

When embedded, the image's creator provided it so that it can be used to reproduce the image on any monitor/printer in the colors that the creator intended. By ignoring the profile, what you get is not what the creator intended. Sometimes it can be radically different. Images without ICC profiles are at the mercy of the rendering application. GDI+ does a fair job without embedded profiles, but its hands are tied when best-guessing how to interpret the colors.

Windows provided color management for quite awhile now, but it is the application's responsibility to apply it. The flat GDI+ API wrapper doesn't support color management directly. But with the use of Windows APIs we can still use GDI+ and apply color management

For a project that doesn't rely on GDI+ for displaying images with embedded ICC profiles, see Tanner's work here. This project is not meant to be competitive with Tanner's hDC-based solution, it is provided as a workaround for those that exclusively use GDI+ for image rendering/processing, no device contexts used in transformations. I started this about 2 years ago & lost interest. Can rest easier now :)

This sample project uses Windows to help transform colors, but the result is maintained and used by GDI+. From the sample screenshot, you can see a radical example along with a real-world example of how color management can improve what is displayed. And this sample project may include the only VB6 code that processes a GIF embedded ICC profile instead of ignoring them. To be fair, embedded GIFs are really hard to find.

To find other images to play with, google for: color profile test

From time to time, will update this as needed

Request. If anyone would like to upload an 8 bit grayscale JPG, TIFF or PNG with the appropriate ICC profile, embedded or not, please do so. I'd like to examine them. Currently, processing 8 bit images other than GIF is turned off in the code.

How do I load any profile I want and use it in the transformation?
Open the file and read it ito a byte array, then sample code provided. Project will need to be modified to accept a user-provided profile handle to the pvColorManageImage method
Code:

hProfile = pvCreateProfile(VarPtr(array(0)), UBound(array)+1)
' array can be erased immediately after function returns

Attached Images
 
Attached Files

[VB6] RSA Public Key Encryption via CNG

$
0
0
Now that Windows XP has joined earlier versions of Windows as unsupported software we can feel more free to move away from legacy technologies.

Cryptography API: Next Generation is one of the new Windows features introduced in Windows Vista.


RSA Public Key Encryption

The basic concept here is that you can create an asymmetric pair of keys: a "public" key that you give to others and a "private" key you keep yourself. Other users can all encrypt messages for you using the public key, but they cannot decrypt each others' messages to you. You can decrypt the messages using your private key.


CngRsa.cls

This is a VB6 Class that uses several CNG API calls to implement basic RSA encryption. It does not implement a key container format portable between operating systems and platforms, or a message container format.

For Windows to Windows messaging the binary BLOBs can be exchanged and work just fine. For multiplatform use you would need to expand upon this.


Caution

I won't pretend to be a cryptographer or cryptography software expert. There may be weaknesses in my usage of these API calls, and there could be quite a few areas worthy of improvement.

However this might be a useful example to get you started using the CNG API for encryption and hashing.


Requirements

As noted above, CNG became available beginning in Windows Vista. There was never a redist version of the Windows libraries involved for installation into Windows XP or earlier.

You'll also need VB6.


Demo

The demo should run fine either in the IDE or compiled. Be sure to set Break on Unhandled Errors unless you need to debug the internals of the CngRsa Class.

Running the demo should be straightforward, most of it is UI management logic that should lead you through testing step by step. There are 6 "panels" selected via buttons along the top, each becoming enabled as it becomes relevant.

After generating the key pair you can view each key in hex, or enter an input message and encrypt it.

Once you have encrypted a message you can view the cipher text and decrypt it.

After this you can go back to the message input panel, clear, and enter another message to decrypt.

You can also go back and generate a new key pair.


Name:  sshot.png
Views: 68
Size:  25.5 KB

Ready to decrypt


The demo does not persist keys or messages.


Usage

Adding CngRas.cls to a new Project is easy. There is just one file (no .BAS modules, etc.). There are no dependencies beyond those that ship as part of Windows.

See the ReadMe.txt file included for some usage notes, required sequence of calls, etc.
Attached Images
 
Attached Files

[VB6] RSA Data Signing via CNG

$
0
0
One of the things we get in post-XP Windows is a new crypto library. This offers a number of small advantages such as being a lttle more "rational" from a usage standpoint (calls are somewhat more symmetric) but also some new crypto features such as longer keysize limits for some existing algorithms, elliptic curve cryptography (ECC), and some other goodies.

So here is a simple class CngRsaSign.cls that makes use of Cryptography API: Next Generation (CNG) for creating RSA key pairs and signing and verifying data blobs.

No formal "certificates" are required or used here.


Scope

I won't go into other issues here such as encrypting the data to be signed, or deriving and verifying "Machine ID" fingerprint values. Those have been covered elsewhere and people have lots of ideas about what makes a good machne ID.

I also haven't addressed things like what your Purchase Server and Product Registration Server might do. At a minimum a Purchase process might accept identifying info and payment and return a Product Key of some type. Then within your program or its installer you might have a Registration process that sends back the entered Product Key, some sort of Machine ID, etc. to your Registration Server which returns the signed license data file which your program records to disk.

However here the issue at hand is simply how to sign a blob of data (for example a software license file) so that your applications can validate it against tampering before trusting the values it contains.

Of course this could also be used to sign "messages" you send to people, with the signature being used to prove the message was from you and not tamepred with.


Requirements

Windows Vista or later. There is no redist version of the bcrypt.dll or its dependencies that can be deployed to a Windows XP or older system.

The VB6 development tools of course.


Simple Demo

The demo here just stores two values (Name and Email) in the data blob. These are just stored as "key=value" lines delimited by CRLF in UTF-16LE ("Unicode") text.

You could use UTF-8. You could use XML or JSON. You could use PropertyBag.Contents format. You could encrypt or obfuscate the blob.

Here we do none of that, we just sign it.


Caution

I am not a crypto expert so you will want to verify that nothing being done here weakens the potential advantages of signing such files.


Two Parts

The attachment contains the two-part demo.

The first is Sign.vbp, a simple VB6 program that can (1.) create a key pair which it writes to disk as two blob files, (2.) import the created Private key blob for use in signing data, and (3.) accept Name and Email and then compose the data blob, sign it, and write it to disk.

The second is Verify.vbp, a simple dummy VB6 application. This is even more trivial, and all it does is read the signed data from disk, verify the signature using the Public key blob, and then extract and display Name and Email.


Name:  sshot1.png
Views: 29
Size:  11.2 KB

We have created a key pair, now import the private key


Name:  sshot2.png
Views: 26
Size:  11.2 KB

We have entered the data, now we can create the signed file


Note that the dummy application has a copy of the Public key stored as a custom resource. After you have generated a new key pair, you must replace the existing Public key with your new one and recompile. Otherwise the next step will fail.


Name:  sshot3.png
Views: 24
Size:  10.2 KB

Now we've run the dummy application and
the signed data file has passed verification


Enhancements

For a purpose such as a key file you might be more comfortable concealing the payload, so as previously mentioned you might obfuscate or even encrypt it. But the aim here is just to show how to detect and reject a file that has been tampered with.

One thing you might want to do is create a second stripped down version of CngRsaSign.cls for use in applications. Typically you'd only need to be able to import a Public key and then verify the signature within deployed applications. You could also obfuscate the names of things to help throw anyone off who tries to decompile and patch your applications to bypass this check.


To Run The Demo

Download and unzip the attachment.

Open Sign.vbp and run it in the IDE or compile it and run the EXE. Create a new key pair. Import the Private key, enter the two items of data, and create the signed file.

Open Verify.vbp and edit the resource file: delete the existing Public key, create a new custom resource using your new Public key and of course set its ID and TYPE to match those used in the program. Then run it in the IDE or compile it and run the EXE.

That's it.


Updated attachment

Added a 3rd project Tamper.vbp that can be run to read the data field values, let you alter them, and store the signed file back to disk with alterations. If you run this and change anything then the Verify program should fail - even if you just change one letter, add one, or delete one.

Updated again

Removed some redundant definitions.
Attached Images
   
Attached Files

[VB6, Vista+] SplitButtons

$
0
0
Now that more people are moving off Windows XP we can start using more of the new features added to Windows back in 2006.

One of these is a funny control called a "Split Button" which is really a variant form of a Win32 Button control such as the ones that live inside of VB6's intrinsic CommandButton control. However Microsoft hasn't updated VB6 and isn't likely to, so as with so many things we have to take matters into our own hands and dig around under the covers.

SplitButtons.bas is a VB6 static module designed to help implement the additional capability in CommandButtons.


Split Button?

There are problems this might be a good solution for, but probably not as many as you might think upon first look.

A Split Button is a sort of "composite control" like the ComboBox. Here we have a button combined with a dropdown list. When clicked the button acts like a button. When clicked at the right on the "dropdown glyph" (triangle) a list drops down and the user can select a new meaning for the button.

Normally this changes the button Caption to reflect the new meaning, and future clicks should repeat this selected meaning. Making the change from the dropdown list also acts like a click with the new meaning.


Name:  sshot1.png
Views: 38
Size:  14.0 KB

Changing the first button


Name:  sshot2.png
Views: 46
Size:  18.5 KB

A few buttons later, changing the button at the bottom
of the Form, note the overhang


For whatever reason Microsoft did not build the dropdown list into the enhanced Button control. They just provide some plumbing that allows you to tie a popup menu to the control yourself.

This means you could put all sorts of weird stuff into that menu and have selection do all sorts of crazy things. But it is probably going to be far better for your users if you stick to the "prescribed" behavior of Split Button controls.


Requirements

Windows Vista or later. Rumored to also work in XP (SP2? SP3?) but Vista is documented as the minimum.


Programming Requirements

This will not do anything at all for you unless your program has an application manifest that selects the Common Controls 6.0 assembly.

And when you do that you really want to use a Sub Main() as your "startup object" that loads a couple of libraries in the correct sequence (see the demo). If you fail to do this your programs might work sometimes and then mysteriously crash other times. I don't know why this isn't consistent, but it does lead to some quirky programs floating around out there. Better to just do the load sequencing and be safe.

See the comments in the demo code. They help explain some extra steps required to use Split Buttons in a UserControl too.


IDE Testing

To have the style change make any sense for testing VB6.EXE will need an application manifest.

I don't normally like to work this way because it can mess up a few things, for example some of the "list" properties of control in the Properties Pane of the IDE.

Manifest caching can also make it annoying to try to use file manifests: a change may not show until next reboot. I've had better luck embedding a manifest in VB6.EXE, but I have a nice tool for this. Your mileage may vary.


Testing the Demo

Assuming you have VB6 installed on Vista or later you can just unzip the archive, open the .VBP file, and compile the program without trying to run it within the IDE. Then exit the IDE and run the compiled EXE.


Some Remarks

While a lot of people forget (never knew?) this, the Windows keystroke to "drop" a list (ComboBox, etc.) is the F4 key. From there the user can up/down arrow to choose a list item and Enter to select it. Since Microsoft didn't seem to implement that either, SplitButtons.bas goes ahead and does so. Sadly this makes the code slightly more complex than it might otherwise need to be, and we have to subclass two windows.

Oh well! At least the mouseless will appreciate the effort.

I have noticed that some people implement the dropdown/popup a little differently, indenting the menu to the right 120 to 180 twips or so. Feel free to change this, it should be simple enough.

I think the demo's buttons are a little tall myself, but you can just size those in design mode as with any CommandButton.
Attached Images
  
Attached Files

HTML converter

$
0
0
hello all. I an new to the forum and I have very limited experience in VB. I am looking for the easiest way to convert an HTML table to other formats (csv, etc.) automatically. Any suggestions would be appreciated.

[VB6] RLE8 Compression Algorithm for Bitmaps

$
0
0
Microsoft allows 8-bit bitmaps to be compressed using a somewhat simple, not terribly efficient, run length encoding (RLE). Strict rules apply, but is rather easy to encode/decode
Quote:

Originally Posted by paraphrased from msdn
Encoded runs cannot be larger than 255 bytes
Encoded scanlines terminate with a double null byte (end of line EOL)
Encoded bitmap terminates with bytes: 00 01 (EOF)
Scanlines are Word aligned, not DWord aligned
Associated BITMAPINFOHEADER fields required: biCompression=BI_RLE8: biSizeImage = size of encoded pixels

Encoding: can have several runs per scanline. Each run starts with a control byte:
01-255 indicates a repeated byte run length. The next byte is the repeated byte
00 indicates EOL, EOF or uncompressed run follows. Next byte determines meaning
00 = EOL
01 = EOF
02 = Delta followed by 2 byte "jump-to" coordinates. Not used in this project
03-255 = uncompressed run length & the uncompressed bytes follow
for odd length runs vs. even length, one padding byte is required at end of encoded run

Compression net gain(+)/loss(-) per run:
repeated byte runs: (length of run) - 2
uncompressed runs: if run is even number of bytes: net loss of 2 else net loss of 3
each scanline removes 2 bytes (EOL marker) from any net gain
loss of 2 bytes (EOF marker) from total net gain after all pixels encoded

Whether you are aware of it or not, you can actually get the API GetDibits to compress these 8-bit bitmaps for you. Niffty, fast, but unfortunately, what is returned can actually be larger than the original uncompressed image at times. In any case, I think we can do a bit better than Windows in this area.

Attached is a sample project wrapped around the key routine: pvCompressRLE8. Also included are 2 simple bitmaps to play with. Now trying to go out and find 8-bit bitmaps can be a bit painful, pun intended ;)
Suggestion: for playing around, use Microsoft Paint. Open image in Paint, save image as 256 color bitmap & don't care if the colors get messed up a bit. It's just for playing anyway

The routine I've written is not guaranteed to compress smaller than the total uncompressed size. But it should 99.9% of the time. In fact, it out-performs GetDibits every time (so far). I'm sure there are a few bitmaps that Windows can compress better via GetDibits.

This routine was created simply because I was inquisitive, wanted to see if I could possibly do it better (given how poorly Windows seems to do it). If there are better routines out there, please link them. Think many would like to learn from those also, me included.

Last but not least, I'm not touting this as the best RLE8 routine for VB6ers. But it ain't bad for a 1st attempt. The one I've included could use a little tune-up also.

Edited: Senior moment. Didn't include a browser class in the zip. It's there now.

FYI: If you want to see how Windows does when the routine fails to compress a bitmap, rem-out the "GoTo ExitRoutine" line after the msgbox displaying the failure

Best case scenario for failure and the "compressed" data being larger than the original data size would be a size equal to that shown below (assuming width < 256 else worse results). This is because if no bytes repeated on any scanline, the scanline would be coded with a 2 byte prefix + the entire scanline bytes + 2 byte scanline terminator. The encoding also requires a 2 byte EOF maker. But when compressing fails, the routine aborts so user can write bitmap in original bytes vs writing an even larger bitmap. Note: standard bitmaps without any compression algo applied have their pixels DWord aligned. This means for an 8-bit bitmap, a maximum of 3 padding bytes per scanline can be used for standard bitmaps. Even if that is the case, the minimum extra bytes used in RLE8 compression would be 4 per scanline. In other words, RLE8 without being able to compress any bytes, would be a larger file than not using RLE8 at all:
Code:

<best-case "compressed" size when bitmap cannot be compressed (not good)>
even-value image width: ImageHeight * 4 + 2 + (ImageHeight * ImageWidth)
odd-value image width: ImageHeight * 5 + 2  + (ImageHeight * ImageWidth)
^^ extra padding byte needed per scanline

Attached Images
 
Attached Files

[VB6] RLE8 Compression Algorithm for Bitmaps (Updated)

$
0
0
Updated. Added another tweak that works pretty well. Post #2 describes additional tweaks that can be made. The tweak in this update was to attempt merging the scanline's final uncompressed and compressed runs. About 10 lines more code, the results were better than expected. Also updated the zip to include 2 more bitmaps: 1) one that this project & Windows can't compress smaller & 2) one where Windows can't compress, but this project compresses pretty well

Microsoft allows 8-bit bitmaps to be compressed using a somewhat simple, not terribly efficient, run length encoding (RLE). Strict rules apply, but is rather easy to encode/decode
Quote:

Originally Posted by paraphrased from msdn
Encoded runs cannot be larger than 255 bytes
Encoded scanlines terminate with a double null byte (end of line EOL)
Encoded bitmap terminates with bytes: 00 01 (EOF)
Scanlines are Word aligned, not DWord aligned
Associated BITMAPINFOHEADER fields required: biCompression=BI_RLE8: biSizeImage = size of encoded pixels

Encoding: can have several runs per scanline. Each run starts with a control byte:
01-255 indicates a repeated byte run length. The next byte is the repeated byte
00 indicates EOL, EOF or uncompressed run follows. Next byte determines meaning
00 = EOL
01 = EOF
02 = Delta followed by 2 byte "jump-to" coordinates. Not used in this project
03-255 = uncompressed run length & the uncompressed bytes follow
for odd length runs vs. even length, one padding byte is required at end of encoded run

Compression net gain(+)/loss(-) per run:
repeated byte runs: (length of run) - 2
uncompressed runs: if run is even number of bytes: net loss of 2 else net loss of 3
each scanline removes 2 bytes (EOL marker) from any net gain
loss of 2 bytes (EOF marker) from total net gain after all pixels encoded

Whether you are aware of it or not, you can actually get the API GetDibits to compress these 8-bit bitmaps for you. Niffty, fast, but unfortunately, what is returned can actually be larger than the original uncompressed image at times. In any case, I think we can do a bit better than Windows in this area.

Attached is a sample project wrapped around the key routine: pvCompressRLE8. Also included are 2 simple bitmaps to play with. Now trying to go out and find 8-bit bitmaps can be a bit painful, pun intended ;)
Suggestion: for playing around, use Microsoft Paint. Open image in Paint, save image as 256 color bitmap & don't care if the colors get messed up a bit. It's just for playing anyway

The routine I've written is not guaranteed to compress smaller than the total uncompressed size. But it should 99.9% of the time. In fact, it out-performs GetDibits every time (so far). I'm sure there are a few bitmaps that Windows can compress better via GetDibits.

This routine was created simply because I was inquisitive, wanted to see if I could possibly do it better (given how poorly Windows seems to do it). If there are better routines out there, please link them. Think many would like to learn from those also, me included.

Last but not least, I'm not touting this as the best RLE8 routine for VB6ers. But it ain't bad for a 1st attempt. The one I've included could use a little tune-up also. See post #2

Edited: Senior moment. Didn't include a browser class in the zip. It's there now.

FYI: If you want to see how Windows does when the routine fails to compress a bitmap, rem-out the "GoTo ExitRoutine" line after the msgbox displaying the failure

Best case scenario for failure and the "compressed" data being larger than the original data size would be a size equal to that shown below (assuming width < 256 else worse results). This is because if no bytes repeated on any scanline, the scanline would be coded with a 2 byte prefix + the entire scanline bytes + 2 byte scanline terminator. The encoding also requires a 2 byte EOF maker. But when compressing fails, the routine aborts so user can write bitmap in original bytes vs writing an even larger bitmap. Note: standard bitmaps without any compression algo applied have their pixels DWord aligned. This means for an 8-bit bitmap, a maximum of 3 padding bytes per scanline can be used for standard bitmaps. Even if that is the case, the minimum extra bytes used in RLE8 compression would be 4 per scanline. In other words, RLE8 without being able to compress any bytes, would be a larger file than not using RLE8 at all:
Code:

<best-case "compressed" size when bitmap cannot be compressed (not good)>
even-value image width: ImageHeight * 4 + 2 + (ImageHeight * ImageWidth)
odd-value image width: ImageHeight * 5 + 2  + (ImageHeight * ImageWidth)
^^ extra padding byte needed per scanline

Attached Images
 
Attached Files

[VB6, Vista+] Query Windows Search

$
0
0
Now that Windows XP is dead we can feel free to make wider use of new features of Windows introduced nearly 8 years ago. One of these that I see almost no use of by VB6 programmers is the ability to query the indexes maintained by Windows Search. Sad, because it is really pretty easy.

I think the easiest way to make use of Windows Search programmatically is to use its SQL syntax via ADO and the data source object provided as part of Windows Search in Windows Vista and later. This was even made available for Windows XP SP2 if you had installed Windows Desktop Search 3.x, which might still be available to download for a few months yet.

This can be used to do simple or complex searches of disk files, Outlook email, and offline files. You can search on a number of properties and even do full-text searching of file types that have an appropriate filter installed.


Here are a few links to articles, mostly old now and mostly .Net oriented:

Searching the Desktop

An Introduction to Vista's Integrated Search Capabilities


There is also the MSDN topic:

Windows Search

Jumping deeper within that section we find:

Querying the Index with Windows Search SQL Syntax


Of course to be of value the data you want to query on needs to be in an indexed location. For example Program Files normally isn't indexed, while the Users area generally is. Indexed locations are determined administratively via the Indexing Options, which you can find in the Control Panel.


Name:  sshot0.jpg
Views: 12
Size:  15.1 KB

Indexing Options


The sample code in the attached demo is an example of some basic use of Windows Search queries. Here you can specify a target folder (or none, meaning all indexed locations on all drives) and an optional list of file names to look for, as well as a limit for the number of hits to report:


Name:  sshot1.jpg
Views: 16
Size:  15.5 KB

Find all "readme.txt" in "d:\Downloads"


When the results are returned the demo lists out the requested property values in a flexgrid:


Name:  sshot2.jpg
Views: 14
Size:  49.0 KB

24 hits


In addition to the documentation on MSDN, I find the propkey.h header file from the Vista SDK quite helpful. The Windows 7 SDK should have a newer version of the same file.
Attached Images
   
Attached Files

[VB6, Vista+] Simple Task Dialog

$
0
0
I posted sample code using this class for raising simple Task Dialogs several times over the years, but I never gave it a CodeBank thread of its own.


Task Dialogs

Now that Windows XP is dead we can start making more use of features like this to avoid that old Windows 3.1/95 look and feel. This class is a basic wrapper for the calls required to make use of the Task Dialog.

You can expand upon this with callbacks to make use of even more Task Dialog features, but here we have the core subset covered without extra modules to host those callbacks. The result is a simple alternative to the VB6 MsgBox.


Requirements

Window Vista or later.

An application manifest selecting the Common Controls 6 assembly.

Startup logic that loads shell32.dll and comctl32.dll before any Forms or other UI elements - and in the correct sequence.


Details

STDlg.cls is a VB_PredeclaredId = True class so you don't have to create additional instances. It wouldn't make sense to have more than one in a program anyway.

It has just one method: TaskDialog(), loosely patterned on MsgBox().


Caution

STDlg.cls is unlikely to work correctly within the IDE if you run VB6.exe with a Common Controls 6 manifest itself. Most people don't do this though.

Normally it checks the loaded comctl32 version to determine whether to try to use Task Dialog or just substitute a MsgBox call instead. You could add a "running in the IDE" test to the code though.


Name:  sshot.png
Views: 36
Size:  16.0 KB
Attached Images
 
Attached Files

Nice Textboxes

$
0
0
Why some functions are so difficult to find. I would like to have some controls without the restrictions for using...this or that themes..manifests or other bad habits..
So i wrote some textboxes. All of them are based in glist (latest edition).
Here I have a TextViewer to display text with line spacing as we wish and wrapping or not. The only limitation is has no drag and drop,and not for this version undo control.. Because is the glist behind this TextViewer can scroll the text holding down the mouse button and doing a move anywhere in the window of the glist

I also have some textboxes with one line only
- a Combobox with auto complete function (shows/hide a listbox of values)
- a Spinner Textbox for a long value. We can alter the value by clicking and writing, by using up down buttons, by using the scroll bar.
- a simple textbox wit centered text that can be edit ...as is, we can use it without edit, just showing text
- a button that can be slide the caption and perform the "click" (by panning right) (2 buttons using here, one to alter the wrapping of the textViewer, and the other to show/hide the paragraphs marks..
- A floating list of values to put in Spinnet TextBbox. We can "call" like a popup menu. See above the spinner textbox, when you right click.

Thats all...
Attached Images
 
Attached Files

[VB6] Color Management with GDI+ (updated 20 Sep 14)

$
0
0
Updates (see post #2 for bug descriptions):
20 Sep 14
:: Added patch for a specific case when GdipBitmapLockBits fails to lock image data
:: Added support for JPGs where GDI+ won't return any ICC information. See posts 9-13
:: Added support for other 8 bpp images. See posts 14-22
10 Sep 14: Added support for ICC profiles embedded into the BMP format
31 Aug 14: Fixed JPG related GDI+ bug

Higher quality images often have a color management profile (ICM/ICC) embedded into their file. These embedded profiles can be retrieved from GDI+ most times. Not many image formats support embedded profiles, but these do per Color.org: png, tif, jpg & gif. Additionally, per Microsoft, bitmaps can support ICC profiles also.

When embedded, the image's creator provided it so that it can be used to reproduce the image on any monitor/printer in the colors that the creator intended. By ignoring the profile, what you get is not what the creator intended. Sometimes it can be radically different. Images without ICC profiles are at the mercy of the rendering application. GDI+ does a fair job without embedded profiles, but its hands are tied when best-guessing how to interpret the colors.

Windows provided color management for quite awhile now, but it is the application's responsibility to apply it. The flat GDI+ API wrapper doesn't support color management directly. But with the use of Windows APIs we can still use GDI+ and apply color management

For a project that doesn't rely on GDI+ for displaying images with embedded ICC profiles, see Tanner's work here. This project is not meant to be competitive with Tanner's hDC-based solution, it is provided as a workaround for those that exclusively use GDI+ for image rendering/processing, no device contexts used in transformations. I started this about 2 years ago & lost interest. Can rest easier now :)

This sample project uses Windows to help transform colors, but the result is maintained and used by GDI+. From the sample screenshot, you can see a radical example along with a real-world example of how color management can improve what is displayed. And this sample project may include the only VB6 code that processes a GIF embedded ICC profile instead of ignoring them. To be fair, embedded GIFs are really hard to find.

To find other images to play with, google for: color profile test

From time to time, will update this as needed

Request. If anyone would like to upload an 8 bit grayscale JPG, TIFF or PNG with the appropriate ICC profile, embedded or not, please do so. I'd like to examine them. Currently, processing 8 bit images other than GIF/BMP is turned off in the code.
Note: 8 bit image processing turned on with the 20 Sep update

Note: The included bitmap sample image will not be read by VB's LoadPicture function. Believe VB does not support any bitmap using version 4 or 5 of the BITMAPINFOHEADER. But such images can be loaded via setting a DIB's pixel data to the pixel data contained in the bitmap file.

How do I load any profile I want and use it in the transformation?
Open the file and read it ito a byte array, then sample code provided. Project will need to be modified to accept a user-provided profile handle to the pvColorManageImage method.
Note: In most recent update, modified function to include an optional FileName parameter
Code:

hProfile = pvCreateProfile(VarPtr(array(0)), UBound(array)+1)
' array can be erased immediately after function returns
' CloseColorProfile must be called on the returned profile handle, when no longer needed

Attached Images
 
Attached Files

[VB6] TaskDialogIndirect Simple Implementation

$
0
0
So I really liked the implementations of TaskDialog that I've seen, and wanted to take it a bit further. TaskDialogIndirect offers a far greater number of options:



This is the first version; a basic implementation of the standard features.

What IS Supported
-Custom Buttons (either CommandLink style or regular style)
-Radio Buttons
-All fields the text fields available
-Verify checkbox
-Hyperlinks (these are launched with ShellExecute)
-Custom icons: see notes at bottom of post

What Is NOT Supported
All of these are in the works for the full implementation.
-Support for ProgressBar
-Autoclose/Timer feedback
-Feedback for user actions in the dialog
-Changing text icons while displayed


The sample project attached calls the dialog shown in the picture above.

The main function is ShowTaskDialogEx:
Code:

Public Function ShowTaskDialogEx(hWnd As Long, _
                                hInstance As Long, _
                                dwFlags As TASKDIALOG_FLAGS, _
                                dwButtons As TDBUTTONS, _
                                sTitle As String, _
                                pszIconMain As TDICONS, _
                                sMainInstr As String, _
                                sContent As String, _
                                cButtons As Long, _
                                uBtns() As TASKDIALOG_BUTTON, _
                                nDefBtn As Long, _
                                cRadButtons As Long, _
                                uRadioBtns() As TASKDIALOG_BUTTON, _
                                nDefRadioBtn As Long, _
                                sVerifyText As String, _
                                sExpandedInfo As String, _
                                sExpandedControlText As String, _
                                sCollapsedControlText As String, _
                                hIconFooter As TDICONS, _
                                sFooter As String, _
                                cxWidth As Long, _
                                out_radio As Long, _
                                out_verify As Long) As TDBUTTONS

hWnd: Parent hWnd; can just be 0& usually.
hInstance: If/when it's required is unclear; so best to just pass App.hInstance to it
dwFlags: See MSDN. All flags can be used, but some would require additional code.
dwButtons: If you're using the standard buttons, set them here using Or to combine multiple buttons. Standard buttons cannot be used by themselves with the CommandLink style.
sTitle: The title of the dialog.
pszIconMain: Specify a value from TDICONS, or an hIcon (see notes)
sMainInstr: Main instruction text
sContent: Text appearing below the main instruction
cButtons: If you're using custom buttons, the number of them, or zero if not used.
uBtns(): The array of custom buttons. Redim(0) and don't set any members if not used, but the empty structure still needs to be passed.
nDefBtn: The button selected by default. Set to the buttons ID, or 0 if unused.
cRadButtons: The number of radio buttons, or 0 if none.
uRadioBtns(): The array of radio buttons. Redim(0) and don't set any members if not used, but the empty structure still needs to be passed.
nDefRadioBtn: The default radio button selected, by ID. 0 if unused.
sVerifyText: The text of the checkbox. If blank, the checkbox is not displayed. Unchecked by default; to make it checked by default use the TDF_VERIFICATION_FLAG_CHECKED flag.
sExpandedInfo: Extra info displayed when the expand button is click. Appears below Content by default; can be made to appear below footer with the TDF_EXPAND_FOOTER_AREA flag, and can be shown by default with the TDF_EXPANDED_BY_DEFAULT flag.
sExpandedControlText: The text for the expand button in its expanded state.
sCollapsedControlText: The text for the expand button in its collapsed state.
hIconFooter: Specify a value from TDICONS, or an hIcon (see notes)
sFooter: The footer text.
cxWidth: Specify a custom width. Set to 0& to have the ideal width determined automatically.

out_radio: Must be passed ByRef; this variable is filled with the ID of the radio button selected (or zero if they're not used).
out_verify: Must be passed ByRef; this variable is 0 if the verification box was unchecked, and 1 if it was checked.

Return value: The ID of the button selected, or 0 if the dialog was cancelled. This will either be a TDICONS value, or the user-supplied ID of the custom button.


Notes:

No subclassing required!

If you don't want to use the radio buttons, the empty structure still needs to be there. Change Redim uRBN(2) to (0), and change cRadButtons to 0.

For custom icons, you must set the TDF_USE_HICON_MAIN flag (and/or TDF_USE_HICON_FOOTER to use one in the footer), then supply an hIcon. Any icon source can be turned into an hIcon, just search for examples. I personally use a method adapted from clsMenuImage. You add the icon to the app's resource file as a custom resource in the VB Resource Editor (NOT as an icon), and then use the technique outlined here. This isn't included in the sample project; it's left to the user to supply the method of getting an hIcon.

As noted above, if you're using TDF_USE_COMMAND_LINKS then you must supply custom buttons. The dialog does not appear at all and the function returns all zeros if you set that flag and don't supply custom buttons. You can, however, use both, by specifying both dwButtons and a uBTN array; but you can't supply custom buttons AND command links.

When using command links, new lines are separated by vbLf alone, instead of vbCrLf. The latter results in the font not being smaller after the first line.

Requirements
TaskDialogIndirect is only supported on Vista and higher.

A CommonControls Manifest is required, both for the compiled project and for VB6.exe to run the code from the IDE, for 6.0 common controls. Like any other such project, it must be started from Sub Main() with an InitCommonControlsEx call.

----------------------------------------------------
In addition to feedback on this, I'd like ideas on how to approach the full implementation. I was thinking of switching over to a class module, that way I could fire events on notifications or the timer, and then update things with property lets. How to approach the progress bar in a way that's useful in general is a particular challenge.
Attached Files
Viewing all 1522 articles
Browse latest View live


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