目录

返回首页

C# 实用代码分享

1. 获取其他程序的句柄模拟键盘按键

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace 命名空间
{
   internal class 类名
   {
       [DllImport("user32.dll")]
       internal static extern int SetForegroundWindow(IntPtr ip);//获取窗口句柄
       internal static void Main()
       {
           Process process = Process.GetProcessById(PID);
           SetForegroundWindow(process.MainWindowHandle);
           SendKeys.SendWait("");
           // ^ = Ctrl
           // % = Alt
           // {按键 数字} = 按{按键}{数字}次
       }
   }
}

2. 内嵌类库加载(先将类库改为内嵌资源)

⚠️ 注意:需在 AssemblyInfo.cs 中添加资源语言配置

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
   string name = "程序的命名空间.文件夹名." + new AssemblyName(args.Name).Name + ".dll";
   var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);                
   byte[] assData = new byte[stream.Length];
   stream.Read(assData, 0, assData.Length);
   return Assembly.Load(assData);
}; 
[assembly: NeutralResourcesLanguage("zh-CN", UltimateResourceFallbackLocation.MainAssembly)]

3. 提取内嵌文件

internal class Extract
{
   internal static void File(string fn, string of)
   {
       BufferedStream bs = null;
       FileStream fs = null;
       try
       {
         Assembly a = Assembly.GetExecutingAssembly();
         bs = new BufferedStream(a.GetManifestResourceStream(fn));
         fs = new FileStream(of, FileMode.Create, FileAccess.Write);
         byte[] buffer = new byte[1024];
         int length;
         while ((length = bs.Read(buffer, 0, buffer.Length)) > 0)
         {
           fs.Write(buffer, 0, length);
         }
         fs.Flush();
       }
       finally
       {
         if (fs != null) fs.Dispose();
         if (bs != null) bs.Dispose();
       }
   }
}

4. 配置文件写法

INI 配置文件(不推荐) > ⚠️ 需要调用 kernel32.dll,安全性较差
JSON 配置文件(推荐)
// 读取配置
internal static dynamic Read(string keywords)
{
   StreamReader sr = File.OpenText("config.json");
   JsonTextReader jtr = new JsonTextReader(sr);
   JObject jo = (JObject)JToken.ReadFrom(jtr);
   dynamic value = (dynamic)jo[keywords];
   sr.Dispose();
   return value;
}
// 写入配置
internal static void Write(string keywords, dynamic newVaelue)
{
   string str = File.ReadAllText("config.json");
   dynamic jo = JsonConvert.DeserializeObject(str);
   jo[keywords] = newVaelue;
   File.WriteAllText("config.json", JsonConvert.SerializeObject(jo, Formatting.Indented));
}

示例 config.json:

{
"对象名一": "字符串",
"对象名二": 0,
"对象名三": false
}

5. 收集目录内指定格式文件

using System;
using System.IO;
namespace MusicCollector
{
   public class MainClass
   {
       public static void Main()
       {
           Console.Write("请输入目录路径: \n>");
           string inputPath = Console.ReadLine();
           string outputPath = inputPath + "\\Output";
           if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath);
           
