Faberc blog website

 Sunday, October 28, 2007

A peer to peer voice/text chat.

http://TalkTogether.faberc.com
10/28/2007 7:43:38 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, March 04, 2006

Usually you move the window tracking the caption bar. To move the window within any client area you need to a bit of subclassing:

Private Const WM_NCHITTEST As Integer = &H84
Private Const WM_ACTIVATEAPP As Integer = &H1C
Private Const HTCAPTION As Integer = 2
Private Const HTCLIENT As Integer = 1

Protected Overrides Sub WndProc(ByRef m As Message)
  ' let the base form process this message
  MyBase.WndProc(m)

  Select Case m.Msg
       Case WM_NCHITTEST
            ' if on client area, make Windows believe it's on caption
            If m.Result.ToInt32 = HTCLIENT Then
              ' the only way to assing an IntPtr
              m.Result = New IntPtr(HTCAPTION)
            End If
  End Select
End Sub

3/4/2006 3:05:42 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, February 18, 2006

We can embedded a resource, like a txt file, forcing the property Build Action=Embedded Resource.

To access programmatically a text file called foo.txt from inside an Assembly whose default namespace is WindowApplication1 you need to write this code:

Dim resFile as String = "WindowApplication1.foo.txt"
'Get a reference to the current assembly
Dim asm as Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
Dim str as Stream = asm.GetManifestResourceStream(resFile)
Dim reader as New StreamReader(str)
Dim txt as string = reader.ReadToEnd()
reader.close

For a bitmap, sample.bmp, the code should be:

Dim resFile as String = "WindowApplication1.sample.bmp"
'Get a reference to the current assembly
Dim asm as Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
Dim str as Stream = asm.GetManifestResourceStream(resFile)
Dim bmp as New Bitmap(str)

2/18/2006 6:27:06 PM (W. Europe Standard Time, UTC+01:00)
 Tuesday, January 03, 2006

Explicitally setting the main procedure to start-up the Application you can have two important features:
- to enable the XP visual styles
- to set unique handlers for any uncatched exception without (or before) to abort the Application
  (these can be defined also in the form.load event of main form)

This is an example:

Module MainModule
  <STAThread()> _
  Sub main()
      Application.EnableVisualStyles() 'the controls need to be set with FlatStyle=System
      Application.DoEvents()

      ''install the global event handler for uncatched exceptions
      AddHandler Application.ThreadException, AddressOf (CallbackApplicationErrProc)      

      AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf (CallbackErrProc) 


      Application.Run(New Form1)
  End Sub

  Sub CallbackApplicationErrProc(sender As Object, e As ThreadExceptionEventArgs)
  Dim ex as Exception = e.Exception
      ''log the error and show user friendly msgbox or
      ''use Application.Exit to quit it!

  End Sub 

 Sub CallbackAppDomainErrProc(sender As Object, e As System.UnhandledExceptionEventArgs)
  Dim ex as Exception = e.ExceptionObject
      ''log the error and show user friendly msgbox or
      ''use Application.Exit to quit it!

  End Sub

End Module

Usefull link: http://blogs.msdn.com/winformsue/archive/2006/02/08/527941.aspx

1/3/2006 12:25:00 PM (W. Europe Standard Time, UTC+01:00)
 Sunday, December 11, 2005

To avoid sneaky errors when running your Application in Machine with a different default culture-specific information,
it is good practice to force explicitally the used culture:

Imports System.Globalization

....
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
....

The culture is used parsing numerical strings, working with currency calculations, manipulating dates, and so on.

12/11/2005 12:05:55 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, December 10, 2005

Tired to have terminated your Application after an axception you can using a simple statment to catch
all exception of Application without automatically abort it:

AddHandler Application.ThreadException, addressOf MyGlobalErrProc


Sub MyGlobalErrProc(sender as Object, e as ThreadExceptionEventArgs)
  Dim ex as Exception = e.Exception
  ''my error management

end Sub

