Progress Bar Percent Calculation - vb6

I am new to VB6 and am working on some code for a business (cattle auction). They are wanting a progress to show on their main page the percent that is left in the sale. the progress bar would be based on (Total head remaining / total head checked In)
I have tried finding information on how to make this work in old forums and on Youtube but since VB6 is so old i'm not finding useful information.
All the videos I have watched and forums I have read show the progress bar moving based on a timer or button. I am needing it to move based on other information entered ( if that makes sense ).

VB6 ProgressBar documentation can be found here: https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa443485(v%3dvs.60)
The ProgressBar is in the common controls library, so you'll need to select Microsoft Windows Common Controls 6.0 in the Toolbox Components list before it will be available in the Toolbox.
I prefer setting the Scrolling property to smooth scrolling.
Using it is easy, a simplest sample using your descriptions could have a HeadsToSell textbox, a StartAuction button, and a CowSold button. Clicking the StartAuction button sets the ProgressBar Max property to the number of heads, then for every head that is sold, clicking the CowSold button decrements the number of available head and updates the ProgressBar value.
Option Explicit
Private CurrentHeadCound As Integer
Private Sub CowSold_Click()
CurrentHeadCound = CurrentHeadCound - 1
ProgressBar1.Value = CurrentHeadCound
End Sub
Private Sub StartAuction_Click()
ProgressBar1.Max = HeadsToSell.Text
ProgressBar1.Value = ProgressBar1.Max
CurrentHeadCound = ProgressBar1.Max
End Sub

Related

How can I make a certain part of my form scrollable?

I'm making a program in vb6 that requires me to be able to scroll a certain area of the screen to the right. It consists solely of lines and picture boxes, is there a way to only scroll that area? Thanks!
You can take advantage from the fact that some visual controls can act as container of other visual controls.
Just an example:
In the VBIDE, place a Frame over a VB Form. Then - inside this Frame place a PictureBox. Pay attention that the PictureBox shall be fully contained inside this Frame.
Now, if you drag the Frame around the Form, you will see that the PictureBox inside is moving together, while keeping the position inside the container Frame, i.e. it will keep the original top & left coordinates relative to the container control.
To find out which visual controls have this capability, simply retry the test. You will see, for example, that a Label can't act as a container.
That said, you need following:
one visual control (preferably a PictureBox) which act as container (the viewport)
one visual control (preferably a PictureBox) which act as scrollable area
a HScrollBar (and, optionally, a VScrollBar) to scroll the
view-able area
Now, inside the second PictureBox (the scrollable area) you can place your controls, the Lines and PictureBoxes you mentioned in your question.
Why is a PictureBox preferable? Because you can profit from the ScaleMode property, set it to 3-Pixeland use pixel-exact scrolling. With Frames you can't do that, you are limited to just Twips.
By using a contained control you have two advantages:
you can visually place and reposition the controls ypu need inside the IDE
you need to scroll just only one control - all other hosted controls will
move together
The boring thing you must code is the synchronization of the container with the ScrollBars.
But luckily, as VB6 has been going a long way, you will find enough cut-and-paste code examples of such a task, one of which is on VBForums: Scroll bar in picturebox
Some final notes:
PictureBoxes in VB6 are constrained to a maximum size of 16,383 x 16,383 pixels. If your scrollable area should be bigger, you may implement a kind of custom "infinite scroller", and manage the position of your controls by grouping them, and you will need some additional coding.
ScrollBars in VB6 can range from a minimum value of -32,768 to a maximum value of 32,767. If you need more, you will end up with some other additional coding tasks.
If you stick to Twips, you can have a bigger logical area available - for example: until 245,745 with the typical 15 TwipsPerPixel - but you can't use such a big value with ScrollBars.
Here is a simple example illustrating what you requested. The key is that the scrollable area must be a container control hosting the controls you wish to scroll.
Option Explicit
Private oldPos As Integer
Private Sub Form_Load()
HScroll1.Min = 0
HScroll1.Max = 1000
HScroll1.SmallChange = Screen.TwipsPerPixelX * 10
HScroll1.LargeChange = HScroll1.SmallChange
End Sub
Private Sub HScroll1_Change()
ScrollPictureBox
End Sub
Private Sub HScroll1_Scroll()
ScrollPictureBox
End Sub
Private Sub ScrollPictureBox()
Dim c As Control
For Each c In Me.Controls
If c.Container.Name = "Picture1" And Not TypeOf c Is HScrollBar Then
c.Left = c.Left - (oldPos - HScroll1.Value)
End If
Next
oldPos = HScroll1.Value
End Sub
In this code, Picture1 is a PictureBox (the scrollable area) containing HScroll1 (a horizontal scrollbar) and the other controls you wish to scroll.