           DirectoryInfo di = new DirectoryInfo(inputPath);
           CollectFiles(di, outputPath);
           Console.WriteLine("完成!");
           Console.ReadKey();
       }
       private static void CollectFiles(DirectoryInfo dir, string output)
       {
           foreach (FileInfo file in dir.GetFiles())
           {
               if (file.Extension == ".ogg")
               {
                   string destPath = Path.Combine(output, 

正在加载文章内容...

quot;{dir.Name}{file.Extension}"); if (File.Exists(destPath)) destPath = Path.Combine(output,

正在加载文章内容...

quot;{dir.Name}_new{file.Extension}"); File.Copy(file.FullName, destPath); } } foreach (DirectoryInfo subDir in dir.GetDirectories()) { if (subDir.Name != "Output") CollectFiles(subDir, output); } } } }

6. Hjson 配置文件

6.1. 基本介绍

说明:TML 1.4新版早已自动生成hjson文件,此教程Localizer.cs为早期教程的内容,现在无需编写,但不删除,仅供参考!

说明:TML 1.4新版早已自动生成hjson文件,此教程Localizer.cs为早期教程的内容,现在无需编写,但不删除,仅供参考!

众所周知:语言是人类进行沟通交流的表达方式。它是人与人之间的一种交流方式,人们彼此的交往离不开语言。尽管通过图片、动作、表情等可以传递人们的思想,但是语言是其中最重要的,也是最方便的媒介。然而世界各地的人们所用的语言各不相同,彼此间直接交谈是困难的,甚至是不可能的。即使是同一种语言,还有不同的方言,其差别程度也不相同。有的方言可以基本上相互理解,有的差别极大。

我们早期的模组开发者早已意识到多语言的重要性,@SweelLong为主要语言文件编写者,并且随着tModLoader的不断更迭,早期使用本地化模组,依靠代码实现自制语言格式的json文件读取……

TML 1.4的发布,TML-Team加入了新的本地化方案{*.hjson},并提供了一系列的工具支持,使得开发者可以轻松的实现多语言支持。本教程将介绍HJSON的语法和用法。

6.2. 文件类型

我们早期的模组开发者早已意识到多语言的重要性,@SweelLong为主要语言文件编写者,并且随着tModLoader的不断更迭,早期使用本地化模组,依靠代码实现自制语言格式的json文件读取……

TML 1.4的发布,TML-Team加入了新的本地化方案{*.hjson},并提供了一系列的工具支持,使得开发者可以轻松的实现多语言支持。本教程将介绍HJSON的语法和用法。

JSON 是我们平时使用非常频繁的数据格式,尤其在网络传输中非常受欢迎。大部分编程语言都支持这种格式。但是作为配置文件还是有些许不足,最主要的一点是缺乏注释(其他比如低信噪比其实还可以接受),所以在 JSON 的基础上衍生出了更方便的作为配置文件的格式 HJSON 。

HJSON的写法毕竟还是多的,甚至可以直接模仿JSON的写法:

Xxx:
{
   Xx: "x"
   Xxx:{
     ...
   }
}

这里称:Xxx和xx为键名、x为键值。

调用HJSON值的方式类似调用命名空间:

现在给定HJSON文件:

Mods:
{
   Terraria:
   {
      Name: "Terraria"
      Description: "一个生存类模组"
   }
   tModLoader:
   {
      Name: "tModLoader"
      Description: "一个模组加载器"
   }
}

在C#中读取HJSON文件(键名的完全路径):

输出Terraria的描述:>>> Mods.Terraria.Description

输出结果:"一个生存类模组"

6.3. TML本地化方案介绍

TML本地化方案:
// You may find this .hjson file approach to translations easier for your mod.
// 你会发现.hjson文件的方法让模组翻译更容易。
// .hjson files contain translations for the language specified in the filename. (Make sure this file is UTF-8 encoded only.)
// .hjson的文件夹名是指定的(确保文件编码只能为UTF-8)
// The possible languages are: English ("en-US"), German ("de-DE"), Italian ("it-IT"), French ("fr-FR"), Spanish ("es-ES"), Russian ("ru-RU"), Chinese ("zh-Hans"), Portuguese ("pt-BR"), and Polish ("pl-PL")
// 可能的语言是(引号内为指定的文件名):英语("en-US"), 德语("de-DE"), 意大利语("it-IT"), 法语("fr-FR"), 西班牙语("es-ES"), 俄语("ru-RU"), 汉语("zh-Hans"), 葡萄牙语("pt-BR"), 波兰语("pl-PL")
// We have organized these files in a folder called Localization. A single file per language makes it extremely easy to to integrate and maintain translations.
// 我们将这些文件组织在一个名为本地化的文件夹中。每种语言只有一个文件,因此非常容易整理和维护翻译。
// Each translation entry in .hjson files contains a key and a value. The key is determined following the rules of JSON [https://www.w3schools.com/js/js_json_syntax.asp]
// 每个翻译条目.hjson文件都包含一个键名和一个键值。键是根据JSON的规则确定的[https://www.w3schools.com/js/js_json_syntax.asp]
// The Key automatically inherits "Mods.ModNameHere.", which is useful to know if you want to use substitutions (as seen in the Paper Airplane example) or use Language.GetTextValue or Network text.
// 键自动继承"Mods.模组名",如果您想使用代码设置语言或使用Language.GetTextValu或网络文本是非常有用的。
// The following are the currently autogenerated keys: ItemName, ItemTooltip, BuffName, BuffDescription, ProjectileName, NPCName, MapObject, and Prefix
// 这些键是自动继承的(开发组要求不使用自动键,可忽略):ItemName, ItemTooltip, BuffName, BuffDescription, ProjectileName, NPCName, MapObject, and Prefix

6.4. Localizer.cs

/// <summary>
/// Items/Weapons文件夹专用键
/// </summary>
/// <param name="keyName"></param>
/// <returns></returns>
internal static string WeaponsText(string keyName) => Language.GetTextValue("Mods.InterspaceMod.Weapons.{0}", keyName);
根据第二行,我们发现这个方法允许Weapons文件夹下的类调用语言文本:
查阅语言文件(如zh-Hans.hjson):如果要调用
Weapons:
{
    InterspaceSword: "星际天河之刃"
}
直接调用:Language.GetTextValue("Mods.InterspaceMod.Weapons.InterspaceSword");
方法调用:WeaponsText("InterspaceSword");
对于Armors键里有多层,则可以这样写:
ArmorsText("InterspaceArmors.Head");
Language.GetTextValue("Mods.InterspaceMod.Armors.InterspaceArmors.Head");