Now to terminate the Application you need explicitally to call Application.Exit.
It is important to call AddHandler before to open any forms [Application.Run(..)]
so the correct place is the Sub Main() subroutine :

<STAThread()>
Sub Main()
    ''''''''force XP styles'''''''''
    Application.EnableVisualStyles()
    Application.DoEvents()
    ''''''''''''''''''''''''''''''''

    AddHandler Application.ThreadException, addressOf MyGlobalErrProc
    Application.Run(new MainForm)
End Sub

12/10/2005 5:28:10 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, November 19, 2005

Sometimes you could loop in a method waiting for an external event using Application.DoEvents().
So you exposure yourself to a recursive reentering in that method. One simple solution is to define a private boolean field
to check/set/reset in the your methods. But if there are more than one method in that situation you need to duplicate the field
for each one. So a most practical solution is using a unique shared function that takes advantage of reflection.

Private Function IsRecursive() As Boolean
  Dim st As New StackTrace
  Dim i As Integer
  Debug.WriteLine(st.GetFrame(0).GetMethod()) ''boolean IsRecursive()
  Debug.WriteLine(st.GetFrame(1).GetMethod()) ''Void Button1_Click(System.Object,System.EventArgs)
  For i = 2 To st.FrameCount - 1
    Debug.WriteLine(st.GetFrame(i).GetMethod()) ''current stack callings
    If (st.GetFrame(1).GetMethod() Is st.GetFrame(i).GetMethod()) Then Return true
  Next i
  Return False
End Function

This function return TRUE if there are more callings of the method, st.GetFrame(1).GetMethod(), which is using it.
For example:


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles   Button1.Click
  Debug.WriteLine("enter")
  '''''''''''''''''''''''''''''''''''
  If (IsRecursive()) Then Exit Sub
  '''''''''''''''''''''''''''''''''''
  Application.DoEvents()
  ''simulation of a waiting for an event
  System.Threading.Thread.Sleep(1000)
  Debug.WriteLine("exit")
End Sub

Clicking more times the button1 you have:


without IsRecursive() check:
enter
enter
enter
enter
exit
exit
exit
exit
with IsRecursive() check:
enter
enter  ''skipped because the first calling is in progress
enter  ''skipped because the first calling is in progress
enter  ''skipped because the first calling is in progress
exit   ''close the first calling!

11/19/2005 4:39:18 PM (W. Europe Standard Time, UTC+01:00)

A thread can suspend itself temporarily by using the Thread.Sleep shared method which takes a timeout in milliseconds:

''Pause for two seconds
Thread.Sleep(2000)

The Sleep methods works only in the current thread. Using this method is similar to calling the Sleep Windows API function.

11/19/2005 4:30:39 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, October 22, 2005

To have a unique single instance of your Application you need to use a mutex in this way:

Private Shared Function PrevInstance() As Boolean
    Dim IsNewMutex As Boolean
    Dim MutexKey As String
    ''try to create a unique mutex (it has a machine wide scope) associated to my Application
    MutexKey = Application.UserAppDataPath.Replace("\", "_")
    Dim mt As New Mutex(True, MutexKey, IsNewMutex)
    PrevInstance = Not IsNewMutex
End Function


Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
   If PrevInstance() = True Then End  ''if I'm already running then quit
End Sub

It's enough to check PrevInstance() function in the load form event.

10/22/2005 6:48:00 PM (W. Europe Standard Time, UTC+01:00)
 Sunday, October 16, 2005

Sometimes with need to have a unique instance of form to interact with it from any other forms. The solution is using the pattern Singleton:

Public Class Form2
    Inherits System.Windows.Forms.Form

    Private Shared thisInstance As Form2
    Public Shared ReadOnly Property Instance() As Form2
        Get
            If (thisInstance Is Nothing OrElse thisInstance.IsDisposed) Then
                thisInstance = New Form2
                Return thisInstance
            Else
                Return thisInstance
            End If

        End Get
    End Property

End Class

The solution is the keyword shared for a unique variable instance and relative property that returns the current or make a new one.

Now you can call the form2 in this way, for example:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Form2.Instance.Show()
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Form2.Instance.TextBox1.Text = TextBox1.Text
End Sub

10/16/2005 2:44:12 PM (W. Europe Standard Time, UTC+01:00)
 Saturday, October 15, 2005

You need to extend the System.Web.Mail.MailMessage class setting .flags (for framework 1.1 or higher) as follow:

Imports System.Web.Mail.MailMessage
Public Class email
   Inherits Mail.MailMessage
   Public Sub New()
     MyBase.New()
   End Sub
   Public WriteOnly Property AuthInfo() As UserInfo
    Set(ByVal value As UserInfo)
       ''auth: 0=none, 1=Basic, 2=NTLM
       Me.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
       Me.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = value.UserName
       Me.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = value.Password
    End Set
   End Property
End Class
Public Class UserInfo
    Public UserName As String
    Public Password As String
    Public Sub New(ByVal user As String, ByVal pass As String)
       UserName = user
       Password = pass
    End Sub
End Class

Usage:

Dim m As New email
m.AuthInfo = New UserInfo("user", "password")
m.Body = "Hello to le monde!"
m.From = "user@server4.com"
m.To = "mickymouse@server4.com"
m.Subject = "test"
SmtpMail.SmtpServer = "mail.server4.com"
SmtpMail.Send(m)

email.zip (,48 KB)
ASPNET | DOTNET | VBNET
10/15/2005 11:14:53 AM (W. Europe Standard Time, UTC+01:00)
 Tuesday, July 19, 2005

When you need to make a long task, as calling remote WS, the best way to do not hang the client is using a thread in background and to be notified at the end of result.

With windows form application(main thread) you cannot update the form's control from the thread because it is a secondary thread.

It's important to make a thread safe programming using delegate and InvokeRequired/Control.Invoke methodology.

Eg.(c#):

//delegate per safe Progress bar invocation

private delegate void InvokeWithParam(int value); //the delegate signature need to be the same of method to call
public void UpdateProgressSafeParam(int value)
{
  if (progress1.InvokeRequired) // this routine is calling from a main or secondary thread?
  {
   InvokeWithParam safeMethod=new InvokeWithParam(UpdateProgressSafeParam);
   object[] par=new object [](value);
   progressbar1.Invoke(safeMethod,par); // force the UpdateProgressSafeParam() function [recursion]
   // to run in the same thread of the control(main).
   //So will go in a queue to be recall from the main thread and in that situation it fall down in the else branch!
  }
 else progressbar1.value=value; //I'm in main thread so can update the progressbar control directly!
}

Eg.(VBNET) working with the main form(me.invoke) instead of a control:

delegate Function GetTextDelegate(ByVal ctrl as Control) as String

'This method might run on a non-UI thread (eg: in a timer event of one instance of System.Timers.Timer)
Sub PerformTask()
  'read the Text property of txtUserName UI control
  Dim userName as String
  if Not Me.InvokeRequired then
    userName = GetText(txtUserName) 'direct access is safe
  else
    ' Call the method indirectly by using a delegate
    Dim args() as Object = {txtUserName}  ''the parameters are passed as an array of objects
    userName = CStr(Me.Invoke(New GetTextDelegate(GetText), args))
  end if
  ' userName now contains the value of txtUserName.Text
  ...
  ...
End Sub

Function GetText(ByVal ctrl as Control) As String
   Return ctrl.Text
End Function

7/19/2005 11:32:19 AM (W. Europe Standard Time, UTC+01:00)
 Saturday, June 18, 2005

Are similar to And and Or but the second espresssion could be skipped from evaluation if the first param is sufficient to resolve the total expression.

So these new operators have a better performance of old operators. 

6/18/2005 11:28:56 AM (W. Europe Standard Time, UTC+01:00)