Displaying info in status bar of main form

G

Guest

I have a Mainform with a Statusbar. When opening another form or doing some
processing I want to display info in the Statusbar of the Mainform. I have
read a lot of articles on this & have come up with the code below. It seems
to work(!!!) in that when coding the second form I can see the
DisplayStatusMsg of the main form. During debug the code runs through &
seemingly executes the call without error. But!...The message is not
displayed. What have I missed or am I on the wrong tram?
Thanks
Terry

At the top of the class code I have:
Public Class Mainform : Inherits Form
Private Shared myInstance As Mainform

Public Shared Function GetInstance() As Mainform
If myInstance Is Nothing Then
myInstance = New Mainform
End If
Return myInstance
End Function

Public Shared Function DisplayStatusMsg(ByVal Msg As String, Optional
ByVal iSecs As Integer = 1000)

myInstance.statPanelMsg.Text = Msg
myInstance.Timer1.Interval = iSecs
End Function

I am calling the sub from a second form using:
Dim frm As frmMain = frmMain.GetInstance
frm.DisplayStatusMsg("Loading Requests: Main...", 9000)
 
J

Joergen Bech

You may be looking at AN instance of MainForm, but
not THE instance you want. If you put a breakpoint in
the form's constructor I'm sure you will find that you are
creating two instances: One when creating the form for
display, and another the first time you try to access the
shared instance. They live happy, separate lives,
oblivious to the existence of each other.

If you are using VB2005 you can already make use of a
shared instance, provided you only show one instance
of MainForm.

If, say, you add a Windows Form named Form2 to your
project, you can execute the following two lines without
any "Dim f As New Form2" stuff:

Form2.Show()
Form2.Text = "Hello, world"

It was something they did, I suppose, to appease those
VB6 developers who were used to having one default global
instance of whatever form was in their project.

If you look at the code above in Reflector, you will see
that a shared Form2 member is found in

<...>.My.MyProject.MyForms.

When accessing Form2 "directly" (without Dim f as Form2 etc)
you go through a Form2 property that looks like this:

