Перевод с VB6 на NET, несколько вопросов.

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Перевод с VB6 на NET, несколько вопросов.

Сообщение Mikle » 14.05.2007 (Пн) 16:39

Вообще-то, большую часть вопросов я, так или иначе, решил. Просто хотелось услышать, что я это сделал правильно.

1. Декларация API, содержащий в параметрах тип Any.
Просто продекларировал одну и ту же ф-цию несколько раз, по каждому конкретному типу параметра, который может быть применен.

2. Где взять VarPtr?
Опять же продекларировал из Msvbvm60.dll несколько раз (по числу возможных типов)

3. Где взять hDC (например для SetDiBits)?
Это я так и не нашел.

Сорри за возможное ламерство, с NET только знакомлюсь. :cry:

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 14.05.2007 (Пн) 16:52

1. Правильно.

2. Неправильно. Менеджер памяти имеет право переместить переменную в другое место, если ему захочется. Для получения указателя надо создать GCHandle с флагом Pinned, тогда переменная не будет перемещена и можно заиметь IntPtr-указатель на неё из того же GCHandle.
Впрочем, неверен сам подход; такие вещи в .net не требуются.

3. Неправильно. Несмотря на то, что hdc есть (graphics.gethdc), лучше обойтись без него.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 14.05.2007 (Пн) 16:53

По 1 пункту можно написать нечто вроде:

Код: Выделить всё
Public Function VarPtr(ByVal o As Object) As Integer
    Dim gc As System.Runtime.InteropServices.GCHandle = _
        System.Runtime.InteropServices.GCHandle.Alloc(o, _
        System.Runtime.InteropServices.GCHandleType.Pinned)
    Dim ptr As Integer = gc.AddrOfPinnedObject.ToInt32()
    Return ptr
End Function


Только сразу скажу - не нужно этого использовать в .NET, не нужно... Это убивает часть преимущества .NET. Зачем тебе указатели?
Последний раз редактировалось gaidar 14.05.2007 (Пн) 17:33, всего редактировалось 1 раз.
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 14.05.2007 (Пн) 16:54

GSerg, ты быстр :)
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 14.05.2007 (Пн) 16:58

Я быстр, а ты неправ: после gc.free() переменную можно перемещать :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 14.05.2007 (Пн) 17:15

Я понимаю, что низкоуровневая VarPtr контрастирует с NET. Просто я решил для тренировки что-нибудь перевести, и этим "чем-то" оказался мой 2D движок. Видимо выбор неудачен.
GSerg
Менеджер памяти имеет право переместить переменную в другое место, если ему захочется.

Полезная информация, запомню. В VB6, насколько понимаю, такого не было.
Вопрос: а когда такие перемещения могут происходить? Если я передаю в DLL (нативную) массив (точнее его первый элемент ByRef), DLL обрабатывает массив достаточно долго, нет ли опасности, что за время работы процедуры сработает менеджер памяти? И вообще, элементы массива в NET расположены в памяти подряд?

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 14.05.2007 (Пн) 17:33

GSerg писал(а):Я быстр, а ты неправ: после gc.free() переменную можно перемещать :)


Да, ты прав. Это я на автомате...
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 14.05.2007 (Пн) 17:33

Элементы массива подряд. Передавать можно, не схавают.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 14.05.2007 (Пн) 17:56

GSerg
Несмотря на то, что hdc есть (graphics.gethdc), лучше обойтись без него.

А как быть с SetDiBitsToDevice? Есть замена?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 14.05.2007 (Пн) 17:58

Вроде нет :)
Тогда юзай.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 15.05.2007 (Вт) 12:41

ААА!!! Три часа копался, искал ошибку, пока не понял, что в .NET размерности массива идут в обратном порядке!

VB-constructor
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 160
Зарегистрирован: 24.07.2006 (Пн) 21:37
Откуда: Ростов-на-Дону

Сообщение VB-constructor » 16.05.2007 (Ср) 23:12

3. Где взять hDC (например для SetDiBits)?
Это я так и не нашел.
забей на любой Devoce

Там есть класс Bitmap, есть класс Graphics, который в .NET заменяет любое контекстное устройство

Не юзай АПИ, которые имеют аналоги в .NET
Человек рождён для того, чтобы достичь жизни...

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.05.2007 (Чт) 7:43

VB-constructor, аналог для SetDiBits ты так и не привёл.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

VB-constructor
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 160
Зарегистрирован: 24.07.2006 (Пн) 21:37
Откуда: Ростов-на-Дону

Сообщение VB-constructor » 17.05.2007 (Чт) 10:11

ну там прямого аналога конечно нету

все завсисит от конкретной ситуации
Человек рождён для того, чтобы достичь жизни...

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.05.2007 (Чт) 14:18

Это используется как команда метафайла кажись. совсем недавно натыкался на нее.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 17.05.2007 (Чт) 16:32

VB-constructor
все завсисит от конкретной ситуации

Ситуация простая. Нужно вывести максимально быстро, но аппаратнонезависимо, графические данные из массива на форму или PictureBox.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 17.05.2007 (Чт) 20:03

Так ведь там у System.Drawing.Bitmap есть метод LockBits?
Разве не подходит?
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.05.2007 (Чт) 20:23

А он начало залоченной зоны возвращает в виде IntPtr...
Опять же путь к CopyMemory. Легче уж hDC.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.05.2007 (Чт) 21:13

Mikle
Здесь массив Colors - это непосредственные данные битмэпа.
Код: Выделить всё
Imports System.Runtime.InteropServices

