Блог программиста Еремина Вячеслава Викторовича
(NET) NET (2002 год)

FRX-парсер - моя утилитка для выкусывания рисунков из шестерочного FRX-файла.

Эту полезную утилитку я набросал за несколько часов. Она предназначена для парсинга рисунков из FRX-файлов и загрузки их в базу.В отличие от весьма и весьма тяжеловесных подходов вот такого плана, где рисунки парсятся с помощью АПИ, я просто разбираю побайтово FRX-файл. К сожалению, полная разборка с помощью АПИ работает НЕ ВСЕГДА, поэтому несмотря на кажущуюся глючность моего подхода - это единственный путь полной разбоки.

Работа с утилиткой крайне проста. Выберите нужный файлик (а их в проекте может быть достаточно много, затем собственно нужный ImageList на форме (которых тоже может быть немало). И наслаждайтесь бинарным представлением рисунков без отягощения себя мыслями - где и откуда вы их взяли.



Сгрузить эту небольшую полезняшку в откомпилированном виде (для единственного ImageList'а на форме) можно отсюда. А ниже приводится ее полный исходный текст (опять же для единственного Imagelist'а):

00001: <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
00002: Partial Class Form1
00003:     Inherits System.Windows.Forms.Form
00004: 
00005:     'Form overrides dispose to clean up the component list.
00006:     <System.Diagnostics.DebuggerNonUserCode()> _
00007:     Protected Overrides Sub Dispose(ByVal disposing As Boolean)
00008:         If disposing AndAlso components IsNot Nothing Then
00009:             components.Dispose()
00010:         End If
00011:         MyBase.Dispose(disposing)
00012:     End Sub
00013: 
00014:     'Required by the Windows Form Designer
00015:     Private components As System.ComponentModel.IContainer
00016: 
00017:     'NOTE: The following procedure is required by the Windows Form Designer
00018:     'It can be modified using the Windows Form Designer.  
00019:     'Do not modify it using the code editor.
00020:     <System.Diagnostics.DebuggerStepThrough()> _
00021:     Private Sub InitializeComponent()
00022:         Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Form1))
00023:         Me.Label1 = New System.Windows.Forms.Label
00024:         Me.SplitContainer1 = New System.Windows.Forms.SplitContainer
00025:         Me.SplitContainer2 = New System.Windows.Forms.SplitContainer
00026:         Me.Button1 = New System.Windows.Forms.Button
00027:         Me.SplitContainer3 = New System.Windows.Forms.SplitContainer
00028:         Me.Label2 = New System.Windows.Forms.Label
00029:         Me.ListBox1 = New System.Windows.Forms.ListBox
00030:         Me.TextBox1 = New System.Windows.Forms.TextBox
00031:         Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
00032:         Me.SplitContainer4 = New System.Windows.Forms.SplitContainer
00033:         Me.ProgressBar1 = New System.Windows.Forms.ProgressBar
00034:         Me.SplitContainer1.Panel1.SuspendLayout()
00035:         Me.SplitContainer1.Panel2.SuspendLayout()
00036:         Me.SplitContainer1.SuspendLayout()
00037:         Me.SplitContainer2.Panel1.SuspendLayout()
00038:         Me.SplitContainer2.Panel2.SuspendLayout()
00039:         Me.SplitContainer2.SuspendLayout()
00040:         Me.SplitContainer3.Panel1.SuspendLayout()
00041:         Me.SplitContainer3.Panel2.SuspendLayout()
00042:         Me.SplitContainer3.SuspendLayout()
00043:         Me.SplitContainer4.Panel1.SuspendLayout()
00044:         Me.SplitContainer4.Panel2.SuspendLayout()
00045:         Me.SplitContainer4.SuspendLayout()
00046:         Me.SuspendLayout()
00047:         '
00048:         'Label1
00049:         '
00050:         Me.Label1.AutoSize = True
00051:         Me.Label1.Location = New System.Drawing.Point(13, 13)
00052:         Me.Label1.Name = "Label1"
00053:         Me.Label1.Size = New System.Drawing.Size(0, 13)
00054:         Me.Label1.TabIndex = 0
00055:         '
00056:         'SplitContainer1
00057:         '
00058:         Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
00059:         Me.SplitContainer1.Location = New System.Drawing.Point(0, 0)
00060:         Me.SplitContainer1.Name = "SplitContainer1"
00061:         Me.SplitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal
00062:         '
00063:         'SplitContainer1.Panel1
00064:         '
00065:         Me.SplitContainer1.Panel1.Controls.Add(Me.SplitContainer2)
00066:         '
00067:         'SplitContainer1.Panel2
00068:         '
00069:         Me.SplitContainer1.Panel2.Controls.Add(Me.SplitContainer4)
00070:         Me.SplitContainer1.Size = New System.Drawing.Size(313, 502)
00071:         Me.SplitContainer1.SplitterDistance = 239
00072:         Me.SplitContainer1.TabIndex = 2
00073:         '
00074:         'SplitContainer2
00075:         '
00076:         Me.SplitContainer2.Dock = System.Windows.Forms.DockStyle.Fill
00077:         Me.SplitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel1
00078:         Me.SplitContainer2.IsSplitterFixed = True
00079:         Me.SplitContainer2.Location = New System.Drawing.Point(0, 0)
00080:         Me.SplitContainer2.Name = "SplitContainer2"
00081:         Me.SplitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal
00082:         '
00083:         'SplitContainer2.Panel1
00084:         '
00085:         Me.SplitContainer2.Panel1.Controls.Add(Me.Button1)
00086:         '
00087:         'SplitContainer2.Panel2
00088:         '
00089:         Me.SplitContainer2.Panel2.Controls.Add(Me.SplitContainer3)
00090:         Me.SplitContainer2.Size = New System.Drawing.Size(313, 239)
00091:         Me.SplitContainer2.SplitterDistance = 39
00092:         Me.SplitContainer2.TabIndex = 3
00093:         '
00094:         'Button1
00095:         '
00096:         Me.Button1.Location = New System.Drawing.Point(37, 8)
00097:         Me.Button1.Name = "Button1"
00098:         Me.Button1.Size = New System.Drawing.Size(252, 23)
00099:         Me.Button1.TabIndex = 3
00100:         Me.Button1.Text = "Укажите расположение FRX и FRM-файла"
00101:         Me.Button1.UseVisualStyleBackColor = True
00102:         '
00103:         'SplitContainer3
00104:         '
00105:         Me.SplitContainer3.Dock = System.Windows.Forms.DockStyle.Fill
00106:         Me.SplitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel1
00107:         Me.SplitContainer3.IsSplitterFixed = True
00108:         Me.SplitContainer3.Location = New System.Drawing.Point(0, 0)
00109:         Me.SplitContainer3.Name = "SplitContainer3"
00110:         Me.SplitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal
00111:         '
00112:         'SplitContainer3.Panel1
00113:         '
00114:         Me.SplitContainer3.Panel1.Controls.Add(Me.Label2)
00115:         '
00116:         'SplitContainer3.Panel2
00117:         '
00118:         Me.SplitContainer3.Panel2.Controls.Add(Me.ListBox1)
00119:         Me.SplitContainer3.Size = New System.Drawing.Size(313, 196)
00120:         Me.SplitContainer3.SplitterDistance = 25
00121:         Me.SplitContainer3.TabIndex = 0
00122:         '
00123:         'Label2
00124:         '
00125:         Me.Label2.Anchor = System.Windows.Forms.AnchorStyles.Top
00126:         Me.Label2.AutoSize = True
00127:         Me.Label2.Location = New System.Drawing.Point(42, 9)
00128:         Me.Label2.Name = "Label2"
00129:         Me.Label2.Size = New System.Drawing.Size(200, 13)
00130:         Me.Label2.TabIndex = 0
00131:         Me.Label2.Text = "Выберите один из ImageList'ов формы"
00132:         '
00133:         'ListBox1
00134:         '
00135:         Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill
00136:         Me.ListBox1.FormattingEnabled = True
00137:         Me.ListBox1.Location = New System.Drawing.Point(0, 0)
00138:         Me.ListBox1.Name = "ListBox1"
00139:         Me.ListBox1.Size = New System.Drawing.Size(313, 160)
00140:         Me.ListBox1.TabIndex = 0
00141:         '
00142:         'TextBox1
00143:         '
00144:         Me.TextBox1.Dock = System.Windows.Forms.DockStyle.Fill
00145:         Me.TextBox1.Location = New System.Drawing.Point(0, 0)
00146:         Me.TextBox1.Multiline = True
00147:         Me.TextBox1.Name = "TextBox1"
00148:         Me.TextBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both
00149:         Me.TextBox1.Size = New System.Drawing.Size(313, 230)
00150:         Me.TextBox1.TabIndex = 0
00151:         '
00152:         'SplitContainer4
00153:         '
00154:         Me.SplitContainer4.Dock = System.Windows.Forms.DockStyle.Fill
00155:         Me.SplitContainer4.FixedPanel = System.Windows.Forms.FixedPanel.Panel2
00156:         Me.SplitContainer4.IsSplitterFixed = True
00157:         Me.SplitContainer4.Location = New System.Drawing.Point(0, 0)
00158:         Me.SplitContainer4.Name = "SplitContainer4"
00159:         Me.SplitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal
00160:         '
00161:         'SplitContainer4.Panel1
00162:         '
00163:         Me.SplitContainer4.Panel1.Controls.Add(Me.TextBox1)
00164:         '
00165:         'SplitContainer4.Panel2
00166:         '
00167:         Me.SplitContainer4.Panel2.Controls.Add(Me.ProgressBar1)
00168:         Me.SplitContainer4.Size = New System.Drawing.Size(313, 259)
00169:         Me.SplitContainer4.SplitterDistance = 230
00170:         Me.SplitContainer4.TabIndex = 0
00171:         '
00172:         'ProgressBar1
00173:         '
00174:         Me.ProgressBar1.Dock = System.Windows.Forms.DockStyle.Fill
00175:         Me.ProgressBar1.Location = New System.Drawing.Point(0, 0)
00176:         Me.ProgressBar1.Name = "ProgressBar1"
00177:         Me.ProgressBar1.Size = New System.Drawing.Size(313, 25)
00178:         Me.ProgressBar1.TabIndex = 0
00179:         '
00180:         'Form1
00181:         '
00182:         Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
00183:         Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
00184:         Me.ClientSize = New System.Drawing.Size(313, 502)
00185:         Me.Controls.Add(Me.SplitContainer1)
00186:         Me.Controls.Add(Me.Label1)
00187:         Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
00188:         Me.Name = "Form1"
00189:         Me.Text = "Парсинг рисунков из FRX-файла VB6"
00190:         Me.SplitContainer1.Panel1.ResumeLayout(False)
00191:         Me.SplitContainer1.Panel2.ResumeLayout(False)
00192:         Me.SplitContainer1.ResumeLayout(False)
00193:         Me.SplitContainer2.Panel1.ResumeLayout(False)
00194:         Me.SplitContainer2.Panel2.ResumeLayout(False)
00195:         Me.SplitContainer2.ResumeLayout(False)
00196:         Me.SplitContainer3.Panel1.ResumeLayout(False)
00197:         Me.SplitContainer3.Panel1.PerformLayout()
00198:         Me.SplitContainer3.Panel2.ResumeLayout(False)
00199:         Me.SplitContainer3.ResumeLayout(False)
00200:         Me.SplitContainer4.Panel1.ResumeLayout(False)
00201:         Me.SplitContainer4.Panel1.PerformLayout()
00202:         Me.SplitContainer4.Panel2.ResumeLayout(False)
00203:         Me.SplitContainer4.ResumeLayout(False)
00204:         Me.ResumeLayout(False)
00205:         Me.PerformLayout()
00206: 
00207:     End Sub
00208:     Friend WithEvents Label1 As System.Windows.Forms.Label
00209:     Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer
00210:     Friend WithEvents SplitContainer2 As System.Windows.Forms.SplitContainer
00211:     Friend WithEvents Button1 As System.Windows.Forms.Button
00212:     Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
00213:     Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog
00214:     Friend WithEvents SplitContainer3 As System.Windows.Forms.SplitContainer
00215:     Friend WithEvents Label2 As System.Windows.Forms.Label
00216:     Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
00217:     Friend WithEvents SplitContainer4 As System.Windows.Forms.SplitContainer
00218:     Friend WithEvents ProgressBar1 As System.Windows.Forms.ProgressBar
00219: End Class