Can you "unroll" an animation in Powerpoint to slides?

I am currently preparing a "final report" document in Powerpoint that requires me not to include animations. However, the various source documents to be combined include animations.
I am searching for a way to automatically generate a slide for each animation step. Basically the same functionality as exporting the slides to PDF with animation steps, with the difference that the animation steps remain powerpoint slides.
Is there a way to achieve this automatically, or do I have to duplicate the slides and prepare the animation steps myself?
Use the PPspliT add-in for MS Office by a man named Massimo Rimondini. It does exactly what you want. I checked in Office 2013 and it works fine.
Bonus:
In case that plugin fails to remove all the animations and convert into separate slides (which is very unlikely), you can disable any remaining animations for slide show, or remove them altogether using a macro.
Disabling animations:
You can turn off the animations by going to "Setup Slide Show" and under "Show Options" tick the "Show without animation" option and click OK. Now run the show and it will display without the animations.
Removing animations altogether:
If you really want to delete all the animations in a single sweep then you will need to run this macro.
Sub StripAllBuilds()
Dim I As Integer: Dim J As Integer
Dim oActivePres As Object
Set oActivePres = ActivePresentation
With oActivePres
For I = 1 To .Slides.Count
If Val(Application.Version) < 10 Then
' Older versions of PowerPoint 97/2000
' In each slide set the animation property
' of the Shape object to FALSE
For J = 1 To .Slides(I).Shapes.Count
.Slides(I).Shapes(J).AnimationSettings.Animate = msoFalse
Next J
Else
' New versions support the Timeline object
For J = .Slides(I).TimeLine.MainSequence.Count To 1 Step -1
.Slides(I).TimeLine.MainSequence(J).Delete
Next J
End If
Next I
End With
Set oActivePres = Nothing
End Sub

How could I use VBA to change a button's picture to one of the embedded default images?

I'm trying to get a button to change from the "Arrow Left" to "Arrow Right" picture when I click it, but I'm not sure how to assign the images through VBA. I tried Me!btnCollapseUnscheduled.Picture = "Arrow Left", but I get an error message this way.
In Access 2010 or later, you can store images in the MSysResources system table. Then choose Shared for your command button's Picture Type property, and select one of those shared images.
Afterward, it's easy to toggle between the shared images from the command buttons's click event. I named my command button "cmdArrow" and the shared images "Arrow Left" and "Arrow Right" ...
Option Compare Database
Option Explicit
Private Sub cmdArrow_Click()
Dim strDirection As String
If Me!cmdArrow.Picture Like "*Left" Then
strDirection = "Right"
Else
strDirection = "Left"
End If
Me!cmdArrow.Picture = "Arrow " & strDirection
Me!txtImage.Value = Me!cmdArrow.Picture
End Sub
Private Sub Form_Load()
Me!txtImage.Value = Me!cmdArrow.Picture
End Sub
Screenshots:
The biggest challenge was loading the images into MSysResources. I created a throwaway form and added a command button. Next I chose Embedded as the button's Picture Type property and selected Arrow Left from the available choices. Then I changed Picture Type from Embedded to Shared, which added a row to MSysResources with the image data in an attachment field and my command button's name in the Name field. So I opened the table, changed Name to "Arrow Left" and closed the table. Note MSysResources will not be visible in the Navigation pane unless you enable "Show System Objects" in the Navigation Options.
I repeated those steps for "Arrow Right". It may sound fiddly, but it's not really a huge hurdle.
The trick is to use the full file path of your icon.
MS-Access might be using some icon map for its native icons, so you might not have much luck getting a path to one of those.
If you definitely can't find the path to the native MS-Access icons, you could always just do a google image search for arrow icons (specify exact size of 16 x 16 pixels).
You can then just save these icons to a folder of your choosing and then use those paths in the following illustrations.
If you just want the button to change its image on the first click and stay that way thereafter:
Make sure the button does not have a picture attached in Design View.
Assign the default image using its full path to your command button using the form's Open event:
Private Sub Form_Open(Cancel As Integer)
Me.cmdButton.Picture = "C:\myFolder\myDefaultIcon.png"
End Sub
Then in the button's click event, assign the .picture property to the icon path you want to change it to:
Private Sub cmdButton_Click()
Me.cmdButton.Picture = "C:\myFolder\myChangedIcon.png"
End Sub
If you just want the button to toggle between 2 images on each click:
Use a toggle button control instead of a command button control
Make sure the button does not have a picture attached in Design View.
Write a sub that will handle the different on/off states of your toggle button:
Public Sub togImg()
If _
Me.togButton = -1 _
Then
Me.togButton.Picture = "C:\myFolder\myChangedIcon.png"
Else
Me.togButton.Picture = "C:\myFolder\myDefaultIcon.png"
End If
End Sub
Call your sub from both the form's Open event and the toggle button's Click event:
Private Sub Form_Open(Cancel As Integer)
togImg
End Sub
Private Sub togButton_Click()
togImg
End Sub
You could create two buttons where only one is visible at a time, both calling the same code.
When one is clicked, unhide the other, set focus to this, then hide the first button. And vice-versa.

