am working on a project where some forms will have duplicate methods of populating comboboxes. In the code snippet below, the fonts installed on a given pc are added as items to a combobox. How can I pass a parameter that is the actual combobox to fill? eg, AddFonts(combobox)
Private Sub AddFonts()
'add the font names installed on this pc to the font name combo box
' Get the installed fonts collection.
Dim allFonts As New InstalledFontCollection
' Get an array of the system's font familiies.
Dim fontFamilies() As FontFamily = allFonts.Families
' Display the font families.
For i As Integer = 0 To fontFamilies.Length - 1
'figure our how to make the textbox passable as a paramter
cbxTitleFonts.Items.Add(fontFamilies(i).Name)
Next
End Sub
Pass the control as Control Datatype and cast it in the actual control in the function.
Public Sub mycallingfunc()
myfunc(textbox1)
End Sub
Public Shared Sub myfunc(ctrl As Control)
Dim txt As TextBox = DirectCast(ctrl, TextBox)
End Sub
Related
I am programmatically creating a GridViewColumn in WPF as follows:
Dim oGVCol As GridViewColumn = New GridViewColumn
Dim oHeaderTemplate As DataTemplate
oHeaderTemplate = New DataTemplate
Dim oGridFactory As FrameworkElementFactory = New FrameworkElementFactory(GetType(Grid))
oHeaderTemplate.VisualTree = oGridFactory
oGridFactory.SetValue(Grid.BackgroundProperty, Brushes.Transparent)
oGVCol.HeaderTemplate = oHeaderTemplate
(I have removed irrelevant code to set the content of the grid)
What I can't figure out is how to add a "click" event for the GridViewColumnHeader itself. I can add events to the Grid and any other Controls I added through the Factory objects, no problem. But I'm stuck on how to add an event to the header itself.
If you have a solution in VB.NET, great, but C# is fine too.
One (failed) attempt:
AddHandler TryCast(oGVCol.Header, GridViewColumnHeader).Click, AddressOf HeaderClick
Sadly it turns out that I cannot cast oGVCol.Header to a GridViewColumnHeader.
Ok, it may not be pretty, but I found a pretty decent solution to the problem.
Firstly, when I create the Grid Factory for the root element in the header's Visual Tree, I give it a name
oGridFactory.SetValue(Grid.NameProperty, <column name here>))
(Please note that the Names must have only letters, numbers and underscores so if your data contains column names that don't have those, you'll need to deal with that both here, to convert invalid names to valid ones, and below, to revert them back to their original names if necessary.... I won't detail that functionality here)
Also, I add an event handler to the Root "Grid" in the Template for the column header:
oGridFactory.AddHandler(Grid.SizeChangedEvent,
New SizeChangedEventHandler(AddressOf ColumnHeaderSizeChanged))
The "magic" happens in the procedure ColumnHeaderSizeChanged. This procedure is called both when the grid is Rendered the first time, but also when the user is manually resizing columns.
Signature:
Private Sub ColumnHeaderSizeChanged(sender As Object, e As SizeChangedEventArgs)
I keep a List(Of GridViewColumnHeaders) which is reset to an empty list when I need to replace the Grid with a different one. In the ColumnHeaderSizeChanged event I then do the following:
The first thing we need to do is get to the Root of the controls in the Column Header. For example, your column header may contain a TextBlock to show a column name, and icons to indicate it's been sorted up or down. That sort of thing. When the user clicks on the header they may be clicking on any of those controls, so:
Dim oParent As Object
Dim oColHeader As GridViewColumnHeader = Nothing
Dim sColHeaderName As String = String.Empty
Dim oGWH As Grid = Nothing
oParent = e.OriginalSource 'This may be any of the controls in the header.
If Not oParent Is Nothing Then
Try
While Not oParent.Parent Is Nothing
'So we keep going down the Tree until we hit the Root Parent
'which will be the main Grid created in the Grid Factory
oParent = oParent.Parent
End While
Catch
End Try
End If
'But at this point, if we still have a control, it will be the main Grid
If oParent Is Nothing Then
Exit Sub
End If
If TryCast(oParent, Grid) Is Nothing Then
'what the heck is this? This SHOULD be the Grid at the root of the Visual Tree,
'so if, for whatever reason, this is NOT a Grid, get outta here.
Exit Sub
End If
By this point we're on the main Grid, but now we need to get the GridViewColumnHeader into which this Grid has been created. So now we go to the TemplatedParent
While Not oParent.TemplatedParent Is Nothing
oParent = oParent.TemplatedParent
oColHeader = TryCast(oParent, GridViewColumnHeader)
If Not oColHeader Is Nothing Then
'This procedure is called both when the Grid View is first rendered,
'and when the user is dragging the column width.
If Mouse.LeftButton = MouseButtonState.Pressed Then
'Do something appropriate to when the user is resizing the column
Else
'Do something appropriate to when the grid
'is first Rendered or re-displayed
End If
Exit While
End If
End While
At this point we have the GridViewColumnHeader we need, so we can add it to the List and add a Handler for its Click event. moColHeaders is the List(Of GridViewColumnHeaders)
If Not oColHeader Is Nothing Then
If Not moColHeaders.Contains(oColHeader) Then
oColHeader.Name = <column name here>
moColHeaders.Add(oColHeader) 'Only need to add it once!
AddHandler oColHeader.Click, AddressOf HeaderClick
End If
End If
Now you can code your HeaderClick procedure to handle the GridViewColumnHeader.Click event.
Signature:
Private Sub HeaderClick(sender As Object, e As RoutedEventArgs)
Hey all I have the following VBA code that allows me to have a click event on a dynamically created comboboxes and textboxes onto the userform.
userform:
Option Explicit
Dim comboboxBoxColct As New Collection
Dim textboxBoxColct As New Collection
Private Sub UserForm_Activate()
Dim comboboxEvent As Class1
Dim textboxEvent As Class1
'..lots more code within here
If LCase(TypeName(controller(i))) = "combobox" Then
Set comboboxEvent = New Class1
Set comboboxEvent.comboboxBox = controller(i)
comboboxBoxColct.Add comboboxEvent
ElseIf LCase(TypeName(controller(i))) = "textbox" Then
Set textboxEvent = New Class1
Set textboxEvent.textboxBox = controller(i)
textboxBoxColct.Add textboxEvent
End If
End Sub
Class1:
Option Explicit
Public WithEvents comboboxBox As MSForms.ComboBox
Public WithEvents textboxBox As MSForms.TextBox
Private Sub comboboxBox_Click()
MsgBox "worked"
End Sub
Private Sub textboxBox_Click()
MsgBox "worked"
End Sub
The above code works just fine when using it for the comboboxes. However, once I get to a textbox within that array it never does the msgbox popup.
I am guessing it may have to do with the array number for that box as it may be looking for a 0 instead of whatever the number is in the array 6 so its starting at 6 instead of 0 since its the first textbox in the array it sees.
What can I do in order to get them both to work within the same array?
Hum... seems that a textbox in VBA does not have a Click event, so when I changed it to handle the Change (no pun intended) event instead, it shows the popup if I type a letter into the textbox.
Private Sub textboxBox_Change() 'was textboxBox_Click()
MsgBox "worked"
End Sub
I have 2 forms; MainWindow and OwnerShares. There is a search on MainWindow that looks up what items are being shared. OwnerShares has a search function that looks up the owner details and what they are sharing. On OwnerShares the options are displayed in a ListView. What i want to do is allow the user to double click on a row in ListView and be directed to the MainWindow which runs the SEARCH based on the value that was selected from the ListView. The variable ACEName will be the one that i want to pass to the MainWindow form search.
Private Sub listSearchOwner_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs) Handles listSearchOwner.MouseDoubleClick
Dim ACEName As String
ACEName = listSearchOwner.SelectedItems(0).xShareName
OwnerShares.Close()
End Sub
The name of the search in MainWindow is (cmdSearch_Click). I am currently getting the value that i click on with the above code. I just dont know how to open the MainWindow form and run the search command automatically.
If I read your question correctly you could just call show your form and run your other routine
Private Sub listSearchOwner_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs) Handles listSearchOwner.MouseDoubleClick
Dim ACEName As String
ACEName = listSearchOwner.SelectedItems(0).xShareName
OwnerShares.Close()
MainWindow.show()
' YourMethod or Button here.
End Sub
Approach it this way:
Add a module to your project, if you don't have one.
Create a public variable in the module, e.g.
Public VariableName As DataType
Everytime that you double-click the listview control, assign a value to your variable.
After getting the value stored in the public variable, delete the value to create a room to pass another value again.
That should do the trick.
I am trying to add a WPF user control to windows form. The WPF user control currently does not have anything in it, but I will be adding buttons. In form load, I do this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Application.EnableVisualStyles()
Dim elemHost As New ElementHost
Dim wuc As WPFUC = New WPFUC
elemHost.Controls.Add(wuc) <<-- I get error here
'elemHost.child = wuc <<-- and here
AddSolid()
'AddPanel()
End Sub
Error is "Value of type WindowsApplication1.WPFUC cannot be converted to System.Windows.Forms.Control. What else should I do?
I just calculated the screen points using PointToScreen method and specify that as location of WPF window wherever I needed.
I'm updating a VB.net project that needs to have cue banners added to text boxes and read-only comboboxes (DropDownStyle=DropDownList). The machine I'm developing on is Windows 7. I'm adding the cue text in a class that extends a combobox and adds a cue text property. This is how the cue text is added to the combobox:
'"Me" refers to a combobox that has been extended to include a Cue Text property
SendMessage(New HandleRef(Me, Me.Handle), CB_SETCUEBANNER, IntPtr.Zero, _cueText)
The above code is from this blog bost: http://www.aaronlerch.com/blog/page/7/, which is in C#; I translated it to VB. I tried other similar variations that I found elsewhere, all with the same result: it works great for text boxes and comboboxes when I run the program in Windows 7; it only works for text boxes in Windows XP.
I've read lots of comments on different forums about making sure visual styles are selected and disabling east Asia languages and complex scripts. I've done all that, but still haven't gotten it to work on XP.
Has anyone gotten cue banners for comboboxes to work on XP?
Using various blog and forum posts, I created a class that extends the ComboBox control and implements a CueText property that works on Windows 7 and XP. I found the most relevant pieces of information here:
How to set cue text in XP: http://www.ageektrapped.com/blog/the-missing-net-1-cue-banners-in-windows-forms-em_setcuebanner-text-prompt/
How to set cue text in Windows 7: http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/
In a nutshell, Windows 7 and XP set the cue banner text slightly differently, so you need to check which operating system the program is running on and then handle the cue text appropriately. You need to use EM_SETCUEBANNER As Integer = &H1501 for XP and CB_SETCUEBANNER As UInteger = &H1703 for Windows 7. You also need to single out the text part of the combo box if the app is running on XP. You can see the details in the code below. To figure out which OS is running, see MS KB articles 304289 (VB) or 304283 (C#). (I would post the links, but I don't have enough reputation points to post more than two.)
One caveat is that this will not work on XP if the combo boxes are read only (DropDownStyle = DropDownList). Windows 7 seems to work fine either way. If your application needs to run on XP and you need the combo boxes to be read only but still display the cue text, here's what you can do:
Create a combo box and use the default DropDownStyle, "DropDown"
Handle the KeyPress event for the combo box(es) and in that method tell it that the event has been handled like this: e.Handled = True. This will prevent text from being typed.
Create a blank ContextMenuStrip using the Toolbox in the design view, click on the combo box, view its properties, and set its ContextMenuStrip to the one you just created. This will cause nothing to happen when the user right clicks in the combo box so they can't paste text into it.
Here's the VB code for a class that inherits the ComboBox control and adds a CueText property that works for XP and 7. The only thing you'll have to do is figure out which OS is running:
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Public Class CueComboBox
Inherits ComboBox
' Occurs when the CueText property value changes.
Public Event CueTextChanged As EventHandler
'Windows XP
Private Shared EM_SETCUEBANNER As Integer = &H1501
'Windows 7
Private Shared CB_SETCUEBANNER As UInteger = &H1703
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As Int32
End Function
<DllImport("user32.dll")> _
Private Shared Function GetComboBoxInfo(ByVal hwnd As IntPtr, ByRef pcbi As COMBOBOXINFO) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)> _
Private Structure COMBOBOXINFO
Public cbSize As Integer
Public rcItem As RECT
Public rcButton As RECT
Public stateButton As IntPtr
Public hwndCombo As IntPtr
Public hwndItem As IntPtr
Public hwndList As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure
Private Shared Function GetComboBoxInfo(ByVal control As Control) As COMBOBOXINFO
Dim info As New COMBOBOXINFO()
'a combobox is made up of three controls, a button, a list and textbox;
'we want the textbox
info.cbSize = Marshal.SizeOf(info)
GetComboBoxInfo(control.Handle, info)
Return info
End Function
Private _cueText As String = [String].Empty
' Gets or sets the text that will display as a cue to the user.
<Description("The text value to be displayed as a cue to the user.")> _
<Category("Appearance")> <DefaultValue("")> <Localizable(True)> _
Public Property CueText() As String
Get
Return _cueText
End Get
Set(ByVal value As String)
If value Is Nothing Then
value = [String].Empty
End If
If Not _cueText.Equals(value, StringComparison.CurrentCulture) Then
_cueText = value
UpdateCue()
OnCueTextChanged(EventArgs.Empty)
End If
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Advanced)> _
Protected Overridable Sub OnCueTextChanged(ByVal e As EventArgs)
RaiseEvent CueTextChanged(Me, e)
End Sub
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
UpdateCue()
MyBase.OnHandleCreated(e)
End Sub
Private Sub UpdateCue()
' If the handle isn't yet created, this will be called when it is created
If Me.IsHandleCreated Then
' Windows XP sets the cue banner differently than Windows 7
If Form1.OPERATING_SYSTEM = "Windows XP" Then
Dim info As COMBOBOXINFO = GetComboBoxInfo(Me)
SendMessage(info.hwndItem, EM_SETCUEBANNER, 0, _cueText)
Else
SendMessage(New HandleRef(Me, Me.Handle), CB_SETCUEBANNER, IntPtr.Zero, _cueText)
End If
End If
End Sub
End Class