Ручное формирование .res файлов

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Ручное формирование .res файлов

Сообщение hCORe » 31.08.2005 (Ср) 16:14

Недавно мне понадобилась утилита, генерирующая .res файлы, содержащие одну STRINGTABLE. Покопался в Интернете (google, wotsit.org), разузнал про общую структуру файлов ресурсов. Написал код (корявый, конечно, работающий в первом приближении), создающий .res файл нужной конфигурации из массива строчек. На некоторых простых примерах он работает, на сложных - нет.

Возникшие сложности:
Проблемы с паддингом (раз), проблемы с форматом строки (два), проблемы с проблемами (три).

Хотелось бы все три проблемы решить.

Выкладываю исходный код утилиты.

Инструкция: запустить проект, загрузить исполняемый файл ("Load Library"), нажать "Generate Resource Script", сохранить файл ресурсов. Потом - проверить работоспособность .res'а, открыв его в Visual Studio или любом редакторе ресурсов.


Заранее спасибо за помощь!


P.S. RC.EXE и RCDLL.DLL не предлагать. Мне нужны строки длиннее 4097 символов. Внешние утилиты типа Restorator'а и Resource Editor'а VB6 - тоже "левый" номер.
P.P.S. Если у кого есть (ну вдруг?!) готовый (или полуготовый) и корректно работающий класс или модуль для работы с .res-файлами, давайте его сюда!..
P.P.P.S. BeginUpdateResource, UpdateResource и EndUpdateResource не предлагать. Мне не нужно менять ресурсы в исполняемом файле, мне надо сгенерировать .res файл для подключения к проекту.
P.P.P.P.S. Я в вопросах работы со структурами - полный ламер, так что - без наездов! :twisted:
Последний раз редактировалось hCORe 31.08.2005 (Ср) 16:21, всего редактировалось 1 раз.
Моду создают модоки, а распространяют модозвоны.

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

Re: Ручное формирование .res файлов

Сообщение tyomitch » 31.08.2005 (Ср) 16:18

hCORe писал(а):Выкладываю исходный код утилиты.

Да? Где?
Изображение

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Ручное формирование .res файлов

Сообщение alibek » 31.08.2005 (Ср) 16:21

tyomitch писал(а):Да? Где?

Из подписи:
Я абсолютно здоров! По крайней мере - психически! Возможно, даже сегодня..

:)
Lasciate ogni speranza, voi ch'entrate.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 16:25

Сеть тормозит :oops:
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 16:43

hCORe писал(а):Сеть тормозит :oops:

По-моему, не только сеть...
Microsoft Visual Basic писал(а):Path not found: '..\..\..\..\VB Programs\!!! Unclassified !!!\QuickCONV\xpstyles.RES'

Недовложение?
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 16:47

Плюнь. Это манифест XP. Общий файл для десятка мелких прог, лежащих приблизительно в одном месте. Его отсутствие работе не мешает :D
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 17:35

Ладно. Читаю исходник. RESHEADER объявлена криво. Но дело не в этом.
Расскажи пожалуйста, что это такое?
Код: Выделить всё
ReDim arrBytes(LenB(arrStrings(i)) - 1)
For j = 1 To Len(arrStrings(i))
    arrBytes((j - 1) * 2) = Asc(Mid$(arrStrings(i), j, 1))
Next j

Почему не просто arrBytes = StrConv(arrStrings(i), vbUnicode)?

И зачем нужно писать "###" & Trim$(Str$(i)) вместо "###" & i :?:


Вот этот код тоже жжот:
Код: Выделить всё
bt = (UBound(objByteRefs.Item("###" & Trim$(Str$(i)))) - _
LBound(objByteRefs.Item("###" & Trim$(Str$(i)))) + 1) \ 2

Put #l, , bt
ReDim ba(UBound(objByteRefs.Item("###" & Trim$(Str$(i)))))
ba = objByteRefs.Item("###" & Trim$(Str$(i)))