OwnerForm loses focus into the background?

I'm facing a weird case in VB6, which is, when I show a form in respect with another OwnerForm, if I did this two/three times for example, when I close all the child forms, suddenly the OwnerForm disappear on background (lose focus and the previous application will be on top), and I will have to click on it on the task bar to show the form again!
A quick sample will be something like that:
Private Sub Command1_Click()
Command1.Enabled = False
Dim frm As New Form1
frm.Show 0, Form1
End Sub
Is there any solution for this?
Thanks.
You're showing the child form on top non-modally, ie, you can have any number of child forms of that type open. When you close them, sometimes the form / app that spawned them will lose focus and disappear behind other applications - as you are experiencing.
You might be able to hide the form being closed (use the _QueryUnload event and cancel the unload), hide, then set the ZOrder on the parent form (to bring it to the front), then carry on unloading the form that is being closed.
Let me know how you get on.

Allow vertical scrolling in listbox, when it is disabled (VB6)

I need to allow the vertical scrollbar in a multiselect listbox (VB6) however, when the control is disabled, I can't scroll.
I would think there is an API to allow this, but my favorite VB6 site (MVPS VB.NET) does not have a way.
I toyed with pretending it was disabled, and ignore the clicks... but to do that with VB6 code is really ugly... so if this is a solution, I need an API to ignore the clicks.
Thanks for your help.
I came up with the following code, which hides all of the gnarly details behind a class. Basically, I implemented greg's idea of using overlaying another scrollbar on top of the disabled list box's scrollbar. In my code, I dynamically create another ListBox control (resized so that only its scrollbar is visible), and use its scrollbar to scroll the actual ListBox. I also specifically avoided using the Windows API (except for the call to GetSystemMetrics that I used to figure how how wide a scroll bar is on the system). The nice thing about using another ListBox's scrollbar is that it will be themed properly (a ListBox uses the OS's theme when it displays it's scrollbar, but a VB.Scrollbar doesn't, so it would look out-of-place). Another advantage of using a second ListBox to scroll the first list box is that it's really easy to implement the scrolling logic (just set the first ListBox's TopIndex property to the second ListBox's TopIndex property whenever the second one is scrolled).
I also set it up to be as low-impact as possible (you only have to call a single function in your Form_Load event to make it work).
Usage
Add CustomScrollingSupport.cls and ListBoxExtras.bas to your project.
In your form's Form_Load event, add the following line:
AddCustomListBoxScrolling Me
This will make every VB.ListBox on the form support scrolling even while they are disabled. If you only want to add this functionality to a select number of ListBox's, you can call AddCustomScrollingSupport instead, passing in a specific ListBox control.
Interesting Note
In an older version of this code, I wasn't calling the ZOrder method on the second listbox (the one that provides the scrollbar) to make sure it would appear on top of the first listbox. This meant the second listbox was actually behind the first listbox; the interesting thing is that the scrolling on the second ListBox still worked when the first ListBox was disabled! Apparently, when the first ListBox is disabled, any mouse and keyboard events that would have gone to that ListBox "bleed through" to the second ListBox, so scrolling support still does work. I'm not sure if this is a bug or by design (I mean, you could argue that it makes sense that controls behind a disabled control would be able to receive events...). However, I found the scrolling to be slightly jerky at times, so I decided to add .ZOrder 0 to make the second listbox render on top of the first one. This has the drawback that you see the frame border for the second listbox (to the left of the scroll bar), which you wouldn't see if it was hidden behind the first listbox, but the scrolling is smoother.
CustomScrollingSupport.cls
This class wraps up the logic necessary to add "custom scrolling support" (for lack of a better name) to a VB.ListBox control. It should not be used directly, instead use the one of the Add* methods in the ListBoxExtras.bas module (I'll provide the code for that module later in the post).
Option Explicit
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Const SM_CXVSCROLL = 2
Private Const SM_CXFRAME = 32
Private m_runningScrollers As Collection
Private WithEvents m_list As VB.listbox
Private WithEvents m_listScroller As VB.listbox
'--------------------------------------------------------------'
' Bind '
' '
' Adds custom scrolling support to a ListBox control. '
' Specifically, it allows the ListBox to be '
' scrolled even when it is disabled. '
' '
' Parameters: '
' '
' + list '
' the ListBox control to add custom scrolling support to '
' '
' + runningScrollers '
' a Collection of CustomScrollingSupport objects. Passed '
' in so that this object can remove itself from the list '
' when it is terminated. '
' '
'--------------------------------------------------------------'
Public Sub Bind(ByVal list As VB.listbox, runningScrollers As Collection)
Set m_list = list
Set m_runningScrollers = runningScrollers
'Create another ListBox loaded with the same number of entries as the real listbox'
Set m_listScroller = m_list.Container.Controls.Add("VB.ListBox", list.Name & "_scroller")
LoadScrollerList
Dim nScrollbarWidth As Long
nScrollbarWidth = GetSystemMetricScaled(SM_CXVSCROLL, m_list) + _
GetSystemMetricScaled(SM_CXFRAME, m_list)
'Display the other listbox (the "scroller"), just wide enough so that only its scrollbar is visible'
'and place it over the real listboxs scroll bar'
With m_listScroller
.Left = m_list.Left + m_list.Width - nScrollbarWidth
.Top = m_list.Top
.Height = m_list.Height
.Width = nScrollbarWidth
.Enabled = True
.Visible = True
.ZOrder 0
End With
End Sub
Private Sub m_listScroller_Scroll()
'If the master list has changed, need to reload scrollers list'
'(not ideal, but there is no ItemAdded event that we could use to keep the lists in sync)'
If m_list.ListCount <> m_listScroller.ListCount Then
LoadScrollerList
End If
'Make any scrolling done on the scroller listbox occur in the real listbox'
m_list.TopIndex = m_listScroller.TopIndex
End Sub
Private Sub Class_Terminate()
Dim scroller As CustomScrollingSupport
Dim nCurrIndex As Long
If m_runningScrollers Is Nothing Then
Exit Sub
End If
'Remove ourselves from the list of running scrollers'
For Each scroller In m_runningScrollers
nCurrIndex = nCurrIndex + 1
If scroller Is Me Then
m_runningScrollers.Remove nCurrIndex
Debug.Print m_runningScrollers.Count & " scrollers are running"
Exit Sub
End If
Next
End Sub
Private Sub LoadScrollerList()
Dim i As Long
m_listScroller.Clear
For i = 1 To m_list.ListCount
m_listScroller.AddItem ""
Next
End Sub
Private Function GetSystemMetricScaled(ByVal nIndex As Long, ByVal ctrl As Control)
GetSystemMetricScaled = ctrl.Container.ScaleX(GetSystemMetrics(nIndex), vbPixels, ctrl.Container.ScaleMode)
End Function
ListBoxExtras.bas
This module contains two utility methods:
AddCustomScrollingSupport adds custom scrolling functionality
to an individual VB.ListBox
control
AddCustomListBoxScrolling adds custom scrolling
functionality to every VB.ListBox
control on a given Form
Option Explicit
Public Sub AddCustomScrollingSupport(ByVal list As VB.listbox)
Static runningScrollers As New Collection
Dim newScroller As CustomScrollingSupport
Set newScroller = New CustomScrollingSupport
runningScrollers.Add newScroller
newScroller.Bind list, runningScrollers
End Sub
Public Sub AddCustomListBoxScrolling(ByVal frm As Form)
Dim ctrl As Control
For Each ctrl In frm.Controls
If TypeOf ctrl Is VB.listbox Then
AddCustomScrollingSupport ctrl
End If
Next
End Sub
Rather than looking for the API to ignore clicks, can't you just ignore the events? (i.e. just don't do when the user clicks/selects something).
And, I think there is a SelectionMode property to disable multiselect and make it single select.
If you don't want the user to be able to select anything at all, you can try hooking into the SelectionIndexChanged event and set the SelectionIndex to -1.
My VB6 is a bit rustly, so sorry if the event/property name don't match exactly.
Speaking of hacks, what if you enable the scrollbar when the mouse is moving over the scroll bar?
Or maybe ... place another scroll bar over the ListBox's SB, and use APIs to scoll the disabled LB.
Enabling just the scrollbar on a disabled listbox is possible (I think), but you'd have to dig into the Windows API and do SendMessage and some other grisly stuff.
I just checked it out, and when a listbox is disabled you can still scroll it up and down programatically by changing the control's ListIndex property. So you could do something like what greg suggests, and "float" an enabled vertical scroll bar over the one on the list box, and use this scrollbar's Value_Changed event (I think that's what it's called) to change the listbox's ListIndex property.
This is a total VB hack, but I think you can leave the listbox enabled, and then drag a transparent label (with blank text) over all of the listbox except the scrollbar. The label will intercept any mouse clicks (although this won't affect keystrokes).
This will only work if the label is transparent like I remember (it may be the image control - without a loaded image - that works like this in VB).

Resources