I have created a custom combobox with a label to cover the combobox (as it's very ugly) when it's not in use. The label, witch is the lid should show the display member. The covering and uncovering forks fine however the text on the label displayed is the previous value and not the current one. Passing over the label with the mouse, triggers the labels mouse enter event and than the display value is correct.
Here is the code for the custom control.
Public Class ComboBoxWithALid
Inherits ComboBox
Private WithEvents Lid As New Label With {.BackColor = Color.LightCyan, .ForeColor = Color.Black,
.TextAlign = ContentAlignment.MiddleCenter}
Protected Overrides Sub OnDataSourceChanged(ByVal e As EventArgs)
MyBase.OnDataSourceChanged(e)
Lid.Location = Location
Lid.Size = Size
Parent.Controls.Add(Lid)
Lid.BringToFront()
End Sub
Private Sub Lid_MouseEnter(sender As Object, e As EventArgs) Handles Lid.MouseEnter
Lid.SendToBack()
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)se
Lid.Text = SelectedText
Lid.BringToFront()
End Sub
Protected Overrides Sub OnDropDownClosed(e As EventArgs)
MyBase.OnDropDownClosed(e)
Lid.BringToFront()
Lid.Text = SelectedText
End Sub
End Class
To test the control, drag the control from the tool box to your form and bind the control to any table you have
I tried to use text in place of selected text - same results
I found the solution. Change the move statement to:
Lid.Text = Items(SelectedIndex)(DisplayMember)
and is works.
SelectedText is for the highlighted portion of the text that is currently selected, not the selected item. You probably want something like this:
If SelectedIndex = -1 Then
Lid.Text = String.Empty
Else
Lid.Text = Items(SelectedIndex).ToString()
End If
Yes, you have an annoying control.
Related
I'm building a form that has many buttons, all buttons do the same thing: add 1 every time they are clicked. Every pressed button is sent to a datagridview along with the time they are pressed. Datagrid values look like this:
a_1_serv (button name), 18:05:00(time).
Sometimes I want to delete the last row. Everything works fine so far.
When I delete the last row, I want to change the text of the button (a_1_serv).
I can parse the dgv value (a_1_serv) to a variable but I can't bind it to the appropriate button name so I can control it.
Is there a way to do it?
Don't store your program state in your UI
Create a data structure to hold the information, and let the DataGridView be a "view", not treating it as a variable. You will save yourself headaches vs using the UI as a variable.
That said, create a class to represent your information
Public Class Data
Public Sub New(button As Button, time As DateTime)
Me.Button = button
Me.Time = time
End Sub
<System.ComponentModel.Browsable(False)>
Public Property Button As Button
Public ReadOnly Property Text As String
Get
Return Button.Name
End Get
End Property
Public Property Time As DateTime
End Class
And your code can manipulate the data in a variable off the UI. Bind the data to the DataGridView for display.
Private datas As New List(Of Data)()
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click, Button4.Click
addButton(DirectCast(sender, Button))
End Sub
Private Sub RemoveLastButton_Click(sender As Object, e As EventArgs) Handles RemoveLastButton.Click
removeLast()
End Sub
Private Sub addButton(b As Button)
datas.Add(New Data(b, DateTime.Now))
bindData()
End Sub
Private Sub removeLast()
Dim b = datas.Last.Button
b.Text = "new text" ' change to whatever
datas.RemoveAt(datas.Count - 1)
bindData()
End Sub
Private Sub bindData()
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = datas
End Sub
This does exactly what you stated but there may be inconsistency in these two bits of information you provided: a_1_serv (button name) and I want to change the text of the button .... This changes the button text but not the name. The name is displayed in the grid. You can change the data class to display the text or whatever. But the point is this approach will keep your data off the UI and you won't need to look up the control by name anymore.
I'm trying to code out a programme where the user sees a form and in that form, there are 2 text boxes and 10 buttons.
Username:
Password:
1 2 3
4 5 6
7 8 9
0
I've tried this code
Private Sub Btn1_Click(sender As Object, e As EventArgs) Handles Btn1.Click
If UsernameTextbox.Focused = True Then
UsernameTextbox.Text = UsernameTextbox.Text + "1"
End If
End Sub
I understand that clicking on Btn1 will steal the focus from the text box. So how can I write the programme?
One option would be to declare a variable of type Control and, in the Leave event handler for each control, assign the sender to that variable. You can then use that variable in the Click event handler of your Button to determine which control had focus and possibly reassign back to that control and then update it appropriately. You can do the lot with two event handlers, e.g.
Private previouslyActiveTextBox As TextBox
Private Sub TextBoxes_Leave(sender As Object, e As EventArgs) Handles TextBox2.Leave,
TextBox1.Leave
previouslyActiveTextBox = DirectCast(sender, TextBox)
End Sub
Private Sub Buttons_Click(sender As Object, e As EventArgs) Handles Button3.Click,
Button2.Click,
Button1.Click
previouslyActiveTextBox.Select()
previouslyActiveTextBox.SelectedText = CStr(DirectCast(sender, Button).Tag)
End Sub
That code handles multiple events with a single method in both cases. It also requires that you assign the number for each Button to the Tag property of that control. Note that it also sets the SelectedText, rather than appending to the Text property. That is more correct because it will add the new text where the caret is actually located and replace text if it is selected.
An even better option might be to use a custom button control that doesn't take focus. Here's one I prepared earlier:
http://www.vbforums.com/showthread.php?459890-Building-Blocks-for-an-On-screen-Keyboard
Items within a ToolStrip do not grab focus when clicked. While the standard ToolStrip usage is as a menu bar, there is nothing that prevents you from using it as a container for buttons laid out in a grid. In fact, the class ToolStrip.LayoutStyle Property allows you select a table style.
The following is a proof-of-concept custom ToolStrip that is prepopulated with the buttons to create a number pad like control. The control has sufficient function to work as intended, but is not locked down to prevent misuse by manipulating the Items collection and other properties.
Public Class NumPadToolstrip : Inherits ToolStrip
Private _ButtonSize As Size = New Size(50, 50)
Private _ButtonMargin As Padding = New Padding(5)
Private _ButtonBackColor As Color = Color.Ivory
Public Sub New()
MyBase.New
LayoutStyle = ToolStripLayoutStyle.Table
Dim settings As TableLayoutSettings = CType(LayoutSettings, TableLayoutSettings)
settings.ColumnCount = 3
settings.RowCount = 4
AddButtons(7, 9)
AddButtons(4, 6)
AddButtons(1, 3)
AddButtons(0, 0)
Dock = DockStyle.None
AutoSize = True
BackColor = Color.LightGray
End Sub
Public Property ButtonSize As Size
Get
Return _ButtonSize
End Get
Set(value As Size)
If value <> _ButtonSize Then
_ButtonSize = value
UpdateButtonSizes()
End If
End Set
End Property
Public Property ButtonMargin As Padding
Get
Return _ButtonMargin
End Get
Set(value As Padding)
If value <> _ButtonMargin Then
_ButtonMargin = value
UpdateMargins()
End If
End Set
End Property
Public Property ButtonBackColor As Color
Get
Return _ButtonBackColor
End Get
Set(value As Color)
If value <> _ButtonBackColor Then
_ButtonBackColor = value
UpdateButtonBackColor()
End If
End Set
End Property
Private Sub AddButtons(start As Int32, [end] As Int32)
For num As Int32 = start To [end]
Dim b As New ToolStripButton With {.Text = num.ToString(),
.Size = ButtonSize,
.Margin = ButtonMargin,
.BackColor = ButtonBackColor,
.AutoSize = False}
AddHandler b.Paint, Sub(sender As Object, e As PaintEventArgs)
With e.Graphics
Dim r As Rectangle = e.ClipRectangle
r.Inflate(-1, -1)
r.Location = Point.Empty
.DrawRectangle(Pens.Black, r)
End With
End Sub
Items.Add(b)
Next
End Sub
Private Sub UpdateButtonSizes()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Size = _ButtonSize
Next
ResumeLayout()
End Sub
Private Sub UpdateMargins()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Margin = _ButtonMargin
Next
ResumeLayout()
End Sub
Private Sub UpdateButtonBackColor()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.BackColor = _ButtonBackColor
Next
ResumeLayout()
End Sub
End Class
Add the above class to your project and perform a build operation. The NumPadToolstrip control should then be available in the ToolBox. Add the control to the form and then add a handler for its ItemClicked event to pass the proper text to the TextBox.
Private Sub NumPadToolstrip1_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles NumPadToolstrip1.ItemClicked
Dim tb As TextBoxBase = TryCast(ActiveControl, TextBoxBase)
If tb IsNot Nothing Then tb.SelectedText = e.ClickedItem.Text
End Sub
This should be easy, however it is eluding me. I have a RichTextBox in VB.NET that the user enters text in. I want them to be able to select some text, then change the font properties of the selection.
Here is something I have quickly written up for you.It will get ALL of the installed fonts on the system and add them to a combobox, so you wont have to add them all manually.Also I have made it so whenever you change the font type for a combobox that I have added, It will update the RichTextBox's font.
Imports System.Drawing.Text
Public Class Form1
''CREATE ANOTHER COMBOBOX TO CHANGE THE SIZE OF THE TEXT USING THE SAME METHOD
''AS THE FONT COMBOBOX.
Dim FONTSIZE = 8
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim InstalledFonts = New InstalledFontCollection
Dim FontFamilies() As FontFamily = InstalledFonts.Families
For Each Font As FontFamily In FontFamilies
ComboBox1.Items.Add(Font.Name)
Next
''THE END USER WONT BE ABOUT TO EDIT THE INSTALLED ITEMS IN THE COMBOBOX
''THE STARTING FONT IS CONSOLAS
ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
ComboBox1.Text = "Consolas"
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
''THIS WILL CHANGE THE HIGHLIGHTED "SELECTED" TEXT FONT ONLY
''AS ASKED FOR IN QUESTION
RichTextBox1.SelectionFont = New Drawing.Font(ComboBox1.Text, FONTSIZE)
End Sub
End Class
You will need to add a combobox to your form and a richtextbox for this too work.If you have any trouble, let me know and I'll try and help you work.
Thanks Werdna, your answer gave me some direction. I did go with the FontDialog as in the end I wanted to allow other font changes such as style and color.
Private Sub rtf_Notes_MouseUp(sender As Object, e As MouseEventArgs) Handles rtf_Notes.MouseUp
'Test for right-click
If (e.Button = Windows.Forms.MouseButtons.Right) Then
With FontDialog1
.ShowColor = True
If (.ShowDialog() = Windows.Forms.DialogResult.OK) Then
rtf_Notes.SelectionFont = New Drawing.Font(.Font.Name, .Font.Size, .Font.Style)
rtf_Notes.SelectionColor = .Color
End If
End With
End If
End Sub
I have a bit of code where i have a dynamically created array or buttons with staff pictures on them, as well as the staff's name. I've added one handler to handle any button click from any of the buttons. where i am stuck is, if you look at the code below, it all works fine, and if you click any of the buttons you get the "aha" test message. but i want the name of the staff clicked on (so btnArray(i).Text) to be passed to the handler for further processing. I tried adding a ByVal parameter to the handler but that caused an error. what's the correct way to do this? As i said, the code below works for me, i just am at a loss as to how to add the extra functionality.
Dim btnArray(staffcount) As System.Windows.Forms.Button
For i As Integer = 1 To staffcount - 1
btnArray(i) = New System.Windows.Forms.Button
btnArray(i).Visible = True
btnArray(i).Width = 80
btnArray(i).Height = 101
btnArray(i).BackgroundImage = Image.FromFile(picloc(i))
btnArray(i).BackgroundImageLayout = ImageLayout.Stretch
btnArray(i).Text = staffname(i)
Dim who As String
who = btnArray(i).Text
AddHandler btnArray(i).Click, AddressOf Me.theButton_Click
btnArray(i).ForeColor = Color.White
btnArray(i).TextAlign = ContentAlignment.BottomCenter
Dim fnt As Font
fnt = btnArray(i).Font
btnArray(i).Font = New Font(fnt.Name, 10, FontStyle.Bold)
FlowLayoutPanel1.Controls.Add(btnArray(i))
Next i
End Sub
Private Sub theButton_Click()
MsgBox("aha")
End Sub
First, correct the signature of your shared handler.
Private Sub theButton_Click(sender As Object, e As EventArgs)
End Sub
Once that is done getting the text of the button clicked is a simple matter.
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim textOfButtonClicked As String = DirectCast(sender, Button).Text
MessageBox.Show(textOfButtonClicked)
End Sub
The sender is the button that was clicked. Since signatures use objects for the sender the DirectCast 'changes' it to button and you then can access the .Text property of the button.
If there are more manipulations you want to perform on the clicked button you could do it this way
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim whBtn As Button = DirectCast(sender, Button) ' get reference to button clicked
Dim textOfButtonClicked As String = whBtn.Text
MessageBox.Show(textOfButtonClicked)
'e.g. change the color
whBtn.BackColor = Color.LightYellow
End Sub
I developed an application which is like a digital comprehension sheet activity.
The order of which this works is:
A user double clicks an underscored text area on a text box
A form opens which asks them to place an answer
The answer is validated, if true it goes back to the original form
The issue here is that for some odd reason my labels don't update on step 3, as- well as the text. I have a label named lbAnswerStatus which notifies the user if they have a correct answer, the text does not update, and the 'SelectedText' on Form 1 should be replaced with the answer (if correct)
Here is my code:
Form 1 (when textbox is clicked):
Form2.Answer(answers(counter))
answers(counter) represents the correct answer being passed on, to compare with users answer in form 2
Form 2:
If tbAnswer.Text = theanswer Then
Form1.answerStatus(True, theanswer)
Form 1:
Public Sub answerStatus(status, answer)
If status = true Then
Form2.Close()
rtb.SelectedText = answer
lbAnswerStatus.ForeColor = Color.Green
End If
End Sub
My first assumption was that the Rich text box's SelectedText wasn't changing because it didn't have focus on it however, the lbAnswerStatus color didn't change either, so I figured that there was issues with making modifications to the form.
I used a message box to test whether lbAnswerStatus.Text would pop up and it did, so it can read but not write.
I also attempted to change the text of the label and selectedtext of the textbox in step 1 and it worked fine.
Any ideas what may be causing this issue?
Thanks.
I guess that you want your Form2 (AnswerForm) presented as a modal dialog. Doing that, you can return a result. You didn't say what you want to happen to the answer status label or the answer form if the supplied answer is incorrect.
Just as an example of how it can be done, create a new Windows Forms project. On Form1, place a button (Button1) and a label ("lblAnswerStatus"). Add a new form named "AnswerForm" to the project, and add a TextBox ("TextBox1") and a button ("bnDone").
As code for AnswerForm:
Public Class AnswerForm
Private statusLabel As Label
Private answerText As String
Private Sub bnDone_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnDone.Click
If TextBox1.Text.Equals(answerText, StringComparison.CurrentCultureIgnoreCase) Then
' Alternative 1: set the color here if you want to
statusLabel.ForeColor = Color.Green
' return a value indicating success
Me.DialogResult = Windows.Forms.DialogResult.Yes
Me.Close()
Else
' indicate error
statusLabel.ForeColor = Color.Red
End If
End Sub
Public Sub New(ByVal statusLabel As Label, ByVal answerText As String)
InitializeComponent()
Me.statusLabel = statusLabel
Me.answerText = answerText
End Sub
End Class
and as code for Form1:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
lblAnswerStatus.ForeColor = Color.Blue
Using answerFrm As New AnswerForm(lblAnswerStatus, "X")
Dim dlgResult = answerFrm.ShowDialog()
' Alternative 2: use this if you want to change the color in this handler
If dlgResult = DialogResult.Yes Then
lblAnswerStatus.ForeColor = Color.Purple
End If
End Using
End Sub
End Class
If you click Button1 on Form1, a dialog box appears. Type into its TextBox1 and click bnDone. Because the instance of AnswerForm has a reference to lblAnswerStatus (supplied in its constructor), it is easy to update the latter, e.g. it turns red if you enter the wrong answer.