Public Class Form1
    Const W As Integer = 300
    Const H As Integer = 300
    Private GCh As GCHandle
    Private Colors(W - 1, H - 1) As Integer
    Private Bmp As Bitmap
    Private BmpRect As New Rectangle(0, 0, W, H)
    Dim Data As Integer = Color.Blue.ToArgb

    Private Sub Form1_HandleCreated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.HandleCreated
        Me.DoubleBuffered = True
        'зафиксировать массив в памяти
        GCh = GCHandle.Alloc(Colors, GCHandleType.Pinned)

        'создать битмэп
        Bmp = New Bitmap( _
            W, _
            H, _
            4 * W, _
            Imaging.PixelFormat.Format32bppRgb, _
            GCh.AddrOfPinnedObject)

        Me.BackgroundImageLayout = ImageLayout.None
        Me.BackgroundImage = Bmp
    End Sub

    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        If GCh.IsAllocated Then GCh.Free()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Const ЧислоКадров As Integer = 500
        Dim Start As Date = Now
        Button1.Enabled = False

        For i As Integer = 1 To ЧислоКадров

            For Row As Integer = 0 To W - 1
                For Col As Integer = 0 To H - 1
                    Colors(Row, Col) = Data
                Next
            Next
            Data = Data Xor &HFF00FF

            'после каждого кадра - рефреш
            Me.Invalidate(BmpRect, False)
            Me.Update()

        Next

        Dim sec As Integer = CType(Now - Start, TimeSpan).TotalSeconds
        MsgBox(ЧислоКадров  / sec & " кадров в секунду")
        Button1.Enabled = True
    End Sub
End Class
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 18.05.2007 (Пт) 7:41

Также обрати внимание на XNA: http://www.xnadev.ru
Производительность в разы больше. Но это уже зависит от твоих потребностей и религии(я не знаю, может у тебя принцип не использовать hardware)
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 18.05.2007 (Пт) 16:37

Nord777
Никакой религии :) Просто не делать же на XNA (Direct3D) графический редактор (например).
А вообще я на некотором перепутье. Достаточно неплохо освоил DX8, а тут этому делу "перерезают горло", уже начал разбираться со статьей Sergа про использование ActiveX без IDispatch на VB6, думал писать замену DX8VB.dll, как стали доходить сведения, что DX8 (и DX9!), вообще говоря, на Висте работают не совсем корректно не только на VB. Про OpenGL лучше вообще молчать. Только начали народ подсаживать на Managed, как тут же прекратили его поддержку. Теперь XNA (я пока вообще не знаю, что это). Долго ли проживет?
И только софтовая эмуляция не подводит... :roll:

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 18.05.2007 (Пт) 20:20

За XNA будущее.

Кстати, ты DirectX 10 видел? Если посмотреть насколько он хорош, то не будет так жалко проблем с 8 и 9 на Vista.
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 18.05.2007 (Пт) 22:05

А DX10, насколько я помню зажористый до видюхи. Да и работать на дркгих осях не будет, наверное.
А вот старый добрый SetDIBitsToDevice никто и никогда не отменит.
Изображение

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 19.05.2007 (Сб) 9:40

gaidar
За XNA будущее.

Надеюсь.
Просто я хочу писать программы, чтобы они СЕЙЧАС работали везде (точнее на большинстве современных компьютеров). Выходит, что не на чем, пока все на Висту не перешли. Разве что MDX, но требовать установку фреймворка для пользователей XP, при размере программы, скажем, 3 мБ, считаю чрезмерным.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 22.05.2007 (Вт) 16:15

Nord777
Интересный код, я много из него почерпнул, но такой способ вывода массива на экран работает в 4 раза медленнее, чем через SetDIBitsToDevice, по крайней мере у меня.
Цикл:
Код: Выделить всё
            For Row As Integer = 0 To W - 1
                For Col As Integer = 0 To H - 1
                    Colors(Row, Col) = Data
                Next
            Next

я, естественно, из замера исключал.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 22.05.2007 (Вт) 21:07

Mikle
Скажу честно - никогда не сравнивал по быстродействию с SetDIBitsToDevice, но очень много эксперементировал с различными вариации этого кода. Разбросы в быстродействии могут быть достаточно большими (также имеются грабли в GDI+).
Где то с пол года назад писал "бегущую волнообразно строку" - быстродействие вполне устраивало(чуть больше 200 fps при высоте строки где-то 50-70пикселей). Выложить пример к сожалению не могу - недавно из за собственного упущения, с моими винтами поработал злобный вирь :)
Как говорится всё что нажито непосильным трудом...
PS: Мне вобщем то интересно будет потестить. Скинуть свой код сможешь?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 23.05.2007 (Ср) 19:31

Nord777
Постараюсь завтра скинуть.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 25.05.2007 (Пт) 15:23

Nord777
Вот тесты, разница даже в 5 раз. (450 vs 2300).

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 27.05.2007 (Вс) 21:24

Mikle
SetDIBitsToDevice рулит.
Быстрее него ничего нет(из software). Только надо помнить о небольших нюансах, тогда его смело можно использовать.
Посмотри код, комментарии внутри.
Вложения
FAST_GRAPHICS.rar
(23.44 Кб) Скачиваний: 219
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 30.05.2007 (Ср) 14:51

Nord777
Изучил, смысл понятен.
Хотелось бы уточнить:
1. Мы фиксируем массив в памяти, в результате можем пользоваться однократно полученным в начале программы хендлом, не боясь, что менеджер памяти переместит данные. А если получать хендл заново каждый раз непосредственно перед применением, избавляет ли это от необходимости фиксации массива в памяти?
2. Нужно ли заново получать хендл при изменении размера массива (формы)?

След.

Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 73

    TopList