From 05c13a15e210000d6750447918f6daf01f70869f Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 12:23:01 +0200 Subject: [PATCH 01/15] Added alt-shortcuts to main context menu --- ReClass.NET/Forms/MainForm.Designer.cs | 32 +++++++++++++------------- ReClass.NET/Forms/MainForm.resx | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index e2b2a199..7b2135f7 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -410,7 +410,7 @@ private void InitializeComponent() this.changeTypeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Exchange_Button; this.changeTypeToolStripMenuItem.Name = "changeTypeToolStripMenuItem"; this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.changeTypeToolStripMenuItem.Text = "Change Type"; + this.changeTypeToolStripMenuItem.Text = "&Change Type"; // // addBytesToolStripMenuItem // @@ -426,7 +426,7 @@ private void InitializeComponent() this.addBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Add_Bytes_X; this.addBytesToolStripMenuItem.Name = "addBytesToolStripMenuItem"; this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.addBytesToolStripMenuItem.Text = "Add Bytes"; + this.addBytesToolStripMenuItem.Text = "&Add Bytes"; // // integerToolStripMenuItem1 // @@ -513,7 +513,7 @@ private void InitializeComponent() this.insertBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Insert_Bytes_X; this.insertBytesToolStripMenuItem.Name = "insertBytesToolStripMenuItem"; this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.insertBytesToolStripMenuItem.Text = "Insert Bytes"; + this.insertBytesToolStripMenuItem.Text = "&Insert Bytes"; // // integerToolStripMenuItem8 // @@ -596,7 +596,7 @@ private void InitializeComponent() this.createClassFromNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Class_Add; this.createClassFromNodesToolStripMenuItem.Name = "createClassFromNodesToolStripMenuItem"; this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.createClassFromNodesToolStripMenuItem.Text = "Create Class from Nodes"; + this.createClassFromNodesToolStripMenuItem.Text = "C&reate Class from Nodes"; this.createClassFromNodesToolStripMenuItem.Click += new System.EventHandler(this.createClassFromNodesToolStripMenuItem_Click); // // toolStripSeparator13 @@ -609,7 +609,7 @@ private void InitializeComponent() this.dissectNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Camera; this.dissectNodesToolStripMenuItem.Name = "dissectNodesToolStripMenuItem"; this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.dissectNodesToolStripMenuItem.Text = "Dissect Node(s)"; + this.dissectNodesToolStripMenuItem.Text = "&Dissect Node(s)"; this.dissectNodesToolStripMenuItem.Click += new System.EventHandler(this.dissectNodesToolStripMenuItem_Click); // // toolStripSeparator9 @@ -622,7 +622,7 @@ private void InitializeComponent() this.searchForEqualValuesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.searchForEqualValuesToolStripMenuItem.Name = "searchForEqualValuesToolStripMenuItem"; this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.searchForEqualValuesToolStripMenuItem.Text = "Search for equal values..."; + this.searchForEqualValuesToolStripMenuItem.Text = "&Search for equal values..."; this.searchForEqualValuesToolStripMenuItem.Click += new System.EventHandler(this.searchForEqualValuesToolStripMenuItem_Click); // // toolStripSeparator15 @@ -635,7 +635,7 @@ private void InitializeComponent() this.findOutWhatAccessesThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Access; this.findOutWhatAccessesThisAddressToolStripMenuItem.Name = "findOutWhatAccessesThisAddressToolStripMenuItem"; this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "Find out what accesses this address..."; + this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "&Find out what accesses this address..."; this.findOutWhatAccessesThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatAccessesThisAddressToolStripMenuItem_Click); // // findOutWhatWritesToThisAddressToolStripMenuItem @@ -643,7 +643,7 @@ private void InitializeComponent() this.findOutWhatWritesToThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Write; this.findOutWhatWritesToThisAddressToolStripMenuItem.Name = "findOutWhatWritesToThisAddressToolStripMenuItem"; this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what writes to this address..."; + this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what &writes to this address..."; this.findOutWhatWritesToThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatWritesToThisAddressToolStripMenuItem_Click); // // toolStripSeparator14 @@ -656,7 +656,7 @@ private void InitializeComponent() this.copyNodeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyNodeToolStripMenuItem.Name = "copyNodeToolStripMenuItem"; this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.copyNodeToolStripMenuItem.Text = "Copy Node(s)"; + this.copyNodeToolStripMenuItem.Text = "C&opy Node(s)"; this.copyNodeToolStripMenuItem.Click += new System.EventHandler(this.copyNodeToolStripMenuItem_Click); // // pasteNodesToolStripMenuItem @@ -664,7 +664,7 @@ private void InitializeComponent() this.pasteNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Paste; this.pasteNodesToolStripMenuItem.Name = "pasteNodesToolStripMenuItem"; this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.pasteNodesToolStripMenuItem.Text = "Paste Node(s)"; + this.pasteNodesToolStripMenuItem.Text = "&Paste Node(s)"; this.pasteNodesToolStripMenuItem.Click += new System.EventHandler(this.pasteNodesToolStripMenuItem_Click); // // toolStripSeparator10 @@ -677,7 +677,7 @@ private void InitializeComponent() this.removeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Delete; this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; this.removeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.removeToolStripMenuItem.Text = "Remove Node(s)"; + this.removeToolStripMenuItem.Text = "&Remove Node(s)"; this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); // // toolStripSeparator12 @@ -690,7 +690,7 @@ private void InitializeComponent() this.hideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.hideNodesToolStripMenuItem.Name = "hideNodesToolStripMenuItem"; this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.hideNodesToolStripMenuItem.Text = "Hide selected Node(s)"; + this.hideNodesToolStripMenuItem.Text = "&Hide selected Node(s)"; this.hideNodesToolStripMenuItem.Click += new System.EventHandler(this.hideNodesToolStripMenuItem_Click); // // unhideNodesToolStripMenuItem @@ -702,7 +702,7 @@ private void InitializeComponent() this.unhideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.unhideNodesToolStripMenuItem.Name = "unhideNodesToolStripMenuItem"; this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.unhideNodesToolStripMenuItem.Text = "Unhide..."; + this.unhideNodesToolStripMenuItem.Text = "&Unhide..."; // // unhideChildNodesToolStripMenuItem // @@ -738,7 +738,7 @@ private void InitializeComponent() this.copyAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyAddressToolStripMenuItem.Name = "copyAddressToolStripMenuItem"; this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.copyAddressToolStripMenuItem.Text = "Copy Address"; + this.copyAddressToolStripMenuItem.Text = "Cop&y Address"; this.copyAddressToolStripMenuItem.Click += new System.EventHandler(this.copyAddressToolStripMenuItem_Click); // // toolStripSeparator11 @@ -751,7 +751,7 @@ private void InitializeComponent() this.showCodeOfClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Code_Cpp; this.showCodeOfClassToolStripMenuItem.Name = "showCodeOfClassToolStripMenuItem"; this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.showCodeOfClassToolStripMenuItem.Text = "Show C++ Code of Class"; + this.showCodeOfClassToolStripMenuItem.Text = "Show C&++ Code of Class"; this.showCodeOfClassToolStripMenuItem.Click += new System.EventHandler(this.showCodeOfClassToolStripMenuItem_Click); // // shrinkClassToolStripMenuItem @@ -759,7 +759,7 @@ private void InitializeComponent() this.shrinkClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Chart_Delete; this.shrinkClassToolStripMenuItem.Name = "shrinkClassToolStripMenuItem"; this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.shrinkClassToolStripMenuItem.Text = "Shrink Class"; + this.shrinkClassToolStripMenuItem.Text = "Shri&nk Class"; this.shrinkClassToolStripMenuItem.Click += new System.EventHandler(this.shrinkClassToolStripMenuItem_Click); // // toolStrip diff --git a/ReClass.NET/Forms/MainForm.resx b/ReClass.NET/Forms/MainForm.resx index c430dab3..0e88c503 100644 --- a/ReClass.NET/Forms/MainForm.resx +++ b/ReClass.NET/Forms/MainForm.resx @@ -206,6 +206,6 @@ - 42 + 104 \ No newline at end of file From e3660a7ab11dd9c203c39b62ef42b3a5c93883ca Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 14:28:17 +0200 Subject: [PATCH 02/15] Defined various shortcut keys on the node type menu items. Changed toolbar button to toolbar menu item so it can have a shortcut too. --- ReClass.NET/Forms/MainForm.Designer.cs | 1 + ReClass.NET/Settings.cs | 36 +++++++++++++++++++++++++- ReClass.NET/UI/NodeTypesBuilder.cs | 18 ++++++++----- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index 7b2135f7..80cf31e4 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -1377,6 +1377,7 @@ private void InitializeComponent() this.Controls.Add(this.toolStrip); this.Controls.Add(this.statusStrip); this.Controls.Add(this.mainMenuStrip); + this.KeyPreview = true; this.MainMenuStrip = this.mainMenuStrip; this.MinimumSize = new System.Drawing.Size(200, 100); this.Name = "MainForm"; diff --git a/ReClass.NET/Settings.cs b/ReClass.NET/Settings.cs index b5d9268b..16f0abb1 100644 --- a/ReClass.NET/Settings.cs +++ b/ReClass.NET/Settings.cs @@ -1,11 +1,39 @@ -using System.Drawing; +using System; +using System.Collections.Generic; +using System.Drawing; using System.Text; +using System.Windows.Forms; +using ReClassNET.Nodes; using ReClassNET.Util; namespace ReClassNET { public class Settings { + private readonly Dictionary _shortcutKeyPerNode; + + public Settings() + { + _shortcutKeyPerNode = new Dictionary + { + { typeof(Hex64Node), Keys.Control | Keys.Shift | Keys.D6 }, + { typeof(ClassInstanceNode), Keys.Control | Keys.Shift | Keys.I }, + { typeof(FloatNode), Keys.Control | Keys.Shift | Keys.F }, + { typeof(Hex8Node), Keys.Control | Keys.Shift | Keys.B }, + { typeof(PointerNode), Keys.Control | Keys.Shift | Keys.P }, + { typeof(Vector2Node), Keys.Control | Keys.Shift | Keys.D2 }, + { typeof(Vector3Node), Keys.Control | Keys.Shift | Keys.D3 }, + { typeof(Vector4Node), Keys.Control | Keys.Shift | Keys.D4 }, + { typeof(VirtualMethodTableNode), Keys.Control | Keys.Shift | Keys.T }, + { typeof(BoolNode), Keys.Control | Keys.Shift | Keys.O }, + { typeof(EnumNode), Keys.Control | Keys.Shift | Keys.E }, + { typeof(Int32Node), Keys.Control | Keys.Shift | Keys.N } + }; + + // Define more here. + } + + // Application Settings public string LastProcess { get; set; } = string.Empty; @@ -76,6 +104,12 @@ public class Settings public CustomDataMap CustomData { get; } = new CustomDataMap(); + + public Keys GetShortcutKeyForNodeType(Type nodeType) + { + return !_shortcutKeyPerNode.TryGetValue(nodeType, out var shortcutKeys) ? Keys.None : shortcutKeys; + } + public Settings Clone() => MemberwiseClone() as Settings; } } diff --git a/ReClass.NET/UI/NodeTypesBuilder.cs b/ReClass.NET/UI/NodeTypesBuilder.cs index 8d519022..b0badd25 100644 --- a/ReClass.NET/UI/NodeTypesBuilder.cs +++ b/ReClass.NET/UI/NodeTypesBuilder.cs @@ -57,14 +57,15 @@ public static IEnumerable CreateToolStripButtons(Action han return CreateToolStripItems(t => { - GetNodeInfoFromType(t, out var label, out var icon); + GetNodeInfoFromType(t, out var label, out var icon, out var shortcutKeys); - var item = new TypeToolStripButton + var item = new TypeToolStripMenuItem { Value = t, ToolTipText = label, DisplayStyle = ToolStripItemDisplayStyle.Image, - Image = icon + Image = icon, + ShortcutKeys = shortcutKeys, }; item.Click += clickHandler; return item; @@ -74,7 +75,7 @@ public static IEnumerable CreateToolStripButtons(Action han Image = p.Icon }, t => { - GetNodeInfoFromType(t, out var label, out var icon); + GetNodeInfoFromType(t, out var label, out var icon, out var shortcutKeys); var item = new TypeToolStripMenuItem { @@ -95,13 +96,14 @@ public static IEnumerable CreateToolStripMenuItems(Action h var items = CreateToolStripItems(t => { - GetNodeInfoFromType(t, out var label, out var icon); + GetNodeInfoFromType(t, out var label, out var icon, out var shortcutKeys); var item = new TypeToolStripMenuItem { Value = t, Text = label, - Image = icon + Image = icon, + ShortcutKeys = shortcutKeys, }; item.Click += clickHandler; return item; @@ -166,10 +168,12 @@ private static IEnumerable CreateToolStripItems(Func Date: Mon, 3 Jul 2023 14:57:10 +0200 Subject: [PATCH 03/15] Moved ReadFromBuffer to MemoryBuffer where it belongs, and it's now usable from different nodes. Changed VTable node so it always displays the RTTI information if available. --- ReClass.NET/Memory/MemoryBuffer.cs | 7 +++++++ ReClass.NET/Nodes/Hex64Node.cs | 12 +++--------- ReClass.NET/Nodes/VirtualMethodTableNode.cs | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/ReClass.NET/Memory/MemoryBuffer.cs b/ReClass.NET/Memory/MemoryBuffer.cs index e1b515a4..bde66ace 100644 --- a/ReClass.NET/Memory/MemoryBuffer.cs +++ b/ReClass.NET/Memory/MemoryBuffer.cs @@ -366,5 +366,12 @@ public bool HasChanged(int offset, int length) return false; } + + + public UInt64FloatDoubleData ReadFromBuffer(int offset) => new UInt64FloatDoubleData + { + Raw1 = ReadInt32(offset), + Raw2 = ReadInt32(offset + sizeof(int)) + }; } } diff --git a/ReClass.NET/Nodes/Hex64Node.cs b/ReClass.NET/Nodes/Hex64Node.cs index d54f1e71..012859ef 100644 --- a/ReClass.NET/Nodes/Hex64Node.cs +++ b/ReClass.NET/Nodes/Hex64Node.cs @@ -18,7 +18,7 @@ public override void GetUserInterfaceInfo(out string name, out Image icon) public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) { - var value = ReadFromBuffer(spot.Memory, Offset); + var value = spot.Memory.ReadFromBuffer(Offset); address = value.IntPtr; @@ -27,7 +27,7 @@ public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) public override string GetToolTipText(HotSpot spot) { - var value = ReadFromBuffer(spot.Memory, Offset); + var value = spot.Memory.ReadFromBuffer(Offset); return $"Int64: {value.LongValue}\nUInt64: 0x{value.ULongValue:X016}\nFloat: {value.FloatValue:0.000}\nDouble: {value.DoubleValue:0.000}"; } @@ -46,17 +46,11 @@ protected override int AddComment(DrawContext context, int x, int y) { x = base.AddComment(context, x, y); - var value = ReadFromBuffer(context.Memory, Offset); + var value = context.Memory.ReadFromBuffer(Offset); x = AddComment(context, x, y, value.FloatValue, value.IntPtr, value.UIntPtr); return x; } - - private static UInt64FloatDoubleData ReadFromBuffer(MemoryBuffer memory, int offset) => new UInt64FloatDoubleData - { - Raw1 = memory.ReadInt32(offset), - Raw2 = memory.ReadInt32(offset + sizeof(int)) - }; } } diff --git a/ReClass.NET/Nodes/VirtualMethodTableNode.cs b/ReClass.NET/Nodes/VirtualMethodTableNode.cs index 9e82ab40..3f58c3e5 100644 --- a/ReClass.NET/Nodes/VirtualMethodTableNode.cs +++ b/ReClass.NET/Nodes/VirtualMethodTableNode.cs @@ -34,6 +34,25 @@ public override void Initialize() } } + + protected override int AddComment(DrawContext context, int x, int y) + { + x = base.AddComment(context, x, y); + + if (context.Settings.ShowCommentRtti) + { + var addressFirstVTableFunction = context.Memory.ReadFromBuffer(Offset).IntPtr; + var rtti = context.Process.ReadRemoteRuntimeTypeInformation(addressFirstVTableFunction); + if (!string.IsNullOrEmpty(rtti)) + { + x = AddText(context, x, y, context.Settings.OffsetColor, HotSpot.ReadOnlyId, rtti) + context.Font.Width; + } + } + + return x; + } + + public override Size Draw(DrawContext context, int x, int y) { if (IsHidden && !IsWrapped) From 4d2f079049b61d83d391e618e04fc927de783c3c Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 15:15:56 +0200 Subject: [PATCH 04/15] Redefined some kb shortcuts, as ctrl-shift-c/v aren't used elsewhere --- ReClass.NET/Settings.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ReClass.NET/Settings.cs b/ReClass.NET/Settings.cs index 16f0abb1..8c0ec099 100644 --- a/ReClass.NET/Settings.cs +++ b/ReClass.NET/Settings.cs @@ -17,17 +17,17 @@ public Settings() _shortcutKeyPerNode = new Dictionary { { typeof(Hex64Node), Keys.Control | Keys.Shift | Keys.D6 }, - { typeof(ClassInstanceNode), Keys.Control | Keys.Shift | Keys.I }, + { typeof(ClassInstanceNode), Keys.Control | Keys.Shift | Keys.C }, { typeof(FloatNode), Keys.Control | Keys.Shift | Keys.F }, { typeof(Hex8Node), Keys.Control | Keys.Shift | Keys.B }, { typeof(PointerNode), Keys.Control | Keys.Shift | Keys.P }, { typeof(Vector2Node), Keys.Control | Keys.Shift | Keys.D2 }, { typeof(Vector3Node), Keys.Control | Keys.Shift | Keys.D3 }, { typeof(Vector4Node), Keys.Control | Keys.Shift | Keys.D4 }, - { typeof(VirtualMethodTableNode), Keys.Control | Keys.Shift | Keys.T }, + { typeof(VirtualMethodTableNode), Keys.Control | Keys.Shift | Keys.V }, { typeof(BoolNode), Keys.Control | Keys.Shift | Keys.O }, { typeof(EnumNode), Keys.Control | Keys.Shift | Keys.E }, - { typeof(Int32Node), Keys.Control | Keys.Shift | Keys.N } + { typeof(Int32Node), Keys.Control | Keys.Shift | Keys.I } }; // Define more here. From 208454edf064e61c79a3c3ecbfef27c60210213a Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 19:26:55 +0200 Subject: [PATCH 05/15] Added a way to name a class after RTTI information associated with the class. This required some hairy work in a lot of places as the context menu wasn't usable on nested classes. It now is --- ReClass.NET/Controls/MemoryViewControl.cs | 19 +++++ ReClass.NET/Forms/MainForm.Designer.cs | 65 +++++++++++------- ReClass.NET/Forms/MainForm.cs | 15 +++- ReClass.NET/Nodes/BaseContainerNode.cs | 4 +- ReClass.NET/Nodes/BaseHexCommentNode.cs | 8 ++- ReClass.NET/Nodes/BaseNode.cs | 13 +++- ReClass.NET/Nodes/ClassNode.cs | 40 +++++++++++ ReClass.NET/Nodes/PointerNode.cs | 36 ++++++++++ ReClass.NET/Nodes/VirtualMethodTableNode.cs | 16 ++++- ReClass.NET/Properties/Resources.Designer.cs | 14 +++- ReClass.NET/Properties/Resources.resx | 3 + ReClass.NET/ReClass.NET.csproj | 3 + .../Images/B16x16_Button_AutoName.png | Bin 0 -> 383 bytes ReClass.NET/UI/HotSpot.cs | 2 +- 14 files changed, 200 insertions(+), 38 deletions(-) create mode 100644 ReClass.NET/Resources/Images/B16x16_Button_AutoName.png diff --git a/ReClass.NET/Controls/MemoryViewControl.cs b/ReClass.NET/Controls/MemoryViewControl.cs index 64b8dfa4..1769f05a 100644 --- a/ReClass.NET/Controls/MemoryViewControl.cs +++ b/ReClass.NET/Controls/MemoryViewControl.cs @@ -704,5 +704,24 @@ public void Reset() VerticalScroll.Value = VerticalScroll.Minimum; } + + + public void AutoNameCurrentClassFromRTTI(ClassNode classNode) + { + var args = new DrawContextRequestEventArgs { Node = classNode }; + + var requestHandler = DrawContextRequested; + requestHandler?.Invoke(this, args); + var view = new DrawContext + { + Settings = args.Settings, + Process = args.Process, + Memory = args.Memory, + CurrentTime = args.CurrentTime, + Address = args.BaseAddress, + Level = 0, + }; + classNode.AutoNameFromRTTI(view); + } } } diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index 80cf31e4..cb15cbe5 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -77,6 +77,7 @@ private void InitializeComponent() this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); this.createClassFromNodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator(); + this.autoNameClassToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dissectNodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); this.searchForEqualValuesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -382,6 +383,7 @@ private void InitializeComponent() this.toolStripSeparator8, this.createClassFromNodesToolStripMenuItem, this.toolStripSeparator13, + this.autoNameClassToolStripMenuItem, this.dissectNodesToolStripMenuItem, this.toolStripSeparator9, this.searchForEqualValuesToolStripMenuItem, @@ -402,14 +404,14 @@ private void InitializeComponent() this.showCodeOfClassToolStripMenuItem, this.shrinkClassToolStripMenuItem}); this.selectedNodeContextMenuStrip.Name = "selectedNodeContextMenuStrip"; - this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(270, 410); + this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(296, 454); this.selectedNodeContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.selectedNodeContextMenuStrip_Opening); // // changeTypeToolStripMenuItem // this.changeTypeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Exchange_Button; this.changeTypeToolStripMenuItem.Name = "changeTypeToolStripMenuItem"; - this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.changeTypeToolStripMenuItem.Text = "&Change Type"; // // addBytesToolStripMenuItem @@ -425,7 +427,7 @@ private void InitializeComponent() this.toolStripMenuItem1}); this.addBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Add_Bytes_X; this.addBytesToolStripMenuItem.Name = "addBytesToolStripMenuItem"; - this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.addBytesToolStripMenuItem.Text = "&Add Bytes"; // // integerToolStripMenuItem1 @@ -512,7 +514,7 @@ private void InitializeComponent() this.toolStripMenuItem2}); this.insertBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Insert_Bytes_X; this.insertBytesToolStripMenuItem.Name = "insertBytesToolStripMenuItem"; - this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.insertBytesToolStripMenuItem.Text = "&Insert Bytes"; // // integerToolStripMenuItem8 @@ -589,52 +591,62 @@ private void InitializeComponent() // toolStripSeparator8 // this.toolStripSeparator8.Name = "toolStripSeparator8"; - this.toolStripSeparator8.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator8.Size = new System.Drawing.Size(292, 6); // // createClassFromNodesToolStripMenuItem // this.createClassFromNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Class_Add; this.createClassFromNodesToolStripMenuItem.Name = "createClassFromNodesToolStripMenuItem"; - this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.createClassFromNodesToolStripMenuItem.Text = "C&reate Class from Nodes"; this.createClassFromNodesToolStripMenuItem.Click += new System.EventHandler(this.createClassFromNodesToolStripMenuItem_Click); // // toolStripSeparator13 // this.toolStripSeparator13.Name = "toolStripSeparator13"; - this.toolStripSeparator13.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator13.Size = new System.Drawing.Size(292, 6); + // + // autoNameClassToolStripMenuItem + // + this.autoNameClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_AutoName; + this.autoNameClassToolStripMenuItem.Name = "autoNameClassToolStripMenuItem"; + this.autoNameClassToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.N))); + this.autoNameClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.autoNameClassToolStripMenuItem.Text = "Auto-Name Class from RTTI"; + this.autoNameClassToolStripMenuItem.Click += new System.EventHandler(this.autoNameClassToolStripMenuItem_Click); // // dissectNodesToolStripMenuItem // this.dissectNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Camera; this.dissectNodesToolStripMenuItem.Name = "dissectNodesToolStripMenuItem"; - this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.dissectNodesToolStripMenuItem.Text = "&Dissect Node(s)"; this.dissectNodesToolStripMenuItem.Click += new System.EventHandler(this.dissectNodesToolStripMenuItem_Click); // // toolStripSeparator9 // this.toolStripSeparator9.Name = "toolStripSeparator9"; - this.toolStripSeparator9.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator9.Size = new System.Drawing.Size(292, 6); // // searchForEqualValuesToolStripMenuItem // this.searchForEqualValuesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.searchForEqualValuesToolStripMenuItem.Name = "searchForEqualValuesToolStripMenuItem"; - this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.searchForEqualValuesToolStripMenuItem.Text = "&Search for equal values..."; this.searchForEqualValuesToolStripMenuItem.Click += new System.EventHandler(this.searchForEqualValuesToolStripMenuItem_Click); // // toolStripSeparator15 // this.toolStripSeparator15.Name = "toolStripSeparator15"; - this.toolStripSeparator15.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator15.Size = new System.Drawing.Size(292, 6); // // findOutWhatAccessesThisAddressToolStripMenuItem // this.findOutWhatAccessesThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Access; this.findOutWhatAccessesThisAddressToolStripMenuItem.Name = "findOutWhatAccessesThisAddressToolStripMenuItem"; - this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "&Find out what accesses this address..."; this.findOutWhatAccessesThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatAccessesThisAddressToolStripMenuItem_Click); // @@ -642,20 +654,20 @@ private void InitializeComponent() // this.findOutWhatWritesToThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Write; this.findOutWhatWritesToThisAddressToolStripMenuItem.Name = "findOutWhatWritesToThisAddressToolStripMenuItem"; - this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what &writes to this address..."; this.findOutWhatWritesToThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatWritesToThisAddressToolStripMenuItem_Click); // // toolStripSeparator14 // this.toolStripSeparator14.Name = "toolStripSeparator14"; - this.toolStripSeparator14.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator14.Size = new System.Drawing.Size(292, 6); // // copyNodeToolStripMenuItem // this.copyNodeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyNodeToolStripMenuItem.Name = "copyNodeToolStripMenuItem"; - this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.copyNodeToolStripMenuItem.Text = "C&opy Node(s)"; this.copyNodeToolStripMenuItem.Click += new System.EventHandler(this.copyNodeToolStripMenuItem_Click); // @@ -663,33 +675,33 @@ private void InitializeComponent() // this.pasteNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Paste; this.pasteNodesToolStripMenuItem.Name = "pasteNodesToolStripMenuItem"; - this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.pasteNodesToolStripMenuItem.Text = "&Paste Node(s)"; this.pasteNodesToolStripMenuItem.Click += new System.EventHandler(this.pasteNodesToolStripMenuItem_Click); // // toolStripSeparator10 // this.toolStripSeparator10.Name = "toolStripSeparator10"; - this.toolStripSeparator10.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator10.Size = new System.Drawing.Size(292, 6); // // removeToolStripMenuItem // this.removeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Delete; this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; - this.removeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.removeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.removeToolStripMenuItem.Text = "&Remove Node(s)"; this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); // // toolStripSeparator12 // this.toolStripSeparator12.Name = "toolStripSeparator12"; - this.toolStripSeparator12.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator12.Size = new System.Drawing.Size(292, 6); // // hideNodesToolStripMenuItem // this.hideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.hideNodesToolStripMenuItem.Name = "hideNodesToolStripMenuItem"; - this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.hideNodesToolStripMenuItem.Text = "&Hide selected Node(s)"; this.hideNodesToolStripMenuItem.Click += new System.EventHandler(this.hideNodesToolStripMenuItem_Click); // @@ -701,7 +713,7 @@ private void InitializeComponent() this.unhideNodesBelowToolStripMenuItem}); this.unhideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.unhideNodesToolStripMenuItem.Name = "unhideNodesToolStripMenuItem"; - this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.unhideNodesToolStripMenuItem.Text = "&Unhide..."; // // unhideChildNodesToolStripMenuItem @@ -731,26 +743,26 @@ private void InitializeComponent() // toolStripSeparator18 // this.toolStripSeparator18.Name = "toolStripSeparator18"; - this.toolStripSeparator18.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator18.Size = new System.Drawing.Size(292, 6); // // copyAddressToolStripMenuItem // this.copyAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyAddressToolStripMenuItem.Name = "copyAddressToolStripMenuItem"; - this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.copyAddressToolStripMenuItem.Text = "Cop&y Address"; this.copyAddressToolStripMenuItem.Click += new System.EventHandler(this.copyAddressToolStripMenuItem_Click); // // toolStripSeparator11 // this.toolStripSeparator11.Name = "toolStripSeparator11"; - this.toolStripSeparator11.Size = new System.Drawing.Size(266, 6); + this.toolStripSeparator11.Size = new System.Drawing.Size(292, 6); // // showCodeOfClassToolStripMenuItem // this.showCodeOfClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Code_Cpp; this.showCodeOfClassToolStripMenuItem.Name = "showCodeOfClassToolStripMenuItem"; - this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.showCodeOfClassToolStripMenuItem.Text = "Show C&++ Code of Class"; this.showCodeOfClassToolStripMenuItem.Click += new System.EventHandler(this.showCodeOfClassToolStripMenuItem_Click); // @@ -758,7 +770,7 @@ private void InitializeComponent() // this.shrinkClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Chart_Delete; this.shrinkClassToolStripMenuItem.Name = "shrinkClassToolStripMenuItem"; - this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); this.shrinkClassToolStripMenuItem.Text = "Shri&nk Class"; this.shrinkClassToolStripMenuItem.Click += new System.EventHandler(this.shrinkClassToolStripMenuItem_Click); // @@ -1543,6 +1555,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem showEnumsToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator23; private System.Windows.Forms.ToolStripMenuItem isLittleEndianToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem autoNameClassToolStripMenuItem; } } diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index e771a10d..435d7a87 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -835,6 +835,7 @@ private void memoryViewControl_SelectionChanged(object sender, EventArgs e) addBytesToolStripDropDownButton.Enabled = parentContainer != null || isContainerNode; insertBytesToolStripDropDownButton.Enabled = selectedNodes.Count == 1 && parentContainer != null && !isContainerNode; + autoNameClassToolStripMenuItem.Enabled = nodeIsClass; var enabled = selectedNodes.Count > 0 && !nodeIsClass; toolStrip.Items.OfType().ForEach(b => b.Enabled = enabled); @@ -1027,7 +1028,7 @@ private void memoryViewControl_DrawContextRequested(object sender, DrawContextRe { var process = Program.RemoteProcess; - var classNode = CurrentClassNode; + var classNode = (args.Node as ClassNode) ?? CurrentClassNode; if (classNode != null) { memoryViewBuffer.Size = classNode.MemorySize; @@ -1051,5 +1052,17 @@ private void memoryViewControl_DrawContextRequested(object sender, DrawContextRe args.BaseAddress = address; } } + + + private void autoNameClassToolStripMenuItem_Click(object sender, EventArgs e) + { + var selectedNodes = memoryViewControl.GetSelectedNodes(); + var node = selectedNodes.FirstOrDefault()?.Node; + if (node == null || !(node is ClassNode)) + { + return; + } + memoryViewControl.AutoNameCurrentClassFromRTTI(node as ClassNode); + } } } diff --git a/ReClass.NET/Nodes/BaseContainerNode.cs b/ReClass.NET/Nodes/BaseContainerNode.cs index 6926111f..aa106dd0 100644 --- a/ReClass.NET/Nodes/BaseContainerNode.cs +++ b/ReClass.NET/Nodes/BaseContainerNode.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics.Contracts; @@ -183,8 +183,8 @@ public void ReplaceChildNode(BaseNode oldNode, BaseNode newNode, ref ListGets or sets the parent node. public BaseNode ParentNode { get; internal set; } - /// Gets a value indicating whether this node is wrapped into an other node. - public bool IsWrapped => ParentNode is BaseWrapperNode; + /// Gets a value indicating whether this node is wrapped into an other node. We see classnodes never as wrapped. + public bool IsWrapped => (ParentNode is BaseWrapperNode && !(this is ClassNode)); /// Gets or sets a value indicating whether this node is hidden. public bool IsHidden { get; set; } @@ -236,6 +236,15 @@ public virtual void ClearSelection() /// The calculated height. public abstract int CalculateDrawnHeight(DrawContext context); + /// + /// Called when this node has been created, initialized and the parent node has been assigned. For some nodes + /// Additional work has to be performed, this work can be done in a derived method of this method. + /// + public virtual void PerformPostInitWork() + { + // nop + } + /// Updates the node from the given . Sets the and of the node. /// The spot. public virtual void Update(HotSpot spot) diff --git a/ReClass.NET/Nodes/ClassNode.cs b/ReClass.NET/Nodes/ClassNode.cs index 9b144061..92aa6691 100644 --- a/ReClass.NET/Nodes/ClassNode.cs +++ b/ReClass.NET/Nodes/ClassNode.cs @@ -52,6 +52,46 @@ public static ClassNode Create() return new ClassNode(true); } + + public void AutoNameFromRTTI(DrawContext context) + { + // first node should be a VTable node or a hex64/32 node + if (Nodes.Count <= 0) + { + return; + } + + var rttiInfoFromFirstNode = string.Empty; + var firstNode = Nodes[0]; + if (firstNode is VirtualMethodTableNode vtableNode) + { + rttiInfoFromFirstNode = vtableNode.GetAssociatedRemoteRuntimeTypeInformation(context); + } + else + { + if (firstNode is BaseHexCommentNode baseHexCommentNode) + { + // ask it as if it might point to a vtable + var value = context.Memory.ReadFromBuffer(Offset); + rttiInfoFromFirstNode = baseHexCommentNode.GetAssociatedRemoteRuntimeTypeInformation(context, value.IntPtr); + if (!string.IsNullOrEmpty(rttiInfoFromFirstNode)) + { + // convert first node to vtable node +#warning IMPLEMENT: CONVERT NODE TO VTABLE NODE + } + } + } + + if (string.IsNullOrEmpty(rttiInfoFromFirstNode)) + { + return; + } + + var fragments = rttiInfoFromFirstNode.Split(':'); + this.Name = fragments[0]; + } + + public override void GetUserInterfaceInfo(out string name, out Image icon) { throw new InvalidOperationException($"The '{nameof(ClassNode)}' node should not be accessible from the ui."); diff --git a/ReClass.NET/Nodes/PointerNode.cs b/ReClass.NET/Nodes/PointerNode.cs index 027b0d28..47431aca 100644 --- a/ReClass.NET/Nodes/PointerNode.cs +++ b/ReClass.NET/Nodes/PointerNode.cs @@ -1,5 +1,6 @@ using System; using System.Drawing; +using ReClassNET.AddressParser; using ReClassNET.Controls; using ReClassNET.Memory; using ReClassNET.UI; @@ -134,5 +135,40 @@ public override int CalculateDrawnHeight(DrawContext context) } return height; } + + + public override void PerformPostInitWork() + { + base.PerformPostInitWork(); + + var parentClass = ParentNode as ClassNode; + if (parentClass == null) + { + return; + } + + var process = Program.RemoteProcess; + IntPtr address; + try + { + address = process.ParseAddress(parentClass.AddressFormula); + } + catch (ParseException) + { + address = IntPtr.Zero; + } + + var memoryBuffer = new MemoryBuffer() { Size = parentClass.MemorySize}; + memoryBuffer.UpdateFrom(process, address); + var ptr = memoryBuffer.ReadIntPtr(Offset); + + var classNode = ((ClassInstanceNode)InnerNode)?.InnerNode as ClassNode; + if (classNode == null) + { + return; + } + + classNode.AddressFormula = ptr.ToString(Constants.AddressHexFormat); + } } } diff --git a/ReClass.NET/Nodes/VirtualMethodTableNode.cs b/ReClass.NET/Nodes/VirtualMethodTableNode.cs index 3f58c3e5..8136a268 100644 --- a/ReClass.NET/Nodes/VirtualMethodTableNode.cs +++ b/ReClass.NET/Nodes/VirtualMethodTableNode.cs @@ -41,18 +41,28 @@ protected override int AddComment(DrawContext context, int x, int y) if (context.Settings.ShowCommentRtti) { - var addressFirstVTableFunction = context.Memory.ReadFromBuffer(Offset).IntPtr; - var rtti = context.Process.ReadRemoteRuntimeTypeInformation(addressFirstVTableFunction); + var rtti = GetAssociatedRemoteRuntimeTypeInformation(context); if (!string.IsNullOrEmpty(rtti)) { x = AddText(context, x, y, context.Settings.OffsetColor, HotSpot.ReadOnlyId, rtti) + context.Font.Width; } } - return x; } + public string GetAssociatedRemoteRuntimeTypeInformation(DrawContext context) + { + var addressFirstVTableFunction = context.Memory.ReadFromBuffer(Offset).IntPtr; + if (addressFirstVTableFunction != IntPtr.Zero) + { + return context.Process.ReadRemoteRuntimeTypeInformation(addressFirstVTableFunction); + } + + return string.Empty; + } + + public override Size Draw(DrawContext context, int x, int y) { if (IsHidden && !IsWrapped) diff --git a/ReClass.NET/Properties/Resources.Designer.cs b/ReClass.NET/Properties/Resources.Designer.cs index 3d412074..3738ffbc 100644 --- a/ReClass.NET/Properties/Resources.Designer.cs +++ b/ReClass.NET/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace ReClassNET.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -190,6 +190,16 @@ internal static System.Drawing.Bitmap B16x16_Button_Array { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap B16x16_Button_AutoName { + get { + object obj = ResourceManager.GetObject("B16x16_Button_AutoName", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -1371,7 +1381,7 @@ internal static System.Drawing.Bitmap B32x32_Plugin { } /// - /// Looks up a localized string similar to 2020/10/17 09:45:04 + /// Looks up a localized string similar to 2023/07/03 12:55:32 ///. /// internal static string BuildDate { diff --git a/ReClass.NET/Properties/Resources.resx b/ReClass.NET/Properties/Resources.resx index 48c2c826..3cee6c55 100644 --- a/ReClass.NET/Properties/Resources.resx +++ b/ReClass.NET/Properties/Resources.resx @@ -517,4 +517,7 @@ ..\Resources\Images\B16x16_Button_NUInt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Images\B16x16_Button_AutoName.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/ReClass.NET/ReClass.NET.csproj b/ReClass.NET/ReClass.NET.csproj index 0c990cc2..6422eb12 100644 --- a/ReClass.NET/ReClass.NET.csproj +++ b/ReClass.NET/ReClass.NET.csproj @@ -1023,6 +1023,9 @@ + + + powershell -Command "((Get-Date).ToUniversalTime()).ToString(\"yyyy\/MM\/dd HH:mm:ss\") | Out-File '$(ProjectDir)Resources\BuildDate.txt'" diff --git a/ReClass.NET/Resources/Images/B16x16_Button_AutoName.png b/ReClass.NET/Resources/Images/B16x16_Button_AutoName.png new file mode 100644 index 0000000000000000000000000000000000000000..bfdd7e644810d074917d6fb6695b76118945290e GIT binary patch literal 383 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+AuIM3VOOYhE&{2`t$$4J+sk{wF{WU z0%{A|CpL002srrgh%hxUBpph#wvv`-;85s_1q$|TFmU*8-J@Up*T}54Y0jKE@(w%= z42KLDWK%RwFaEH2(V_zq93qWvHb4y<7;iZJ`~Cg>|M?lOnrtN!*TafU%+6T^g^@(K+z3R-Q>lnGR%CbV1?P!Iqb!!|*D!^8ah z`~H>}75)1E@UOc;Z%<;9f++*z5vQKXj&*Kq+1J*!ZDwTZcwunj)ETy90S->S)^27N z0q%`#KC|saS6etRY!t}0KJ)U#wq^zg2E#?q-JX;@c>K8e`UBnQZ3YZ10&&b8g|ZF} aj10baJB3T{WX=GFAcLo?pUXO@geCxDU5-Hj literal 0 HcmV?d00001 diff --git a/ReClass.NET/UI/HotSpot.cs b/ReClass.NET/UI/HotSpot.cs index 3a0d4bc0..27b949d0 100644 --- a/ReClass.NET/UI/HotSpot.cs +++ b/ReClass.NET/UI/HotSpot.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Drawing; using ReClassNET.Memory; using ReClassNET.Nodes; From b61edca698a3c7111c2d328e289ea966340b81f4 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 20:36:54 +0200 Subject: [PATCH 06/15] Changed 'Auto-name' into 'Init from RTTI' and it now also inits the vtable pointer automatically. --- ReClass.NET/Controls/MemoryViewControl.cs | 4 +- ReClass.NET/Forms/MainForm.Designer.cs | 72 +++++++++++------------ ReClass.NET/Forms/MainForm.cs | 6 +- ReClass.NET/Nodes/BaseNode.cs | 9 ++- ReClass.NET/Nodes/ClassNode.cs | 13 +++- 5 files changed, 57 insertions(+), 47 deletions(-) diff --git a/ReClass.NET/Controls/MemoryViewControl.cs b/ReClass.NET/Controls/MemoryViewControl.cs index 1769f05a..58aafb91 100644 --- a/ReClass.NET/Controls/MemoryViewControl.cs +++ b/ReClass.NET/Controls/MemoryViewControl.cs @@ -706,7 +706,7 @@ public void Reset() } - public void AutoNameCurrentClassFromRTTI(ClassNode classNode) + public void InitCurrentClassFromRTTI(ClassNode classNode) { var args = new DrawContextRequestEventArgs { Node = classNode }; @@ -721,7 +721,7 @@ public void AutoNameCurrentClassFromRTTI(ClassNode classNode) Address = args.BaseAddress, Level = 0, }; - classNode.AutoNameFromRTTI(view); + classNode.InitFromRTTI(view); } } } diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index cb15cbe5..5fd3c74e 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -77,7 +77,7 @@ private void InitializeComponent() this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); this.createClassFromNodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator(); - this.autoNameClassToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.initClassToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dissectNodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); this.searchForEqualValuesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -383,7 +383,7 @@ private void InitializeComponent() this.toolStripSeparator8, this.createClassFromNodesToolStripMenuItem, this.toolStripSeparator13, - this.autoNameClassToolStripMenuItem, + this.initClassToolStripMenuItem, this.dissectNodesToolStripMenuItem, this.toolStripSeparator9, this.searchForEqualValuesToolStripMenuItem, @@ -404,14 +404,14 @@ private void InitializeComponent() this.showCodeOfClassToolStripMenuItem, this.shrinkClassToolStripMenuItem}); this.selectedNodeContextMenuStrip.Name = "selectedNodeContextMenuStrip"; - this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(296, 454); + this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(270, 454); this.selectedNodeContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.selectedNodeContextMenuStrip_Opening); // // changeTypeToolStripMenuItem // this.changeTypeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Exchange_Button; this.changeTypeToolStripMenuItem.Name = "changeTypeToolStripMenuItem"; - this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.changeTypeToolStripMenuItem.Text = "&Change Type"; // // addBytesToolStripMenuItem @@ -427,7 +427,7 @@ private void InitializeComponent() this.toolStripMenuItem1}); this.addBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Add_Bytes_X; this.addBytesToolStripMenuItem.Name = "addBytesToolStripMenuItem"; - this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.addBytesToolStripMenuItem.Text = "&Add Bytes"; // // integerToolStripMenuItem1 @@ -514,7 +514,7 @@ private void InitializeComponent() this.toolStripMenuItem2}); this.insertBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Insert_Bytes_X; this.insertBytesToolStripMenuItem.Name = "insertBytesToolStripMenuItem"; - this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.insertBytesToolStripMenuItem.Text = "&Insert Bytes"; // // integerToolStripMenuItem8 @@ -591,62 +591,62 @@ private void InitializeComponent() // toolStripSeparator8 // this.toolStripSeparator8.Name = "toolStripSeparator8"; - this.toolStripSeparator8.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator8.Size = new System.Drawing.Size(266, 6); // // createClassFromNodesToolStripMenuItem // this.createClassFromNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Class_Add; this.createClassFromNodesToolStripMenuItem.Name = "createClassFromNodesToolStripMenuItem"; - this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.createClassFromNodesToolStripMenuItem.Text = "C&reate Class from Nodes"; this.createClassFromNodesToolStripMenuItem.Click += new System.EventHandler(this.createClassFromNodesToolStripMenuItem_Click); // // toolStripSeparator13 // this.toolStripSeparator13.Name = "toolStripSeparator13"; - this.toolStripSeparator13.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator13.Size = new System.Drawing.Size(266, 6); // - // autoNameClassToolStripMenuItem + // initClassToolStripMenuItem // - this.autoNameClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_AutoName; - this.autoNameClassToolStripMenuItem.Name = "autoNameClassToolStripMenuItem"; - this.autoNameClassToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.initClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_AutoName; + this.initClassToolStripMenuItem.Name = "initClassToolStripMenuItem"; + this.initClassToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.N))); - this.autoNameClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); - this.autoNameClassToolStripMenuItem.Text = "Auto-Name Class from RTTI"; - this.autoNameClassToolStripMenuItem.Click += new System.EventHandler(this.autoNameClassToolStripMenuItem_Click); + this.initClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); + this.initClassToolStripMenuItem.Text = "Init Class from RTTI"; + this.initClassToolStripMenuItem.Click += new System.EventHandler(this.initClassToolStripMenuItem_Click); // // dissectNodesToolStripMenuItem // this.dissectNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Camera; this.dissectNodesToolStripMenuItem.Name = "dissectNodesToolStripMenuItem"; - this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.dissectNodesToolStripMenuItem.Text = "&Dissect Node(s)"; this.dissectNodesToolStripMenuItem.Click += new System.EventHandler(this.dissectNodesToolStripMenuItem_Click); // // toolStripSeparator9 // this.toolStripSeparator9.Name = "toolStripSeparator9"; - this.toolStripSeparator9.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator9.Size = new System.Drawing.Size(266, 6); // // searchForEqualValuesToolStripMenuItem // this.searchForEqualValuesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.searchForEqualValuesToolStripMenuItem.Name = "searchForEqualValuesToolStripMenuItem"; - this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.searchForEqualValuesToolStripMenuItem.Text = "&Search for equal values..."; this.searchForEqualValuesToolStripMenuItem.Click += new System.EventHandler(this.searchForEqualValuesToolStripMenuItem_Click); // // toolStripSeparator15 // this.toolStripSeparator15.Name = "toolStripSeparator15"; - this.toolStripSeparator15.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator15.Size = new System.Drawing.Size(266, 6); // // findOutWhatAccessesThisAddressToolStripMenuItem // this.findOutWhatAccessesThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Access; this.findOutWhatAccessesThisAddressToolStripMenuItem.Name = "findOutWhatAccessesThisAddressToolStripMenuItem"; - this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "&Find out what accesses this address..."; this.findOutWhatAccessesThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatAccessesThisAddressToolStripMenuItem_Click); // @@ -654,20 +654,20 @@ private void InitializeComponent() // this.findOutWhatWritesToThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Write; this.findOutWhatWritesToThisAddressToolStripMenuItem.Name = "findOutWhatWritesToThisAddressToolStripMenuItem"; - this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what &writes to this address..."; this.findOutWhatWritesToThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatWritesToThisAddressToolStripMenuItem_Click); // // toolStripSeparator14 // this.toolStripSeparator14.Name = "toolStripSeparator14"; - this.toolStripSeparator14.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator14.Size = new System.Drawing.Size(266, 6); // // copyNodeToolStripMenuItem // this.copyNodeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyNodeToolStripMenuItem.Name = "copyNodeToolStripMenuItem"; - this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.copyNodeToolStripMenuItem.Text = "C&opy Node(s)"; this.copyNodeToolStripMenuItem.Click += new System.EventHandler(this.copyNodeToolStripMenuItem_Click); // @@ -675,33 +675,33 @@ private void InitializeComponent() // this.pasteNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Paste; this.pasteNodesToolStripMenuItem.Name = "pasteNodesToolStripMenuItem"; - this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.pasteNodesToolStripMenuItem.Text = "&Paste Node(s)"; this.pasteNodesToolStripMenuItem.Click += new System.EventHandler(this.pasteNodesToolStripMenuItem_Click); // // toolStripSeparator10 // this.toolStripSeparator10.Name = "toolStripSeparator10"; - this.toolStripSeparator10.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator10.Size = new System.Drawing.Size(266, 6); // // removeToolStripMenuItem // this.removeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Delete; this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; - this.removeToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.removeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.removeToolStripMenuItem.Text = "&Remove Node(s)"; this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); // // toolStripSeparator12 // this.toolStripSeparator12.Name = "toolStripSeparator12"; - this.toolStripSeparator12.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator12.Size = new System.Drawing.Size(266, 6); // // hideNodesToolStripMenuItem // this.hideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.hideNodesToolStripMenuItem.Name = "hideNodesToolStripMenuItem"; - this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.hideNodesToolStripMenuItem.Text = "&Hide selected Node(s)"; this.hideNodesToolStripMenuItem.Click += new System.EventHandler(this.hideNodesToolStripMenuItem_Click); // @@ -713,7 +713,7 @@ private void InitializeComponent() this.unhideNodesBelowToolStripMenuItem}); this.unhideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.unhideNodesToolStripMenuItem.Name = "unhideNodesToolStripMenuItem"; - this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.unhideNodesToolStripMenuItem.Text = "&Unhide..."; // // unhideChildNodesToolStripMenuItem @@ -743,26 +743,26 @@ private void InitializeComponent() // toolStripSeparator18 // this.toolStripSeparator18.Name = "toolStripSeparator18"; - this.toolStripSeparator18.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator18.Size = new System.Drawing.Size(266, 6); // // copyAddressToolStripMenuItem // this.copyAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyAddressToolStripMenuItem.Name = "copyAddressToolStripMenuItem"; - this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.copyAddressToolStripMenuItem.Text = "Cop&y Address"; this.copyAddressToolStripMenuItem.Click += new System.EventHandler(this.copyAddressToolStripMenuItem_Click); // // toolStripSeparator11 // this.toolStripSeparator11.Name = "toolStripSeparator11"; - this.toolStripSeparator11.Size = new System.Drawing.Size(292, 6); + this.toolStripSeparator11.Size = new System.Drawing.Size(266, 6); // // showCodeOfClassToolStripMenuItem // this.showCodeOfClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Code_Cpp; this.showCodeOfClassToolStripMenuItem.Name = "showCodeOfClassToolStripMenuItem"; - this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.showCodeOfClassToolStripMenuItem.Text = "Show C&++ Code of Class"; this.showCodeOfClassToolStripMenuItem.Click += new System.EventHandler(this.showCodeOfClassToolStripMenuItem_Click); // @@ -770,7 +770,7 @@ private void InitializeComponent() // this.shrinkClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Chart_Delete; this.shrinkClassToolStripMenuItem.Name = "shrinkClassToolStripMenuItem"; - this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(295, 22); + this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); this.shrinkClassToolStripMenuItem.Text = "Shri&nk Class"; this.shrinkClassToolStripMenuItem.Click += new System.EventHandler(this.shrinkClassToolStripMenuItem_Click); // @@ -1555,7 +1555,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem showEnumsToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator23; private System.Windows.Forms.ToolStripMenuItem isLittleEndianToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem autoNameClassToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem initClassToolStripMenuItem; } } diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index 435d7a87..0f02dbf2 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -835,7 +835,7 @@ private void memoryViewControl_SelectionChanged(object sender, EventArgs e) addBytesToolStripDropDownButton.Enabled = parentContainer != null || isContainerNode; insertBytesToolStripDropDownButton.Enabled = selectedNodes.Count == 1 && parentContainer != null && !isContainerNode; - autoNameClassToolStripMenuItem.Enabled = nodeIsClass; + initClassToolStripMenuItem.Enabled = nodeIsClass; var enabled = selectedNodes.Count > 0 && !nodeIsClass; toolStrip.Items.OfType().ForEach(b => b.Enabled = enabled); @@ -1054,7 +1054,7 @@ private void memoryViewControl_DrawContextRequested(object sender, DrawContextRe } - private void autoNameClassToolStripMenuItem_Click(object sender, EventArgs e) + private void initClassToolStripMenuItem_Click(object sender, EventArgs e) { var selectedNodes = memoryViewControl.GetSelectedNodes(); var node = selectedNodes.FirstOrDefault()?.Node; @@ -1062,7 +1062,7 @@ private void autoNameClassToolStripMenuItem_Click(object sender, EventArgs e) { return; } - memoryViewControl.AutoNameCurrentClassFromRTTI(node as ClassNode); + memoryViewControl.InitCurrentClassFromRTTI(node as ClassNode); } } } diff --git a/ReClass.NET/Nodes/BaseNode.cs b/ReClass.NET/Nodes/BaseNode.cs index 43a0bd97..b5cefb00 100644 --- a/ReClass.NET/Nodes/BaseNode.cs +++ b/ReClass.NET/Nodes/BaseNode.cs @@ -39,8 +39,11 @@ public abstract class BaseNode /// Gets or sets the parent node. public BaseNode ParentNode { get; internal set; } - /// Gets a value indicating whether this node is wrapped into an other node. We see classnodes never as wrapped. - public bool IsWrapped => (ParentNode is BaseWrapperNode && !(this is ClassNode)); + /// Gets a value indicating whether this node is wrapped into an other node. + public bool IsWrapped => (ParentNode is BaseWrapperNode); + + /// All nodes that are wrapped can't be selected except classnodes because they have a context menu + public bool CanBeSelected => (!IsWrapped || (this is ClassNode)); /// Gets or sets a value indicating whether this node is hidden. public bool IsHidden { get; set; } @@ -376,7 +379,7 @@ protected void AddSelection(DrawContext context, int x, int y, int height) Contract.Requires(context != null); Contract.Requires(context.Graphics != null); - if (y > context.ClientArea.Bottom || y + height < 0 || IsWrapped) + if (y > context.ClientArea.Bottom || y + height < 0 || !CanBeSelected) { return; } diff --git a/ReClass.NET/Nodes/ClassNode.cs b/ReClass.NET/Nodes/ClassNode.cs index 92aa6691..05aa9077 100644 --- a/ReClass.NET/Nodes/ClassNode.cs +++ b/ReClass.NET/Nodes/ClassNode.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Drawing; using System.Linq; @@ -52,8 +53,12 @@ public static ClassNode Create() return new ClassNode(true); } - - public void AutoNameFromRTTI(DrawContext context) + + /// + /// Initializes the class' name and vtable node from RTTI information, if it's not set already + /// + /// + public void InitFromRTTI(DrawContext context) { // first node should be a VTable node or a hex64/32 node if (Nodes.Count <= 0) @@ -77,7 +82,9 @@ public void AutoNameFromRTTI(DrawContext context) if (!string.IsNullOrEmpty(rttiInfoFromFirstNode)) { // convert first node to vtable node -#warning IMPLEMENT: CONVERT NODE TO VTABLE NODE + var newVTableNode = BaseNode.CreateInstanceFromType(typeof(VirtualMethodTableNode)); + var createdNodes = new List(); + this.ReplaceChildNode(firstNode, newVTableNode, ref createdNodes); } } } From 68b44d51caf501dfb4d8b98e6b383ed6bf0b10df Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Mon, 3 Jul 2023 20:42:12 +0200 Subject: [PATCH 07/15] Removed alt-key shortcuts from context menu as they can't be viewed anyway --- ReClass.NET/Forms/MainForm.Designer.cs | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index 5fd3c74e..adf1cf64 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -412,7 +412,7 @@ private void InitializeComponent() this.changeTypeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Exchange_Button; this.changeTypeToolStripMenuItem.Name = "changeTypeToolStripMenuItem"; this.changeTypeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.changeTypeToolStripMenuItem.Text = "&Change Type"; + this.changeTypeToolStripMenuItem.Text = "Change Type"; // // addBytesToolStripMenuItem // @@ -428,7 +428,7 @@ private void InitializeComponent() this.addBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Add_Bytes_X; this.addBytesToolStripMenuItem.Name = "addBytesToolStripMenuItem"; this.addBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.addBytesToolStripMenuItem.Text = "&Add Bytes"; + this.addBytesToolStripMenuItem.Text = "Add Bytes"; // // integerToolStripMenuItem1 // @@ -515,7 +515,7 @@ private void InitializeComponent() this.insertBytesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Insert_Bytes_X; this.insertBytesToolStripMenuItem.Name = "insertBytesToolStripMenuItem"; this.insertBytesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.insertBytesToolStripMenuItem.Text = "&Insert Bytes"; + this.insertBytesToolStripMenuItem.Text = "Insert Bytes"; // // integerToolStripMenuItem8 // @@ -598,7 +598,7 @@ private void InitializeComponent() this.createClassFromNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Class_Add; this.createClassFromNodesToolStripMenuItem.Name = "createClassFromNodesToolStripMenuItem"; this.createClassFromNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.createClassFromNodesToolStripMenuItem.Text = "C&reate Class from Nodes"; + this.createClassFromNodesToolStripMenuItem.Text = "Create Class from Nodes"; this.createClassFromNodesToolStripMenuItem.Click += new System.EventHandler(this.createClassFromNodesToolStripMenuItem_Click); // // toolStripSeparator13 @@ -621,7 +621,7 @@ private void InitializeComponent() this.dissectNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Camera; this.dissectNodesToolStripMenuItem.Name = "dissectNodesToolStripMenuItem"; this.dissectNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.dissectNodesToolStripMenuItem.Text = "&Dissect Node(s)"; + this.dissectNodesToolStripMenuItem.Text = "Dissect Node(s)"; this.dissectNodesToolStripMenuItem.Click += new System.EventHandler(this.dissectNodesToolStripMenuItem_Click); // // toolStripSeparator9 @@ -634,7 +634,7 @@ private void InitializeComponent() this.searchForEqualValuesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.searchForEqualValuesToolStripMenuItem.Name = "searchForEqualValuesToolStripMenuItem"; this.searchForEqualValuesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.searchForEqualValuesToolStripMenuItem.Text = "&Search for equal values..."; + this.searchForEqualValuesToolStripMenuItem.Text = "Search for equal values..."; this.searchForEqualValuesToolStripMenuItem.Click += new System.EventHandler(this.searchForEqualValuesToolStripMenuItem_Click); // // toolStripSeparator15 @@ -647,7 +647,7 @@ private void InitializeComponent() this.findOutWhatAccessesThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Access; this.findOutWhatAccessesThisAddressToolStripMenuItem.Name = "findOutWhatAccessesThisAddressToolStripMenuItem"; this.findOutWhatAccessesThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "&Find out what accesses this address..."; + this.findOutWhatAccessesThisAddressToolStripMenuItem.Text = "Find out what accesses this address..."; this.findOutWhatAccessesThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatAccessesThisAddressToolStripMenuItem_Click); // // findOutWhatWritesToThisAddressToolStripMenuItem @@ -655,7 +655,7 @@ private void InitializeComponent() this.findOutWhatWritesToThisAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Find_Write; this.findOutWhatWritesToThisAddressToolStripMenuItem.Name = "findOutWhatWritesToThisAddressToolStripMenuItem"; this.findOutWhatWritesToThisAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what &writes to this address..."; + this.findOutWhatWritesToThisAddressToolStripMenuItem.Text = "Find out what writes to this address..."; this.findOutWhatWritesToThisAddressToolStripMenuItem.Click += new System.EventHandler(this.findOutWhatWritesToThisAddressToolStripMenuItem_Click); // // toolStripSeparator14 @@ -668,7 +668,7 @@ private void InitializeComponent() this.copyNodeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyNodeToolStripMenuItem.Name = "copyNodeToolStripMenuItem"; this.copyNodeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.copyNodeToolStripMenuItem.Text = "C&opy Node(s)"; + this.copyNodeToolStripMenuItem.Text = "Copy Node(s)"; this.copyNodeToolStripMenuItem.Click += new System.EventHandler(this.copyNodeToolStripMenuItem_Click); // // pasteNodesToolStripMenuItem @@ -676,7 +676,7 @@ private void InitializeComponent() this.pasteNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Paste; this.pasteNodesToolStripMenuItem.Name = "pasteNodesToolStripMenuItem"; this.pasteNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.pasteNodesToolStripMenuItem.Text = "&Paste Node(s)"; + this.pasteNodesToolStripMenuItem.Text = "Paste Node(s)"; this.pasteNodesToolStripMenuItem.Click += new System.EventHandler(this.pasteNodesToolStripMenuItem_Click); // // toolStripSeparator10 @@ -689,7 +689,7 @@ private void InitializeComponent() this.removeToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_Delete; this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; this.removeToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.removeToolStripMenuItem.Text = "&Remove Node(s)"; + this.removeToolStripMenuItem.Text = "Remove Node(s)"; this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); // // toolStripSeparator12 @@ -702,7 +702,7 @@ private void InitializeComponent() this.hideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.hideNodesToolStripMenuItem.Name = "hideNodesToolStripMenuItem"; this.hideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.hideNodesToolStripMenuItem.Text = "&Hide selected Node(s)"; + this.hideNodesToolStripMenuItem.Text = "Hide selected Node(s)"; this.hideNodesToolStripMenuItem.Click += new System.EventHandler(this.hideNodesToolStripMenuItem_Click); // // unhideNodesToolStripMenuItem @@ -714,7 +714,7 @@ private void InitializeComponent() this.unhideNodesToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Eye; this.unhideNodesToolStripMenuItem.Name = "unhideNodesToolStripMenuItem"; this.unhideNodesToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.unhideNodesToolStripMenuItem.Text = "&Unhide..."; + this.unhideNodesToolStripMenuItem.Text = "Unhide..."; // // unhideChildNodesToolStripMenuItem // @@ -750,7 +750,7 @@ private void InitializeComponent() this.copyAddressToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Copy; this.copyAddressToolStripMenuItem.Name = "copyAddressToolStripMenuItem"; this.copyAddressToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.copyAddressToolStripMenuItem.Text = "Cop&y Address"; + this.copyAddressToolStripMenuItem.Text = "Copy Address"; this.copyAddressToolStripMenuItem.Click += new System.EventHandler(this.copyAddressToolStripMenuItem_Click); // // toolStripSeparator11 @@ -763,7 +763,7 @@ private void InitializeComponent() this.showCodeOfClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Page_Code_Cpp; this.showCodeOfClassToolStripMenuItem.Name = "showCodeOfClassToolStripMenuItem"; this.showCodeOfClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.showCodeOfClassToolStripMenuItem.Text = "Show C&++ Code of Class"; + this.showCodeOfClassToolStripMenuItem.Text = "Show C++ Code of Class"; this.showCodeOfClassToolStripMenuItem.Click += new System.EventHandler(this.showCodeOfClassToolStripMenuItem_Click); // // shrinkClassToolStripMenuItem @@ -771,7 +771,7 @@ private void InitializeComponent() this.shrinkClassToolStripMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Chart_Delete; this.shrinkClassToolStripMenuItem.Name = "shrinkClassToolStripMenuItem"; this.shrinkClassToolStripMenuItem.Size = new System.Drawing.Size(269, 22); - this.shrinkClassToolStripMenuItem.Text = "Shri&nk Class"; + this.shrinkClassToolStripMenuItem.Text = "Shrink Class"; this.shrinkClassToolStripMenuItem.Click += new System.EventHandler(this.shrinkClassToolStripMenuItem_Click); // // toolStrip From c831f9bd3ada8adc84072ed478ee9161263fe14b Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 10:10:40 +0200 Subject: [PATCH 08/15] Added a toolstrip button for Init class from RTTI so the shortcut works without opening the menu. Made the window a bit wider (was too small already) so all toolbar buttons are visible --- ReClass.NET/Forms/MainForm.Designer.cs | 28 +++++++++++++++++++------- ReClass.NET/Forms/MainForm.cs | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index adf1cf64..c889df6c 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -107,6 +107,7 @@ private void InitializeComponent() this.saveToolStripButton = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); this.newClassToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.initClassFromRTTIToolStripBarMenuItem = new ReClassNET.Controls.TypeToolStripMenuItem(); this.addBytesToolStripDropDownButton = new System.Windows.Forms.ToolStripDropDownButton(); this.add4BytesToolStripMenuItem = new ReClassNET.Controls.IntegerToolStripMenuItem(); this.add8BytesToolStripMenuItem = new ReClassNET.Controls.IntegerToolStripMenuItem(); @@ -203,7 +204,7 @@ private void InitializeComponent() // this.splitContainer.Panel2.BackColor = System.Drawing.SystemColors.Control; this.splitContainer.Panel2.Controls.Add(this.memoryViewControl); - this.splitContainer.Size = new System.Drawing.Size(1141, 524); + this.splitContainer.Size = new System.Drawing.Size(1313, 524); this.splitContainer.SplitterDistance = 201; this.splitContainer.TabIndex = 4; // @@ -365,7 +366,7 @@ private void InitializeComponent() this.memoryViewControl.Location = new System.Drawing.Point(0, 0); this.memoryViewControl.Name = "memoryViewControl"; this.memoryViewControl.NodeContextMenuStrip = this.selectedNodeContextMenuStrip; - this.memoryViewControl.Size = new System.Drawing.Size(936, 524); + this.memoryViewControl.Size = new System.Drawing.Size(1108, 524); this.memoryViewControl.TabIndex = 0; this.memoryViewControl.DrawContextRequested += new ReClassNET.Controls.DrawContextRequestEventHandler(this.memoryViewControl_DrawContextRequested); this.memoryViewControl.SelectionChanged += new System.EventHandler(this.memoryViewControl_SelectionChanged); @@ -404,7 +405,7 @@ private void InitializeComponent() this.showCodeOfClassToolStripMenuItem, this.shrinkClassToolStripMenuItem}); this.selectedNodeContextMenuStrip.Name = "selectedNodeContextMenuStrip"; - this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(270, 454); + this.selectedNodeContextMenuStrip.Size = new System.Drawing.Size(270, 432); this.selectedNodeContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.selectedNodeContextMenuStrip_Opening); // // changeTypeToolStripMenuItem @@ -783,12 +784,13 @@ private void InitializeComponent() this.saveToolStripButton, this.toolStripSeparator7, this.newClassToolStripButton, + this.initClassFromRTTIToolStripBarMenuItem, this.addBytesToolStripDropDownButton, this.insertBytesToolStripDropDownButton, this.nodeTypesToolStripSeparator}); this.toolStrip.Location = new System.Drawing.Point(0, 24); this.toolStrip.Name = "toolStrip"; - this.toolStrip.Size = new System.Drawing.Size(1141, 25); + this.toolStrip.Size = new System.Drawing.Size(1313, 25); this.toolStrip.TabIndex = 3; // // attachToProcessToolStripSplitButton @@ -844,6 +846,17 @@ private void InitializeComponent() this.newClassToolStripButton.ToolTipText = "Add a new class to this project"; this.newClassToolStripButton.Click += new System.EventHandler(this.newClassToolStripButton_Click); // + // initClassFromRTTIToolStripBarMenuItem + // + this.initClassFromRTTIToolStripBarMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_AutoName; + this.initClassFromRTTIToolStripBarMenuItem.Name = "initClassFromRTTIToolStripBarMenuItem"; + this.initClassFromRTTIToolStripBarMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.N))); + this.initClassFromRTTIToolStripBarMenuItem.Size = new System.Drawing.Size(28, 25); + this.initClassFromRTTIToolStripBarMenuItem.ToolTipText = "Init selected class from RTTI info"; + this.initClassFromRTTIToolStripBarMenuItem.Value = null; + this.initClassFromRTTIToolStripBarMenuItem.Click += new System.EventHandler(this.initClassToolStripMenuItem_Click); + // // addBytesToolStripDropDownButton // this.addBytesToolStripDropDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -1035,7 +1048,7 @@ private void InitializeComponent() this.infoToolStripStatusLabel}); this.statusStrip.Location = new System.Drawing.Point(0, 573); this.statusStrip.Name = "statusStrip"; - this.statusStrip.Size = new System.Drawing.Size(1141, 22); + this.statusStrip.Size = new System.Drawing.Size(1313, 22); this.statusStrip.TabIndex = 1; // // processInfoToolStripStatusLabel @@ -1060,7 +1073,7 @@ private void InitializeComponent() this.helpToolStripMenuItem}); this.mainMenuStrip.Location = new System.Drawing.Point(0, 0); this.mainMenuStrip.Name = "mainMenuStrip"; - this.mainMenuStrip.Size = new System.Drawing.Size(1141, 24); + this.mainMenuStrip.Size = new System.Drawing.Size(1313, 24); this.mainMenuStrip.TabIndex = 2; // // fileToolStripMenuItem @@ -1384,7 +1397,7 @@ private void InitializeComponent() this.AllowDrop = true; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1141, 595); + this.ClientSize = new System.Drawing.Size(1313, 595); this.Controls.Add(this.splitContainer); this.Controls.Add(this.toolStrip); this.Controls.Add(this.statusStrip); @@ -1556,6 +1569,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripSeparator toolStripSeparator23; private System.Windows.Forms.ToolStripMenuItem isLittleEndianToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem initClassToolStripMenuItem; + private TypeToolStripMenuItem initClassFromRTTIToolStripBarMenuItem; } } diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index 0f02dbf2..0d968bfc 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -836,6 +836,7 @@ private void memoryViewControl_SelectionChanged(object sender, EventArgs e) addBytesToolStripDropDownButton.Enabled = parentContainer != null || isContainerNode; insertBytesToolStripDropDownButton.Enabled = selectedNodes.Count == 1 && parentContainer != null && !isContainerNode; initClassToolStripMenuItem.Enabled = nodeIsClass; + initClassFromRTTIToolStripBarMenuItem.Enabled = nodeIsClass; var enabled = selectedNodes.Count > 0 && !nodeIsClass; toolStrip.Items.OfType().ForEach(b => b.Enabled = enabled); From 59310506e78e9ff1e4e4f0cc5698df04955b2b5e Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 10:19:08 +0200 Subject: [PATCH 09/15] Initial packages update --- ReClass.NET/ReClass.NET.csproj | 7 +++++++ ReClass.NET/packages.config | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 ReClass.NET/packages.config diff --git a/ReClass.NET/ReClass.NET.csproj b/ReClass.NET/ReClass.NET.csproj index 6422eb12..3a98a45a 100644 --- a/ReClass.NET/ReClass.NET.csproj +++ b/ReClass.NET/ReClass.NET.csproj @@ -122,6 +122,12 @@ False ..\Dependencies\Microsoft.ExceptionMessageBox.dll + + ..\packages\SD.Tools.Algorithmia.1.4.0\lib\net452\SD.Tools.Algorithmia.dll + + + ..\packages\SD.Tools.BCLExtensions.1.2.2\lib\net452\SD.Tools.BCLExtensions.dll + @@ -608,6 +614,7 @@ Resources.Designer.cs + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/ReClass.NET/packages.config b/ReClass.NET/packages.config new file mode 100644 index 00000000..67c03fdf --- /dev/null +++ b/ReClass.NET/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From dc5225e0cdf16611ffde03ef09c454c183db38a7 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 10:20:16 +0200 Subject: [PATCH 10/15] Marked Init class from RTTI toolbar button as 'Overflow as needed' so it gets removed when the window is too narrow --- ReClass.NET/Forms/MainForm.Designer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index c889df6c..081e2c0d 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -848,8 +848,10 @@ private void InitializeComponent() // // initClassFromRTTIToolStripBarMenuItem // + this.initClassFromRTTIToolStripBarMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; this.initClassFromRTTIToolStripBarMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Button_AutoName; this.initClassFromRTTIToolStripBarMenuItem.Name = "initClassFromRTTIToolStripBarMenuItem"; + this.initClassFromRTTIToolStripBarMenuItem.Overflow = System.Windows.Forms.ToolStripItemOverflow.AsNeeded; this.initClassFromRTTIToolStripBarMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.N))); this.initClassFromRTTIToolStripBarMenuItem.Size = new System.Drawing.Size(28, 25); From 35afcee8ea1666bfa3fa3af3bbfdf5973dba6902 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 10:36:40 +0200 Subject: [PATCH 11/15] Defined some node type toolbar buttons as 'As Needed' for overflow if the window is too narrow to make room for undo/redo buttons --- ReClass.NET/Forms/MainForm.Designer.cs | 12 ++++++------ ReClass.NET/UI/NodeTypesBuilder.cs | 5 +++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index 081e2c0d..b2448e7d 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -204,7 +204,7 @@ private void InitializeComponent() // this.splitContainer.Panel2.BackColor = System.Drawing.SystemColors.Control; this.splitContainer.Panel2.Controls.Add(this.memoryViewControl); - this.splitContainer.Size = new System.Drawing.Size(1313, 524); + this.splitContainer.Size = new System.Drawing.Size(1103, 524); this.splitContainer.SplitterDistance = 201; this.splitContainer.TabIndex = 4; // @@ -366,7 +366,7 @@ private void InitializeComponent() this.memoryViewControl.Location = new System.Drawing.Point(0, 0); this.memoryViewControl.Name = "memoryViewControl"; this.memoryViewControl.NodeContextMenuStrip = this.selectedNodeContextMenuStrip; - this.memoryViewControl.Size = new System.Drawing.Size(1108, 524); + this.memoryViewControl.Size = new System.Drawing.Size(898, 524); this.memoryViewControl.TabIndex = 0; this.memoryViewControl.DrawContextRequested += new ReClassNET.Controls.DrawContextRequestEventHandler(this.memoryViewControl_DrawContextRequested); this.memoryViewControl.SelectionChanged += new System.EventHandler(this.memoryViewControl_SelectionChanged); @@ -790,7 +790,7 @@ private void InitializeComponent() this.nodeTypesToolStripSeparator}); this.toolStrip.Location = new System.Drawing.Point(0, 24); this.toolStrip.Name = "toolStrip"; - this.toolStrip.Size = new System.Drawing.Size(1313, 25); + this.toolStrip.Size = new System.Drawing.Size(1103, 25); this.toolStrip.TabIndex = 3; // // attachToProcessToolStripSplitButton @@ -1050,7 +1050,7 @@ private void InitializeComponent() this.infoToolStripStatusLabel}); this.statusStrip.Location = new System.Drawing.Point(0, 573); this.statusStrip.Name = "statusStrip"; - this.statusStrip.Size = new System.Drawing.Size(1313, 22); + this.statusStrip.Size = new System.Drawing.Size(1103, 22); this.statusStrip.TabIndex = 1; // // processInfoToolStripStatusLabel @@ -1075,7 +1075,7 @@ private void InitializeComponent() this.helpToolStripMenuItem}); this.mainMenuStrip.Location = new System.Drawing.Point(0, 0); this.mainMenuStrip.Name = "mainMenuStrip"; - this.mainMenuStrip.Size = new System.Drawing.Size(1313, 24); + this.mainMenuStrip.Size = new System.Drawing.Size(1103, 24); this.mainMenuStrip.TabIndex = 2; // // fileToolStripMenuItem @@ -1399,7 +1399,7 @@ private void InitializeComponent() this.AllowDrop = true; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1313, 595); + this.ClientSize = new System.Drawing.Size(1103, 595); this.Controls.Add(this.splitContainer); this.Controls.Add(this.toolStrip); this.Controls.Add(this.statusStrip); diff --git a/ReClass.NET/UI/NodeTypesBuilder.cs b/ReClass.NET/UI/NodeTypesBuilder.cs index b0badd25..79d4bfbe 100644 --- a/ReClass.NET/UI/NodeTypesBuilder.cs +++ b/ReClass.NET/UI/NodeTypesBuilder.cs @@ -14,6 +14,7 @@ internal static class NodeTypesBuilder { private static readonly List defaultNodeTypeGroupList = new List(); private static readonly Dictionary> pluginNodeTypes = new Dictionary>(); + private static readonly HashSet nodeTypesWhichCanOverflowInToolbar; static NodeTypesBuilder() { @@ -27,6 +28,9 @@ static NodeTypesBuilder() defaultNodeTypeGroupList.Add(new[] { typeof(PointerNode), typeof(ArrayNode), typeof(UnionNode) }); defaultNodeTypeGroupList.Add(new[] { typeof(ClassInstanceNode) }); defaultNodeTypeGroupList.Add(new[] { typeof(VirtualMethodTableNode), typeof(FunctionNode), typeof(FunctionPtrNode) }); + + // define the node types which can overflow in the toolbar if the window is too narrow. Add types here which aren't used that much + nodeTypesWhichCanOverflowInToolbar = new HashSet { typeof(NIntNode), typeof(NUIntNode), typeof(BitFieldNode), typeof(Utf16TextNode), typeof(Utf16TextPtrNode) } ; } public static void AddPluginNodeGroup(Plugin plugin, IReadOnlyList nodeTypes) @@ -66,6 +70,7 @@ public static IEnumerable CreateToolStripButtons(Action han DisplayStyle = ToolStripItemDisplayStyle.Image, Image = icon, ShortcutKeys = shortcutKeys, + Overflow = nodeTypesWhichCanOverflowInToolbar.Contains(t) ? ToolStripItemOverflow.AsNeeded : ToolStripItemOverflow.Never, }; item.Click += clickHandler; return item; From fb7b4d69ba5e3ca0427304fa592cc4d48279eebe Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 11:41:41 +0200 Subject: [PATCH 12/15] Initial undo/redo system in place. Class name is now undo/redo aware --- ReClass.NET/Constants.cs | 11 +++++++- ReClass.NET/Forms/MainForm.Designer.cs | 28 +++++++++++++++++++- ReClass.NET/Forms/MainForm.Functions.cs | 9 +++++++ ReClass.NET/Forms/MainForm.cs | 35 +++++++++++++++++++++++++ ReClass.NET/Nodes/BaseNode.cs | 23 +++++++++++++--- ReClass.NET/Program.cs | 9 +++++++ 6 files changed, 110 insertions(+), 5 deletions(-) diff --git a/ReClass.NET/Constants.cs b/ReClass.NET/Constants.cs index 4e54782a..bd918dbe 100644 --- a/ReClass.NET/Constants.cs +++ b/ReClass.NET/Constants.cs @@ -1,4 +1,4 @@ -namespace ReClassNET +namespace ReClassNET { public class Constants { @@ -39,5 +39,14 @@ public static class CommandLineOptions public const string FileExtRegister = "registerfileext"; public const string FileExtUnregister = "unregisterfileext"; } + + /// + /// Change type for commandified members in classes which is used to signal what change occurred exactly. As we don't use this feature of the commandified + /// class, this enum is defined to simply signal 'no specific change other than it changed' happened. + /// + public enum GeneralPurposeChangeType + { + None + } } } diff --git a/ReClass.NET/Forms/MainForm.Designer.cs b/ReClass.NET/Forms/MainForm.Designer.cs index b2448e7d..20b2c907 100644 --- a/ReClass.NET/Forms/MainForm.Designer.cs +++ b/ReClass.NET/Forms/MainForm.Designer.cs @@ -169,6 +169,8 @@ private void InitializeComponent() this.generateCSharpCodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.undoToolbarMenuItem = new ReClassNET.Controls.TypeToolStripMenuItem(); + this.redoToolbarMenuItem = new ReClassNET.Controls.TypeToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); @@ -787,7 +789,9 @@ private void InitializeComponent() this.initClassFromRTTIToolStripBarMenuItem, this.addBytesToolStripDropDownButton, this.insertBytesToolStripDropDownButton, - this.nodeTypesToolStripSeparator}); + this.nodeTypesToolStripSeparator, + this.undoToolbarMenuItem, + this.redoToolbarMenuItem}); this.toolStrip.Location = new System.Drawing.Point(0, 24); this.toolStrip.Name = "toolStrip"; this.toolStrip.Size = new System.Drawing.Size(1103, 25); @@ -1394,6 +1398,26 @@ private void InitializeComponent() this.aboutToolStripMenuItem.Text = "About..."; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); // + // undoToolbarMenuItem + // + this.undoToolbarMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Undo; + this.undoToolbarMenuItem.Name = "undoToolbarMenuItem"; + this.undoToolbarMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z))); + this.undoToolbarMenuItem.Size = new System.Drawing.Size(28, 25); + this.undoToolbarMenuItem.ToolTipText = "Undo the latest change"; + this.undoToolbarMenuItem.Value = null; + this.undoToolbarMenuItem.Click += new System.EventHandler(this.undoToolbarMenuItem_Click); + // + // redoToolbarMenuItem + // + this.redoToolbarMenuItem.Image = global::ReClassNET.Properties.Resources.B16x16_Redo; + this.redoToolbarMenuItem.Name = "redoToolbarMenuItem"; + this.redoToolbarMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y))); + this.redoToolbarMenuItem.Size = new System.Drawing.Size(28, 25); + this.redoToolbarMenuItem.ToolTipText = "Redo the latest undone change"; + this.redoToolbarMenuItem.Value = null; + this.redoToolbarMenuItem.Click += new System.EventHandler(this.redoToolbarMenuItem_Click); + // // MainForm // this.AllowDrop = true; @@ -1572,6 +1596,8 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem isLittleEndianToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem initClassToolStripMenuItem; private TypeToolStripMenuItem initClassFromRTTIToolStripBarMenuItem; + private TypeToolStripMenuItem undoToolbarMenuItem; + private TypeToolStripMenuItem redoToolbarMenuItem; } } diff --git a/ReClass.NET/Forms/MainForm.Functions.cs b/ReClass.NET/Forms/MainForm.Functions.cs index 84f1b53a..bc668e01 100644 --- a/ReClass.NET/Forms/MainForm.Functions.cs +++ b/ReClass.NET/Forms/MainForm.Functions.cs @@ -16,6 +16,7 @@ using ReClassNET.Nodes; using ReClassNET.Project; using ReClassNET.UI; +using SD.Tools.Algorithmia.Commands; namespace ReClassNET.Forms { @@ -213,6 +214,10 @@ public void LoadProjectFromPath(string path) { Contract.Requires(path != null); + CommandQueueManagerSingleton.GetInstance().ResetActiveCommandQueue(); + CommandQueueManagerSingleton.GetInstance().BeginNonUndoablePeriod(); // we don't want to trigger undo/redo activity while loading + CommandQueueManagerSingleton.GetInstance().RaiseEvents = false; + var project = new ReClassNetProject(); LoadProjectFromPath(path, ref project); @@ -224,6 +229,10 @@ public void LoadProjectFromPath(string path) } SetProject(project); + + // Done loading, resume undo/redo activity + CommandQueueManagerSingleton.GetInstance().RaiseEvents = true; + CommandQueueManagerSingleton.GetInstance().EndNonUndoablePeriod(); } /// Loads the file into the given project. diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index 0d968bfc..c694ca31 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -22,6 +22,7 @@ using ReClassNET.UI; using ReClassNET.Util; using ReClassNET.Util.Conversion; +using SD.Tools.Algorithmia.Commands; namespace ReClassNET.Forms { @@ -95,8 +96,11 @@ public MainForm() }; pluginManager = new PluginManager(new DefaultPluginHost(this, Program.RemoteProcess, Program.Logger)); + + CommandQueueManagerSingleton.GetInstance().CommandQueueActionPerformed += OnCommandQueueActionPerformed; } + protected override void OnLoad(EventArgs e) { base.OnLoad(e); @@ -135,6 +139,8 @@ protected override void OnLoad(EventArgs e) { AttachToProcess(Program.CommandLineArgs[Constants.CommandLineOptions.AttachTo]); } + + SetStateOfUndoRedoButtons(); } protected override void OnFormClosed(FormClosedEventArgs e) @@ -1063,7 +1069,36 @@ private void initClassToolStripMenuItem_Click(object sender, EventArgs e) { return; } + + var cmd = new UndoablePeriodCommand("InitClassFromRTTI"); + CommandQueueManagerSingleton.GetInstance().BeginUndoablePeriod(cmd); memoryViewControl.InitCurrentClassFromRTTI(node as ClassNode); + CommandQueueManagerSingleton.GetInstance().EndUndoablePeriod(cmd); + } + + + private void SetStateOfUndoRedoButtons() + { + undoToolbarMenuItem.Enabled = CommandQueueManagerSingleton.GetInstance().CanUndo(Program.CommandQueueID); + redoToolbarMenuItem.Enabled = CommandQueueManagerSingleton.GetInstance().CanDo(Program.CommandQueueID); + } + + + private void OnCommandQueueActionPerformed(object sender, CommandQueueActionPerformedEventArgs e) + { + SetStateOfUndoRedoButtons(); + } + + + private void undoToolbarMenuItem_Click(object sender, EventArgs e) + { + CommandQueueManagerSingleton.GetInstance().UndoLastCommand(); + } + + + private void redoToolbarMenuItem_Click(object sender, EventArgs e) + { + CommandQueueManagerSingleton.GetInstance().RedoLastCommand(); } } } diff --git a/ReClass.NET/Nodes/BaseNode.cs b/ReClass.NET/Nodes/BaseNode.cs index b5cefb00..ff18e9f1 100644 --- a/ReClass.NET/Nodes/BaseNode.cs +++ b/ReClass.NET/Nodes/BaseNode.cs @@ -7,6 +7,8 @@ using ReClassNET.Extensions; using ReClassNET.UI; using ReClassNET.Util; +using SD.Tools.Algorithmia.GeneralDataStructures; +using SD.Tools.Algorithmia.GeneralDataStructures.EventArguments; namespace ReClassNET.Nodes { @@ -24,14 +26,26 @@ public abstract class BaseNode private static int nodeIndex = 0; - private string name = string.Empty; + //private string name = string.Empty; + private CommandifiedMember name; private string comment = string.Empty; /// Gets or sets the offset of the node. public int Offset { get; set; } /// Gets or sets the name of the node. If a new name was set the property changed event gets fired. - public virtual string Name { get => name; set { if (value != null && name != value) { name = value; NameChanged?.Invoke(this); } } } + public virtual string Name + { + get => name.MemberValue; + set + { + if (value == null) + { + return; + } + name.MemberValue = value; + } + } /// Gets or sets the comment of the node. public string Comment { get => comment; set { if (value != null && comment != value) { comment = value; CommentChanged?.Invoke(this); } } } @@ -100,12 +114,15 @@ protected BaseNode() Contract.Ensures(name != null); Contract.Ensures(comment != null); - Name = $"N{nodeIndex++:X08}"; + name = new CommandifiedMember("Name", Constants.GeneralPurposeChangeType.None, $"N{nodeIndex++:X08}"); + name.ValueChanged += Name_ValueChanged; Comment = string.Empty; LevelsOpen[0] = true; } + private void Name_ValueChanged(object sender, MemberChangedEventArgs e) => NameChanged?.Invoke(this); + public abstract void GetUserInterfaceInfo(out string name, out Image icon); public virtual bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) diff --git a/ReClass.NET/Program.cs b/ReClass.NET/Program.cs index f28cb0bd..4a1dd5d4 100644 --- a/ReClass.NET/Program.cs +++ b/ReClass.NET/Program.cs @@ -11,6 +11,7 @@ using ReClassNET.Native; using ReClassNET.UI; using ReClassNET.Util; +using SD.Tools.Algorithmia.Commands; namespace ReClassNET { @@ -34,10 +35,13 @@ public static class Program public static FontEx MonoSpaceFont { get; private set; } + public static Guid CommandQueueID { get; private set; } + [STAThread] static void Main(string[] args) { DesignMode = false; // The designer doesn't call Main() + CommandQueueID = Guid.NewGuid(); CommandLineArgs = new CommandLineArgs(args); @@ -63,6 +67,11 @@ static void Main(string[] args) Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + // switch is set to false, so Do actions during Undo actions are ignored. + CommandQueueManager.ThrowExceptionOnDoDuringUndo = false; + // activate our command queue stack. We're only changing things from the main thread so we don't need multiple stacks. + CommandQueueManagerSingleton.GetInstance().ActivateCommandQueueStack(CommandQueueID); + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; Settings = SettingsSerializer.Load(); From aa8a85788a1410ab7ef5dfdf529fa596552b2a43 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 11:53:02 +0200 Subject: [PATCH 13/15] Removed 2nd empty lines when introduced, added 32bit version of ReadFromBuffer to MemoryBuffer, have refactored Hex32Node to use this method instead, have removed unnecessary braces and brackets. --- ReClass.NET/Controls/MemoryViewControl.cs | 3 +-- ReClass.NET/Forms/MainForm.cs | 3 +-- ReClass.NET/Memory/MemoryBuffer.cs | 11 ++++++--- ReClass.NET/Nodes/BaseHexCommentNode.cs | 1 - ReClass.NET/Nodes/BaseNode.cs | 4 ++-- ReClass.NET/Nodes/ClassNode.cs | 25 +++++++++------------ ReClass.NET/Nodes/Hex32Node.cs | 11 +++------ ReClass.NET/Nodes/Hex64Node.cs | 6 ++--- ReClass.NET/Nodes/PointerNode.cs | 3 +-- ReClass.NET/Nodes/VirtualMethodTableNode.cs | 11 ++++----- ReClass.NET/Settings.cs | 6 +---- 11 files changed, 34 insertions(+), 50 deletions(-) diff --git a/ReClass.NET/Controls/MemoryViewControl.cs b/ReClass.NET/Controls/MemoryViewControl.cs index 58aafb91..d323903b 100644 --- a/ReClass.NET/Controls/MemoryViewControl.cs +++ b/ReClass.NET/Controls/MemoryViewControl.cs @@ -704,8 +704,7 @@ public void Reset() VerticalScroll.Value = VerticalScroll.Minimum; } - - + public void InitCurrentClassFromRTTI(ClassNode classNode) { var args = new DrawContextRequestEventArgs { Node = classNode }; diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index 0d968bfc..11c0d42d 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -1053,8 +1053,7 @@ private void memoryViewControl_DrawContextRequested(object sender, DrawContextRe args.BaseAddress = address; } } - - + private void initClassToolStripMenuItem_Click(object sender, EventArgs e) { var selectedNodes = memoryViewControl.GetSelectedNodes(); diff --git a/ReClass.NET/Memory/MemoryBuffer.cs b/ReClass.NET/Memory/MemoryBuffer.cs index bde66ace..cb7361ec 100644 --- a/ReClass.NET/Memory/MemoryBuffer.cs +++ b/ReClass.NET/Memory/MemoryBuffer.cs @@ -366,12 +366,17 @@ public bool HasChanged(int offset, int length) return false; } - - - public UInt64FloatDoubleData ReadFromBuffer(int offset) => new UInt64FloatDoubleData + + public UInt64FloatDoubleData InterpretData64(int offset) => new UInt64FloatDoubleData { Raw1 = ReadInt32(offset), Raw2 = ReadInt32(offset + sizeof(int)) }; + + + public UInt32FloatData InterpretData32(int offset) => new UInt32FloatData + { + Raw = ReadInt32(offset) + }; } } diff --git a/ReClass.NET/Nodes/BaseHexCommentNode.cs b/ReClass.NET/Nodes/BaseHexCommentNode.cs index da9f180e..98305d8c 100644 --- a/ReClass.NET/Nodes/BaseHexCommentNode.cs +++ b/ReClass.NET/Nodes/BaseHexCommentNode.cs @@ -111,7 +111,6 @@ protected int AddComment(DrawContext view, int x, int y, float fvalue, IntPtr iv return x; } - public string GetAssociatedRemoteRuntimeTypeInformation(DrawContext context, IntPtr ivalue) { return context.Process.ReadRemoteRuntimeTypeInformation(ivalue); diff --git a/ReClass.NET/Nodes/BaseNode.cs b/ReClass.NET/Nodes/BaseNode.cs index b5cefb00..958bf654 100644 --- a/ReClass.NET/Nodes/BaseNode.cs +++ b/ReClass.NET/Nodes/BaseNode.cs @@ -40,10 +40,10 @@ public abstract class BaseNode public BaseNode ParentNode { get; internal set; } /// Gets a value indicating whether this node is wrapped into an other node. - public bool IsWrapped => (ParentNode is BaseWrapperNode); + public bool IsWrapped => ParentNode is BaseWrapperNode; /// All nodes that are wrapped can't be selected except classnodes because they have a context menu - public bool CanBeSelected => (!IsWrapped || (this is ClassNode)); + public bool CanBeSelected => !IsWrapped || (this is ClassNode); /// Gets or sets a value indicating whether this node is hidden. public bool IsHidden { get; set; } diff --git a/ReClass.NET/Nodes/ClassNode.cs b/ReClass.NET/Nodes/ClassNode.cs index 05aa9077..fe51a32f 100644 --- a/ReClass.NET/Nodes/ClassNode.cs +++ b/ReClass.NET/Nodes/ClassNode.cs @@ -52,8 +52,7 @@ public static ClassNode Create() return new ClassNode(true); } - - + /// /// Initializes the class' name and vtable node from RTTI information, if it's not set already /// @@ -72,20 +71,17 @@ public void InitFromRTTI(DrawContext context) { rttiInfoFromFirstNode = vtableNode.GetAssociatedRemoteRuntimeTypeInformation(context); } - else + else if (firstNode is BaseHexCommentNode baseHexCommentNode) { - if (firstNode is BaseHexCommentNode baseHexCommentNode) + // ask it as if it might point to a vtable + var value = context.Memory.InterpretData64(Offset); + rttiInfoFromFirstNode = baseHexCommentNode.GetAssociatedRemoteRuntimeTypeInformation(context, value.IntPtr); + if (!string.IsNullOrEmpty(rttiInfoFromFirstNode)) { - // ask it as if it might point to a vtable - var value = context.Memory.ReadFromBuffer(Offset); - rttiInfoFromFirstNode = baseHexCommentNode.GetAssociatedRemoteRuntimeTypeInformation(context, value.IntPtr); - if (!string.IsNullOrEmpty(rttiInfoFromFirstNode)) - { - // convert first node to vtable node - var newVTableNode = BaseNode.CreateInstanceFromType(typeof(VirtualMethodTableNode)); - var createdNodes = new List(); - this.ReplaceChildNode(firstNode, newVTableNode, ref createdNodes); - } + // convert first node to vtable node + var newVTableNode = BaseNode.CreateInstanceFromType(typeof(VirtualMethodTableNode)); + var createdNodes = new List(); + this.ReplaceChildNode(firstNode, newVTableNode, ref createdNodes); } } @@ -98,7 +94,6 @@ public void InitFromRTTI(DrawContext context) this.Name = fragments[0]; } - public override void GetUserInterfaceInfo(out string name, out Image icon) { throw new InvalidOperationException($"The '{nameof(ClassNode)}' node should not be accessible from the ui."); diff --git a/ReClass.NET/Nodes/Hex32Node.cs b/ReClass.NET/Nodes/Hex32Node.cs index c7b54027..2329c954 100644 --- a/ReClass.NET/Nodes/Hex32Node.cs +++ b/ReClass.NET/Nodes/Hex32Node.cs @@ -18,7 +18,7 @@ public override void GetUserInterfaceInfo(out string name, out Image icon) public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) { - var value = ReadFromBuffer(spot.Memory, Offset); + var value = spot.Memory.InterpretData32(Offset); address = value.IntPtr; @@ -27,7 +27,7 @@ public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) public override string GetToolTipText(HotSpot spot) { - var value = ReadFromBuffer(spot.Memory, Offset); + var value = spot.Memory.InterpretData32(Offset); return $"Int32: {value.IntValue}\nUInt32: 0x{value.UIntValue:X08}\nFloat: {value.FloatValue:0.000}"; } @@ -46,16 +46,11 @@ protected override int AddComment(DrawContext context, int x, int y) { x = base.AddComment(context, x, y); - var value = ReadFromBuffer(context.Memory, Offset); + var value = context.Memory.InterpretData32(Offset); x = AddComment(context, x, y, value.FloatValue, value.IntPtr, value.UIntPtr); return x; } - - private static UInt32FloatData ReadFromBuffer(MemoryBuffer memory, int offset) => new UInt32FloatData - { - Raw = memory.ReadInt32(offset) - }; } } diff --git a/ReClass.NET/Nodes/Hex64Node.cs b/ReClass.NET/Nodes/Hex64Node.cs index 012859ef..61749e46 100644 --- a/ReClass.NET/Nodes/Hex64Node.cs +++ b/ReClass.NET/Nodes/Hex64Node.cs @@ -18,7 +18,7 @@ public override void GetUserInterfaceInfo(out string name, out Image icon) public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) { - var value = spot.Memory.ReadFromBuffer(Offset); + var value = spot.Memory.InterpretData64(Offset); address = value.IntPtr; @@ -27,7 +27,7 @@ public override bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address) public override string GetToolTipText(HotSpot spot) { - var value = spot.Memory.ReadFromBuffer(Offset); + var value = spot.Memory.InterpretData64(Offset); return $"Int64: {value.LongValue}\nUInt64: 0x{value.ULongValue:X016}\nFloat: {value.FloatValue:0.000}\nDouble: {value.DoubleValue:0.000}"; } @@ -46,7 +46,7 @@ protected override int AddComment(DrawContext context, int x, int y) { x = base.AddComment(context, x, y); - var value = context.Memory.ReadFromBuffer(Offset); + var value = context.Memory.InterpretData64(Offset); x = AddComment(context, x, y, value.FloatValue, value.IntPtr, value.UIntPtr); diff --git a/ReClass.NET/Nodes/PointerNode.cs b/ReClass.NET/Nodes/PointerNode.cs index 47431aca..9df3b8b0 100644 --- a/ReClass.NET/Nodes/PointerNode.cs +++ b/ReClass.NET/Nodes/PointerNode.cs @@ -135,8 +135,7 @@ public override int CalculateDrawnHeight(DrawContext context) } return height; } - - + public override void PerformPostInitWork() { base.PerformPostInitWork(); diff --git a/ReClass.NET/Nodes/VirtualMethodTableNode.cs b/ReClass.NET/Nodes/VirtualMethodTableNode.cs index 8136a268..2c9099a0 100644 --- a/ReClass.NET/Nodes/VirtualMethodTableNode.cs +++ b/ReClass.NET/Nodes/VirtualMethodTableNode.cs @@ -33,8 +33,7 @@ public override void Initialize() AddNode(CreateDefaultNodeForSize(IntPtr.Size)); } } - - + protected override int AddComment(DrawContext context, int x, int y) { x = base.AddComment(context, x, y); @@ -49,11 +48,10 @@ protected override int AddComment(DrawContext context, int x, int y) } return x; } - - + public string GetAssociatedRemoteRuntimeTypeInformation(DrawContext context) { - var addressFirstVTableFunction = context.Memory.ReadFromBuffer(Offset).IntPtr; + var addressFirstVTableFunction = context.Memory.InterpretData64(Offset).IntPtr; if (addressFirstVTableFunction != IntPtr.Zero) { return context.Process.ReadRemoteRuntimeTypeInformation(addressFirstVTableFunction); @@ -61,8 +59,7 @@ public string GetAssociatedRemoteRuntimeTypeInformation(DrawContext context) return string.Empty; } - - + public override Size Draw(DrawContext context, int x, int y) { if (IsHidden && !IsWrapped) diff --git a/ReClass.NET/Settings.cs b/ReClass.NET/Settings.cs index 8c0ec099..32eafc3d 100644 --- a/ReClass.NET/Settings.cs +++ b/ReClass.NET/Settings.cs @@ -29,10 +29,7 @@ public Settings() { typeof(EnumNode), Keys.Control | Keys.Shift | Keys.E }, { typeof(Int32Node), Keys.Control | Keys.Shift | Keys.I } }; - - // Define more here. } - // Application Settings @@ -103,8 +100,7 @@ public Settings() public Color PluginColor { get; set; } = Color.FromArgb(255, 0, 255); public CustomDataMap CustomData { get; } = new CustomDataMap(); - - + public Keys GetShortcutKeyForNodeType(Type nodeType) { return !_shortcutKeyPerNode.TryGetValue(nodeType, out var shortcutKeys) ? Keys.None : shortcutKeys; From 528708debe6a5a506c9174549c372f698d2345d6 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 12:19:34 +0200 Subject: [PATCH 14/15] Added undo/redo for Class AddressFormula. Wired up auto-exception handlers to the ShowException method in Program so it always catches all exceptions thrown --- ReClass.NET/Nodes/BaseNode.cs | 1 - ReClass.NET/Nodes/ClassNode.cs | 10 +++++++++- ReClass.NET/Program.cs | 18 +++++++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ReClass.NET/Nodes/BaseNode.cs b/ReClass.NET/Nodes/BaseNode.cs index 6bb12224..edac2e11 100644 --- a/ReClass.NET/Nodes/BaseNode.cs +++ b/ReClass.NET/Nodes/BaseNode.cs @@ -26,7 +26,6 @@ public abstract class BaseNode private static int nodeIndex = 0; - //private string name = string.Empty; private CommandifiedMember name; private string comment = string.Empty; diff --git a/ReClass.NET/Nodes/ClassNode.cs b/ReClass.NET/Nodes/ClassNode.cs index fe51a32f..d5eba916 100644 --- a/ReClass.NET/Nodes/ClassNode.cs +++ b/ReClass.NET/Nodes/ClassNode.cs @@ -5,6 +5,8 @@ using System.Linq; using ReClassNET.Controls; using ReClassNET.UI; +using SD.Tools.Algorithmia.GeneralDataStructures; +using SD.Tools.Algorithmia.GeneralDataStructures.EventArguments; namespace ReClassNET.Nodes { @@ -28,7 +30,12 @@ public class ClassNode : BaseContainerNode public Guid Uuid { get; set; } - public string AddressFormula { get; set; } = DefaultAddressFormula; + private CommandifiedMember addressFormula; + public string AddressFormula + { + get => addressFormula.MemberValue; + set => addressFormula.MemberValue = value; + } public event NodeEventHandler NodesChanged; @@ -36,6 +43,7 @@ internal ClassNode(bool notifyClassCreated) { Contract.Ensures(AddressFormula != null); + addressFormula = new CommandifiedMember("AddressFormula", Constants.GeneralPurposeChangeType.None, DefaultAddressFormula); LevelsOpen.DefaultValue = true; Uuid = Guid.NewGuid(); diff --git a/ReClass.NET/Program.cs b/ReClass.NET/Program.cs index 4a1dd5d4..aba0f3f1 100644 --- a/ReClass.NET/Program.cs +++ b/ReClass.NET/Program.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Drawing; using System.Globalization; +using System.Threading; using System.Windows.Forms; using Microsoft.SqlServer.MessageBox; using ReClassNET.Core; @@ -43,6 +44,11 @@ static void Main(string[] args) DesignMode = false; // The designer doesn't call Main() CommandQueueID = Guid.NewGuid(); + // wire event handlers for unhandled exceptions, so these will be shown using our own method. + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.Automatic, true); + Application.ThreadException += new ThreadExceptionEventHandler(Program.Application_ThreadException); + AppDomain.CurrentDomain.UnhandledException+=new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + CommandLineArgs = new CommandLineArgs(args); try @@ -107,7 +113,17 @@ static void Main(string[] args) SettingsSerializer.Save(Settings); } - + + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { + ShowException(e.Exception); + } + + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + ShowException(e.ExceptionObject as Exception); + } + /// Shows the exception in a special form. /// The exception. public static void ShowException(Exception ex) From 69790cd91102a9973c3b776dcc1a78a4e82e9479 Mon Sep 17 00:00:00 2001 From: Frans Bouma Date: Tue, 4 Jul 2023 16:30:30 +0200 Subject: [PATCH 15/15] Implemented class list undo/redo, and further class node undo/redo. Most elements are now undo/redo aware --- ReClass.NET/Forms/MainForm.Functions.cs | 5 +++++ ReClass.NET/Nodes/BaseContainerNode.cs | 11 ++++++++-- ReClass.NET/Project/ReClassNetProject.cs | 27 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ReClass.NET/Forms/MainForm.Functions.cs b/ReClass.NET/Forms/MainForm.Functions.cs index bc668e01..d5eaeeab 100644 --- a/ReClass.NET/Forms/MainForm.Functions.cs +++ b/ReClass.NET/Forms/MainForm.Functions.cs @@ -319,6 +319,9 @@ public void ReplaceSelectedNodesWithType(Type type) { var selected = hotSpotsToReplace.Dequeue(); + // Use a single command here to wrap all state changes into one single undoable object, so everything gets undone/redone in 1 go + var cmd = new UndoablePeriodCommand("Replace node"); + CommandQueueManagerSingleton.GetInstance().BeginUndoablePeriod(cmd); var node = BaseNode.CreateInstanceFromType(type); var createdNodes = new List(); @@ -338,6 +341,8 @@ public void ReplaceSelectedNodesWithType(Type type) hotSpotsToReplace.Enqueue(new MemoryViewControl.SelectedNodeInfo(createdNode, selected.Process, selected.Memory, selected.Address + createdNode.Offset - node.Offset, selected.Level)); } } + // Mark the end of the activities that have to be tracked with this single command + CommandQueueManagerSingleton.GetInstance().EndUndoablePeriod(cmd); } } diff --git a/ReClass.NET/Nodes/BaseContainerNode.cs b/ReClass.NET/Nodes/BaseContainerNode.cs index aa106dd0..1d3ec5e8 100644 --- a/ReClass.NET/Nodes/BaseContainerNode.cs +++ b/ReClass.NET/Nodes/BaseContainerNode.cs @@ -1,12 +1,16 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using ReClassNET.Extensions; +using SD.Tools.Algorithmia.Commands; +using SD.Tools.Algorithmia.GeneralDataStructures; namespace ReClassNET.Nodes { public abstract class BaseContainerNode : BaseNode { - private readonly List nodes = new List(); + //private readonly List nodes = new List(); + private readonly CommandifiedList nodes = new CommandifiedList(); private int updateCount; @@ -262,7 +266,8 @@ protected void InsertBytes(int index, int size, ref List createdNodes) { return; } - + // Mark the actions that follow as actions that have to be ignored so they're not ending up in a command's command queue + CommandQueueManagerSingleton.GetInstance().BeginNonUndoablePeriod(); while (size > 0) { var node = CreateDefaultNodeForSize(size); @@ -281,6 +286,8 @@ protected void InsertBytes(int index, int size, ref List createdNodes) index++; } + // Mark the end of the actions that have to be ignored for undo/redo + CommandQueueManagerSingleton.GetInstance().EndNonUndoablePeriod(); OnNodesUpdated(); } diff --git a/ReClass.NET/Project/ReClassNetProject.cs b/ReClass.NET/Project/ReClassNetProject.cs index 90f4b5ca..bd2be84b 100644 --- a/ReClass.NET/Project/ReClassNetProject.cs +++ b/ReClass.NET/Project/ReClassNetProject.cs @@ -1,9 +1,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics.Contracts; using System.Linq; +using ReClassNET.Extensions; using ReClassNET.Nodes; using ReClassNET.Util; +using SD.Tools.Algorithmia.GeneralDataStructures; +using SD.Tools.Algorithmia.GeneralDataStructures.EventArguments; namespace ReClassNET.Project { @@ -18,7 +22,7 @@ public class ReClassNetProject : IDisposable public event EnumsChangedEvent EnumRemoved; private readonly List enums = new List(); - private readonly List classes = new List(); + private readonly CommandifiedList classes = new CommandifiedList(); // use a commandified list for the set of classes so we get auto undo/redo tracking public IReadOnlyList Enums => enums; @@ -36,6 +40,25 @@ public class ReClassNetProject : IDisposable /// List of data types to use while generating C++ code for nodes. /// public CppTypeMapping TypeMapping { get; } = new CppTypeMapping(); + + public ReClassNetProject() + { + // We're using ListChanged instead of ElementAdding here because ListChanged is also raised when 'Redo' is executed on the list re-adding the already created element. + classes.ListChanged += Classes_ListChanged; + classes.ElementRemoved += Classes_ElementRemoved; + } + + private void Classes_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + { + // nothing. The removed event is handled separately because ListChangedType.ItemRemoved doesn't give access to the removed element and ElementRemoved does. + if (e.ListChangedType == ListChangedType.ItemAdded) + { + ClassAdded?.Invoke(classes[e.NewIndex]); + } + } + + private void Classes_ElementRemoved(object sender, CollectionElementRemovedEventArgs e) => ClassRemoved?.Invoke(e.InvolvedElement); + private void Enums_ElementRemoved(object sender, CollectionElementRemovedEventArgs e) => EnumRemoved?.Invoke(e.InvolvedElement); public void Dispose() { @@ -56,7 +79,7 @@ public void AddClass(ClassNode node) node.NodesChanged += NodesChanged_Handler; - ClassAdded?.Invoke(node); + // No need to invoke the ClassAdded event here, as it's automatically raised when the class is added to the commandified list. } public bool ContainsClass(Guid uuid)