diff --git a/AssetStudio/AssetStudio-x86.csproj b/AssetStudio/AssetStudio-x86.csproj
index 0677ef5..3840483 100644
--- a/AssetStudio/AssetStudio-x86.csproj
+++ b/AssetStudio/AssetStudio-x86.csproj
@@ -211,6 +211,7 @@
+
AssetStudioForm.cs
Designer
diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj
index 6f1cfca..c566505 100644
--- a/AssetStudio/AssetStudio.csproj
+++ b/AssetStudio/AssetStudio.csproj
@@ -211,6 +211,7 @@
AssetStudioForm.cs
+
ExportOptions.cs
diff --git a/AssetStudio/AssetStudioForm.cs b/AssetStudio/AssetStudioForm.cs
index 3a0960c..ae99a71 100644
--- a/AssetStudio/AssetStudioForm.cs
+++ b/AssetStudio/AssetStudioForm.cs
@@ -30,34 +30,27 @@ namespace AssetStudio
private FMOD.MODE loopMode = FMOD.MODE.LOOP_OFF;
private uint FMODlenms;
private float FMODVolume = 0.8f;
- private float FMODfrequency;
private Bitmap imageTexture;
- #region OpenTK variables
- int pgmID, pgmColorID, pgmBlackID;
- int attributeVertexPosition;
- int attributeNormalDirection;
- int attributeVertexColor;
- int uniformModelMatrix;
- int uniformViewMatrix;
- int vao;
- int vboPositions;
- int vboNormals;
- int vboColors;
- int vboModelMatrix;
- int vboViewMatrix;
- int eboElements;
- Vector3[] vertexData;
- Vector3[] normalData;
- Vector3[] normal2Data;
- Vector4[] colorData;
- Matrix4 modelMatrixData;
- Matrix4 viewMatrixData;
- int[] indiceData;
- int wireFrameMode;
- int shadeMode;
- int normalMode;
+ #region OpenTK
+ private int pgmID, pgmColorID, pgmBlackID;
+ private int attributeVertexPosition;
+ private int attributeNormalDirection;
+ private int attributeVertexColor;
+ private int uniformModelMatrix;
+ private int uniformViewMatrix;
+ private int vao;
+ private Vector3[] vertexData;
+ private Vector3[] normalData;
+ private Vector3[] normal2Data;
+ private Vector4[] colorData;
+ private Matrix4 modelMatrixData;
+ private Matrix4 viewMatrixData;
+ private int[] indiceData;
+ private int wireFrameMode;
+ private int shadeMode;
+ private int normalMode;
#endregion
//asset list sorting helpers
@@ -70,8 +63,6 @@ namespace AssetStudio
private int nextGObject;
private List treeSrcResults = new List();
- private PrivateFontCollection pfc = new PrivateFontCollection();
-
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
@@ -176,16 +167,12 @@ namespace AssetStudio
return;
}
- bool optionLoadAssetsMenuItem = !dontLoadAssetsMenuItem.Checked;
- bool optionDisplayAll = displayAll.Checked;
- bool optionBuildHierarchyMenuItem = !dontBuildHierarchyMenuItem.Checked;
- bool optionBuildClassStructuresMenuItem = buildClassStructuresMenuItem.Checked;
-
- BuildAssetStructures(optionLoadAssetsMenuItem, optionDisplayAll, optionBuildHierarchyMenuItem, optionBuildClassStructuresMenuItem, displayOriginalName.Checked);
+ BuildAssetStructures(!dontLoadAssetsMenuItem.Checked, displayAll.Checked, !dontBuildHierarchyMenuItem.Checked, buildClassStructuresMenuItem.Checked,
+ displayOriginalName.Checked, out var fileNodes);
BeginInvoke(new Action(() =>
{
- if (productName != "")
+ if (!string.IsNullOrEmpty(productName))
{
Text = $"AssetStudio - {productName} - {assetsfileList[0].m_Version} - {assetsfileList[0].platformStr}";
}
@@ -203,7 +190,10 @@ namespace AssetStudio
{
sceneTreeView.BeginUpdate();
sceneTreeView.Nodes.AddRange(fileNodes.ToArray());
- fileNodes.Clear();
+ foreach (TreeNode node in sceneTreeView.Nodes)
+ {
+ node.HideCheckBox();
+ }
sceneTreeView.EndUpdate();
}
if (buildClassStructuresMenuItem.Checked)
@@ -676,7 +666,6 @@ namespace AssetStudio
assetInfoLabel.Text = null;
textPreviewBox.Visible = false;
fontPreviewBox.Visible = false;
- pfc.Dispose();
FMODpanel.Visible = false;
glControl1.Visible = false;
lastLoadedAsset = null;
@@ -759,10 +748,10 @@ namespace AssetStudio
FMODpanel.Visible = true;
- result = channel.getFrequency(out FMODfrequency);
+ result = channel.getFrequency(out var frequency);
if (ERRCHECK(result)) { break; }
- FMODinfoLabel.Text = FMODfrequency + " Hz";
+ FMODinfoLabel.Text = frequency + " Hz";
FMODtimerLabel.Text = $"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}";
break;
}
@@ -808,38 +797,38 @@ namespace AssetStudio
var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);
if (re != IntPtr.Zero)
{
- pfc = new PrivateFontCollection();
- pfc.AddMemoryFont(data, m_Font.m_FontData.Length);
- Marshal.FreeCoTaskMem(data);
- if (pfc.Families.Length > 0)
+ using (var pfc = new PrivateFontCollection())
{
- //textPreviewBox.Font = new Font(pfc.Families[0], 16, FontStyle.Regular);
- //textPreviewBox.Text = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ\r\n1234567890.:,;'\"(!?)+-*/=\r\nThe quick brown fox jumps over the lazy dog. 1234567890";
- fontPreviewBox.SelectionStart = 0;
- fontPreviewBox.SelectionLength = 80;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 16, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 81;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 12, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 138;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 18, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 195;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 24, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 252;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 36, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 309;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 48, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 366;
- fontPreviewBox.SelectionLength = 56;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 60, FontStyle.Regular);
- fontPreviewBox.SelectionStart = 423;
- fontPreviewBox.SelectionLength = 55;
- fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 72, FontStyle.Regular);
- fontPreviewBox.Visible = true;
+ pfc.AddMemoryFont(data, m_Font.m_FontData.Length);
+ Marshal.FreeCoTaskMem(data);
+ if (pfc.Families.Length > 0)
+ {
+ fontPreviewBox.SelectionStart = 0;
+ fontPreviewBox.SelectionLength = 80;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 16, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 81;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 12, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 138;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 18, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 195;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 24, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 252;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 36, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 309;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 48, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 366;
+ fontPreviewBox.SelectionLength = 56;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 60, FontStyle.Regular);
+ fontPreviewBox.SelectionStart = 423;
+ fontPreviewBox.SelectionLength = 55;
+ fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 72, FontStyle.Regular);
+ fontPreviewBox.Visible = true;
+ }
}
break;
}
@@ -1576,20 +1565,20 @@ namespace AssetStudio
GL.DeleteVertexArray(vao);
GL.GenVertexArrays(1, out vao);
GL.BindVertexArray(vao);
- createVBO(out vboPositions, vertexData, attributeVertexPosition);
+ createVBO(out var vboPositions, vertexData, attributeVertexPosition);
if (normalMode == 0)
{
- createVBO(out vboNormals, normal2Data, attributeNormalDirection);
+ createVBO(out var vboNormals, normal2Data, attributeNormalDirection);
}
else
{
if (normalData != null)
- createVBO(out vboNormals, normalData, attributeNormalDirection);
+ createVBO(out var vboNormals, normalData, attributeNormalDirection);
}
- createVBO(out vboColors, colorData, attributeVertexColor);
- createVBO(out vboModelMatrix, modelMatrixData, uniformModelMatrix);
- createVBO(out vboViewMatrix, viewMatrixData, uniformViewMatrix);
- createEBO(out eboElements, indiceData);
+ createVBO(out var vboColors, colorData, attributeVertexColor);
+ createVBO(out var vboModelMatrix, modelMatrixData, uniformModelMatrix);
+ createVBO(out var vboViewMatrix, viewMatrixData, uniformViewMatrix);
+ createEBO(out var eboElements, indiceData);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
}
@@ -1826,7 +1815,7 @@ namespace AssetStudio
var savePath = saveFolderDialog1.Folder + "\\";
progressBar1.Value = 0;
progressBar1.Maximum = sceneTreeView.Nodes.Count;
- ExportSplitObjectsNew(savePath, sceneTreeView.Nodes);
+ ExportSplitObjects(savePath, sceneTreeView.Nodes, true);
}
}
else
diff --git a/AssetStudio/StudioClasses/FBXExporter.cs b/AssetStudio/StudioClasses/FBXExporter.cs
index 66677b2..a98a203 100644
--- a/AssetStudio/StudioClasses/FBXExporter.cs
+++ b/AssetStudio/StudioClasses/FBXExporter.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using System.Web.Script.Serialization;
using static AssetStudio.Studio;
using static AssetStudio.Exporter;
@@ -13,6 +14,15 @@ namespace AssetStudio
public static void WriteFBX(string FBXfile, List gameObjects)
{
var timestamp = DateTime.Now;
+ Dictionary> jsonMats = null;
+ if (File.Exists(mainPath + "\\materials.json"))
+ {
+ using (var reader = File.OpenText(mainPath + "\\materials.json"))
+ {
+ var matLine = reader.ReadToEnd();
+ jsonMats = new JavaScriptSerializer().Deserialize>>(matLine);
+ }
+ }
using (StreamWriter FBXwriter = new StreamWriter(FBXfile))
{
diff --git a/AssetStudio/StudioClasses/Studio.cs b/AssetStudio/StudioClasses/Studio.cs
index 2590f66..e5355ad 100644
--- a/AssetStudio/StudioClasses/Studio.cs
+++ b/AssetStudio/StudioClasses/Studio.cs
@@ -5,7 +5,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
-using System.Web.Script.Serialization;
using System.Windows.Forms;
using static AssetStudio.Exporter;
@@ -19,13 +18,9 @@ namespace AssetStudio
public static List exportableAssets = new List(); //used to hold all assets while the ListView is filtered
private static HashSet exportableAssetsHash = new HashSet(); //avoid the same name asset
public static List visibleAssets = new List(); //used to build the ListView from all or filtered assets
-
- public static string productName = "";
- public static string mainPath = "";
- public static List fileNodes = new List();
-
- public static Dictionary> jsonMats;
public static Dictionary> AllClassStructures = new Dictionary>();
+ public static string mainPath;
+ public static string productName = "";
//UI
public static Action SetProgressBarValue;
@@ -154,10 +149,12 @@ namespace AssetStudio
return extractedCount;
}
- public static void BuildAssetStructures(bool loadAssetsMenuItem, bool displayAll, bool buildHierarchyMenuItem, bool buildClassStructuresMenuItem, bool displayOriginalName)
+ public static void BuildAssetStructures(bool loadAssets, bool displayAll, bool buildHierarchy, bool buildClassStructures, bool displayOriginalName, out List fileNodes)
{
+ fileNodes = null;
+
#region first loop - read asset data & create list
- if (loadAssetsMenuItem)
+ if (loadAssets)
{
SetProgressBarValue(0);
SetProgressBarMaximum(assetsfileList.Sum(x => x.preloadTable.Values.Count));
@@ -325,115 +322,107 @@ namespace AssetStudio
#endregion
#region second loop - build tree structure
- fileNodes = new List();
- if (buildHierarchyMenuItem)
+ if (buildHierarchy)
{
- SetProgressBarValue(0);
- SetProgressBarMaximum(assetsfileList.Sum(x => x.GameObjectList.Values.Count));
- StatusStripUpdate("Building tree structure...");
-
- foreach (var assetsFile in assetsfileList)
+ fileNodes = new List();
+ var gameObjectCount = assetsfileList.Sum(x => x.GameObjectList.Values.Count);
+ if (gameObjectCount > 0)
{
- GameObject fileNode = new GameObject(null);
- fileNode.Text = Path.GetFileName(assetsFile.filePath);
- fileNode.m_Name = "RootNode";
+ SetProgressBarValue(0);
+ SetProgressBarMaximum(gameObjectCount);
+ StatusStripUpdate("Building tree structure...");
- foreach (var m_GameObject in assetsFile.GameObjectList.Values)
+ foreach (var assetsFile in assetsfileList)
{
- foreach (var m_Component in m_GameObject.m_Components)
+ GameObject fileNode = new GameObject(null);
+ fileNode.Text = Path.GetFileName(assetsFile.filePath);
+ fileNode.m_Name = "RootNode";
+
+ foreach (var m_GameObject in assetsFile.GameObjectList.Values)
{
- if (m_Component.m_FileID >= 0 && m_Component.m_FileID < assetsfileList.Count)
+ foreach (var m_Component in m_GameObject.m_Components)
{
- var sourceFile = assetsfileList[m_Component.m_FileID];
- if (sourceFile.preloadTable.TryGetValue(m_Component.m_PathID, out var asset))
+ if (m_Component.m_FileID >= 0 && m_Component.m_FileID < assetsfileList.Count)
{
- switch (asset.Type)
+ var sourceFile = assetsfileList[m_Component.m_FileID];
+ if (sourceFile.preloadTable.TryGetValue(m_Component.m_PathID, out var asset))
{
- case ClassIDReference.Transform:
- {
- m_GameObject.m_Transform = m_Component;
- break;
- }
- case ClassIDReference.MeshRenderer:
- {
- m_GameObject.m_MeshRenderer = m_Component;
- break;
- }
- case ClassIDReference.MeshFilter:
- {
- m_GameObject.m_MeshFilter = m_Component;
- if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
+ switch (asset.Type)
+ {
+ case ClassIDReference.Transform:
{
- var m_MeshFilter = new MeshFilter(assetPreloadData);
- if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out assetPreloadData))
- {
- assetPreloadData.gameObject = m_GameObject;
- }
+ m_GameObject.m_Transform = m_Component;
+ break;
}
- break;
- }
- case ClassIDReference.SkinnedMeshRenderer:
- {
- m_GameObject.m_SkinnedMeshRenderer = m_Component;
- if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
+ case ClassIDReference.MeshRenderer:
{
- var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(assetPreloadData);
- if (assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out assetPreloadData))
- {
- assetPreloadData.gameObject = m_GameObject;
- }
+ m_GameObject.m_MeshRenderer = m_Component;
+ break;
}
- break;
- }
- case ClassIDReference.Animator:
- {
- m_GameObject.m_Animator = m_Component;
- asset.Text = m_GameObject.asset.Text;
- break;
- }
+ case ClassIDReference.MeshFilter:
+ {
+ m_GameObject.m_MeshFilter = m_Component;
+ if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
+ {
+ var m_MeshFilter = new MeshFilter(assetPreloadData);
+ if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out assetPreloadData))
+ {
+ assetPreloadData.gameObject = m_GameObject;
+ }
+ }
+ break;
+ }
+ case ClassIDReference.SkinnedMeshRenderer:
+ {
+ m_GameObject.m_SkinnedMeshRenderer = m_Component;
+ if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
+ {
+ var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(assetPreloadData);
+ if (assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out assetPreloadData))
+ {
+ assetPreloadData.gameObject = m_GameObject;
+ }
+ }
+ break;
+ }
+ case ClassIDReference.Animator:
+ {
+ m_GameObject.m_Animator = m_Component;
+ asset.Text = m_GameObject.asset.Text;
+ break;
+ }
+ }
}
}
}
- }
- var parentNode = fileNode;
+ var parentNode = fileNode;
- if (assetsfileList.TryGetTransform(m_GameObject.m_Transform, out var m_Transform))
- {
- if (assetsfileList.TryGetTransform(m_Transform.m_Father, out var m_Father))
+ if (assetsfileList.TryGetTransform(m_GameObject.m_Transform, out var m_Transform))
{
- //GameObject Parent;
- if (assetsfileList.TryGetGameObject(m_Father.m_GameObject, out parentNode))
+ if (assetsfileList.TryGetTransform(m_Transform.m_Father, out var m_Father))
{
- //parentNode = Parent;
+ if (assetsfileList.TryGetGameObject(m_Father.m_GameObject, out parentNode))
+ {
+ }
}
}
+
+ parentNode.Nodes.Add(m_GameObject);
+ ProgressBarPerformStep();
}
- parentNode.Nodes.Add(m_GameObject);
- ProgressBarPerformStep();
+ if (fileNode.Nodes.Count > 0)
+ {
+ fileNodes.Add(fileNode);
+ }
}
-
- if (fileNode.Nodes.Count > 0)
- {
- fileNodes.Add(fileNode);
- }
- }
-
- if (File.Exists(mainPath + "\\materials.json"))
- {
- string matLine;
- using (StreamReader reader = File.OpenText(mainPath + "\\materials.json"))
- {
- matLine = reader.ReadToEnd();
- }
- jsonMats = new JavaScriptSerializer().Deserialize>>(matLine);
}
}
#endregion
#region build list of class strucutres
- if (buildClassStructuresMenuItem)
+ if (buildClassStructures)
{
//group class structures by versionv
foreach (var assetsFile in assetsfileList)
@@ -595,7 +584,7 @@ namespace AssetStudio
});
}
- public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes)
+ public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes, bool isNew = false)
{
ThreadPool.QueueUserWorkItem(state =>
{
@@ -629,7 +618,10 @@ namespace AssetStudio
Directory.CreateDirectory(targetPath);
//导出FBX
StatusStripUpdate($"Exporting {filename}.fbx");
- FBXExporter.WriteFBX($"{targetPath}{filename}.fbx", gameObjects);
+ if (isNew)
+ ExportGameObject((GameObject)j, targetPath);
+ else
+ FBXExporter.WriteFBX($"{targetPath}{filename}.fbx", gameObjects);
StatusStripUpdate($"Finished exporting {filename}.fbx");
}
ProgressBarPerformStep();
@@ -637,48 +629,6 @@ namespace AssetStudio
});
}
- public static void ExportSplitObjectsNew(string savePath, TreeNodeCollection nodes)
- {
- ThreadPool.QueueUserWorkItem(state =>
- {
- foreach (TreeNode node in nodes)
- {
- //遍历一级子节点
- foreach (TreeNode j in node.Nodes)
- {
- //收集所有子节点
- var gameObjects = new List();
- CollectNode(j, gameObjects);
- //跳过一些不需要导出的object
- if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
- continue;
- //处理非法文件名
- var filename = FixFileName(j.Text);
- //每个文件存放在单独的文件夹
- var targetPath = $"{savePath}{filename}\\";
- //重名文件处理
- for (int i = 1; ; i++)
- {
- if (Directory.Exists(targetPath))
- {
- targetPath = $"{savePath}{filename} ({i})\\";
- }
- else
- {
- break;
- }
- }
- Directory.CreateDirectory(targetPath);
- //导出FBX
- StatusStripUpdate($"Exporting {j.Text}.fbx");
- ExportGameObject((GameObject)j, targetPath);
- StatusStripUpdate($"Finished exporting {j.Text}.fbx");
- }
- ProgressBarPerformStep();
- }
- });
- }
-
private static void CollectNode(TreeNode node, List gameObjects)
{
gameObjects.Add((GameObject)node);
diff --git a/AssetStudio/TreeViewExtensions.cs b/AssetStudio/TreeViewExtensions.cs
new file mode 100644
index 0000000..4eedecd
--- /dev/null
+++ b/AssetStudio/TreeViewExtensions.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+
+namespace AssetStudio
+{
+ public static class TreeViewExtensions
+ {
+ private const int TVIF_STATE = 0x8;
+ private const int TVIS_STATEIMAGEMASK = 0xF000;
+ private const int TV_FIRST = 0x1100;
+ private const int TVM_SETITEM = TV_FIRST + 63;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
+ private struct TVITEM
+ {
+ public int mask;
+ public IntPtr hItem;
+ public int state;
+ public int stateMask;
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpszText;
+ public int cchTextMax;
+ public int iImage;
+ public int iSelectedImage;
+ public int cChildren;
+ public IntPtr lParam;
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam);
+
+ ///
+ /// Hides the checkbox for the specified node on a TreeView control.
+ ///
+ public static void HideCheckBox(this TreeNode node)
+ {
+ var tvi = new TVITEM
+ {
+ hItem = node.Handle,
+ mask = TVIF_STATE,
+ stateMask = TVIS_STATEIMAGEMASK,
+ state = 0
+ };
+ SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
+ }
+ }
+}