Accessing a class function?
Accessing a class function?
Accessing a class function?
Accessing a class function?
Accessing a class function?
Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function?
Accessing a class function? Accessing a class function?
Accessing a class function?
Go Back  Xtreme Visual Basic Talk > > > Accessing a class function?


Reply
 
Thread Tools Display Modes
  #1  
Old 10-28-2008, 01:14 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default Accessing a class function?


Hi,

I am working on this project and this question seems to be stupid, but I am not really getting the point.

I have the following class:

Code:
Public Class ConnectedServer

    Public MYPORT As String = "8000"

    Public mySubscriptions(0) As String

    Public MyServer As System.Net.Sockets.TcpClient
    Public Const BYTES_TO_READ As Integer = 255
    Public readBuffer(BYTES_TO_READ) As Byte
    Public Delegate Sub WriteText(ByVal text As String)

    Public Sub New()
    End Sub

    Public Sub New(ByVal serverip As String)
        ConnectMe(serverip)
    End Sub

    Public Sub ConnectMe(ByVal ServerIP As String)
        Dim str(2) As String
        Dim itm As ListViewItem
        Try
            MyServer = New System.Net.Sockets.TcpClient(ServerIP, MYPORT)
            MyServer.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf DoRead, Nothing)
            ForwardMessage("/CONNECT|" & frmMainClient.txtUsername.Text)
            str(1) = "Connected!"
        Catch ex As Exception
            MsgBox(ex.ToString)
            str(1) = "Failed..."
        End Try
        itm = New ListViewItem(str)
        frmMainClient.lstconnections.Items.Add(itm)
    End Sub

    Public Sub DoRead(ByVal ar As System.IAsyncResult)
        Dim totalRead As Integer
        Try
            totalRead = MyServer.GetStream.EndRead(ar) 'Ends the reading and returns the number of bytes read.
        Catch ex As Exception
            'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections            'to this client and remove it from the list of connected clients.
        End Try
        If totalRead > 0 Then
            'the readBuffer array will contain everything read from the client
            Dim receivedString As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, totalRead)
            MessageReceived(receivedString)
        End If
        Try
            MyServer.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf DoRead, Nothing) 'Begin the reading again.
        Catch ex As Exception
            'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections                'to this client and remove it from the list of connected clients.
        End Try
    End Sub

    Public Sub MessageReceived(ByVal message As String)
        Select Case message
            Case "/Connected"
                'ConnectionStatus("Client : Connected")
            Case Else
                WriteToMainText(message & vbCrLf)
        End Select

    End Sub

    Public Sub WriteToMainText(ByVal Message As String)
        If frmMainClient.txtMain.InvokeRequired Then
            frmMainClient.Invoke(New WriteText(AddressOf WriteToMainText), Message)
        Else
            frmMainClient.txtMain.AppendText(Message)
            frmMainClient.txtMain.SelectionStart = frmMainClient.txtMain.Text.Length
        End If
    End Sub

    Public Sub ForwardMessage(ByVal Msg As String)
        Dim sw As IO.StreamWriter
        Try
            sw = New IO.StreamWriter(MyServer.GetStream)
            sw.Write(Msg)
            sw.Flush()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    Public Sub SendMessage(ByVal msg As String)
        ForwardMessage(frmMainClient.txtUsername.Text & ": " & msg)
    End Sub

    Public Sub DisconnectMe()
        ForwardMessage("/DISCONNECT|" & frmMainClient.txtUsername.Text)
    End Sub

End Class
And the following form:

Code:
Public Class frmMainClient
    Dim connServer As New ConnectedServer()

    Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
        Dim connServer As New ConnectedServer("192.168.0.159")
    End Sub

    Private Function GetMyIP() As String
        Dim strHostName As String
        Dim strIPAddress As String
        strHostName = System.Net.Dns.GetHostName()
        strIPAddress = System.Net.Dns.GetHostEntry(strHostName).AddressList(0).ToString()
        Return strIPAddress
    End Function

    Private Sub frmMainClient_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Text = GetMyIP()
    End Sub

    Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
        connServer.DisconnectMe()
    End Sub

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        connServer.SendMessage(txtSend.Text)
    End Sub
