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 поучительный и вы можете его сгрузить с этой странички, но я думаю, ошибку в нем все равно никто найти не сможет... И поэтому - мой код рулит!
|