Нет чтобы ключ во временную переменную сохранить, так ты для каждой строки 4 раза выполняешь Str$, Trim$, и конкатенацию.


Чудесный цикл
Код: Выделить всё
    Do
        'выравнивание по границам DWORD
        If (LOF(l) + p) Mod 32 <> 0 Then p = p + 1 Else Exit Do
    Loop

Заменяется одной строчкой:
Код: Выделить всё
p = 32 - (LOF(l) Mod 32): If p = 32 Then p = 0



Вот это, как уже подсказали в соседнем топике, делают проще:
Код: Выделить всё
    'дописать
    Dim sc3() As Byte
    ReDim sc3(p - 1)
    Put #l, , sc3

Put #l, LOF(l) + p - 1, CByte(0)
Последний раз редактировалось tyomitch 31.08.2005 (Ср) 17:55, всего редактировалось 2 раз(а).
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 17:47

1) Пережиток версии 0.1, где преобразование строки в Юникод давало непредсказуемые результаты. Заменено.
2) Привычка. Хотя, в принципе, "###" & i - быстрее. Заменил.

Результаты: размеры исходного файла и файла, сгенерированного программой, стали равными.

RESHEADER объявлен криво, я согласен. Как объявить "прямо"? Как я уже говорил, информации по этому делу в Сети - ноль.
Моду создают модоки, а распространяют модозвоны.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 17:50

Кроме того... Подсчет длины всей STRINGTABLE тоже идет не так, как "надо". Должно быть - &h3642, получается - &hff74.

И еще. Если сделать выравнивание по твоему методу, то исходный файл и сгенерированный прогой становятся разными по длине. Причем сгенерированный - меньше.
Последний раз редактировалось hCORe 31.08.2005 (Ср) 18:08, всего редактировалось 1 раз.
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 17:51

hCORe писал(а):RESHEADER объявлен криво, я согласен. Как объявить "прямо"? Как я уже говорил, информации по этому делу в Сети - ноль.

Код: Выделить всё
Private Type RESHEADER
    datasize As Long
    headersize As Long
    type As Long
    id As Long
    dataversion As Long
    flags As Integer
    language As Integer
    version As Long
    characteristics As Long
End Type

Взято один-в-один с wotsit.org

Ещё прочитай мой предыдущий пост, я туда дописал новые фи.
Изображение

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

Сообщение tyomitch » 31.08.2005 (Ср) 18:05

hCORe писал(а):Кроме того... Подсчет длины всей STRINGTABLE тоже идет не так, как "надо". Референс - &h3642, получается - &hff74.

Это потому, что в референсе четыре STRINGTABLE идут подряд, а ты всё в одну пихаешь. Скорее всего, нельзя создавать STRINGTABLE отрицательной длины, как у тебя. Бей на куски.

И ещё, раз уж ты ничего дельного не выгуглил: http://simtech.sourceforge.net/tech/strings.html
Всё, я твою прогу бросаю. Если ты будешь бить строки на куски, а оно не заработает - посмотрю ещё :-)
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 18:13

Ты чего... Это же описание формата ресурсов игры The Sims! :)
Моду создают модоки, а распространяют модозвоны.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 18:23

А вот это ценный ресурс:
http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/resfmt.txt
Может, чего найду интересного :)
Моду создают модоки, а распространяют модозвоны.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 18:33

These tables are constructed in blocks of 16 strings. The
organization of these blocks of 16 is determined by the IDs given to
the various strings. The lowest four bits of the ID determine a
string's position in the block. The upper twelve bits determine
which block the string is in. Each block of 16 strings is stored as
one resource entry. Each string or error table resource block is
stored as follows:

[Normal resource header (type = 6 for strings)]

[Block of 16 strings. The strings are Pascal style with a WORD
length preceding the string. 16 strings are always written, even
if not all slots are full. Any slots in the block with no string
have a zero WORD for the length.]