End Class
Every time I type a different username in the txtUsername field and click the btnConnect button, it instanciates a new ConnectedServer and create a new connection with the server (in the future, when it is working fine I will enter IP too as the idea is allow a single client to connect to multiple servers).

Ok, my question is about how to access a function within the class from the form. For instances, to send a message to the server I have the button btnSend that should send the message typed in the txtSend field.

The problem is that when I click the btnSend button I get the message:
Object reference not set to an instance of an object
Reply With Quote
  #2  
Old 10-28-2008, 02:02 PM
Roger_Wgnr's Avatar
Roger_Wgnr Roger_Wgnr is offline
CodeASaurus Hex

Forum Leader
* Expert *
 
Join Date: Jul 2006
Location: San Antonio TX
Posts: 2,427
Default

Have not worked with this myself but I think your problem is in this part of the code
Code:
Public Class frmMainClient Dim connServer As New ConnectedServer() Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click Dim connServer As New ConnectedServer("192.168.0.159") End Sub
You create a New ConnectedServer within the button event. This instance is not available outside of the button click event Since you define a new instance within the class you just need to set the instance in the button click event.
Code:
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click connServer = ConnectedServer("192.168.0.159") End Sub
I think this will correct the issue.
__________________
Code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. ~Martin Golding
The user is a peripheral that types when you issue a read request. ~Peter Williams
MSDN Visual Basic .NET General FAQ
Reply With Quote
  #3  
Old 10-28-2008, 02:20 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

Hi Roger,

Thank you!

However I figured this out, just by creating an array to hold the multiple connections, like this:

Code:
Public Class frmMainClient
    Private aConnections(0) As ConnectedServer

    Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
        aConnections(0) = New ConnectedServer("192.168.0.159")
    End Sub
Now it is just to get on track through the array with a pointer.

However, I am experiencing another funny issue. When the server sends a message to the client, the client IS RECEIVING the message (I tested it with breakpoint), and it is calling the proper functions, but the message is not being displayed in the txtMain textbox!

Look at this portion of code:

Code:
    Public Sub DoRead(ByVal ar As System.IAsyncResult)
        Dim totalRead As Integer
        Try
            totalRead = MyServer.GetStream.EndRead(ar) 'Ends the reading and returns the number of bytes read.
        Catch ex As Exception
            'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections            'to this client and remove it from the list of connected clients.
        End Try
        If totalRead > 0 Then
            'the readBuffer array will contain everything read from the client
            Dim receivedString As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, totalRead)
            WriteToMainText(receivedString)
        End If
        Try
            MyServer.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf DoRead, Nothing) 'Begin the reading again.
        Catch ex As Exception
            'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections                'to this client and remove it from the list of connected clients.
        End Try
    End Sub

    Public Sub WriteToMainText(ByVal Message As String)
        If frmMainClient.txtMain.InvokeRequired Then
            frmMainClient.Invoke(New WriteText(AddressOf WriteToMainText), Message)
        Else
            frmMainClient.txtMain.AppendText(Message)
            frmMainClient.txtMain.SelectionStart = frmMainClient.txtMain.Text.Length
        End If
    End Sub
The WriteToMainText function is processing fine, and the message IS THERE but it just doesnt output in the form.

Any idea?

Thanks!
Reply With Quote
  #4  
Old 10-28-2008, 03:21 PM
Roger_Wgnr's Avatar
Roger_Wgnr Roger_Wgnr is offline
CodeASaurus Hex

Forum Leader
* Expert *
 
Join Date: Jul 2006
Location: San Antonio TX
Posts: 2,427
Default

Try adding a frmMainClient.txtMain.Refresh() I often find I need to refresh a control to see the updated data.
__________________
Code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. ~Martin Golding
The user is a peripheral that types when you issue a read request. ~Peter Williams
MSDN Visual Basic .NET General FAQ
Reply With Quote
  #5  
Old 10-29-2008, 11:40 AM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

Roger,

Refresh didnt work.



I thought that the problem could be the delegate, then I did that:

Code:
    Public Sub WriteToMainText(ByVal Message As String)
        If frmMainClient.txtMain.InvokeRequired Then
            MsgBox(1)
            frmMainClient.Invoke(New WriteText(AddressOf WriteToMainText), Message)
        Else
            MsgBox(2)
            frmMainClient.txtMain.AppendText(Message + vbCrLf)
            frmMainClient.txtMain.SelectionStart = frmMainClient.txtMain.Text.Length
        End If
        frmMainClient.Refresh()
        frmMainClient.txtMain.Refresh()
        MsgBox(Message)
    End Sub
