Changing usercontrol background colour doesn't show on form - vb.net

I'm just porting a load of FoxPro code to VB.NET. I have a csslbuttonpanel user control with a background colour of skyblue. This control is dropped onto various winforms. If I change the colour in csslbuttonpanel to red the forms still show skyblue.
Am I missing something?
Regards
Graham
Public Class csslButtonPanel
Inherits Panel
Public Sub New()
' This call is required by the designer.
InitializeComponent()
BackColor = Color.Red
' Add any initialization after the InitializeComponent() call.
End Sub
End Class

This happened because you made a mistake in the first version of the UserControl. You forgot to tell the designer what the default value is. You can easily see this back in the Properties window. Select one of the existing ones on the form and note how the BackColor property is displayed. It is shown in bold type, indicating that its value is not the default.
And since it is wasn't the default, it recorded Color.SkyBlue in the form's InitializeComponent() method. Changing the default in your UserControl now has no effect, it keeps using the value selected in the form's InitializeComponent() method.
What you should have done is tell the designer about the default with an attribute. Like this:
<DefaultValue(GetType(Color), "255, 135, 206, 235")> _
Public Overrides Property BackColor As Color
Get
Return MyBase.BackColor
End Get
Set(value As Color)
MyBase.BackColor = value
End Set
End Property
The <DefaultValue> attribute informs the designer about the default, SkyBlue in this case. Now the value doesn't get recorded in the form and changing your default in the user control can be effective.
Easy mistake, everybody makes it at least once. The attribute format is pretty awkward for Color, that doesn't help. Easy to fix however, simply copy/paste the snippet and change the string to "255, 255, 0, 0" to match Color.Red. Rebuild. Go back to the form and right-click the BackColor property on the existing controls and select Reset. They'll now turn Red.

Related

DataBinding - Toggle Enabled Based on Input

I'm using Visual Basic .NET developing a windows form application and I want to toggle the enabled property of a Button based on if there is anything in a TextBox. I attempted to setup the DataBinding using the following:
ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "TextLength")
This successfully disables the Button, but whenever anything is typed in the TextBox, the Button never gets enabled. I would much rather do this via DataBindings if possible as opposed to setting the Enabled property manually in the TextChanged or Validating event of the TextBox.
I usually implement this kind of custom property binding by "subclassing" the control that requires the "new" property, as in your case, TextBox needs an HasLength Boolean property (or whatever name you want to give it).
Here's MyTextBox.vb:
Public Class MyTextBox
Inherits TextBox
Public Event HasLengthChanged As EventHandler
Private _HasLength As Boolean
Public Property HasLength() As Boolean
Get
Return _HasLength
End Get
Set(ByVal value As Boolean)
If value <> _HasLength Then
_HasLength = value
OnHasLengthChanged()
End If
End Set
End Property
Public Sub New()
_HasLength = False
End Sub
Protected Sub OnHasLengthChanged()
RaiseEvent HasLengthChanged(Me, New EventArgs())
End Sub
Protected Overrides Sub OnTextChanged(e As EventArgs)
MyBase.OnTextChanged(e)
HasLength = Not (String.IsNullOrEmpty(Text))
End Sub
End Class
And here's Form1.vb:
Public Class Form1
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
ButtonBack.DataBindings.Add("Enabled", Me.MyTextBox1, "HasLength", True, DataSourceUpdateMode.OnPropertyChanged)
End Sub
End Class
Of course, you need a Form with a MyTextBox instance and a regular Button instance.
With this method, as soon as the user types something in the textbox, the button becomes enabled, and as soon as the textbox becomes empty, the button is disabled. Please note that I used the DataSourceUpdateMode.OnPropertyChanged so that the update is done as you type, and not only when the textbox loses focus.
EDIT: I thought I'd add a bit of background about the PropertyNameChanged pattern in .NET.
There are different ways to let observers know that a property has changed on an object, and most of the time we use the INotifyPropertyChanged interface, but for controls, the recommended method is still to use the PropertyNameChanged pattern, which is recognized by .NET, and thus the Binding object can do its job and know when the desired property has changed.
INotifyPropertyChanged is recommended for data objects that participate in binding.
By the way, the PropertyNameChanged works in both Windows Forms and WPF.
As reference MSDN:
https://learn.microsoft.com/en-us/dotnet/framework/winforms/how-to-apply-the-propertynamechanged-pattern
EDIT 2: I'm a C# programmer, and I've done my best to apply the residual knowledge that I have of VB.NET. Any error is really the result of my being too rusty in VB. Sorry for any inconvenience, but I can assure you that the code runs just fine here.
As #LarsTech stated in his comment, you need to use a property of the TextBox Class that raises changed notifications. The Text property is the appropriate one to use.
Your request to do this strictly via the binding is possible, but it will still involve using an event handler. As such, I don't see much value in this approach over handling the TextBoxValue.TextChanged event.
One way of doing this is to use the Binding.Format Event to convert the string of the Text Property to a boolean based on if it contains any characters.
Dim b As Binding = ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "Text", True, DataSourceUpdateMode.OnPropertyChanged)
AddHandler b.Format, Sub(s As Object, args As ConvertEventArgs) args.Value = Not String.IsNullOrEmpty(CStr(args.Value))
Because the binding is two way, if your code changes the ButtonBack.Enabled property, it will send the string representation of the property back to TextBoxValue and its text will read either "True" or "False". This would not be a desirable consequence. To rectify this possibility, the Binding.Parse Event will need to be handled.
AddHandler b.Parse, Sub(s As Object, args As ConvertEventArgs) args.Value = Me.TextBoxValue.Text