It is important to note that the various blocks need not be written
out in numerical order in the resource file. Each block is assigned
an ordinal ID. This ID is the high 12 bits of the string IDs in the
block plus one (ordinal IDs can't be zero). The blocks are written
to the .RES file in the order the blocks are encountered in the .RC
file, while the CVTRES utility will cause them to become ordered in
the COFF object, and hence the image file.


Бррр.... То есть для каждых 16 строк - отдельный заголовок... Ужас!..
Пошел лечиться.
Моду создают модоки, а распространяют модозвоны.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 18:50

Привожу код, который (гипотетически) работать должен, но - не работает... Вернее, работает, но не генерирует корректные .res-файлы...

Код: Выделить всё
'в модуль
Option Explicit

Public Type RESHEADER
    datasize As Long
    headersize As Long
    type As Long
    id As Long
    dataversion As Long
    flags As Integer
    language As Integer
    version As Long
    characteristics As Long
End Type

Public Sub Main()
    Dim strings(31) As String
    Dim data(99) As String
    Dim i As Integer
    Dim lInd As Integer
   
    For i = 0 To 99
        data(i) = i + 1
    Next
    Randomize Timer * Fix(Rnd * 5)
    For i = 0 To 31
gen:
        lInd = Fix(Rnd * 99)
        If data(lInd) <> -1 And Len(CStr(data(lInd))) > 1 Then
            strings(i) = data(lInd)
            data(lInd) = -1
        Else
            GoTo gen
        End If
    Next
    For i = 0 To 31
        Debug.Print strings(i) & " ";
    Next
   
    Dim rh As RESHEADER
    Dim rh2 As RESHEADER
   
    Dim l As Byte
    l = FreeFile
    On Error Resume Next
    Kill "C:\res2.res"
    Err.Clear
    Open "C:\res2.res" For Binary As #l
   
    'пустой заголовок - 16 байт
    Dim sc(31) As Byte
    sc(0) = 0
    sc(1) = 0
    sc(2) = 0
    sc(3) = 0
    sc(4) = &H20
    sc(5) = 0
    sc(6) = 0
    sc(7) = 0
    sc(8) = &HFF
    sc(9) = &HFF
    sc(10) = 0
    sc(11) = 0
    sc(12) = &HFF
    sc(13) = &HFF
    sc(14) = 0
    sc(15) = 0
   
    For i = 0 To 15
        rh.datasize = rh.datasize + LenB(strings(i))
    Next
   
    Dim p As Long
    p = 32 - (rh.datasize Mod 32)
    If p = 32 Then p = 0
    rh.datasize = rh.datasize + p
   
    rh.dataversion = 0
    rh.flags = 0
    rh.id = &H7FFFF     'таблица 7
    rh.language = 0     'lang neutral, sublang neutral
    rh.type = 6         'RT_STRING
    rh.headersize = Len(rh)
   
    Put #l, , sc
    Put #l, , rh
    For i = 0 To 15
        Put #l, , CInt(Len(strings(i)) \ 2)
        Put #l, , StrConv(strings(i), vbUnicode)
    Next i
    Put #l, LOF(l) + p - 1, CByte(0)
    Close #l
   
End Sub
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 19:06

hCORe писал(а): Put #l, , CInt(Len(strings(i)) \ 2)
Put #l, , StrConv(strings(i), vbUnicode)

Вот сюда не верю. У тебя длина строки в чём указывается, в DWORD-ах, что ли?

hCORe писал(а):
Dim p As Long
p = 32 - (rh.datasize Mod 32)
If p = 32 Then p = 0
rh.datasize = rh.datasize + p

И сюда не верю.
3.1 DataSize

This field gives the size of the data that follows the header, not
including any file padding
between this resource and any resource
that follows this resource in the resource file.
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 20:07

Длина строки указывается в WORD'ах. WORD = Integer.
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 20:32

hCORe писал(а):Длина строки указывается в WORD'ах. WORD = Integer.

hCORe писал(а):Put #l, , CInt(Len(strings(i)) \ 2) 'Возвращает половину числа символов в строке
Put #l, , StrConv(strings(i), vbUnicode) 'Пишет два байта на символ

Если всё ещё непонятно, поясню на примере.
Вопрос: что запишется в файл для строки strings(i) = "Hello!"?
Ответ: сначала число 3 (потому что 6 символов), потом 12 байт (потому что Юникод).
Вывод: у тебя длина указывается вовсе не в WORD-ах.


И что про паддинг?
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 31.08.2005 (Ср) 20:35

Паддинг поправил.
Как тогда правильно указать длину и записать строку? А то я уже путаюсь :?
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 31.08.2005 (Ср) 21:19

Убрать деление пополам надо.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 01.09.2005 (Чт) 9:11

Очередной велосипед избретался в муках и корчах. Темыча.
Лучший способ понять что-то самому — объяснить это другому.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 01.09.2005 (Чт) 11:30

Муки преимущественно мои. Я ведь уже четвертый день эту прогу пишу :)

