There are 25 Pictureboxes containing different image. User can click on the anyone of the pictureboxes and the image will be shown at the confirmation picturebox as a final decision to proceed.
The code I apply on here is PictureBoxConfirmation.Image = My.Resources._XX (XX will be 1-25 in number respectively.). Later on, I will present a cofirmation button for the user to finalize their decision, and the chosen image will be locked in PictureBoxFinal.
The problem is I can't implement the PictureBoxFinal.Image = My.Resources._XX anymore since the selection will be on randomize input by user. So, how do I code for the button to utilize this functionality. I had tried to put a tag for the PictureBoxConfirmaton when the image is being inserted to it. But, after that I am stuck. I Googled everything but still no result could help my situation.
You need to create a Event listener for the clik in all your PictureBoxes (this is a method/function that listen all you selectable pictureboxes). Inside the method, you get the Image from the clicked picturebox... and assign it to the PictureBoxFinal one.
To add the handler for the Click in all PictureBoxes:
AddHandler PictureBox1.Click, AddressOf pic_Click
AddHandler PictureBox2.Click, AddressOf pic_Click
AddHandler PictureBox3.Click, AddressOf pic_Click
...
The method that does the magic:
Private Sub pic_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim picClicked As PictureBox = DirectCast(sender, PictureBox)
PictureBoxFinal.Image = picClicked.Image
End Sub
Related
I'm having an issue with a process that involves the LostFocus event.
When the cursor loses focus from a particular textbox, I'm simply putting the focus back into that box.
My issue is removing focus long enough for the user to click a log out button. Is there a way to intercept the LostFocus event long enough to allow the user to click the log out button?
Obviously I don't know the big picture here. But keeping only with what you said, the following does the trick. Effectively the event is delayed briefly, allowing the button to be clicked:
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub Text1_LostFocus()
Sleep 100
DoEvents
Text1.SetFocus
End Sub
With a combination of a Timer and another control that is outside of the borders of your form, you can achieve this.
Private Sub Text1_LostFocus()
Combo1.SetFocus
ReturnFocusTimer.Enabled = True
End Sub
Private Sub ReturnFocusTimer_Timer()
ReturnFocusTimer.Enabled = False
Text1.SetFocus
End Sub
In this example Combo1 is positioned beyond the bottom of the form. You can control the ReturnFocusTimer interval to however long you need.
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.
Right now my label is having a text "hello", how can I change it to "world" by a button click while running in Visual Basic.
Write a button click event. It can be done either manually or by double clocking on the button in the designer view:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
End If
Notice the end of it how it says "Button1.Click". Change Button1 to whatever the name of your button is.
Now add the code to change your textbox's text:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Textbox1.text = "world"
End If
Again note the name of the textbox and change "Textbox1" to whatever your textbox is named.
I assume you are new to learning how to program since what you asked is pretty basic. Try to find some tutorials online to help you better understand things. In this case you should look up and understand how control properties work along with events.
I have a custom control that's essentially a drawing canvas, and a program that uses it for editing files. When a new file is opened, though, something very strange can happen.
If the user double-clicks on the file in the Open File dialog (standard TOpenDialog control) instead of selecting an item and hitting ENTER, the canvas underneath registers a click event and ends up executing a draw action at the position of the cursor immediately after loading is complete.
Obviously this is not the intended behavior for this. I've noticed before that when you double-click the mouse, the double-click message arrives before the second click message. I think the dialog box might be closing from the double-click, and then the second click message arrives and gets sent to whatever's at the appropriate coordinates now that it's gone.
Is there any way I can make this stop happening? I can't tell my code "after loading, just eat the next click," because it could have been opened with the 'ENTER' key instead, and then it would miss the first legitimate click. Can anyone think of a better way to handle this? (Using Windows 7, in case it makes a difference.)
If there's a "second click message," there's something wrong. (For one thing, Windows doesn't have "click" messages, just mouse-up and mouse-down messages.) A double click goes like this: mouse down, mouse up, double click, mouse up. The dialog disappears between the double-click message and the second mouse-up message. If your control receives the mouse-up message and treats it as a full click, then that explains the issue and you need to stop; a click is always a pair of mouse-down and mouse-up messages. If you haven't gotten both, then it's not a click.
In fact, it is The 2nd mouse-up event got fired on the picture box, which leads to the event handler invocation. This seems an OpenFileDialog bug. Need to add check for the IsMouseCaptured for the mouse up event, one click is mouse down and mouse up, instead of only a mouse up.
I solved it that way (it is of course an work-around):
CFileDialog my_file_dialog(...);
if ( my_file_dialog.DoModal()!=IDOK )
return;
CString fileName= my_file_dialog.GetPathName();
//...
CSelectItemsDlg dlg;
// Avoid that the double-click on the CFileDialog sends the WM_LBUTTONUP message to the next window causing the Unselect of an item that is under the mouse cursor.
// http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_10287063.html#a2476475
MSG msg;
while(PeekMessage(&msg,0,WM_LBUTTONUP,WM_LBUTTONUP,PM_REMOVE));
int DoModalRes = dlg.DoModal();
And you can believe that I have put a big smile on the face of my boss :)
Private IsMouseDown As Boolean
Private Sub picNenIn_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseDown
IsMouseDown = True
'Code
End Sub
Private Sub picNenIn_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseMove
If IsMouseDown Then
'Code
End If
End Sub
Private Sub picNenIn_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseUp
IsMouseDown = False
'Code
End Sub
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).