It splashes me "2" (delegate is not being invoked) and splashes the message, but the message simply doesnt appear in the txtMain!

Reply With Quote
  #6  
Old 10-29-2008, 11:56 AM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

It is very odd. I traced the steps by breakpointing, and VB is executing every single line of code - the impression is that the txtMain control is simply being overrided.
Reply With Quote
  #7  
Old 10-29-2008, 01:45 PM
AtmaWeapon's Avatar
AtmaWeaponAccessing a class function? AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Let me go out on a limb and guess something.

frmMainClient, as referenced in your code samples, is not a variable of type frmMainClient. You are using the "default forms" feature of VB .NET, correct?

If this is the case, it's possible through several different scenarios that the form on your screen is not the form that frmMainClient refers to; this would be consistent with the variables being correct but the text box not updating: you are updating a text box on an invisible form.

One other insidious problem is if an exception is thrown on a worker thread it is usually sucked into a black hole instead of being reported. Since you say you're getting the final message box, it's likely that this isn't the case, but a debugger could reveal if this were happening.

There's an easy way to tell. Just modify WriteToMainText to do something readily visible to the form, and you'll know for certain if it's the right one. You really shouldn't be calling Refresh outside of the thread-protected method anyway. Here's an example that might shed some light:

Code:
Public Sub WriteToMainText(ByVal Message As String)
    If frmMainClient.txtMain.InvokeRequired Then
        MsgBox(1)
        frmMainClient.Invoke(New WriteText(AddressOf WriteToMainText), Message)
    Else
        MsgBox(2)
        frmMainClient.txtMain.AppendText(Message + vbCrLf)
        frmMainClient.txtMain.SelectionStart = frmMainClient.txtMain.Text.Length
        frmMainClient.Refresh()
        frmMainClient.txtMain.Refresh()
        
        ' Let's do some disruptive things
        frmMainClient.Show()
        frmMainClient.BackColor = Colors.Green
        frmMainClient.Text = "It worked already!
    End If

    MsgBox(Message)
End Sub
Now, one of two things will happen. If the form that you see turns green and has its caption text changed, I'm wrong and you're modifying the correct Form, though I strongly recommend turning away from this "feature" of VB. If I'm right, what you'll see happen is a second form appear, turn green, change caption text, and have the correct message in its text box. In this case, you will see why I recommend you turn away from this "feature" of VB.

If I'm right about this, we can discuss how to work with a better design that does a better job of decoupling classes and hiding implementation details. If I'm wrong, I'll take a closer look and try to figure out what's going on.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #8  
Old 10-29-2008, 04:11 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

Hey AW,

You got it right between the eyes - not exactly, but it doesnt matter, since it was enough to show that the problem is the "invisible form thing".

When the class received the message it launched a new form with the new caption - it just not turned to green (it became an unresponsive form and I needed to kill the task). But it doesnt matter, as it was just for testing.

However, for sure the fact is that VB is stuned and do not know where is my visible form - it is some kind of miscontroling of internal pointers? Anyway, do you have a guess about how to figure this out?

Thanks!
Reply With Quote
  #9  
Old 11-03-2008, 06:18 AM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

Any idea????
Reply With Quote
  #10  
Old 11-03-2008, 08:32 AM
AtmaWeapon's Avatar
AtmaWeaponAccessing a class function? AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Ahh... I missed that you had asked for some more information. Sadly, I'm in a hurry because my car is badly in need of service, but I can show you something quick before I have to go wake my wife up so she can bring me to work.

I'd like to point out early on that this "feature" of VB .NET is the most stupid of the brain-dead poor design features of VB6 that were vomited into VB .NET in 2005 because of equally stupid, brain-dead, dial-a-program "developers" that were too afraid to move from VB6 to VB .NET. They claimed they wouldn't move unless features like this were carried over. Microsoft fell for it and added the feature, then the VB6 developers laughed at them as they continued to ignore .NET because it's scary to change. Thanks a lot, VB6 developers. You just cost this guy a few days' work.