---snip---
Public Property Form2 As Form2
Get
Me.m_Form2 = MyForms.Create__Instance__(Of
Form2)(Me.m_Form2)
Return Me.m_Form2
End Get
Set(ByVal Value As Form2)
If (Not Value Is Me.m_Form2) Then
If (Not Value Is Nothing) Then
Throw New ArgumentException("Property can only
be set to Nothing")
End If
Me.Dispose__Instance__(Of Form2)(Me.m_Form2)
End If
End Set
End Property
---snip---

Can you see the difference between this and your approach?

If you are using VS2002/VS2003 you might want to copy the
VS2005 approach above. If using VS2005, just use the built-in
support for those singleton form objects.

Hope this helps,

Joergen Bech
 
G

Guest

Thanks Joergen
I am TOTALLY lost on Instances. I am using VB 2003. I understand that I may
be using two instances (not sure why). What is Reflector? frmMain is a MDI
form and will only ever exist in a single instance (at least I think so as
there is nothing to stop the user starting it all over - don't know what
happens then). I am also tracking what forms (MDI Children) are open so that
each form can be opened only once.

In the line:
MyForms.Create__Instance__(Of frmMain)(Me.frmMain)

MyForms appears to be unknown. Should I be declaring or inheriting something?
..Create_Instance_(Of frmMain) Is this .Create(Me.frmMain)
(As MyForms is not defined I an not sure where to go with the Create)

The Dispose line is also unintelligible to me
Me.Dispose__Instance__(Of frmmain)(Me.frmmain)

I apologise for my total lack of understanding but I have been thrown in the
deep end. The books I have do not really cover this & the references I have
found on Google do not work (at least I cannot get them to work).
Terry
 
J

Joergen Bech

..Net Reflector is a tool for decompiling .Net assemblies, provided
they have not been obfuscated. This allows you to look at the
source code for the classes in the .Net Framework (and in other
assemblies, such as your own or 3rd-party controls) so you can
study what is going on with those commands you are issuing.

It's freeware and can be downloaded from
http://www.aisto.com/roeder/dotnet/

As for MyForms: It's only available in VS2005. I was merely
copy/pasting a chunk of the code to give you a general idea
of how it could be done. You cannot do anything with that code
in VS2003.

Basically, it boils down to this:

Create a global m_FormMain variable. Set a reference to this
variable when your one and only FormMain form is created and
displayd. Whenever another form wishes to display status information,
they should access your FormMain instance through this variable.
If the variable is Nothing, don't do anything with it, as this would
mean that the one and only FormMain instance has not been
created yet. For the same reason, make sure that m_FormMain
is set to nothing as soon as the FormMain instance is closed and
no longer available to service the other forms.

Hope that clears some of it up.

/Jorgen Bech
 
G

Guest

OK. I have created a global variable gfrmMain. However, how do you access the
Sub/Function in frmMain. In the Load event of frmMain I gfrmMain=frmMain. I
have a Public Sub DispStatMsg in frmMain. This does not expose
gfrmMain.DispStatMsg. A reference to gfrmMain.DispStatMsg causes a compile
error and does not display the message. I had tried this & re-did it to check
Terry
 
J

Joergen Bech

OK. I have created a global variable gfrmMain. However, how do you access the
Sub/Function in frmMain. In the Load event of frmMain I gfrmMain=frmMain. I
have a Public Sub DispStatMsg in frmMain. This does not expose
gfrmMain.DispStatMsg. A reference to gfrmMain.DispStatMsg causes a compile
error and does not display the message. I had tried this & re-did it to check
Terry

Here is a complete (quick'n'dirty) sample. Most of it
is just generated by the wizard.

Set Sub Main or frmMain as the startup object.

Your original code could probably be fixed to work so
gfrmMain would be a shared member of the FormMain
class, but I am not sure it makes any sense to have a
shared member or function of a class that will only exist
in a single instance.

/JB



---Module1.vb ---

Module Module1
Public gfrmMain As frmMain

Public Sub DisplayStatusMessage(ByVal message As String)
If Not gfrmMain Is Nothing Then
gfrmMain.StatusBarPanel1.Text = message
End If
End Sub

Public Sub main()
Dim frm As New frmMain
Application.Run(frm)
End Sub
End Module



--- frmMain.vb ---

Public Class frmMain
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents StatusBar1 As System.Windows.Forms.StatusBar
Friend WithEvents StatusBarPanel1 As
System.Windows.Forms.StatusBarPanel
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.StatusBar1 = New System.Windows.Forms.StatusBar
Me.StatusBarPanel1 = New System.Windows.Forms.StatusBarPanel
CType(Me.StatusBarPanel1,
System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'StatusBar1
'
Me.StatusBar1.Location = New System.Drawing.Point(0, 251)
Me.StatusBar1.Name = "StatusBar1"
Me.StatusBar1.Panels.AddRange(New
System.Windows.Forms.StatusBarPanel() {Me.StatusBarPanel1})
Me.StatusBar1.ShowPanels = True
Me.StatusBar1.Size = New System.Drawing.Size(292, 22)
Me.StatusBar1.TabIndex = 0
Me.StatusBar1.Text = "StatusBar1"
'
'StatusBarPanel1
'
Me.StatusBarPanel1.AutoSize =
System.Windows.Forms.StatusBarPanelAutoSize.Spring
Me.StatusBarPanel1.Width = 276
'
'frmMain
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.StatusBar1)
Me.Name = "frmMain"
Me.Text = "frmMain"
CType(Me.StatusBarPanel1,
System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
gfrmMain = Me

Dim frm2 As New Form2
frm2.Owner = Me
frm2.Show()

Dim frm3 As New Form3
frm3.Owner = Me
frm3.Show()

End Sub

Private Sub frmMain_Closing(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
'Note: I chose the _Closing event rather than the
' _Closed or _HandleDestroyed ones, as the
' form is still alive at _Closing time and
' the statusbar therefore still accessible.
gfrmMain = Nothing
End Sub
End Class



--- Form2.vb ---

Public Class Form2
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(32, 24)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form2
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.Button1)
Me.Name = "Form2"
Me.Text = "Form2"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click
DisplayStatusMessage("Message from Form2")
End Sub
End Class



--- Form3.vb ---

Public Class Form3
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(16, 24)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form3
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.Button1)
Me.Name = "Form3"
Me.Text = "Form3"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click
DisplayStatusMessage("Message from Form3")
End Sub
End Class
 
G

Guest

Thank you very much for your help. You have been patient & most helpful.

As you may have gathered this is my first attempt at VB .Net & I must say it
is somewhat convoluted. What used to be done in one line now requires scores
of lines. I am yet to be convinced that it is worth it. VB .Net requires
significantly more work to accomplish the same thing. I would normally knock
this job out in 3-5 working days but, using VB .Net it will take
significantly longer. It may be purer but....
Terry
 
G

Guest

Works a treat AND I understand what is happening. Didn't think that would
happen
Thanks again
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top