Показаны сообщения с ярлыком VB.Net. Показать все сообщения
Показаны сообщения с ярлыком VB.Net. Показать все сообщения

понедельник, 13 июня 2011 г.

VB.Net. Пересылка данных по локальной сети

Итак, в качестве примера пересылки данных по локальной сети сделаем простейший чат. В нашем случае будем пересылать текст в кодировке Юникод, но в общем случае это может быть любая последовательность байт. Пересылку организуем при помощи классов UdpClient и Socket из пространства имён System.Net.Sockets.

Отправляем данные мы при помощи функции SendTo(b, ep) экземпляра класса Socket, где b — массив байт (наши данные), а ep — конечная точка (экземпляр класса System.Net.IPEndPoint, для инициализации которого нужно знать IP-адрес и порт адресата).

При загрузке формы запускается таймер, в обработчике события Tick которого мы опрашиваем порт нашей машины, на который должны поступить ответные данные, и получаем их при помощи функции Receive(ep) экземпляра класса UdpClient.

IP-адрес 127.0.0.1 — это так называемая петля. Т.е. данные, отправленные на этот адрес, возвращаются нам.

Полный код формы приведён ниже:

Public Class Form1

    Private lport As Integer
    Private udpc As Net.Sockets.UdpClient
    Private soc As Net.Sockets.Socket
    Private sent As Boolean = False

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lport = 9999
        udpc = New Net.Sockets.UdpClient(lport)
        soc = New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Dgram, Net.Sockets.ProtocolType.Udp)
        If ComboBox1.Items.Count > 0 Then ComboBox1.SelectedIndex = 0
        TextBox2.Select()
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If udpc.Available > 0 Then
            Dim ep As New Net.IPEndPoint(Net.IPAddress.Any, lport)
            Dim b = udpc.Receive(ep)
            Dim txt = System.Text.Encoding.Unicode.GetString(b)
            TextBox1.Text &= String.Format("{0:HH:mm:ss} from [{1}]:{3}{2}{3}----------------------------{3}", Now, ep.ToString, txt, ControlChars.NewLine)
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If TextBox2.Text.Length > 0 AndAlso ComboBox1.Text.Length > 0 Then
            Dim b = System.Text.Encoding.Unicode.GetBytes(TextBox2.Text)
            Dim ipadr = Net.IPAddress.Parse("127.0.0.1")
            Net.IPAddress.TryParse(ComboBox1.Text, ipadr)
            Dim ep As New Net.IPEndPoint(ipadr, lport)
            soc.SendTo(b, ep)
            TextBox1.Text &= String.Format("{0:HH:mm:ss} Me (to [{1}]):{3}{2}{3}----------------------------{3}", Now, ep.ToString, TextBox2.Text, ControlChars.NewLine)
            TextBox2.Text = ""
            TextBox2.Select()
            If Not ComboBox1.Items.Contains(ComboBox1.Text) Then ComboBox1.Items.Add(ComboBox1.Text)
        End If
    End Sub

    Private Sub TextBox2_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox2.KeyDown
        If e.Control AndAlso e.KeyCode = Keys.Enter Then
            Button1_Click(Nothing, Nothing)
            sent = True
        End If
    End Sub

    Private Sub TextBox2_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged
        If sent Then
            TextBox2.Text = ""
            sent = False
        End If
    End Sub

    Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        TextBox1.SelectionStart = TextBox1.Text.Length - 1
        TextBox1.SelectionLength = 1
        TextBox1.ScrollToCaret()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Timer1.Stop()
        udpc.Close()
        soc.Close()
    End Sub
End Class

Архив с проектом Visual Studio:

NetTest.zip (105 КБ)

VB.Net. Как объявить массив

Одной строкой объявить и инициализировать массив можно так:

Dim arr = New ТипЭлементовМассива() {значение0, значение1, значение2 и т.д.}

Где это можно использовать? Ну, например, при задании первичного ключа для таблицы, который должен быть массивом колонок этой таблицы:

Dim dt As New DataTable
dt.Columns.Add("id", GetType(Integer))
dt.Columns.Add("name", GetType(String))
dt.Columns.Add("description", GetType(String))
dt.PrimaryKey = New DataColumn() {dt.Columns("id")}

пятница, 23 июля 2010 г.

VB.Net. Сравнение быстродействия операций

Приблизительно оценить время выполнения той или иной операции можно следующим образом:

Dim t As DateTime = Now
'некоторая операция 
Console.WriteLine((Now - t).ToString)

Причем, если операция выполняется быстро, имеет смысл поместить ее в цикл. В качестве примера, оценим разницу в быстродействии вариантов проверки пустой строки. Для пущего интересу, пусть строковая переменная будет пустая и непустая.

Dim s As String = "a"
Dim t As DateTime

Console.WriteLine("s = ""a""")

t = Now
For i = 0 To 99999999
    If s = "" Then s.ToString()
Next
Console.WriteLine("If s = """" Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s = String.Empty Then s.ToString()
Next
Console.WriteLine("If s = String.Empty Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s.Length = 0 Then s.ToString()
Next
Console.WriteLine("If s.Length = 0 Then --> " & (Now - t).ToString)

s = ""
Console.WriteLine("s = """"")

t = Now
For i = 0 To 99999999
    If s = "" Then s.ToString()