As a rule of thumb, to avoid this in the future, never ever create a variable with the same name as a form class. VB is not case-sensitive, and it's not always clear whether it's interpreting your variable as a variable or a default instance of a form. This means that you should never write code that looks like this:
Code:
Dim mainForm As MainForm
I believe that's a very appropriate name for the variable, but depending on its scope and whether it is instantiated at declaration, it can accidentally end up looking like MainForm to the compiler and refer to the default instance of the form. Don't like it? Find your closest VB6 holdout and smack them around a bit, they're the reason for this.

Somewhere in your program, you create the form that's on the screen, and you want to be able to interact with that form from other forms. However, in order to interact with that form, you need a reference to the form; think of this like mailing a letter to a friend: if you don't have their address you can't send the letter. I can think of two scenarios you might be in:

1: The form you want to modify is the main form.
In this case, your main form creates child forms, and the child forms want to alter the main form. The best way to do this is to give each child form a property that can hold a reference to the main form:
Code:
Private _mainForm As MainForm

Public Property MainForm As MainForm
   Get
         ' blah blah you know the rest
When the child form needs to do something to the main form, it can use this property:
Code:
MainForm.Text = "Child set this"
Now, when you create the child forms, make sure to set the reference:
Code:
Dim frm As New ChildForm()
frm.MainForm = Me
frm.Show()
2: The form you want to modify is a child form.

In this case, your main form creates the form you want to modify. This is very similar; make the property in your main form, set it when you create the child form, then use that property to work with the child form.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #11  
Old 11-03-2008, 12:30 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

AW,

I kind of got your point, but the fact is that I have not child forms! I just have a mainform (that I have called frmGUI) and the classes trying to reach it.

Actually, the form is not being able to reach itself!

If I do Me.Show() it just pops a new form!

Ahhhh! It is driving me crazy!
Reply With Quote
  #12  
Old 11-03-2008, 01:47 PM
AtmaWeapon's Avatar
AtmaWeaponAccessing a class function? AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

The technique is the same for classes; keep in mind that a form is just a class that derives from Form.

This is starting to sound like an application architecture problem. Are you using the built-in Application Framework, or have you defined your own Sub Main for starting the application? If you've defined your own, something's going wrong.

I just tried a basic application with nothing but a button that called Me.Show(); it didn't do what you describe. In fact, the behavior you describe shouldn't happen at all. I'm afraid I really can't help unless you can post a project that reproduces the behavior.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #13  
Old 11-04-2008, 12:26 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

Hi AW,

I have figured out the CLIENT application problem regarding to write to the main form!

I dont know if I mentioned before, but I have transformed the client code (that was in the form) into a class, so now I can have several concurrent connections with different servers, that is, the same client can connect to multiple servers. I suspect that every time I created a new connection instance, it was creating some kind of "phantom copy" of the main form attached to it - is that possible????. So whenever I was trying to access a control in the form, it wasnt reaching the "main" main form, but a hidden instance of it.

Anyway, I figured the problem out by just delegating it. So, when I instantiate the new connection, I just pass the main form reference as parameter, and, when necessary, the instance writes directly to it. Worked like a charm! Thumbs up!!!!

However, I am still haveing problem to convert the SERVER application that is in its form, into a class. A lot of problems are happening. Could you take a look in the code, and suggest me the best way to do that?

I am sending attached the original code (in the form) and the code that I have tried to convert into a class. The updated client code is going together.

Thanks for all!
Attached Files
File Type: zip client-server.zip (385.2 KB, 3 views)

Last edited by JustAGuy; 11-04-2008 at 01:54 PM.
Reply With Quote
  #14  
Old 11-05-2008, 12:34 PM
JustAGuy JustAGuy is offline
Centurion
 
Join Date: Jul 2003
Posts: 193
Default

The case is that it isnt managing properly the connected clients list.

Connect with an username and then disconnect it. Then reconnect with the same username again - you will see that it will not be removed from the list for the second time. It removes the username just the first time...
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Accessing a class function?
Accessing a class function?
Accessing a class function? Accessing a class function?
Accessing a class function?
Accessing a class function?
Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function? Accessing a class function?
Accessing a class function?
Accessing a class function?
 
Accessing a class function?
Accessing a class function?
 
-->