И не велосипед это вовсе. А даже если и велосипед, - то с моторчиком :P
Моду создают модоки, а распространяют модозвоны.

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

Сообщение tyomitch » 01.09.2005 (Чт) 12:45

hCORe, заработало у тебя наконец или как? :-)
Изображение

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 01.09.2005 (Чт) 13:07

Близко к тому, чтобы заработало :D

Странный прикол с выводом строк: если пишешь
Код: Выделить всё
Open "H:\a.bin" For Binary As #1
    Put #1, , StrConv("Hello", vbUnicode)
    Put #1, , "-- delimiter --"
    Dim s As String
    s = StrConv("Hello", vbUnicode)
    Put #1, , s
Close


То в a.bin будет (hex):
08 00 0A 00 48 00 65 00 6C 00 6C 00 6F 00 2D 2D
20 64 65 6C 69 6D 69 74 72 20 2D 2D 48 00 65
00 6C 00 6C 00 6F 00


Жирным выделена сама строка "Hello" в Unicode, подчеркнут заголовок Unicode-строки.

То есть, если пишем
Код: Выделить всё
Put #1, , StrConv("Hello", vbUnicode)

- то получаем полноценный Юникод, а если
Код: Выделить всё
Dim s As String
s = StrConv("Hello", vbUnicode)

- то полноценный ANSI с Unicode-кодированием "внутри".

Забавно... Из-за этого и глючила запись строк. Теперь, вроде, поправил. Как только что-нибудь заработает - сразу выложу рабочую версию. ОК?
Моду создают модоки, а распространяют модозвоны.

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

Сообщение GSerg » 01.09.2005 (Чт) 13:27

Гы.

Дык при записи строки в файл VB сам переводит в ANSI всегда :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 01.09.2005 (Чт) 13:30

Поэтому надо записывать не строку, а байтовый массив.
Lasciate ogni speranza, voi ch'entrate.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 01.09.2005 (Чт) 13:31

Просто я детально записью в режиме Binary не занимался, поэтому и не знал эту "фишку". Только с текстовыми файлами работал более-менее прилично. :D
Моду создают модоки, а распространяют модозвоны.

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

Сообщение GSerg » 01.09.2005 (Чт) 13:46

Гы :)

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

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 01.09.2005 (Чт) 14:50

Я в курсе :)

Знаком с проблемой, но с другой стороны.
Чтобы передать строку юникодной API-функции приходится объявлять параметр функции как ByVal ptr As Long и передавать строчку как StrPtr(исходная_строка). :)
Последний раз редактировалось hCORe 01.09.2005 (Чт) 15:04, всего редактировалось 1 раз.
Моду создают модоки, а распространяют модозвоны.

След.

Вернуться в Visual Basic 1–6

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

Сейчас этот форум просматривают: Google-бот, Yandex-бот и гости: 2

    TopList  
cron