I'm having problem with FlowLayoutPanel, i have custom control created with labels on it, looks like row with size: 250:20. I'm adding it to Flowlayoutpanel programmatically. When i Add 200 or 300 rows on FlowLayoutPanel, it seems ok, but when i'm importing text file with say 1000 lines, so it needs to create 1000 rows (mycontrol) to FlowLayoutPanel, it tooks 30 seconds its slow. How to add it faster and also delete faster.
My FlowLayoutPanel is covered with custom code:
Public Sub New()
MyBase.New()
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
SetStyle(ControlStyles.DoubleBuffer, True)
DoubleBuffered = True
UpdateStyles()
End Sub
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
Return cp
End Get
End Property
Screenshot Here: My FlowLayoutPanel and custom Control(Row with Labels)
Adding Items code:
For Each item As String In MyList
Dim a As New customControl
Dim col(1) As String
col(0) = item
col(1) = ""
a.lblTxt.Text = item
FlowLayoutPanel.SuspendLayout()
FlowLayoutPanell.Controls.Add(a)
FlowLayoutPanel.ResumeLayout()
Next
Deleting Items Code:
FlowLayoutPanell.Controls.Clear()
I wanted to use ListView, but it has no options like Transparent Color and other stuff to customize, that's why i use FlowLayoutPanel and customControl.
Related
I want clean the PictureBox image, so I make this code: TransparentPictureBox.Image = Nothing, the image don't disappear and I obtain all new image overlapping to the previous. How can I fix this?
I stay using a custom control, this is the class:
Public Class TransparentPictureBox
Inherits PictureBox
Public Sub New()
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20 ' Turn on WS_EX_TRANSPARENT
Return cp
End Get
End Property
End Class
The control is working exactly as you designed it.
With the ControlStyles.Opaque option set to True, it does not draw its background:
If true, the control is drawn opaque and the background is not painted.
When you set the Image property to Nothing, you're expecting it to be emptied.
How does a PictureBox draw itself though? It first draws the background color, then it draws the image on top of that. Since you've disabled background painting, though, the background doesn't get drawn and the previous image doesn't get erased.
Why do you have that option set? Remove it if that is not the behavior you're looking for.
Just write this although this not optimal solution but it will work
picturebox1.imagelocation = ""
I have a control derived from checkbook which I called "SettingBooleanButton", but when any window or dialog is dragged over the control the control keeps signs of the drag
The next image shows the effect of dragging an application window over control
This is the code block that I have for OnPaint()
Public Class SettingBooleanButton
Inherits CheckBox
Private _settingSection As String
Private _settingName As String
Private _associatedSetting As Setting
Public Event StateChange(ByVal affectedSetting As Setting)
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Appearance = Appearance.Button
FlatStyle = FlatStyle.Flat
TextAlign = ContentAlignment.MiddleCenter
AutoSize = False
End Sub
Public Property SettingSection As String
Get
Return _settingSection
End Get
Set(value As String)
_settingSection = value
End Set
End Property
Public Property SettingName As String
Get
Return _settingName
End Get
Set(value As String)
_settingName = value
End Set
End Property
''' <summary>
''' Sets a boolean value to indicate the initial checked state of the control.
''' </summary>
''' <value>
''' <c>true</c> to set it as [checked state]; otherwise, <c>false</c>.
''' </value>
Public Property CheckedState As Boolean
Get
Return Checked
End Get
Set(value As Boolean)
_associatedSetting = New Setting(_settingSection, _settingName, String.Empty)
RemoveHandler CheckedChanged, AddressOf StateChanged
Checked = value
SetText()
AddHandler CheckedChanged, AddressOf StateChanged
End Set
End Property
Private Sub StateChanged(sender As Object, e As EventArgs)
If IsNothing(_associatedSetting) Then
Return
End If
_associatedSetting.Value = Checked.ToString()
SetText()
RaiseEvent StateChange(_associatedSetting)
End Sub
Public Sub SetText()
If Checked Then
Font = New Font(Font.FontFamily, Font.Size, FontStyle.Bold)
ForeColor = Color.WhiteSmoke
Text = Resource.SettingBooleanButton_TrueState
Else
Font = New Font(Font.FontFamily, Font.Size, FontStyle.Regular)
ForeColor = SystemColors.ControlText
Text = Resource.SettingBooleanButton_FalseState
End If
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
If Checked Then
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, Color.Black, ButtonBorderStyle.Solid)
End If
End Sub
End Class
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, ...)
Using e.ClipRectangle like this is a traditional bug in a Paint event handler. It is not a rectangle that matches the border you want to draw. It is only the part of the control that needs to be painted. Which is usually the entire control, but not always. Such as in your case when you drag a window across your control, only the part that is revealed needs to be repainted. So now you are painting the border in the wrong position, producing those black lines.
You only ever use the ClipRectangle if your painting code is expensive and you want to take the opportunity to skip that expensive code when it isn't needed anyway. Which is pretty rare, clipping in Windows is already pretty efficient.
You'll need to pass the actual rectangle of your border. Fix:
ControlPaint.DrawBorder(e.Graphics, Me.ClientRectangle, _
Color.Black, ButtonBorderStyle.Solid)
Sometimes the simplest solutions (or causes) are overlooked.
I have a panel with 15 buttons on it and each has an image. Depending on rows selected from a data grid they all might be enabled or disabled.
It all worked fine except toggling between enabled and disabled was taking 2+ seconds and caused lag when multi-selecting from the data grid.
Tried a few things, then I thought maybe it was something to do with the images.
The images were all in an imagelist and size was set to 24,24 which was a compromise between 32,32 and 16,16. I changed the size in the imagelist to 32,32 as that is the native size of all the images... and shazam!!! All the buttons are basically rendered instantly now. No idea ATM whether being small PNG images makes a difference... but I'm going to convert all the images I have to ICO format.
Also... as all my buttons are on a panel I enable/disable the panel which in turn enables and disables all the children on it.
I am trying to set the background color of textbox to transparent, to blend with my backcolor of my form.
I have tried the following below.
TextBox1.BackColor = Color.Transparent 'This doesn't work it stays white'
Is there something I am missing?
When I set TextBox.BackColor to Color.Transparent, it throws System.ArgumentException. I got this message :
Unvalid property value, The control does not support transparent colors background.
Hope am not late to the party, but this actually works for me. First create a class for the panel as below
Partial Public Class iPanel
Inherits Panel
Public Sub New()
SetStyle(ControlStyles.SupportsTransparentBackColor Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
BackColor = Color.Transparent
End Sub
End Class
Then create a RichTextBox (Instead of a Textbox) as below
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim CP As CreateParams = MyBase.CreateParams
CP.ExStyle = CP.ExStyle Or &H20
Return CP
End Get
End Property
Now compile the code and add the iRichTextBox inside the panel. Works for me
Private Sub TextBox1_Paint(sender As Object, e As PaintEventArgs) Handles TextBox1.Paint
TextBox1.ForeColor = Color.White
TextBox1.BackColor = Color.Transparent
End Sub
Instead of doing the first one, You can try this. Just put your code in Form Load
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TextBox1.BackColor = color.(color of your Choice, same color of your background)
TextBox1.ForeColor = color.White
End Sub
As simple as that, it works for me
As far as I know textbox does not support transparent color property. But if you set the back color of the textbox to the same color as of its background component, still it can be considered as transparent.
How to do that - You can get the color name of the background component(in your case it is the form) and pass that name to the component which you want to be transparent.
Dim lname As String = Me.BackColor.ToString
Dim name As String = lname.Substring(7, lname.Length - 8)
txtbox1.BackColor = System.Drawing.Color.FromName(name)
Explanation -
The first line in the code gets you the name of the color, but there's a rub, it gets the name something like this - Color [Dark Orange] and we need only the name of the color i.e Dark Orange.
Thus the second line is to get the exact color name by removing this - Color [] part
And the last line to set that color same as of the background component color.
Hope it works, still have problem let me know...
I have made a sort of custom list box and have included the ability to add an image to each item.
I want to be able to change these images one by one at will and am not too sure on how to go about it. At the moment you can only select which image you would like in every item.
Public Class CustomListBox
Public label As Label
Public pic As PictureBox
Public panel As Panel
Public itemID As String
Public itemCollection As New Collection
Public bgColor As Color
Public txtEnterColor As Color = Color.FromArgb(80, 80, 80)
Public txtColor As Color = Color.FromArgb(150, 150, 150)
Public bgEntercolor As Color = Color.FromArgb(230, 230, 230)
Public x, y, paddingInt As Integer
Public itemHeight As Integer = 40
Public image As Image = My.Resources.FavNone
Public Event Item_Clicked()
Private Property ItemBackColor As Color
Get
Return BackColor
End Get
Set(ByVal value As Color)
bgColor = value
End Set
End Property
Private Property ItemPadding As Padding
Get
Return Padding
End Get
Set(ByVal value As Padding)
Padding = value
End Set
End Property
Public Property HoverBackColor As Color
Get
Return bgEntercolor
End Get
Set(ByVal value As Color)
bgEntercolor = value
End Set
End Property
Public Property ItemImage As Image
Get
Return image
End Get
Set(ByVal value As Image)
image = value
End Set
End Property
Public Property HoverTextColor As Color
Get
Return txtEnterColor
End Get
Set(ByVal value As Color)
txtEnterColor = value
End Set
End Property
Public Property TextColor As Color
Get
Return txtColor
End Get
Set(ByVal value As Color)
txtColor = value
End Set
End Property
Public Property TrueItemHeight As Integer
Get
Return itemHeight
End Get
Set(ByVal value As Integer)
itemHeight = value
End Set
End Property
Public Sub UpdateItems()
For Each item As String In itemCollection
label = New Label
pic = New PictureBox
panel = New Panel
With pic
.Width = itemHeight
.Height = itemHeight
.SizeMode = PictureBoxSizeMode.Zoom
.Image = image
End With
With label
.BackColor = (bgColor)
.ForeColor = (txtColor)
.Width = Me.Width - itemHeight
.Height = itemHeight
.Tag = item
.Height = itemHeight
.Padding = ItemPadding
.Text = item
.Left = itemHeight
.TextAlign = ContentAlignment.MiddleLeft
AddHandler label.MouseEnter, AddressOf Item_Enter
AddHandler label.MouseLeave, AddressOf Item_Leave
AddHandler label.MouseUp, AddressOf Item_Mousedown
End With
With panel
.Location = New Point(x, y)
.Width = Me.Width
.Height = itemHeight
.Controls.Add(pic)
.Controls.Add(label)
y += .Height + paddingInt
End With
Me.Controls.Add(panel)
Next
End Sub
Private Sub Item_Enter(ByVal sender As Label, ByVal e As EventArgs)
sender.BackColor = (bgEnterColor)
sender.ForeColor = (txtEnterColor)
itemID = sender.Tag
End Sub
Private Sub Item_Leave(ByVal sender As Label, ByVal e As EventArgs)
sender.BackColor = (bgColor)
sender.ForeColor = (txtColor)
End Sub
Private Sub Item_Mousedown(ByVal sender As Label, ByVal e As MouseEventArgs)
Select Case e.button
Case Windows.Forms.MouseButtons.Left
RaiseEvent Item_Clicked()
End Select
End Sub
End Class
I know I'll need to add something into the click event of the items.Possible set a variable with the index number of the label, maybe...?
Also, how do I get auto-suggestions when typing the code. For example, I want to be able to type CustomListBox1.itemCollection.add("Text", imageSrc)...etc I just have no idea what to type into Google apart from looking through loads of custom controls until I find one that includes this.
EDIT
I have looked into this custom Listbox.
I tried to add a MouseMove event to each item so thought it would be as easy as placing this:
Private Sub HoverItem(ByVal item As ColorListboxItem, ByVal e As MouseEventArgs)
msgbox(1)
End Sub
...in the "Methods" region and then
AddHandler .mousemove, AddressOf HoverItem
to the "OnDrawItem" sub. Unfortunately for me, it obviously isn't that easy as no msgbox shows.
Could anybody with experience on this control give a bit of insight as to how it works. And maybe an example of the MouseMove event so then I'll get an idea on how to add in more events (Mouseleave, DblClick...etc)
What #JoshMason said is correct for the most part, but if you insist on doing that, then you need not only an indexed collection/array for your items but also a linked associated collection/array for the corresponding images.
So that way the index of the item/image is accessible to you (properly exposed of course) so that you can assign an image to it like you would assign a text to the item(index) and you need to make sure your code accounts for removing an item also removes the corresponding image, but if you link them properly, that should happen automatically.
EDIT: For inspiration, give this a quick look.
That looks familiar - I have something very similar to house and track a bunch of thumbnails. A few things. The way it is written it is more of a ListBox helper than a custom control. There is nothing wrong with that, but if you want it to show up in the toolbox and be more reusable, consider reworking it:
Public Class CustomListBox
Inherits Panel ' or maybe Component, depending....
The way yours is written, you are trying to emulate ListBox functionality by maintaining a collection of labels and picboxes and panels. If you start to think about each panel+picbox+textbox as its OWN integral thing (control), you can internalize some of the functionality at that level (Event processing for instance) and leave the ListBox helper mainly to manage the interactions with the user or app (or go away). I dont think auto-suggest is going to work until it is an actual control or component.
Private WithEvents mLbl As TextBox ' just recently decided to allow text edits
Private WithEvents mPic As PictureBox
Public Sub New(ByVal uniqueName As String)
mLbl = New TextBox
mPic = New PictureBox
Name = uniqueName
.... set required lbl/txt properties
MyBase.Controls.Add(mLbl) ' we inherit from Panel
.... set pic controls
MyBase.Controls.Add(mPic)
...
...
' no need for AddHandler, each Item comes with its own built in event
Private Sub mPic_DClick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mPic.DoubleClick, mLbl.DoubleClick
IsSelected = Not _IsSelected
End Sub
After it is created with default or basic props, the class that is creating it sets the unique ones like Text, Image and location on the scrolling panel before adding it to the scrollpanel:
frmMain.pnlImgList.Controls.Add(newImgItem)
IsSelected (above) is a property, that when it changes from False to True, I raise a new event ItemSelected to notify the app/panel housing each "ImgItem" Control. The app need not know whether it was the textbox or pic clicked because ImgItem will handle that (like edit Text). In your case, this could be changing the color when selected/focused etc. (Breaking it down into 2 pieces would eventually let you get rid of that big procedure to create all new items).
What I dont have is any internal collection of these. They are added to a panel on the form and that panel's controls collection serves that purpose. When a new one of these things is added to the form, it DOES have to be hooked up to events using AddHandler to process events like ItemSelected (there is a ControlAdded/ControlRemoved event that makes a nice spot for hooking/unhooking these to the Selected event handler!)
You could do something similar using a scrolling panel of items which looks and acts like a Listbox.
Before you can do things like change an image, you need a unique identifier so you know WHICH picture to change. It looks like you use the text as the name. Depending on how you use it, that might work but if the user can edit the text, they could create a duplicate; and if the name changes you run the risk of loosing track of things. So, consider tagging them with your own unique name that isnt exposed to the user:
' this would be passed to Sub New when creating a new Item
newName = System.Guid.NewGuid.ToString()
The unique ID (Name) is part of the events args in the ItemSelected event, making it easy to find each control on the form:
ThisCtl = pnlItems.Controls(sender.Name)
To change an image, just expose it at the "item" level:
Friend Property Pic() As Bitmap
Get
' I dont recall why this is this way, maybe an artifact
' from trying different things.
Return CType(mPic.BackgroundImage, Bitmap)
End Get
The form or your helper can then change the image:
ThisCtl = pnlItems.Controls(sender.Name)
ThisCtl.Pic = newImage
Or frmName.pnlItems(sender.Name).Pic = newImage
Re your edit: Some of what you want to do with the mouse (Change colors) might be able to be done on the cheap by changing BackColor in mouse events. Some things though might be better handled by making it a proper component so that you can Shadow and OVerride mouse and paint procedures as needed. If you keep the items in an actual ListBOx, you almost certainly are going to have to hook into the DrawItem paint events. Worry about that after you decide whether or not to convert it to a component.
HTH
I'm filling the background of some VB.NET 2005 WinForms form with a nice pretty gradient fill (by overriding the OnPaint event). This works fine but the various labels etc on the form show with a solid background even after I set the BackColor to Color.Transparent. Setting the transparency key of the form itself seems to affect this but I cannot get the labels to have a truely transparent BackColor, is there an easy way to get around this or am I looking at custom controls etc?
Add a new class to your project and paste the code shown below. Build. Drop the new control from the top of your toolbox onto your form.
Public Class TransparentLabel
Inherits Label
Public Sub New()
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20 ' Turn on WS_EX_TRANSPARENT
Return cp
End Get
End Property
End Class
The flicker might be noticeable, no fix.
After some experimentation I've found that the following works for gradiant filling form backgrounds and preserving label transparency:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim formGraphics As Graphics = e.Graphics
Dim gradientBrush As New LinearGradientBrush(New Point(0, Height), New Point(0, 0), Me.AppSettings.FormGradiantFrom, Me.AppSettings.FormGradiantTo)
formGraphics.FillRectangle(gradientBrush, ClientRectangle)
End Sub
And in the form load event:
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.DoubleBuffer Or _
ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)