Next
Console.WriteLine("If s = """" Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s = String.Empty Then s.ToString()
Next
Console.WriteLine("If s = String.Empty Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s.Length = 0 Then s.ToString()
Next
Console.WriteLine("If s.Length = 0 Then --> " & (Now - t).ToString)

А вот и результаты испытаний, выведенные в консоль:

s = "a"
If s = "" Then --> 00:00:02.2656250
If s = String.Empty Then --> 00:00:02.3125000
If s.Length = 0 Then --> 00:00:00.4062500
s = ""
If s = "" Then --> 00:00:00.7968750
If s = String.Empty Then --> 00:00:02.2187500
If s.Length = 0 Then --> 00:00:00.5000000


Как видим, в любом случае, целесообразнее обращаться к свойству Length. 

четверг, 22 июля 2010 г.

VB.Net. Пустая строка

И еще, к слову. Возможно, кто-то использует такую проверку пустой строки:

If s = "" Then...
или If s = String.Empty Then...

Так проверять не рекомендуется (не рационально). Лучше использовать свойство Length объектов типа String, т.е. делать так:

If s.Length = 0 Then...

Вот так красиво! :)

VB.Net. Удаление элементов коллекции в цикле

Предположим, надо нам удалить из контейнера все элементы управления, свойство Text которых пустое. Как-то раз, не долго думая, я взял и сделал так:

For Each с As Control In Panel1.Controls
    If c.Text.Length = 0 Then Panel1.Controls.Remove(c) 
Next 

Но так делать нельзя! Потому что нельзя изменить коллекцию во время прохода циклом по элементам этой коллекции (а удаляя элемент из коллекции, мы изменяем коллекцию). А вот как можно сделать:
Dim lst As Control() = Panel1.Controls.Cast(Of Control).Where(Function(c) c.Text.Length = 0).ToArray
For Each c In lst
    Panel1.Controls.Remove(c)
    c.Dispose()
Next

Что мы сделали? Сначала поместили все удаляемые элементы коллекции в новый массив lst. Теперь проходим по элементам массива в цикле и делаем, все, что нужно. Можем удалять элемент из исходной коллекции - в массиве он остается, а значит работа цикла не сбивается. Dispose() освобождает ресурсы, занятые объектом. А созданный массив, как локальный объект, прекратит свое существование при выходе из текущей процедуры.

среда, 21 июля 2010 г.

VB.Net. Перетаскивание элемента управления мышью по форме

В данном примере мышью по форме перетаскивается элемент управления Label. Конечно, подобным образом может перетаскиваться и любой другой контрол, и не только по форме. Во время перемещения указателя мыши по элементу управления (при нажатой кнопке мыши) положение элемента управления изменяется на величину смещения указателя относительно исходной позиции контрола. Ну, вобщем, вроде бы, все понятно. :) Остальные комментарии смотрите в коде.


Public Class Form1

    Private isMouseDown As Boolean = False 'признак удерживания кнопки мыши
    Private StartPoint As Point 'начальная позиция элемента управления

    Private Sub Label1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then 'если нажата левая кнопка мыши
            isMouseDown = True
            StartPoint = e.Location 'запоминаем текущую позицию элемента управления
            Label1.Cursor = Cursors.SizeAll 'меняем вид указателя мыши над элементом управления
        End If
    End Sub

    Private Sub Label1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseUp
        isMouseDown = False
        Label1.Cursor = Cursors.Default 'восстанавливаем вид курсора
    End Sub

    Private Sub Label1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove
        If isMouseDown Then 'если кнопка мыши удерживается
            'вычисляем новые координаты элемента управления
            Label1.Left += (e.X - StartPoint.X)
            Label1.Top += (e.Y - StartPoint.Y)
        End If
    End Sub

    Private Sub Label1_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.LocationChanged
        'если большая часть элемента управления выходит за границу формы, возвращаем его в центр
        Dim w2 As Integer = Convert.ToInt32(Label1.Width / 2)
        Dim h2 As Integer = Convert.ToInt32(Label1.Height / 2)
        If Label1.Top < -h2 Or Label1.Left < -w2 Or Label1.Top > Me.ClientSize.Height - h2 Or Label1.Left > Me.ClientSize.Width - w2 Then
            Label1.Location = New Point(Convert.ToInt32(Me.ClientSize.Width / 2) - w2, Convert.ToInt32(Me.ClientSize.Height / 2) - h2)
            isMouseDown = False
            Label1.Cursor = Cursors.Default
        End If
    End Sub

End Class

среда, 14 июля 2010 г.

G-Move или «Ход конем» (VB.Net)

Древняя логическая мини-игрушка про посещение одной известной шахматной фигурой полей игральной доски. Целью игры может быть: посещение всех полей игровой доски или посещение минимально-возможного количества полей. Передвигаться по игровой доске следует только определенным образом и до тех пор, пока существует такая возможность. Начать игру можно с произвольного поля, но побывать в любом из полей можно только один раз. Максимальный результат — 100%, т.е. посещение всех полей, а минимальный — не более 12% (меньше мне набрать не удалось). Текущая позиция, возможные ходы, посещенные поля отличаются друг от друга цветами. Цвета эти можно поменять в настройках программы. Если включить режим «автопилот», программа попробует поиграть в себя сама. И хотя руководствуется при выборе очередного хода она отнюдь не логикой, а исключительно генератором случайных чисел, тем не менее иногда ей все же удается показывать неплохие результаты, которые тут же бережно записываются в таблицу рекордов.

ОС: Windows
Требования: Microsoft .NET Framework 2.0
Лицензия: Freeware
Язык: English, Русский
Версия: 1.1.0


GMoveSetup.zip(224 КБ)Установщик с игрушкой
GMove.zip(655 КБ)Проект с исходниками для Visual Studio 2008

Го вверх!