I am new to using classes and OOP. I have created a class that will create a new label every time it is called. here is my code:
Public lbl As New Label
Public txt As New TextBox
Public controls As List(Of Control)
Public Sub New()
'Add a label
lbl.Name = "Label" & 1
lbl.Text = "Student " & 1 & ":"
lbl.Size = New Size(65, 20)
lbl.Location = New Point(10, (10 * 22) + 5)
controls.Add(lbl)
End Sub
When i call this class i get this error message:
An unhandled exception of type 'System.NullReferenceException' occurred in Project.exe Additional information: Object reference not set to an instance of an object.
The line of code the message highlights is:
controls.Add(lbl)
Any help would be appreciated, thanks.
Public lbl As New Label
Public txt As New TextBox
Public controls As List(Of Control)
Public Sub New()
'Add a label
lbl.Name = "Label" & 1
lbl.Text = "Student " & 1 & ":"
lbl.Size = New Size(65, 20)
lbl.Location = New Point(10, (10 * 22) + 5)
If (controls is nothing) = True Then controls = new list(of Control)
controls.Add(lbl)
End Sub
Related
I have following code and it is not working and calculate cost is zero. What is the mistake here?
.Columns.Add("Total", Type.GetType("System.Int32"))
.Columns("Total").Expression = "200 * " & FxRate.ToString
FxRate is a public variable.
when FxRate changes, the Total fields should automatically update.
The DataColumn.Expression does not provide a way to reference external variables. However, you can update the expression at any time.
You will need to call the update method when FxRate changes. If FxRate is a property, you can call the update method from its setter method.
Changes to the Expression will not be automatically be reflect on bound control. The update method will also need to tell the bindings to update. If you are binding through a BindingSource instance, call its ResetBindings(False) method. If you are binding directly to the DataTable, a more complex method would be to obtain theDataTable'sCurrencyManagerand call itsRefresh` method.
Assuming the DataTable variable is named dt, the following code will acquire the CurrencyManager; Me refers to the containing Form.
Dim mngr As CurrencyManager = CType(Me.BindingContext.Item(dt), CurrencyManager)
mngr.Refresh()
Edit: A working example using a BindingSource as requested in the comments.
In a new WinForm project, replace the contents of Form1.vb with the following code (all controls are created by this code - no designer support).
The code creates: a TextBox for changing the "Quantity" field", a Label to display the "Total" field, a NumericUpDown to allow changing the value of the FxRate property, and two button to allow navigating through the records in the DataTable.
The DataTable has three records. A record comprise two fields "Quantity" and "Total". "Total" will be computed as the product of the form's FxRate property and and the field "Quantity" by setting the Expression property of the "Quantity" column each time FxRate changes.
Public Class Form1
Inherits Form
Private tbInput As TextBox
Private lblTotal As Label
Private nudFxRate As NumericUpDown
Private btnNext As Button
Private btnPrevious As Button
Private bs As BindingSource
Private _FxRate As Int32
Private dt As DataTable
Public Sub New()
MyBase.New()
SetupControls()
dt = New DemoTable ' create a preconfigured DataTable
bs = New BindingSource(dt, Nothing)
SetBindings()
FxRate = 5
AttachControlEventHandlers()
End Sub
Public Property FxRate As Int32
Get
Return _FxRate
End Get
Set(value As Int32)
If value <> _FxRate Then
_FxRate = value
UpdateTotalExpression() ' only update the Expression if the value changes
End If
End Set
End Property
Private Sub UpdateTotalExpression()
' Change the expression to reflect the current value of FxRate
Dim totalColumn As DataColumn = dt.Columns("Total")
totalColumn.Expression = $"[Quantity] * {FxRate}"
' Expression changes do not notify the BindingSource of value changes
' so tell the BindingSource to reload all values
bs.ResetBindings(False)
End Sub
Private Sub tbInput_KeyPress(sender As Object, e As KeyPressEventArgs)
If e.KeyChar = Convert.ToChar(Keys.Enter) Then
Me.Validate() ' force tbInput to Validate
e.Handled = True ' eat the enter key
End If
End Sub
Private Sub tbInput_Validated(sender As Object, e As EventArgs)
' if tbInput successfully validated, push the values in the BindingSource to the DataTable
bs.EndEdit() ' push the editted value to the DataTable, causing Total to update
End Sub
Private Sub SetBindings()
' Update BindingSource once tbInput Validates successfully
tbInput.DataBindings.Add("Text", bs, "Quantity", True, DataSourceUpdateMode.OnValidation)
' lblTotal never updates the BindingSource
lblTotal.DataBindings.Add("Text", bs, "Total", True, DataSourceUpdateMode.Never)
' nudFxRate updates the FxRate property
nudFxRate.DataBindings.Add("Value", Me, "FxRate", True, DataSourceUpdateMode.OnPropertyChanged)
End Sub
Private Sub SetupControls()
tbInput = New System.Windows.Forms.TextBox()
lblTotal = New System.Windows.Forms.Label()
nudFxRate = New System.Windows.Forms.NumericUpDown()
btnNext = New System.Windows.Forms.Button()
btnPrevious = New System.Windows.Forms.Button()
CType(nudFxRate, System.ComponentModel.ISupportInitialize).BeginInit()
SuspendLayout()
'
'tbInput
'
tbInput.Location = New System.Drawing.Point(27, 40)
tbInput.Name = "tbInput"
tbInput.Size = New System.Drawing.Size(100, 22)
tbInput.TabIndex = 0
'
'lblTotal
'
lblTotal.AutoSize = False
lblTotal.BackColor = Color.Yellow
lblTotal.Location = New System.Drawing.Point(299, 42)
lblTotal.Name = "lblTotal"
lblTotal.Size = New System.Drawing.Size(100, 17)
lblTotal.TabIndex = 1
lblTotal.Text = "0"
'
'nudFxRate
'
nudFxRate.Location = New System.Drawing.Point(28, 94)
nudFxRate.Name = "nudFxRate"
nudFxRate.Size = New System.Drawing.Size(120, 22)
nudFxRate.TabIndex = 3
nudFxRate.Value = 5
'
'btnNext
'
btnNext.Location = New System.Drawing.Point(27, 136)
btnNext.Name = "btnNext"
btnNext.Size = New System.Drawing.Size(75, 23)
btnNext.TabIndex = 4
btnNext.Text = "Next"
btnNext.UseVisualStyleBackColor = True
'
'btnPrevious
'
btnPrevious.Location = New System.Drawing.Point(28, 171)
btnPrevious.Name = "btnPrevious"
btnPrevious.Size = New System.Drawing.Size(75, 23)
btnPrevious.TabIndex = 5
btnPrevious.Text = "Previous"
btnPrevious.UseVisualStyleBackColor = True
'
'Form1
'
AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 16.0!)
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
ClientSize = New System.Drawing.Size(800, 450)
Controls.Add(btnPrevious)
Controls.Add(btnNext)
Controls.Add(nudFxRate)
Controls.Add(lblTotal)
Controls.Add(tbInput)
Name = "Form1"
Text = "Form1"
CType(nudFxRate, System.ComponentModel.ISupportInitialize).EndInit()
ResumeLayout(False)
PerformLayout()
End Sub
Private Sub AttachControlEventHandlers()
AddHandler btnNext.Click, Sub() bs.MoveNext() ' move to next record in bindingsource
AddHandler btnPrevious.Click, Sub() bs.MovePrevious() ' move to previous record in bindingsource
AddHandler tbInput.KeyPress, AddressOf tbInput_KeyPress ' allow enter key to validate textbox
AddHandler tbInput.Validated, AddressOf tbInput_Validated ' update bindingsource on validation
End Sub
Private Class DemoTable : Inherits DataTable
Public Sub New()
Columns.Add("Quantity", GetType(Int32))
Columns.Add("Total", GetType(Int32))
Rows.Add(New Object() {10})
Rows.Add(New Object() {20})
Rows.Add(New Object() {30})
End Sub
End Class
End Class
Add the column FxRate. Change the expression of the Total column to "200 * FxRate", and the value of the Total column will be automatically set based on whatever FxRate is set to.
.Columns.Add("FxRate", Type.GetType("System.Int32"))
.Columns.Add("Total", Type.GetType("System.Int32"))
.Columns("Total").Expression = "200 * FxRate"
' Example of setting FxRate in row 0.
' (Assuming row 0 exists.)
.Rows(0).Item("FxRate") = 3
So I am trying to create an application to ease creation of pixel arts (school project), what I've done so far is draw a grid in a panel, next step would be to allow the user to click on a cell and have it painted, but I can't manage to make it work, here's the code I have:
Private Sub drawGrid(g As Graphics, rows As Integer, columns As Integer)
Dim originPoint As Point = New Point(10, 2)
Dim size As Size = New Size(64, 64)
Dim left As Integer = originPoint.X
Dim up As Integer = originPoint.Y
Dim right As Integer = originPoint.X + (columns * size.Width)
Dim down As Integer = originPoint.Y + (rows * size.Height)
For y As Integer = up To down + 1 Step size.Height
Dim pt1 As New Point(left, y)
Dim pt2 As New Point(right, y)
g.DrawLine(Pens.Black, pt1, pt2)
Next
For x As Integer = left To right + 1 Step size.Width
Dim pt1 As New Point(x, up)
Dim pt2 As New Point(x, down)
g.DrawLine(Pens.Black, pt1, pt2)
Next
End Sub
This draws a grid with the amount of columns and rows the user wants, but I've been struggling to allow painting
What I've been thinking is: dispose this code, and create a 'pixel' class, create the amount of 'pixel' objects based on user rows and columns, and draw each one individually, then just change each 'pixel's' color
This is a Grid class that allows setting the color of its cells.
The Grid cell are referenced using a List(Of List(Of Class)).
The Cell class Object contains is a simple Rectagle property that measures the size of the cell, and a Color property, which allows to set the color of the single cell:
Friend Class GridCell
Public Property Cell() As Rectangle
Public Property CellColor() As Color
End Class
You can define:
The size of the Grid → ColoredGrid.GridSize = new Size(...)
The number of Columns and Rows → ColoredGrid.GridColumnsRows = new Size(...)
The position of the Grid inside the Canvas → ColoredGrid.GridPosition = New Point(...)
The color of the Grid → ColoredGrid.GridColor = Color.Gray
The BackGround color of the cells → ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
The color of a selected cell → ColoredGrid.SelectedCellColor = Color.OrangeRed
The Grid class holds a reference to the control which will be used as the Canvas for the grid painting. This reference is set in the class contructor.
The Grid registers the Canvas control Paint() and MouseClick() events to respond to the related actions automatically.
When a Mouse Click is detected on the Canvas surface, the MouseEventArgs e.Location property reports the coordinates where the Click occurred.
To identify the Grid Cell where this action is performed, the GetUpdateCell() method inspects the List(Of List(Of GridCell)) using a simple LINQ SelectMany() and identified the Cell rectangle that contains the Mouse Click coordinates (expressed as a Point() value).
This identification is performed simply checking whether the Cell Rectangle.Contains(Point()).
When the cell is identified, the Canvas Invalidate() method is called, specifing the area to repaint.
This area corresponds to the Cell Rectangle, so only this section is repainted when a Cell is colored, to save resources and time.
To test it, create a Panel and a Button in a Form:
Imports System.Drawing
'This Grid object in defined at Form Class scope
Public ColoredGrid As ColorGrid
'Button used to trigger the Grid painting
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If ColoredGrid IsNot Nothing Then
ColoredGrid.Dispose()
End If
ColoredGrid = New ColorGrid(Panel1)
ColoredGrid.GridSize = New Size(300, 300)
ColoredGrid.GridColumnsRows = New Size(10, 10)
ColoredGrid.GridPosition = New Point(10, 10)
ColoredGrid.GridColor = Color.White
ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
ColoredGrid.SelectedCellColor = Color.OrangeRed
ColoredGrid.BuildGrid()
End Sub
This is a visual sample that shows how it works:
This is the main Grid class.
The ColorGrid Class supports IDisposable, because it registers the described events. These must be unregistered when the Class is not used anymore. Weird things can happen if you don't.
Public Class ColorGrid
Implements IDisposable
Private Grid As List(Of List(Of GridCell))
Private CurrentGridSize As New Size(100, 100)
Private GridColRows As New Size(10, 10)
Private CellSize As New Size(10, 10)
Private MouseCell As Point = Point.Empty
Private Canvas As Control = Nothing
Private UpdateCell As Boolean = False
Private NewGrid As Boolean = False
Public Sub New(DrawingControl As Control)
If DrawingControl IsNot Nothing Then
Me.Canvas = DrawingControl
AddHandler Me.Canvas.Paint, New PaintEventHandler(AddressOf Me.ControlPaint)
AddHandler Me.Canvas.MouseClick, New MouseEventHandler(AddressOf Me.MouseHandler)
Me.GridPosition = New Point(10, 10)
Me.CellColor = Color.FromArgb(32, 32, 32)
End If
End Sub
Public Property GridPosition() As Point
Public Property CellColor() As Color
Public Property SelectedCellColor() As Color
Public Property GridColor() As Color
Public Property GridSize() As Size
Get
Return Me.CurrentGridSize
End Get
Set(value As Size)
Me.CurrentGridSize = value
SetCellSize()
End Set
End Property
Public Property GridColumnsRows() As Size
Get
Return Me.GridColRows
End Get
Set(value As Size)
Me.GridColRows = value
SetCellSize()
End Set
End Property
Private Property RefreshCell() As GridCell
Friend Class GridCell
Public Property Cell() As Rectangle
Public Property CellColor() As Color
End Class
Private Sub SetCellSize()
Me.CellSize = New Size((Me.CurrentGridSize.Width \ Me.GridColRows.Width),
(Me.CurrentGridSize.Height \ Me.GridColRows.Height))
If Me.CellSize.Width < 4 Then Me.CellSize.Width = 4
If Me.CellSize.Height < 4 Then Me.CellSize.Height = 4
End Sub
Public Sub BuildGrid()
If Me.Canvas Is Nothing Then Return
Me.Grid = New List(Of List(Of GridCell))()
For row As Integer = 0 To GridColumnsRows.Height - 1
Dim RowCells As New List(Of GridCell)()
For col As Integer = 0 To GridColumnsRows.Width - 1
RowCells.Add(New GridCell() With {
.Cell = New Rectangle(New Point(Me.GridPosition.X + (col * Me.CellSize.Width),
Me.GridPosition.Y + (row * Me.CellSize.Height)),
Me.CellSize),
.CellColor = Me.CellColor})
Next
Me.Grid.Add(RowCells)
Next
Me.NewGrid = True
Me.Canvas.Invalidate()
End Sub
Private Sub ControlPaint(o As Object, e As PaintEventArgs)
If Me.NewGrid Then
e.Graphics.Clear(Me.Canvas.BackColor)
Me.NewGrid = False
End If
Me.Grid.
SelectMany(Function(rowcells) rowcells).
Select(Function(colcell)
If Me.UpdateCell Then
Using brush As New SolidBrush(Me.RefreshCell.CellColor)
e.Graphics.FillRectangle(brush, Me.RefreshCell.Cell.X + 1, Me.RefreshCell.Cell.Y + 1,
Me.RefreshCell.Cell.Width - 1, Me.RefreshCell.Cell.Height - 1)
End Using
Me.UpdateCell = False
Return Nothing
Else
Using pen As New Pen(Me.GridColor)
e.Graphics.DrawRectangle(pen, colcell.Cell)
End Using
Using brush As New SolidBrush(colcell.CellColor)
e.Graphics.FillRectangle(brush, colcell.Cell.X + 1, colcell.Cell.Y + 1,
colcell.Cell.Width - 1, colcell.Cell.Height - 1)
End Using
End If
Return colcell
End Function).TakeWhile(Function(colcell) colcell IsNot Nothing).ToList()
End Sub
Private Sub MouseHandler(o As Object, e As MouseEventArgs)
Me.RefreshCell = GetUpdateCell(e.Location)
Me.RefreshCell.CellColor = Me.SelectedCellColor
Dim CellColorArea As Rectangle = Me.RefreshCell.Cell
CellColorArea.Inflate(-1, -1)
Me.UpdateCell = True
Me.Canvas.Invalidate(CellColorArea)
End Sub
Private Function GetUpdateCell(CellPosition As Point) As GridCell
Return Me.Grid.
SelectMany(Function(rowcells) rowcells).
Select(Function(gridcell) gridcell).
Where(Function(gridcell) gridcell.Cell.Contains(CellPosition)).
First()
End Function
Public Sub Dispose() Implements IDisposable.Dispose
If Me.Canvas IsNot Nothing Then
RemoveHandler Me.Canvas.Paint, AddressOf Me.ControlPaint
RemoveHandler Me.Canvas.MouseClick, AddressOf Me.MouseHandler
Me.Grid = Nothing
End If
End Sub
End Class
I am referring to a previous post somewhere in the past (cf. Hyperlink). I could not add any comments, nor did I consider writing a reply since my Problem differs slightly. Please excuse if I posted in the wrong section or for opening a new thread on this topic, I am still new to this Forum.
Please let me illustrate the following issue: Similar to this post, I would like to access and retrieve emails and attachments from a MS Exchange Server. I mainly used the code provided by in the Hyperlink above, but I could not connect to the mail Server (I used port 587). In my opinion there was a successful Connection, but the code stops when reaching the following line
Dim Read_Stream2 = New StreamReader(Sstream)
Saying that the data stream could not be read.
I also have a question about this particular line, since I am unable to figure out why there is need to convert the NetworkStream into an SslStream and then into a StreamReader Object. Could somebody please explain this necessity?
As for the remaining Problem, please consider my code so far below. If it might be too cumbersome using IMAP, I would also welcome hints about how to achieve this goal using POP3.
Thanks a mil in advance for any help provided.
Imports System.Net.Sockets
Imports System.IO
Imports System.Text
Imports System.Net.Security
Public Class emailDownloader
Dim ServerNm As String
Dim UsrNm As String
Dim PassStr As String
Dim _IntPort As Integer
Dim ImapClient As New Net.Sockets.TcpClient
Dim NetworkS_stream As NetworkStream
Dim m_sslStream As SslStream
Dim Read_Stream As StreamReader
Dim StatResp As String
Dim m_buffer() As Byte
Function Login(ByVal Sstream As SslStream, ByVal Server_Command As String)
ImapClient = New TcpClient(ServerNm, _IntPort)
NetworkS_stream = ImapClient.GetStream 'Read the stream
Sstream = New SslStream(NetworkS_stream)
Dim Read_Stream2 = New StreamReader(Sstream)
Server_Command = Server_Command ' + vbCrLf
m_buffer = System.Text.Encoding.ASCII.GetBytes(Server_Command.ToCharArray())
Sstream.Write(m_buffer, 0, m_buffer.Length)
Dim Server_Reponse As String
Server_Reponse = Read_Stream2.ReadLine()
Return Server_Reponse
End Function
Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
lbMailsRetrieved.Items.Clear()
ServerNm = tbServerName.Text
_IntPort = tbPortName.Text
UsrNm = tbUserName.Text
PassStr = tbPasswort.Text
StatResp = Login(m_sslStream, "LOGIN " + UsrNm + " " + PassStr + " ") & vbCrLf
lbMailsRetrieved.Items.Add(StatResp)
End Sub
End Class
There was a solution initially programmed in C#, which can be found here. I modified the code a bit and it is working for exchange (and only that).
Imports Microsoft.Exchange.WebServices.Data
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms
Namespace ReadMailFromExchangeServer
Public Class Form1
Inherits Form
Private exchange As ExchangeService
Public Sub New()
InitializeComponent()
lstMsg.Clear()
lstMsg.View = View.Details
lstMsg.Columns.Add("Date", 150)
lstMsg.Columns.Add("From", 250)
lstMsg.Columns.Add("Subject", 400)
lstMsg.Columns.Add("Has Attachment", 50)
lstMsg.Columns.Add("Id", 100)
lstMsg.FullRowSelect = True
End Sub
Private Sub btnRead_Click(sender As Object, e As EventArgs) Handles btnRead.Click
ConnectToExchangeServer()
'Dim ts As New TimeSpan(0, -1, 0, 0)
'Dim [date] As DateTime = DateTime.Now.Add(ts)
'Dim filter As New SearchFilter.IsGreaterThanOrEqualTo(ItemSchema.DateTimeReceived, [date])
If exchange IsNot Nothing Then
Dim findResults As FindItemsResults(Of Item) = exchange.FindItems(WellKnownFolderName.Inbox, New ItemView(50))
'Original
'Dim findResults As FindItemsResults(Of Item) = exchange.FindItems(WellKnownFolderName.Inbox, filter, New ItemView(50))
For Each item As Item In findResults
Dim message As EmailMessage = EmailMessage.Bind(exchange, item.Id)
Dim listItem As New ListViewItem({message.DateTimeReceived.ToString(), _
message.From.Name.ToString() + _
"(" + message.From.Address.ToString() + ")", _
message.Subject, (If((message.HasAttachments), "Yes", "No")), _
message.Id.ToString()})
lstMsg.Items.Add(listItem)
Next
If findResults.Items.Count <= 0 Then
lstMsg.Items.Add("No Messages found!!")
End If
End If
End Sub
Public Sub ConnectToExchangeServer()
lblMsg.Text = "Connecting to Exchange Server.."
lblMsg.Refresh()
Try
exchange = New ExchangeService(ExchangeVersion.Exchange2007_SP1)
exchange.Credentials = New WebCredentials("abc", "xyz")
exchange.AutodiscoverUrl("efg")
lblMsg.Text = "Connected to Exchange Server : " + exchange.Url.Host
lblMsg.Refresh()
Catch ex As Exception
lblMsg.Text = "Error Connecting to Exchange Server!!" + ex.Message
lblMsg.Refresh()
End Try
End Sub
Private Sub btnLoadAttachment_Click(sender As Object, e As EventArgs) Handles btnLoadAttachment.Click
If exchange IsNot Nothing Then
If lstMsg.Items.Count > 0 Then
Dim item As ListViewItem = lstMsg.SelectedItems(0)
If item IsNot Nothing Then
Dim msgid As String = item.SubItems(4).Text.ToString()
Dim message As EmailMessage = EmailMessage.Bind(exchange, New ItemId(msgid))
If message.HasAttachments AndAlso TypeOf message.Attachments(0) Is FileAttachment Then
Dim fileAttachment As FileAttachment = TryCast(message.Attachments(0), FileAttachment)
'Change the below Path
fileAttachment.Load("C:[my_path]" + fileAttachment.Name)
lblAttach.Text = "Attachment Downloaded : " + fileAttachment.Name
Else
MessageBox.Show("No Attachments found!!")
End If
Else
MessageBox.Show("Please select a Message!!")
End If
Else
MessageBox.Show("Messages not loaded!!")
End If
Else
MessageBox.Show("Not Connected to Mail Server!!")
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs)
End Sub
Private Sub InitializeComponent()
Me.btnRead = New System.Windows.Forms.Button()
Me.lstMsg = New System.Windows.Forms.ListView()
Me.btnLoadAttachment = New System.Windows.Forms.Button()
Me.lblMsg = New System.Windows.Forms.Label()
Me.label1 = New System.Windows.Forms.Label()
Me.lblAttach = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'btnRead
'
Me.btnRead.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None
Me.btnRead.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.btnRead.Location = New System.Drawing.Point(39, 284)
Me.btnRead.Name = "btnRead"
Me.btnRead.Size = New System.Drawing.Size(174, 23)
Me.btnRead.TabIndex = 0
Me.btnRead.Text = "Read Mails"
Me.btnRead.UseVisualStyleBackColor = True
'
'lstMsg
'
Me.lstMsg.Location = New System.Drawing.Point(27, 70)
Me.lstMsg.Name = "lstMsg"
Me.lstMsg.Size = New System.Drawing.Size(664, 191)
Me.lstMsg.TabIndex = 1
Me.lstMsg.UseCompatibleStateImageBehavior = False
'
'btnLoadAttachment
'
Me.btnLoadAttachment.FlatStyle = System.Windows.Forms.FlatStyle.System
Me.btnLoadAttachment.Location = New System.Drawing.Point(517, 284)
Me.btnLoadAttachment.Name = "btnLoadAttachment"
Me.btnLoadAttachment.Size = New System.Drawing.Size(174, 23)
Me.btnLoadAttachment.TabIndex = 2
Me.btnLoadAttachment.Text = "Load Attachments"
Me.btnLoadAttachment.UseVisualStyleBackColor = True
'
'lblMsg
'
Me.lblMsg.AutoSize = True
Me.lblMsg.Location = New System.Drawing.Point(36, 361)
Me.lblMsg.Name = "lblMsg"
Me.lblMsg.Size = New System.Drawing.Size(38, 13)
Me.lblMsg.TabIndex = 3
Me.lblMsg.Text = "Ready"
'
'label1
'
Me.label1.AutoSize = True
Me.label1.Location = New System.Drawing.Point(24, 54)
Me.label1.Name = "label1"
Me.label1.Size = New System.Drawing.Size(82, 13)
Me.label1.TabIndex = 4
Me.label1.Text = "Today's Messages"
'
'lblAttach
'
Me.lblAttach.AutoSize = True
Me.lblAttach.Location = New System.Drawing.Point(514, 361)
Me.lblAttach.Name = "lblAttach"
Me.lblAttach.Size = New System.Drawing.Size(148, 13)
Me.lblAttach.TabIndex = 5
Me.lblAttach.Text = "No attachmment downloaded"
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(812, 591)
Me.Controls.Add(Me.lblAttach)
Me.Controls.Add(Me.label1)
Me.Controls.Add(Me.lblMsg)
Me.Controls.Add(Me.btnLoadAttachment)
Me.Controls.Add(Me.lstMsg)
Me.Controls.Add(Me.btnRead)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents btnRead As System.Windows.Forms.Button
Friend WithEvents lstMsg As System.Windows.Forms.ListView
Friend WithEvents btnLoadAttachment As System.Windows.Forms.Button
Friend WithEvents lblMsg As System.Windows.Forms.Label
Friend WithEvents label1 As System.Windows.Forms.Label
Friend WithEvents lblAttach As System.Windows.Forms.Label
End Class
End Namespace
For the issue described in the beginning, the present code provides a solution. Thus I would like to mark this is an answer and close this thread (I know, usually one should not mark their very own answer as answer). Hope this approach is ok.
I have created this class in visual Basic it works fine but there is a slight design issue. As you can see there is this small bumb, how can I fix this? And also, how can I fix the spacing between the content Box and the selection menu.
Public Class VerticallTabControll
Inherits TabControl
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
DoubleBuffered = True
SizeMode = TabSizeMode.Fixed
ItemSize = New Size(30, 170)
End Sub
Protected Overrides Sub CreateHandle()
MyBase.CreateHandle()
Alignment = TabAlignment.Left
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim selected As New SolidBrush(Color.FromArgb(0, 122, 204))
Dim notSelected As New SolidBrush(Color.FromArgb(63, 63, 70))
Dim B As New Bitmap(Width, Height)
Dim G As Graphics = Graphics.FromImage(B)
G.Clear(Color.FromArgb(63, 63, 70))
For i = 0 To TabCount - 1
Dim TabRectangle As Rectangle = GetTabRect(i)
If i = SelectedIndex Then
'// if tab is selected
G.FillRectangle(selected, TabRectangle)
Else
'// tab is not selected
G.FillRectangle(notSelected, TabRectangle)
End If
'Line Test
'Dim start As New Point(10, 31 * (i + 1))
'Dim ende As New Point(160, 31 * (i + 1))
'G.DrawLine(Pens.White, start, ende)
G.DrawString(TabPages(i).Text, Font, Brushes.White, TabRectangle, New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Next
e.Graphics.DrawImage(B.Clone, 0, 0)
G.Dispose() : B.Dispose() : selected.Dispose() : notSelected.Dispose()
MyBase.OnPaint(e)
e.Dispose()
End Sub
End Class
You can try overriding the DisplayRectangle property to adjust the interior space accordingly:
Public Overrides ReadOnly Property DisplayRectangle As Rectangle
Get
Return New Rectangle(MyBase.DisplayRectangle.Left,
MyBase.DisplayRectangle.Top - 2,
MyBase.DisplayRectangle.Width + 2,
MyBase.DisplayRectangle.Height + 4)
End Get
End Property
I've dynamically added a text box to my main form on a button press:
Public Widget As UUTWidgetPanel
...
Public Sub New(ByVal UnitNo As Integer)
Me.UnitNo = UnitNo
Widget = New UUTWidgetPanel(UnitNo)
End Sub
...
Public Class UUTWidgetPanel
Public ContainerWidget As New FlowLayoutPanel
Public UnitLabel as New Label
Public CurrDrawTB As New TextBox
Public Sub New(ByVal UnitNo As Integer)
With UnitLabel
.Text = "Unit " & UnitNo.ToString
.Height = 25
.Anchor = AnchorStyles.Top + AnchorStyles.Left
.TextAlign = ContentAlignment.MiddleCenter
End With
With CurrDrawTB
.Width = 123
.Height = 25
.Text = "some text"
.ReadOnly = False
.Visible = True
.ForeColor = Color.Blue
'.Text = "CurrDrawTB"
End With
With ContainerWidget
.Controls.Add(UnitLabel)
.Controls.Add(CurrDrawTB)
I add the "ContainerWidget" FlowLayoutPanel to my main form from a method called by a button click as follows:
Private Sub AddUUT() 'adds instance of TestUnit to TestUnits, then it's controls to main form's "FlowLayoutPanel1"
Dim highestArrIdx As Integer = TestUnits.Count
TestUnits.Add(New TestUnit(highestArrIdx + 1))
FlowLayoutPanel1.Controls.Add(TestUnits.Item(highestArrIdx).Widget.ContainerWidget)
End Sub
Oddly enough, when I try to retrieve the info from CurrDrawTB, I receive an empty string, rather than the value "some text":
Dim text As String
text = Me.Widget.CurrDrawTB.Text
But writing to the textbox works:
Me.Widget.CurrDrawTB.Text = "Hi!" <--I see "Hi!" in the debugger and on the form.
Thanks in advance :)
Your CurrDrawTB Text property is being overwritten. This is a very common issue. The logic that you have posted works fine apart from this.