I am doing something for my VB.NET class in high school and I previously found on the internet a way to use Controls("lbl" & i).Text = "Example" to quickly change/set multiple labels.
Now we are doing somewhat simple animations (I like to take it a step further) and I want to have a timer that makes it so every rectangle that gets created with a key press starts moving through a timer. If that's confusing basically what I want to do is (incorrect syntax of course because I'm using controls() as my example):
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
For i = 0 to createdRectangleAmount
Controls("rec" & i).left += 1
Next
End Sub
Also as one last side note, the timer only gets enabled AFTER a rectangle as been created (rectangle 0), so this wouldn't produce errors, outside of the obvious misuse of Controls()
Get a specific control collection with filter. OfType asks for what control type you are looking for. The Where predicate does some filtering with condition expression as below). This also assumes that all controls are located in the forms control collection and not in any other container(panel, groupbox, etc...). As always check your MSDN
Dim recs = Me.Controls.OfType(Of RectangleShape)().
Where(Function(r) r.Name.StartsWith("rec"))
For Each rec In recs
rec.SetBounds(recBounds.Left + 1, rec.Bounds.Top, rec.Width, rec.Height)
Next
Related
I am in the process of migrating a VB6 app to .Net and we must provide like-for-like functionality at all times. In one form is a treeview with checkboxes that has three levels of nodes. The first level serves only to group the next level down and they are not checkable. The second level nodes are checkable by the user and when checked or unchecked all its children follow suit. At all levels, clicking a node or its checkbox will mean it becomes selected, regardless of whether or not the check state is affected.
The third level is the crux of the problem (although the issue itself manifests on all treeview checkboxes): this level contains two 'types' of node, one which can be checked and unchecked by the user (if the parent is checked) and one type which cannot be checked or unchecked by the user regardless of the state of the parent, but its state mirrors that of its parent.
In normal use this all works as expected. However, if you quickly click one of the third level nodes (which is not supposed to be directly checkable) twice, it appears to change its check state. But if you examine the underlying value of the Checked property, it remains unaffected, so it seems it is simply a display issue. If discovered, this anomaly will be an issue for our clients as users may think they can do something that they cannot leading to expensive confusion.
I am fresh out of ideas on this one - has anyone else observed this behaviour or know about it and are there workarounds/solutions to it? I can't help feeling I've missed something really obvious but after a day and a half I now have tunnel vision. Here's some code to demonstrate the problem. Create a form with a treeview (big enough to see what's going on) and two buttons then drop this in:
Private _node As TreeNode = Nothing
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MessageBox.Show(_node.Text & " : " & _node.Checked.ToString)
_node = Nothing
End Sub
Private Sub InitialiseTreeview()
TreeView1.Nodes.Clear()
Dim ran As New Random
Randomize()
For i As Int32 = 1 To 5
Dim TLNode As New TreeNode
Dim children As Int32 = 0
children = ran.Next(1, 5)
TLNode.Text = "Top Level Node " & i.ToString
For j As Int32 = 1 To children
TLNode.Nodes.Add("Child Node " & j.ToString)
Next
TreeView1.Nodes.Add(TLNode)
Next
TreeView1.ExpandAll()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
InitialiseTreeview()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
InitialiseTreeview()
End Sub
Run it, and click on a node ONCE. Click Button 1 and it will tell you the node text and it's checked state. Now click the same nodes checkbox twice, fast, observe the state of the checkmark and click button 1 again. You'll see what I mean. Button 2 generates a fresh set of tree nodes.
Yes, this is a bug introduced by the Vista version of the native TreeView control. When it sees the double-click event, it will automatic toggle the check state of the item. Without telling the .NET TreeView wrapper about it, the Before/AfterCheck event won't run. This hasn't been fixed in the .NET wrapper and probably never will.
Working around this bug requires preventing the native control from seeing the double-click message. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form, replacing the existing TreeView.
Public Class MyTreeView
Inherits TreeView
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
'' Filter the WM_LBUTTONDBLCLK message
If m.Msg <> &H203 Then MyBase.WndProc(m)
End Sub
End Class
I'm struggling with some functionality I want to use on my Windows form.
( Just for info, this is for an AutoDesk Inventor AddIn. )
This is my form layout.
The current workflow
The top 4 list-boxes are filled with available parameter names. The user chooses the parameter(s) he/she wants to use and drags and drops it into one of the driving parameter text-boxes ( marked with the <1> label ).
The code that relates to the drag and drop operations
Private Sub lstTemp_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles lbModelParameters.MouseDown,
lbUserParameters.MouseDown,
lbReferenceParameters.MouseDown,
lbLinkedParameters.MouseDown
' In order to access a specific item in a listbox.itemcollection, you must think of it
' as an array of data or a collection and access it in the same manner by always
' letting VB know which item you intend to use by identifying it with its index location
' within the collection. And this is better than taking up basket weaving :-)
lbModelParameters.DoDragDrop(sender.Items(sender.SelectedIndex()).ToString, DragDropEffects.Move)
End Sub
Private Sub txtTemp_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) _
Handles tbParameter1.DragEnter,
tbParameter2.DragEnter,
tbParameter3.DragEnter,
tbParameter4.DragEnter,
tbParameter5.DragEnter
'Check the format of the incoming data and accept it if the destination control is able to handle
' the data format
'Data verification
If e.Data().GetDataPresent(DataFormats.Text) Then
e.Effect() = DragDropEffects.Move
Else
e.Effect() = DragDropEffects.None
End If
End Sub
Private Sub txtTemp_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) _
Handles tbParameter1.DragDrop,
tbParameter2.DragDrop,
tbParameter3.DragDrop,
tbParameter4.DragDrop,
tbParameter5.DragDrop
'This procedure receives the dragged data once it passes the data verification handled by the DragEnter method
'Drops the data onto the destination control
sender.Text() = e.Data().GetData(DataFormats.Text).ToString()
End Sub
New functionality
Now I would like to decrease the user mouse movement for ergonomic reasons and speed. But I would also like to keep to the drag and drop functionality. As it can overwrite a value that has already been added by the user.
I would like to be able to DoubleClick a item in the listbox, and that item should be added to the first empty textbox. I named my textboxes with a number so it's easy to loop over them all to check if it's empty.
I tried doing it with this code, but my double click event never gets fired. It always goes to the drag and drop. How do you do handle this, that the double click gets fired instead of drag drop?
Private Sub ParameterAddDoubleClick(sender As Object, e As EventArgs) _
Handles lbModelParameters.DoubleClick,
lbUserParameters.DoubleClick,
lbReferenceParameters.DoubleClick,
lbLinkedParameters.DoubleClick
Dim oControl As Windows.Forms.ListBox
oControl = DirectCast(sender, Windows.Forms.ListBox)
' Add line in likedparameters listbox
If oControl.SelectedIndex <> -1 Then
' Loop trough all the controls to see if one is empty
' if it's empty add parameter, else go to next
' if all textboxes are used do nothing.
For i = 1 To 6
Dim oTextbox As Windows.Forms.TextBox =
CType(gbDrivingParameters.Controls("tbParameter" & i),
Windows.Forms.TextBox)
If oTextbox.TextLength = 0 Then
' Add the sender item into the linked listbox
oTextbox.Text = oControl.Items.Item(oControl.SelectedIndex)
End If
Next
End If
End Sub
I hope my question is clear, and well prepared. If there is additional information needed, please let me know in a comment.
Mousedown triggers the DoDragDrop, wich stops the doubleclick-event from firing.
To identify if a user doubleclicks or wants to perform a dragdrop, consider the following:
Private Sub ListBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseDown
' Determine whether we are performing a drag operation OR a double click
If e.Clicks = 1 Then
TextBox1.Text = "mousedown"
Else
TextBox1.Text = "dblclick"
End If
End Sub
I'm building a form Access with a load of TextBox controls on it. The GotFocus() event for every one of them will be exactly the same:
Private Sub Text1_GotFocus()
Text1.BorderColor = RGB(100, 100, 255)
...
End Sub
Private Sub Text2_GotFocus()
Text2.BorderColor = RGB(100, 100, 255)
...
End Sub
'... ad infinitum
This is, naturally, a maintanence nightmare and aesthetically a vast wad I have to keep scrolling past. I can throw BorderColor = RGB(100, 100, 255) etc into a function and have every handler call that function, but I'm still left with 3-line identical blocks for every single TextBox - throw in LostFocus and other events that are handled identically regardless of the TextBox, and it just becomes silly.
So the sensible thing to do would be to have a single AllTextBoxes_GotFocus() method, and have every TextBox's On Got Focus event point to that. Two problems though:
I cannot see any functions or subs I've defined in VBA in the drop-down in the form designer, only [Event Procedure] (which generates the standard Private Sub Text1_GotFocus() method) and any Macros in the application. Which is... odd. Considering Macros have a RunCode option for calling VBA functions, it seems a bizarre round-the-houses way of calling code, having to get the control to call the macro to call the code. Surely there's a better way (and I think Macros can only call functions in modules, not on forms).
I'm not sure how to get the sender, so I can set the appropriate control's border. VB.NET passes in the sender and event args in its events: Private Sub Text1_GotFocus(ByVal sender As System.Object, ByVal e As System.EventArgs), but VBA does not.
How can I handle mutliple events with a single handler, and get the sender of the event within the handler?
Here is how I do it but know this will overwrite any custom GotFocus events
Private Sub Form_Load()
On Error Resume Next
Dim ctrl As Control
For Each ctrl In Me.Form.Controls
If ctrl.ControlType = acTextBox Then
ctrl.GotFocus = "=changeColor('" & ctrl.name & "',100,100,255)"
'For LostFocus
ctrl.LostFocus = "=changeColor('" & ctrl.name & "')"
End If
Next ctrl
End Sub
Function changeColor(field As String, Optional red AS Integer =0 ,green AS Integer =0,blue As Integer = 0)
Me.Form.Controls(field).BorderColor = RGB(red, green, blue)
End Function
If I have a winform, may I know how can I control the zoom level of the font in the application (as well as the application window itself obviously) by using Ctrl + Mouse Scroll Wheel? I see there is a Delta in the Scroll Wheel event, but not sure how that works. Is there any code sample that I can look into?
I suspect that you can just test:
(VB.NET):
If (ModifierKeys And Keys.Control) = Keys.Control Then
(C#):
if( (ModifierKeys & Keys.Control) == Keys.Control )
to check if the control key is down.
You'll have to handle the KeyDown and KeyUp event in order to determine whether or not Ctrl key is being held down. This value should be stored at class-level because it will be used by other subroutines besides the KeyDown and KeyUp events.
You then write code to handle the form's MouseWheel event. Scrolling downwards (towards you) causes a negative value for the Delta property of the MouseEventArgs. Scrolling upwards is obviously the reverse. The value of the Delta property is always currently 120.
Microsoft's reason for this value is as follows:
Currently, a value of 120 is the standard for one detent. If higher resolution mice are introduced, the definition of WHEEL_DELTA might become smaller. Most applications should check for a positive or negative value rather than an aggregate total.
In your context you'll just check for the sign of the Delta and perform an action.
Here is a sample code implementing basic 'zoom' functionality:
Public Class Form1
Enum ZoomDirection
None
Up
Down
End Enum
Dim CtrlIsDown As Boolean
Dim ZoomValue As Integer
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
ZoomValue = 100
End Sub
Private Sub Form1_KeyDown_KeyUp(ByVal sender As Object, _
ByVal e As KeyEventArgs) _
Handles Me.KeyDown, Me.KeyUp
CtrlIsDown = e.Control
End Sub
Private Sub Form1_MouseWheel(ByVal sender As Object,
ByVal e As MouseEventArgs) _
Handles Me.MouseWheel
'check if control is being held down
If CtrlIsDown Then
'evaluate the delta's sign and call the appropriate zoom command
Select Case Math.Sign(e.Delta)
Case Is < 0
Zoom(ZoomDirection.Down)
Case Is > 0
Zoom(ZoomDirection.Up)
Case Else
Zoom(ZoomDirection.None)
End Select
End If
End Sub
Private Sub Zoom(ByVal direction As ZoomDirection)
'change the zoom value based on the direction passed
Select Case direction
Case ZoomDirection.Up
ZoomValue += 1
Case ZoomDirection.Down
ZoomValue -= 1
Case Else
'do nothing
End Select
Me.Text = ZoomValue.ToString()
End Sub
End Class
Read on the following for more information about your question:
MSDN: Control.KeyDown Event
MSDN: Control.KeyUp Event
MSDN: Control.MouseWheel Event
MSDN: MouseEventArgs Class
For CrystalReportViewer1
Just put CrystalReportViewer1.Zoom(ZoomValue)
instead of the line Me.Text = ZoomValue.ToString() in the Sub Zoom
Hey all, i am trying to figure out how to go about finding this window's label when the control name is the same as all the other labels on the program.
WindowsForms10.STATIC.app.0.378734a
WindowsForms10.STATIC.app.0.378734a
WindowsForms10.STATIC.app.0.378734a
All 3 labels are named the same. The one i am most interested in is a progress % counter (1%, 2%, 3%, etc..)
How can i get the value (using a timer of course) from that label without knowing the caption of it at any given time??
Any help would be great! :o)
David
The obvious answer would be to get the text from all three labels and check which one looks like "1%", "55%" etc.
If strText Like "#%" Or strText Like "##%" Or strText = "100%" Then
' ...
The less obvious answer (if the Windows API is too cumbersome for your requirements) would be to use the Microsoft UI Automation API.
Not sure if you're just looking for a more complete code sample, but here you go.
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'This block of code creates a list of all the labels on my form.
'Replace this with code to get a list of labels on the form you are scraping
Dim LblList As New List(Of Label)
For Each ctrl As Control In Me.Controls
If TypeOf ctrl Is Label Then
LblList.Add(CType(ctrl, Label))
End If
Next
'End
Dim ProgressLblTxt As String = String.Empty
For Each lbl As Label In LblList
If lbl.Text.Contains("%") Then 'You could use several different criteria here as mentioned in the previous answer
ProgressLblTxt = lbl.Text
End If
If ProgressLblTxt <> String.Empty Then Exit For
Next
'Do something with ProgressLblTxt
MsgBox(ProgressLblTxt)
End Sub