how to set transparent opacity to panel

how do i set panel transparent like opacity to 0. i set the panel by program and it was on top of video player. the code is like this
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ', AxVLCPlugin21.Click
Dim panelx As New Panel
panelx.Visible = True
panelx.Size = New Size(AxVLCPlugin21.Width, CInt(AxVLCPlugin21.Height / 2))
panelx.BackColor = System.Drawing.Color.Transparent
AxVLCPlugin21.Controls.Add(panelx)
panelx.BringToFront()
'AddHandler panelx.DoubleClick, AddressOf panelx_click
End Sub
the result is like this
then i try to play the video it only show the half
the reason i use panel is to pause the video (set panel on top of video by transparent), when i click the panel since the video doesn't support click event
update
i put the code in usercontrol1
still got me an error, although i have insert the code in designer. too clarify i put the code designer after below the main designer code. i have tried to put only inherit panel code in main designer code but it only take one inherit only.
The best way to do this is to create a custom control that inherits the panel class and overrides CreateParams and OnPaintBackground with this bit of code:
(Props to Zohar Peled for his post here)
Replace the code behind with:
Public Class TransparentPanel
Inherits System.Windows.Forms.Panel
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
' Make background transparent
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20
Return cp
End Get
End Property
Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
' call MyBase.OnPaintBackground(e) only if the backColor is not Color.Transparent
If Me.BackColor <> Color.Transparent Then
MyBase.OnPaintBackground(e)
End If
End Sub
End Class
And replace the designer code with:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class TransparentPanel
Inherits System.Windows.Forms.Panel
'Control overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Control Designer
Private components As System.ComponentModel.IContainer
' NOTE: The following procedure is required by the Component Designer
' It can be modified using the Component Designer. Do not modify it
' using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
End Class
The code you're replacing may look different initially, but using this code will ensure everything works.
NOTE: This code will make the panel transparent if the backcolor is set to Transparent or Control (which depending on the control is normally actually the same as transparent.)
I tried to find an updated resource for creating and implementing a custom control, but I wasn't able to find a maintained resource. So here are some step by step instructions on how to create a custom control.
To create custom control usable in the designer:
(I'm using Visual Studio 2015 for the examples below, it may appear different in other versions.)
1. Create new Windows Forms Control Library
2. Then right click and rename your control to "TransparentPanel" (or
whatever name you like)
3. Paste the code above into the code behind and the designer code respectively (changing the class name if you didn't use "TransparentPanel")
4. Build the project (this will create the .dll you will need to reference in your main project)
5. This one is optional, but it is good to store your DLLs somewhere consistent, other than the project bin folder, so, optionally, navigate to the control library bin folder and copy the created DLL to another location you want to store your custom DLLs.
6. Go to the project you want to use the control in, and right click in the toolbox and click "Choose Items..."
7. Make sure you are on the the ".NET Framework Component" tap and select "Browse".
8. Navigate to the bin folder of the control library (or where ever you stored the DLL), select the control and click "Open".
9. You will see the TransparentControl selected now in the "Choose Toolbox Items" form. Click "OK"
10. Then you should be able to find the control under "General" section.
11. Drag and drop the control onto your form.
NOTE:
The control may not look transparent in the designer, but on runtime it should do what you are looking for.
I hope this works for you!

Block focus/select in a ReadOnly textbox

Someone knows how to block the focus/select in a read-only textbox (ReadOnly = true), without using enabled = false?
Thanks!
Controls have a GotFocus Event. You can add an event handler for this event and give another control focus, for example by calling Select() on another control or by using SelectNextControl:
Private Sub MyTextBox_GotFocus(sender as Object, e as EventArgs) _
Handles MyTextBox.GotFocus
MyTextBox.Parent.SelectNextControl(MyTextBox, True, True, True, True)
End Sub
Alternately, you can create a custom control that inherits TextBox and set ControlStyles.Selectable to False.
Public Class NonSelectableTextBox Inherits TextBox
Public Sub New()
SetStyle(ControlStyles.Selectable, false)
End Sub
End Class
Setting ControlStyles.Selectable to false will make the TextBox mimic the behavior of other controls which have this bit set to False:
Label
Panel
GroupBox
PictureBox
ProgressBar
Splitter
LinkLabel (when there is no link present in the control)
I'm not sure I understand fully why you would want that. A read only text box allows selection to allow users to copy the text in there for other purposes. What I assume from your question is that you don't want the TextBox to accept input focus when a user is tabbing through controls, which I've seen to be a more common requirement.
You can achieve this via code:
TextBox1.TabStop = False
to ensure that tab doesn't direct focus to the readonly textbox. You can also achieve this in the designer using the same property as the screenshot shows.

DatetimePicker and other Controls in MenuStrip

I know I can add a DateTimePicker to my MenuStrip with the following lines
Dim dp = New ToolStripControlHost(New DateTimePicker)
MenuStrip1.Items.Add(dp)
But I can't figure out how to add a DateTimePicker to the MenuStrip at designtime. What's the trick behind it? I have been trying and searching for like an hour and I am about to give up even though I know there has to be a way!
TL;DR
How do I add a DateTimePicker to my MenuStrip at design-time?
Alternatively we can add it to a ToolStrip instead.
You are close to a solution in using the ToolStripControlHost, but you will need to derive from that class as shown in the linked-to example. The frustrating thing with that example is that it does not decorate the derived class with the System.Windows.Forms.Design.ToolStripItemDesignerAvailabilityAttribute to make it available on the design surface.
The following is a minimalist implementation to get a working example. You may need to override the automatic sizing to suit your needs/wants for the control. The implementation overrides the Text property to prevent designer from assigning invalid text to the underlying DateTimerPicker control.
<System.Windows.Forms.Design.ToolStripItemDesignerAvailability(
System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip _
Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip _
Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.MenuStrip)> _
Public Class TSDatePicker : Inherits ToolStripControlHost
Public Sub New()
MyBase.New(New System.Windows.Forms.DateTimePicker())
End Sub
Public ReadOnly Property ExposedControl() As DateTimePicker
Get
Return CType(Control, DateTimePicker)
End Get
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Advanced), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
Public Overrides Property Text As String
Get
Return ExposedControl.Text
End Get
Set(value As String)
' verify valid date
Dim dt As DateTime
If DateTime.TryParse(value, dt) Then
ExposedControl.Text = value
End If
End Set
End Property
End Class
Was going to add as a comment but I trust it justifies an answer.
The only way I have succeeded in this is to add one at design time (to the form) and set Visible to False and use the menu item to set Visible to True (may also need to set the position and/or bring it to the front).
You do need to manually handle setting Visible to False again.

How to have an invisible start up form?

I have an application that is a part of a solution of projects. In this project I would like for it to start up form to be invisible, but still have a notification icon in the tray visible for this form.
I know that adding me.hide into the form_load doesn't work. I tried adding a module that instantiates the startup form and I set it as the startup object. Although that didn't work either. I am running out of ideas to have this form invisible. Could anyone help out? I am using VB.NET.
Paste this in your form code:
Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
If Not Me.IsHandleCreated Then
Me.CreateHandle()
value = False
End If
MyBase.SetVisibleCore(value)
End Sub
The way that works is that the very first request to show the form, done by the Application class, this code overrides the Visible property back to False. The form will behave as normal after this, you can call Show() to make it visible and Close() to close it, even when it was never visible. Note that the Load event doesn't fire until you show it so be sure to move any code in your event handler for it, if any, to the constructor or this override.
Put this in the form's Shown event
Me.Visible = False
The easiest way is to set the opacity of the form to 0%. When you want it to appear, set it back to 100%
Here is another way that I've found to do this.
Set the form properties with
ShowInTaskbar = False
Then in the form's constructor add
WindowState = FormWindowState.Minimized
This is very easy to implement and works with no flicker. In my case I also use a NotifyIcon to access the program from the notification tray and just set
WindowState = FormWindowState.Normal
Show()
BringToFront()
In the Notify_MouseClick event handler.
To hide the form again after displaying it, just minimizing again doesn't quite do the job. In my case I use the Form_Closing event and just hide the form.
Hide()
Use Me.Opacity = 0 to hide the form on load event.
Then use the following code in the form.Shown event
Me.Hide()
Me.Opacity = 100
Just to throw out a completely different approach, have you considered not using the overload of Application.Run() that takes (and automatically shows) a Form? If you use the one that passes in an ApplicationContext (or more tyoically, your own subclass of ApplicationContext) then you can choose what your behavior is. See here for more details:
http://msdn.microsoft.com/en-us/library/ms157901
Try this:
Sub New()
MyBase.SetVisibleCore(False)
End Sub