00001: Option Compare Text
00002: Public Class Form1
00003: 
00004:     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
00005:         SplitContainer3.Visible = False
00006:     End Sub
00007:     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
00008:         OpenFileDialog1.Filter = "*.FRX|*.FRX"
00009:         OpenFileDialog1.ShowDialog()
00010:         If OpenFileDialog1.FileName <> "" Then
00011:             SplitContainer3.Visible = True
00012:         End If
00013:         Dim F0 As New IO.StreamReader(OpenFileDialog1.FileName.Replace(".FRX", ".FRM").Replace(".frx", ".frm"))
00014:         While Not F0.EndOfStream
00015:             Dim Str0 As String = F0.ReadLine
00016:             If Str0.Contains("Begin MSComctlLib.ImageList ") Then
00017:                 ListBox1.Items.Add(Str0.Replace("Begin MSComctlLib.ImageList", "").Trim)
00018:             End If
00019:         End While
00020:         F0.Close()
00021:     End Sub
00022: 
00023:     Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
00024:         Dim C As Windows.Forms.Cursor = Me.Cursor
00025:         Me.Cursor = Windows.Forms.Cursors.WaitCursor
00026:         Dim IconName As New Collection
00027:         Dim F1 As New IO.StreamReader(OpenFileDialog1.FileName.Replace(".FRX", ".FRM").Replace(".frx", ".frm"))
00028:         'прокрутили до выбранного ImageLista
00029:         While Not F1.EndOfStream
00030:             Dim S0 As String = F1.ReadLine.Replace("Begin MSComctlLib.ImageList", "").Trim
00031:             If S0 = CType(sender, Windows.Forms.ListBox).SelectedItem.ToString.Trim Then
00032:                 GoTo OK1
00033:             End If
00034:         End While
00035:         If F1.EndOfStream Then
00036:             F1.Close()
00037:             Me.Cursor = C
00038:             Exit Sub
00039:         End If
00040: OK1:    While Not F1.EndOfStream
00041:             Dim Str1 As String = F1.ReadLine
00042:             If Str1.Contains("Key") Then
00043:                 Dim Str2() As String = Str1.Split(CChar(""""))
00044:                 'взяли имена рисунков из FRM-файла
00045:                 IconName.Add(Str2(1))
00046:             End If
00047:             If Str1.Trim = "END" Then Exit While
00048:         End While
00049:         F1.Close()
00050:         If IconName.Count = 0 Then
00051:             Me.Cursor = C
00052:             MsgBox(CType(sender, Windows.Forms.ListBox).SelectedItem.ToString & " пуст.")
00053:             Exit Sub
00054:         End If
00055:         Dim F2 As New IO.FileStream(OpenFileDialog1.FileName.Replace(".frm", ".frx"), IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
00056:         Dim X(CInt(F2.Length)) As Byte
00057:         ProgressBar1.Maximum = X.Length
00058:         ProgressBar1.Step = 1
00059:         ProgressBar1.Show()
00060:         F2.Read(X, 0, CInt(F2.Length))
00061:         F2.Close()
00062:         Dim Z As New Text.StringBuilder
00063:         Dim l As Integer = 1
00064:         For i As Integer = 0 To X.Length - 3
00065:             ProgressBar1.PerformStep()
00066:             'парсим по признаку наличия BM- для BMP-файла
00067:             Dim IconLen As Integer
00068:             If X(i) = 66 And X(i + 1) = 77 And X(i + 2) = 246 Then
00069:                 For j = i + 1 To X.Length - 3
00070:                     If X(j) = 66 And X(j + 1) = 77 And X(j + 2) = 246 Then
00071:                         GoTo No1
00072:                     End If
00073:                 Next
00074:                 IconLen = j - i
00075:                 GoTo No2
00076: No1:            IconLen = j - 28 - i - 1
00077: No2:            Dim Y(IconLen) As Byte
00078:                 Array.Clear(Y, 0, Y.Length)
00079:                 Array.ConstrainedCopy(X, i, Y, 0, IconLen)
00080:                 Z.AppendLine("Insert SY_Image(Image,Alias)")
00081:                 Z.Append("Values(0x")
00082:                 For k = 0 To Y.Length - 1
00083:                     'Console.Write(" {#0:X}", Y(k)) пропускает лидирующие нули
00084:                     Z.Append(ToHex(Y(k)))
00085:                 Next
00086:                 Z.AppendLine(",'" & CStr(IconName(l)) & "')")
00087:                 If l < IconName.Count Then
00088:                     l += 1
00089:                 Else
00090:                     Exit For
00091:                 End If
00092:             End If
00093:         Next
00094:         ProgressBar1.Hide()
00095:         TextBox1.Text = Z.ToString
00096:         Me.Cursor = C
00097:     End Sub
00098: 
00099:     Private Function ToHex(ByVal X As Byte) As String
00100:         Dim out1 As String
00101:         Select Case X \ 16
00102:             Case 0 : out1 = "0"
00103:             Case 1 : out1 = "1"
00104:             Case 2 : out1 = "2"
00105:             Case 3 : out1 = "3"
00106:             Case 4 : out1 = "4"
00107:             Case 5 : out1 = "5"
00108:             Case 6 : out1 = "6"
00109:             Case 7 : out1 = "7"
00110:             Case 8 : out1 = "8"
00111:             Case 9 : out1 = "9"
00112:             Case 10 : out1 = "A"
00113:             Case 11 : out1 = "B"
00114:             Case 12 : out1 = "C"
00115:             Case 13 : out1 = "D"
00116:             Case 14 : out1 = "E"
00117:             Case 15 : out1 = "F"
00118:         End Select
00119:         Select Case X Mod 16
00120:             Case 0 : out1 &= "0"
00121:             Case 1 : out1 &= "1"
00122:             Case 2 : out1 &= "2"
00123:             Case 3 : out1 &= "3"
00124:             Case 4 : out1 &= "4"
00125:             Case 5 : out1 &= "5"
00126:             Case 6 : out1 &= "6"
00127:             Case 7 : out1 &= "7"
00128:             Case 8 : out1 &= "8"
00129:             Case 9 : out1 &= "9"
00130:             Case 10 : out1 &= "A"
00131:             Case 11 : out1 &= "B"
00132:             Case 12 : out1 &= "C"
00133:             Case 13 : out1 &= "D"
00134:             Case 14 : out1 &= "E"
00135:             Case 15 : out1 &= "F"
00136:         End Select
00137:         Return out1
00138:     End Function
00139: 
00140: End Class

На самом деле, такой разбор для единственного ImageList'а все равно дает лучший результат, чем выделение с помощью АПИ прогой GrapHicsFromFrx (Brad Martinez), которая, несмотря на жуткое количество вызовов АПИ, все равно определяет этот ImageList неправильно - просто как BinaryData длиной 13004 байт:





Код, конечно, у Brad Martinez поучительный и вы можете его сгрузить с этой странички, но я думаю, ошибку в нем все равно никто найти не сможет... И поэтому - мой код рулит!



Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/windows/frx.htm
<Назад>  <На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>