Hi! First off, great work. I've been trying to find a way to add better graphics to my Panelviews without a lot of luck. This solution is a step in the right direction. My question is whether you could provide a tutorial on creating components. I've been trying to modify yours without much luck.
Thanks!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Building components can get very complex. The best thing to do is to start by making a copy of a component that is closest to the one you want to create. You would create the graphics in PNG format and add them to the resources of the project. You can them search the code for the references of the graphic and change it to your newly created graphic.
If you give me an idea of what you want to create and what problems you are running into, I can give you more specific help.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thats what I tried to do. :) I used your pilot light component. I was trying to do a simple switch of two duplicate graphics with different gradients to simulate rotation, like you did with the motor shaft. On my last attempt before posting, I just went through and changed the references to redlightoff/on and what not but I get an error when I try to put it on the form.
Imports System.Drawing
'*******************************************************************************
'* 2-MAY-09 Added ReverseLogic and PLCAddressForButton
'*********************************************************************************
Public Class Screw
Inherits System.Windows.Forms.UserControl
Private StaticImage As Bitmap
Private ButtonImage, LightOnImage, LightOffImage As Bitmap
Private TextRect As New Rectangle
Private ImageRatio As Single
Private m As New System.Drawing.Drawing2D.Matrix
#Region "Properties"
Private m_Value As Single
Public Property Value() As Boolean
Get
Return m_Value
End Get
Set(ByVal value As Boolean)
If value <> m_Value Then
m_Value = value
If (m_Value Xor Not m_ReverseLogic) Then
ButtonImage = LightOffImage
Else
ButtonImage = LightOnImage
End If
Me.Invalidate()
Me.Invalidate(New Rectangle(Me.Width * 0.14, Me.Height * 0.14, Me.Width * 0.72, Me.Height * 0.63))
End If
End Set
End Property
Private m_ReverseLogic As Single
Public Property ReverseLogic() As Boolean
Get
Return m_ReverseLogic
End Get
Set(ByVal value As Boolean)
If value <> m_ReverseLogic Then
m_ReverseLogic = value
If (m_Value Xor Not m_ReverseLogic) Then
ButtonImage = LightOnImage
Else
ButtonImage = LightOffImage
End If
Me.Invalidate()
Me.Invalidate(New Rectangle(Me.Width * 0.14, Me.Height * 0.14, Me.Width * 0.72, Me.Height * 0.63))
End If
End Set
End Property
'*****************************************
'* Property - Color and type of button
'*****************************************
Public Enum ButtonColors
Red
Green
End Enum
Private m_ButtonColor As ButtonColors = ButtonColors.Green
Public Property ButtonColor() As ButtonColors
Get
Return (m_ButtonColor)
End Get
Set(ByVal value As ButtonColors)
m_ButtonColor = value
RefreshImage()
Me.Invalidate()
End Set
End Property
'*****************************************
'* Property - Text on Legend Plate
'*****************************************
Private m_LegendText As String = "Text"
Public Property LegendText() As String
Get
Return m_LegendText
End Get
Set(ByVal value As String)
m_LegendText = value
RefreshImage()
Me.Invalidate()
End Set
End Property
'*****************************************************
'* Property - Component to communicate to PLC through
'*****************************************************
Private m_CommComponent As ICommComponent
Public Property CommComponent() As ICommComponent
Get
Return m_CommComponent
End Get
Set(ByVal value As ICommComponent)
m_CommComponent = value
End Set
End Property
'*****************************************
'* Property - Address in PLC to Link to
'*****************************************
Private m_PLCaddress As String = "B3/0"
Public Property PLCaddress() As String
Get
Return m_PLCaddress
End Get
Set(ByVal value As String)
m_PLCaddress = value
End Set
End Property
Private m_PLCaddressForButton As String = "B3/1"
Public Property PLCaddressForButton() As String
Get
Return m_PLCaddressForButton
End Get
Set(ByVal value As String)
m_PLCaddressForButton = value
End Set
End Property
'*****************************************
'* Property - What to do to bit in PLC
'*****************************************
Public Enum OutputTypes
MomentarySet
MomentaryReset
SetTrue
SetFalse
Toggle
End Enum
Private m_OutputType As OutputTypes = OutputTypes.MomentarySet
Public Property OutputType() As OutputTypes
Get
Return m_OutputType
End Get
Set(ByVal value As OutputTypes)
m_OutputType = value
End Set
End Property
'* This is necessary to make the background draw correctly
'* http://www.bobpowell.net/transcontrols.htm
'*part of the transparent background code
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As System.Windows.Forms.CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or 32
Return cp
Return MyBase.CreateParams
End Get
End Property
#End Region
#Region "Events"
'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing And m_CommComponent IsNot Nothing Then
m_CommComponent.UnSubscribe(NotificationID)
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'* This is part of the transparent background code and it stops flicker
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
'MyBase.OnPaintBackground(e)
End Sub
'*************************************************************************
'* Manually double buffer in order to allow a true transparent background
'**************************************************************************
Private _backBuffer As Bitmap
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If StaticImage Is Nothing Or _backBuffer Is Nothing Then Exit Sub
Dim g As Graphics = Graphics.FromImage(_backBuffer)
'Copy the back buffer to the screen
e.Graphics.DrawImage(_backBuffer, 0, 0)
End Sub
Private WithEvents tmrError As New Timer
'****************************
'* Event - Mouse Down
'****************************
Private Sub MomentaryButton_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
'Exit Sub
'ButtonImage = LightOnImage
'Me.Invalidate()
'*** TODO:
Try
'Select Case m_OutputType
' Case OutputTypes.MomentarySet : m_CommComponent.WriteData(m_PLCaddress, 1)
' Case OutputTypes.MomentaryReset : m_CommComponent.WriteData(m_PLCaddress, 0)
' Case OutputTypes.SetTrue : m_CommComponent.WriteData(m_PLCaddress, 1)
' Case OutputTypes.SetFalse : m_CommComponent.WriteData(m_PLCaddress, 0)
' Case OutputTypes.Toggle
Dim CurrentValue As Boolean
CurrentValue = m_CommComponent.ReadAny(m_PLCaddressForButton)
If CurrentValue Then
m_CommComponent.WriteData(m_PLCaddressForButton, 0)
Else
m_CommComponent.WriteData(m_PLCaddressForButton, 1)
End If
'End Select
If tmrError.Enabled Then
tmrError.Enabled = False
End If
Catch
'* Start the message flashing
tmrError.Enabled = True
End Try
End Sub
'****************************
'* Event - Mouse Up
'****************************
Private Sub MomentaryButton_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
Exit Sub
ButtonImage = LightOffImage
Me.Invalidate()
Try
Select Case m_OutputType
'Case OutputTypes.MomentarySet : m_CommComponent.WriteData(m_PLCaddress, 0)
'Case OutputTypes.MomentaryReset : m_CommComponent.WriteData(m_PLCaddress, 1)
End Select
'tmrError.Enabled = False
Catch
tmrError.Enabled = True
End Try
End Sub
'********************************************************************
'* When an instance is added to the form, set the comm component
'* property. If a comm component does not exist, add one to the form
'********************************************************************
Protected Overrides Sub OnCreateControl()
MyBase.OnCreateControl()
If Me.DesignMode Then
'If Me Is Nothing OrElse Me.Parent Is Nothing OrElse Me.Parent.Site Is Nothing Then Exit Sub
'********************************************************
'* Search for ICommComponent component in parent form
'* If one exists, set the client of this component to it
'********************************************************
Dim i = 0
Dim j As Integer = Me.Parent.Site.Container.Components.Count - 1
While m_CommComponent Is Nothing And i < j
If Me.Parent.Site.Container.Components(i).GetType.GetInterface("ICommComponent") IsNot Nothing Then m_CommComponent = Me.Parent.Site.Container.Components(i)
i += 1
End While
'************************************************
'* If no comm component was found, then add one and
'* point the CommComponent property to it
'*********************************************
If m_CommComponent Is Nothing Then
Me.Parent.Site.Container.Add(New DF1Comm)
m_CommComponent = Me.Parent.Site.Container.Components(Me.Parent.Site.Container.Components.Count - 1)
End If
End If
End Sub
Private WithEvents SetupDelay As New Timer
Private Sub Meter_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.DesignMode Then
If m_CommComponent IsNot Nothing And m_PLCaddress.Length > 0 Then
SetupDelay.Enabled = True
End If
End If
End Sub
Private NotificationID As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SetupDelay.Tick
If IsHandleCreated Then
SetupDelay.Enabled = False
NotificationID = m_CommComponent.Subscribe(Me.m_PLCaddress, 1, AddressOf PolledDataReturned)
If NotificationID < 0 Then
LegendText = "INVALID PLC ADDRESS!"
End If
SetupDelay.Dispose()
SetupDelay = Nothing
End If
End Sub
Private Sub PolledDataReturned(ByVal Values() As String)
Try
Value = Values(0)
Catch
If Values(0).Length < 10 Then
LegendText = "INVALID VALUE!"
Else
LegendText = Values(0)
End If
End Try
End Sub
Private Sub tmrError_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrError.Tick
'If Label1.Text = m_LegendText Then
' Label1.Text = "COMM ERROR!"
'Else
' Label1.Text = m_LegendText
'End If
End Sub
#End Region
'Private NamePlateRatio As Single = My.Resources.NamePlate.Height / My.Resources.NamePlate.Width
Private LegendPlateRatio As Single = My.Resources.screw1.Height / My.Resources.screw1.Width
Private LastWidth, LastHeight As Integer
Private Sub MomentaryButton_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
If LastHeight < Me.Height Or LastWidth < Me.Width Then
If Me.Height / Me.Width > LegendPlateRatio Then
Me.Width = Me.Height / LegendPlateRatio
Else
Me.Height = Me.Width * LegendPlateRatio
End If
Else
If Me.Height / Me.Width > LegendPlateRatio Then
Me.Height = Me.Width * LegendPlateRatio
Else
Me.Width = Me.Height / LegendPlateRatio
End If
End If
LastWidth = Me.Width
LastHeight = Me.Height
RefreshImage()
End Sub
Private Sub RefreshImage()
Dim WidthRatio As Single = CSng(Me.Width) / CSng(My.Resources.screw1.Width)
Dim HeightRatio As Single = CSng(Me.Height) / CSng(My.Resources.screw1.Height)
If WidthRatio < HeightRatio Then
ImageRatio = WidthRatio
Else
ImageRatio = HeightRatio
End If
'****************************************************************
' Scale the gauge image so it will draw faster in Paint event
'****************************************************************
' Make a bitmap for the result.
If StaticImage IsNot Nothing Then StaticImage.Dispose()
StaticImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio), CInt(My.Resources.screw1.Height * ImageRatio))
' Make a Graphics object for the result Bitmap.
Dim gr_dest As Graphics = Graphics.FromImage(StaticImage)
m.Reset()
m.Scale(ImageRatio * 1.25, ImageRatio * 1.25)
gr_dest.Transform = m
' Copy the source image into the destination bitmap.
gr_dest.DrawImage(My.Resources.screw1, 0, 0)
TextRect.X = 5
TextRect.Width = StaticImage.Width / 1.25 / ImageRatio - 10
TextRect.Y = 5
TextRect.Height = StaticImage.Height / 1.25 / ImageRatio * 0.33
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
'gr_dest.DrawRectangle(Pens.Black, TextRect)
Dim b As New SolidBrush(Color.FromArgb(250, 130, 140, 160))
gr_dest.DrawString(m_LegendText, New Font("Arial", 22, FontStyle.Regular, GraphicsUnit.Point), b, TextRect, sf)
Dim x() As Int16 = {My.Resources.screw1.Width, My.Resources.screw2.Width}
Select Case m_ButtonColor
Case ButtonColors.Red
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
Case Else
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
End Select
gr_dest = Graphics.FromImage(LightOffImage)
Dim gr_dest2 As Graphics = Graphics.FromImage(LightOnImage)
m.Reset()
m.Scale(ImageRatio * 1.25, ImageRatio * 1.25)
gr_dest.Transform = m
gr_dest2.Transform = m
Select Case m_ButtonColor
Case ButtonColors.Red
gr_dest.DrawImage(My.Resources.screw1, 0, 0)
gr_dest2.DrawImage(My.Resources.screw1, 0, 0)
Case Else
gr_dest.DrawImage(My.Resources.screw2, 0, 0)
gr_dest2.DrawImage(My.Resources.screw2, 0, 0)
End Select
ButtonImage = LightOffImage
'* Perform some cleanup
gr_dest.Dispose()
gr_dest2.Dispose()
'* Create a new resized backbuffer for double buffering
If _backBuffer IsNot Nothing Then _backBuffer.Dispose()
_backBuffer = New Bitmap(Me.Width, Me.Height)
End Sub
End Class
The error is : Failed to create component 'Screw'/ the error message follows: 'System.NullReferenceException: Object reference not set to an instance of an object. at AdvancedHMI.Screw…ctor() in blah blah Screw.vb:line 292
Any ideas?
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I copy and pasted your code, created a couple generic graphics to represent screw1 and 2. I then added a screw and a windows button to the MainForm. I added code to toggle screw1.value everytime I clicked the button. It's working here on my computer with no problems. What is the code that you have on line 292?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm testing on Visual Studio 2008, so there may be some difference. Try these couple code changes:
Private WithEvents SetupDelay As Timer
Private Sub Meter_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.DesignMode Then
If m_CommComponent IsNot Nothing AndAlso m_PLCaddress.Length > 0 Then
SetupDelay = New Timer
AddHandler SetupDelay.Tick, AddressOf Timer1_Tick
SetupDelay.Enabled = True
End If
End If
End Sub
Private NotificationID As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ok, I created a copy of the pilot light again, built the project and tested it. Put the new control on the form, no problem. Went into the code, and changed JUST THIS: Private LegendPlateRatio As Single = My.Resources.screw1.Height / My.Resources.screw1.Width
which is line 343, the first place I ran into reference to the original graphics. saved it, rebuilt and I get the error. (at line 292)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I put the original graphic back in, saved and rebuilt and it's fine again. Must be something to do with the way I added those images to the project, don't you think?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I added the graphics files by 1)right click the resources folder in solution explorer, add, then existing and picking the graphic. After that, I had to also add (via copy and past) them to the Resources.Designer.vb file. The graphic is .png
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The method I use is to go to the project properties by right clicking the project name in the Solution Explorer. Then select the resources tab. You can then drop down the Add Resources and select Existing File.
That way you do not have to modify the designer file. VB tends not to like the Designer files modified manually.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I was looking at that, as there was an unexpected space bwt obj,System.Drawing.Bitmap that isn't with the original components. I couldn't make it go away either. So, I started poking around in the project folder and found Resources.resx, which I added to the resources folder and got this whole new screen which I'm sure you saw before.:) Using your method, that is the same screen that comes up to add resources. That screen didn't contain my .png files, which would explain the error. I'm going to try it, but I think that was the problem.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well, looks like I need to start over. Building the project after all my screwing around throws off error after error. LOL I guess I'll delete it and start from scratch in the AM. Thanks for your help!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sooooo, No more error but now the images won't display right. I'm seeing both images in the containing image. I did manage to get one to go away, but was still having problems with scaling. How do you determine the values used here:
Private _backBuffer As Bitmap
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If StaticImage Is Nothing Or _backBuffer Is Nothing Then Exit Sub
Dim g As Graphics = Graphics.FromImage(_backBuffer)
The best thing to do is to use PNG format and save them at 96DPI. My first components I built used 72DPI and I had to put in 1.25 scale factors. I later learned that 72 is the Apple way of doing things and 96 is Windows.
Look in the code where it creates the static images. I think it is the last subroutine.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi! First off, great work. I've been trying to find a way to add better graphics to my Panelviews without a lot of luck. This solution is a step in the right direction. My question is whether you could provide a tutorial on creating components. I've been trying to modify yours without much luck.
Thanks!
Building components can get very complex. The best thing to do is to start by making a copy of a component that is closest to the one you want to create. You would create the graphics in PNG format and add them to the resources of the project. You can them search the code for the references of the graphic and change it to your newly created graphic.
If you give me an idea of what you want to create and what problems you are running into, I can give you more specific help.
Thats what I tried to do. :) I used your pilot light component. I was trying to do a simple switch of two duplicate graphics with different gradients to simulate rotation, like you did with the motor shaft. On my last attempt before posting, I just went through and changed the references to redlightoff/on and what not but I get an error when I try to put it on the form.
Imports System.Drawing
'*******************************************************************************
'* 2-MAY-09 Added ReverseLogic and PLCAddressForButton
'*********************************************************************************
Public Class Screw
Inherits System.Windows.Forms.UserControl
Private StaticImage As Bitmap
Private ButtonImage, LightOnImage, LightOffImage As Bitmap
Private TextRect As New Rectangle
Private ImageRatio As Single
Private m As New System.Drawing.Drawing2D.Matrix
#Region "Properties"
Private m_Value As Single
Public Property Value() As Boolean
Get
Return m_Value
End Get
Set(ByVal value As Boolean)
If value <> m_Value Then
m_Value = value
If (m_Value Xor Not m_ReverseLogic) Then
ButtonImage = LightOffImage
Else
ButtonImage = LightOnImage
End If
Me.Invalidate()
Me.Invalidate(New Rectangle(Me.Width * 0.14, Me.Height * 0.14, Me.Width * 0.72, Me.Height * 0.63))
End If
End Set
End Property
Private m_ReverseLogic As Single
Public Property ReverseLogic() As Boolean
Get
Return m_ReverseLogic
End Get
Set(ByVal value As Boolean)
If value <> m_ReverseLogic Then
m_ReverseLogic = value
If (m_Value Xor Not m_ReverseLogic) Then
ButtonImage = LightOnImage
Else
ButtonImage = LightOffImage
End If
Me.Invalidate()
Me.Invalidate(New Rectangle(Me.Width * 0.14, Me.Height * 0.14, Me.Width * 0.72, Me.Height * 0.63))
End If
End Set
End Property
'*****************************************
'* Property - Color and type of button
'*****************************************
Public Enum ButtonColors
Red
Green
End Enum
Private m_ButtonColor As ButtonColors = ButtonColors.Green
Public Property ButtonColor() As ButtonColors
Get
Return (m_ButtonColor)
End Get
Set(ByVal value As ButtonColors)
m_ButtonColor = value
RefreshImage()
Me.Invalidate()
End Set
End Property
'*****************************************
'* Property - Text on Legend Plate
'*****************************************
Private m_LegendText As String = "Text"
Public Property LegendText() As String
Get
Return m_LegendText
End Get
Set(ByVal value As String)
m_LegendText = value
RefreshImage()
Me.Invalidate()
End Set
End Property
'*****************************************************
'* Property - Component to communicate to PLC through
'*****************************************************
Private m_CommComponent As ICommComponent
Public Property CommComponent() As ICommComponent
Get
Return m_CommComponent
End Get
Set(ByVal value As ICommComponent)
m_CommComponent = value
End Set
End Property
'*****************************************
'* Property - Address in PLC to Link to
'*****************************************
Private m_PLCaddress As String = "B3/0"
Public Property PLCaddress() As String
Get
Return m_PLCaddress
End Get
Set(ByVal value As String)
m_PLCaddress = value
End Set
End Property
Private m_PLCaddressForButton As String = "B3/1"
Public Property PLCaddressForButton() As String
Get
Return m_PLCaddressForButton
End Get
Set(ByVal value As String)
m_PLCaddressForButton = value
End Set
End Property
'*****************************************
'* Property - What to do to bit in PLC
'*****************************************
Public Enum OutputTypes
MomentarySet
MomentaryReset
SetTrue
SetFalse
Toggle
End Enum
Private m_OutputType As OutputTypes = OutputTypes.MomentarySet
Public Property OutputType() As OutputTypes
Get
Return m_OutputType
End Get
Set(ByVal value As OutputTypes)
m_OutputType = value
End Set
End Property
'* This is necessary to make the background draw correctly
'* http://www.bobpowell.net/transcontrols.htm
'*part of the transparent background code
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As System.Windows.Forms.CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or 32
Return cp
Return MyBase.CreateParams
End Get
End Property
#End Region
#Region "Events"
'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing And m_CommComponent IsNot Nothing Then
m_CommComponent.UnSubscribe(NotificationID)
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'* This is part of the transparent background code and it stops flicker
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
'MyBase.OnPaintBackground(e)
End Sub
'*************************************************************************
'* Manually double buffer in order to allow a true transparent background
'**************************************************************************
Private _backBuffer As Bitmap
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If StaticImage Is Nothing Or _backBuffer Is Nothing Then Exit Sub
Dim g As Graphics = Graphics.FromImage(_backBuffer)
g.DrawImage(StaticImage, 0, 0)
g.DrawImage(ButtonImage, CInt((StaticImage.Width / 2 - ButtonImage.Width / 2)), CInt(StaticImage.Height * 0.43))
'Copy the back buffer to the screen
e.Graphics.DrawImage(_backBuffer, 0, 0)
End Sub
Private WithEvents tmrError As New Timer
'****************************
'* Event - Mouse Down
'****************************
Private Sub MomentaryButton_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
'Exit Sub
'ButtonImage = LightOnImage
'Me.Invalidate()
'*** TODO:
Try
'Select Case m_OutputType
' Case OutputTypes.MomentarySet : m_CommComponent.WriteData(m_PLCaddress, 1)
' Case OutputTypes.MomentaryReset : m_CommComponent.WriteData(m_PLCaddress, 0)
' Case OutputTypes.SetTrue : m_CommComponent.WriteData(m_PLCaddress, 1)
' Case OutputTypes.SetFalse : m_CommComponent.WriteData(m_PLCaddress, 0)
' Case OutputTypes.Toggle
Dim CurrentValue As Boolean
CurrentValue = m_CommComponent.ReadAny(m_PLCaddressForButton)
If CurrentValue Then
m_CommComponent.WriteData(m_PLCaddressForButton, 0)
Else
m_CommComponent.WriteData(m_PLCaddressForButton, 1)
End If
'End Select
If tmrError.Enabled Then
tmrError.Enabled = False
End If
Catch
'* Start the message flashing
tmrError.Enabled = True
End Try
End Sub
'****************************
'* Event - Mouse Up
'****************************
Private Sub MomentaryButton_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
Exit Sub
ButtonImage = LightOffImage
Me.Invalidate()
Try
Select Case m_OutputType
'Case OutputTypes.MomentarySet : m_CommComponent.WriteData(m_PLCaddress, 0)
'Case OutputTypes.MomentaryReset : m_CommComponent.WriteData(m_PLCaddress, 1)
End Select
'tmrError.Enabled = False
Catch
tmrError.Enabled = True
End Try
End Sub
'********************************************************************
'* When an instance is added to the form, set the comm component
'* property. If a comm component does not exist, add one to the form
'********************************************************************
Protected Overrides Sub OnCreateControl()
MyBase.OnCreateControl()
If Me.DesignMode Then
'If Me Is Nothing OrElse Me.Parent Is Nothing OrElse Me.Parent.Site Is Nothing Then Exit Sub
'********************************************************
'* Search for ICommComponent component in parent form
'* If one exists, set the client of this component to it
'********************************************************
Dim i = 0
Dim j As Integer = Me.Parent.Site.Container.Components.Count - 1
While m_CommComponent Is Nothing And i < j
If Me.Parent.Site.Container.Components(i).GetType.GetInterface("ICommComponent") IsNot Nothing Then m_CommComponent = Me.Parent.Site.Container.Components(i)
i += 1
End While
'************************************************
'* If no comm component was found, then add one and
'* point the CommComponent property to it
'*********************************************
If m_CommComponent Is Nothing Then
Me.Parent.Site.Container.Add(New DF1Comm)
m_CommComponent = Me.Parent.Site.Container.Components(Me.Parent.Site.Container.Components.Count - 1)
End If
End If
End Sub
Private WithEvents SetupDelay As New Timer
Private Sub Meter_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.DesignMode Then
If m_CommComponent IsNot Nothing And m_PLCaddress.Length > 0 Then
SetupDelay.Enabled = True
End If
End If
End Sub
Private NotificationID As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SetupDelay.Tick
If IsHandleCreated Then
SetupDelay.Enabled = False
NotificationID = m_CommComponent.Subscribe(Me.m_PLCaddress, 1, AddressOf PolledDataReturned)
If NotificationID < 0 Then
LegendText = "INVALID PLC ADDRESS!"
End If
SetupDelay.Dispose()
SetupDelay = Nothing
End If
End Sub
Private Sub PolledDataReturned(ByVal Values() As String)
Try
Value = Values(0)
Catch
If Values(0).Length < 10 Then
LegendText = "INVALID VALUE!"
Else
LegendText = Values(0)
End If
End Try
End Sub
Private Sub tmrError_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrError.Tick
'If Label1.Text = m_LegendText Then
' Label1.Text = "COMM ERROR!"
'Else
' Label1.Text = m_LegendText
'End If
End Sub
#End Region
'Private NamePlateRatio As Single = My.Resources.NamePlate.Height / My.Resources.NamePlate.Width
Private LegendPlateRatio As Single = My.Resources.screw1.Height / My.Resources.screw1.Width
Private LastWidth, LastHeight As Integer
Private Sub MomentaryButton_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
If LastHeight < Me.Height Or LastWidth < Me.Width Then
If Me.Height / Me.Width > LegendPlateRatio Then
Me.Width = Me.Height / LegendPlateRatio
Else
Me.Height = Me.Width * LegendPlateRatio
End If
Else
If Me.Height / Me.Width > LegendPlateRatio Then
Me.Height = Me.Width * LegendPlateRatio
Else
Me.Width = Me.Height / LegendPlateRatio
End If
End If
LastWidth = Me.Width
LastHeight = Me.Height
RefreshImage()
End Sub
Private Sub RefreshImage()
Dim WidthRatio As Single = CSng(Me.Width) / CSng(My.Resources.screw1.Width)
Dim HeightRatio As Single = CSng(Me.Height) / CSng(My.Resources.screw1.Height)
If WidthRatio < HeightRatio Then
ImageRatio = WidthRatio
Else
ImageRatio = HeightRatio
End If
'****************************************************************
' Scale the gauge image so it will draw faster in Paint event
'****************************************************************
' Make a bitmap for the result.
If StaticImage IsNot Nothing Then StaticImage.Dispose()
StaticImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio), CInt(My.Resources.screw1.Height * ImageRatio))
' Make a Graphics object for the result Bitmap.
Dim gr_dest As Graphics = Graphics.FromImage(StaticImage)
m.Reset()
m.Scale(ImageRatio * 1.25, ImageRatio * 1.25)
gr_dest.Transform = m
' Copy the source image into the destination bitmap.
gr_dest.DrawImage(My.Resources.screw1, 0, 0)
TextRect.X = 5
TextRect.Width = StaticImage.Width / 1.25 / ImageRatio - 10
TextRect.Y = 5
TextRect.Height = StaticImage.Height / 1.25 / ImageRatio * 0.33
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
'gr_dest.DrawRectangle(Pens.Black, TextRect)
Dim b As New SolidBrush(Color.FromArgb(250, 130, 140, 160))
gr_dest.DrawString(m_LegendText, New Font("Arial", 22, FontStyle.Regular, GraphicsUnit.Point), b, TextRect, sf)
Dim x() As Int16 = {My.Resources.screw1.Width, My.Resources.screw2.Width}
Select Case m_ButtonColor
Case ButtonColors.Red
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
Case Else
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
End Select
gr_dest = Graphics.FromImage(LightOffImage)
Dim gr_dest2 As Graphics = Graphics.FromImage(LightOnImage)
m.Reset()
m.Scale(ImageRatio * 1.25, ImageRatio * 1.25)
gr_dest.Transform = m
gr_dest2.Transform = m
Select Case m_ButtonColor
Case ButtonColors.Red
gr_dest.DrawImage(My.Resources.screw1, 0, 0)
gr_dest2.DrawImage(My.Resources.screw1, 0, 0)
Case Else
gr_dest.DrawImage(My.Resources.screw2, 0, 0)
gr_dest2.DrawImage(My.Resources.screw2, 0, 0)
End Select
ButtonImage = LightOffImage
'* Perform some cleanup
gr_dest.Dispose()
gr_dest2.Dispose()
'* Create a new resized backbuffer for double buffering
If _backBuffer IsNot Nothing Then _backBuffer.Dispose()
_backBuffer = New Bitmap(Me.Width, Me.Height)
End Sub
End Class
The error is : Failed to create component 'Screw'/ the error message follows: 'System.NullReferenceException: Object reference not set to an instance of an object. at AdvancedHMI.Screw…ctor() in blah blah Screw.vb:line 292
Any ideas?
Thanks
I copy and pasted your code, created a couple generic graphics to represent screw1 and 2. I then added a screw and a windows button to the MainForm. I added code to toggle screw1.value everytime I clicked the button. It's working here on my computer with no problems. What is the code that you have on line 292?
That's it. I gave it to you. :) Line 292 starts the SetupDelay event timer
code there be a size requirement for the images?
And by the way, I'm using VB express 2010
I'm testing on Visual Studio 2008, so there may be some difference. Try these couple code changes:
Private WithEvents SetupDelay As Timer
Private Sub Meter_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.DesignMode Then
If m_CommComponent IsNot Nothing AndAlso m_PLCaddress.Length > 0 Then
SetupDelay = New Timer
AddHandler SetupDelay.Tick, AddressOf Timer1_Tick
SetupDelay.Enabled = True
End If
End If
End Sub
Private NotificationID As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
changes the error line to 199, but that's it.
It seems like there is a trend here with the timers. Comment out every reference to the tmrError because it is not used anyway in this component.
I'll give it a shot, but I think I tried that. Yes I did. lol now the error is at line 138
comment that out and it's at 108, which is kinda important.
ok, I created a copy of the pilot light again, built the project and tested it. Put the new control on the form, no problem. Went into the code, and changed JUST THIS: Private LegendPlateRatio As Single = My.Resources.screw1.Height / My.Resources.screw1.Width
which is line 343, the first place I ran into reference to the original graphics. saved it, rebuilt and I get the error. (at line 292)
I put the original graphic back in, saved and rebuilt and it's fine again. Must be something to do with the way I added those images to the project, don't you think?
I am in the process of Installing VB Express 2010 to test things.
Are you adding the graphic files using the Resources tab in the project properties? What format is your graphics file?
I added the graphics files by 1)right click the resources folder in solution explorer, add, then existing and picking the graphic. After that, I had to also add (via copy and past) them to the Resources.Designer.vb file. The graphic is .png
The method I use is to go to the project properties by right clicking the project name in the Solution Explorer. Then select the resources tab. You can then drop down the Add Resources and select Existing File.
That way you do not have to modify the designer file. VB tends not to like the Designer files modified manually.
I was looking at that, as there was an unexpected space bwt obj,System.Drawing.Bitmap that isn't with the original components. I couldn't make it go away either. So, I started poking around in the project folder and found Resources.resx, which I added to the resources folder and got this whole new screen which I'm sure you saw before.:) Using your method, that is the same screen that comes up to add resources. That screen didn't contain my .png files, which would explain the error. I'm going to try it, but I think that was the problem.
Well, looks like I need to start over. Building the project after all my screwing around throws off error after error. LOL I guess I'll delete it and start from scratch in the AM. Thanks for your help!
Hope that resolves the issue. Let me know how it works out.
Sooooo, No more error but now the images won't display right. I'm seeing both images in the containing image. I did manage to get one to go away, but was still having problems with scaling. How do you determine the values used here:
Private _backBuffer As Bitmap
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If StaticImage Is Nothing Or _backBuffer Is Nothing Then Exit Sub
Dim g As Graphics = Graphics.FromImage(_backBuffer)
g.DrawImage(StaticImage, 0, 0)
g.DrawImage(ButtonImage, CInt((StaticImage.Width / 2 - ButtonImage.Width / 2)), CInt(StaticImage.Height * 0.43))
'Copy the back buffer to the screen
e.Graphics.DrawImage(_backBuffer, 0, 0)
End Sub
I notice they are different on the components I looked at.
Thanks,
Mike
The best thing to do is to use PNG format and save them at 96DPI. My first components I built used 72DPI and I had to put in 1.25 scale factors. I later learned that 72 is the Apple way of doing things and 96 is Windows.
Look in the code where it creates the static images. I think it is the last subroutine.
I saved it at 96 dpi but it's still clipping the bottom and right sides of the image.
That is caused by this:
Select Case m_ButtonColor
Case ButtonColors.Red
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
Case Else
LightOffImage = New Bitmap(CInt(My.Resources.screw1.Width * ImageRatio * 0.8), CInt(My.Resources.screw1.Height * ImageRatio * 0.8))
LightOnImage = New Bitmap(CInt(My.Resources.screw2.Width * ImageRatio * 0.8), CInt(My.Resources.screw2.Height * ImageRatio * 0.8))
End Select
right?
Thanks,
Mike
The original buttons are 72DPI, so there is a 1.25 scale factor. If you are using the 96, remove this 1.25 in this line:
m.Scale(ImageRatio * 1.25, ImageRatio * 1.25)
That took care of the clipping! Now the image won't scale with the box though. LOL I'll start over and just comment that line.