本页说明如何在 .NET Framework 4.8 窗体项目中加入图片、JSON 等文件,如何设置「成功行为」(Build Action)与「复制到输出目录」,以及两种常用读取方式:嵌入到程序集(含 Properties.Resources)与随 EXE 落地的内容文件。操作文案以 LCode 中文界面为准;凡有代码均同时给出 C# 5.0 与 VB.NET。新建文件通用步骤见 文件与编辑器

向项目添加图片 / JSON

推荐先把资源放到项目目录下的固定文件夹(例如 Images\Data\),再纳入项目树,避免绝对路径散落。

  1. 在项目浏览器中选中目标项目或子文件夹。
  2. 右键 → 添加添加已存在的文件(对话框标题同名;可多选)。筛选器含「图片文件」「资源文件」「所有文件」等。
  3. 若所选文件不在当前目录内,会询问「您是想把文件复制到目标目录还是想创建指向原文件的链接?」:日常选复制;仅当共享磁盘上的同一份原件时再选链接
  4. 确认后文件出现在项目树中。图片 / JSON 默认「成功行为」为 None(见下一节),需按用途改成 EmbeddedResourceContent

也可新建空白 .resx:菜单 文件 → 新建 → 文件…,或右键项目 → 添加新建项…,在分类其它中选空资源文件(默认名形如 ResourceN.resx)。建议放到 Properties\ 并命名为 Resources.resx,以便生成 Properties.Resources 强类型类。

提示:LCode 窗体项目模板默认只有 Properties\AssemblyInfo不自带 Properties\Resources.resx。需要 Properties.Resources 时请自行添加空资源文件,并在属性面板把「自定义工具」设为 ResXFileCodeGenerator(或 PublicResXFileCodeGenerator),保存后生成 Resources.Designer.cs / .vb
界面文案 含义
添加 项目树右键菜单分组
添加已存在的文件 把磁盘上的图片、JSON、.resx 等纳入项目
新建项… 从模板创建新文件(含「空资源文件」)
空资源文件 模板名;分类「其它」;生成空 .resx
复制 / 链接 添加项目外文件时的两种纳入方式

生成操作与项目树位置

选中项目树中的文件后,在属性面板查看:

默认规则(以 LCode / .csproj 实际为准):

成功行为(ItemType) 写入 .csproj 运行时如何拿到 典型用途
None <None Include="…" /> 默认不进输出目录;除非改「复制到输出目录」 仅纳入源码管理、构建时不需要的文件
Content <Content Include="…" /> 配合「复制到输出目录」= Always / PreserveNewest,相对 EXE 路径读取 可替换的配置 JSON、外部图片、运行时可改文件
EmbeddedResource <EmbeddedResource Include="…" /> 嵌入程序集;可用清单流或 .resx 强类型属性 必须随程序发布、不希望被轻易改掉的资源
Compile <Compile Include="…" /> 参与编译,不是数据资源 源码文件
建议:窗体图标、按钮固定图片优先放进 Resources.resx(嵌入)。需要用户或运维改配置的 JSON,用 Content + 复制到输出目录。改完属性后执行 编译 → 编译解决方案F8),再核对 bin\Debug(或当前配置)是否出现预期文件。

代码中使用图片

方式 A:在资源编辑器中打开 Properties\Resources.resx,右键 → 添加文件…,选入图片(键名如 Logo)。确认「自定义工具」为 ResXFileCodeGenerator 并已生成 Designer 文件后,在代码中用强类型属性:

C#
using System;
using System.Windows.Forms;

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        // 键名 Logo 对应 Resources.resx 中的图片项
        this.pictureBox1.Image = Properties.Resources.Logo;
    }
}
VB.NET
Imports System
Imports System.Windows.Forms

Public Class MainForm
    Inherits Form

    Public Sub New()
        InitializeComponent()
        ' 键名 Logo 对应 Resources.resx 中的图片项
        Me.PictureBox1.Image = Properties.Resources.Logo
    End Sub
End Class

命名空间以 Designer 生成为准(Properties\Resources.resx 一般为 Properties.Resources)。若资源类为 Friend/internal,请在同一程序集内访问;需要跨程序集时把自定义工具改为 PublicResXFileCodeGenerator

方式 B:把图片设为 Content,并将「复制到输出目录」设为 PreserveNewestAlways,再按相对 EXE 的路径加载:

C#
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

public partial class MainForm : Form
{
    private void LoadLogoFromDisk()
    {
        string path = Path.Combine(Application.StartupPath, "Images", "logo.png");
        if (File.Exists(path))
        {
            this.pictureBox1.Image = Image.FromFile(path);
        }
    }
}
VB.NET
Imports System
Imports System.Drawing
Imports System.IO
Imports System.Windows.Forms

Public Class MainForm
    Inherits Form

    Private Sub LoadLogoFromDisk()
        Dim path As String = Path.Combine(Application.StartupPath, "Images", "logo.png")
        If File.Exists(path) Then
            Me.PictureBox1.Image = Image.FromFile(path)
        End If
    End Sub
End Class

项目树中路径为 Images\logo.png 时,复制到输出后应为 bin\…\Images\logo.png(相对结构一般会保留)。若仍找不到文件,先确认「成功行为」与「复制到输出目录」,再看输出目录实际内容。

代码中读取 JSON 资源

同样可走「落地文件」或「嵌入」两条路。下面以 Content + 复制到输出为例:项目中有 Data\appsettings.json,内容为 {"Title":"Demo"}。本页只演示读入文本并取一个字段;完整解析见后续专题 JSON 与 XML 解析

C#
using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Script.Serialization;
using System.Windows.Forms;

public partial class MainForm : Form
{
    private void LoadTitleFromJson()
    {
        string path = Path.Combine(Application.StartupPath, "Data", "appsettings.json");
        string json = File.ReadAllText(path);
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        Dictionary<string, object> map =
            serializer.Deserialize<Dictionary<string, object>>(json);
        object titleObj;
        if (map.TryGetValue("Title", out titleObj) && titleObj != null)
        {
            this.Text = titleObj.ToString();
        }
    }
}
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Web.Script.Serialization
Imports System.Windows.Forms

Public Class MainForm
    Inherits Form

    Private Sub LoadTitleFromJson()
        Dim path As String = Path.Combine(Application.StartupPath, "Data", "appsettings.json")
        Dim json As String = File.ReadAllText(path)
        Dim serializer As New JavaScriptSerializer()
        Dim map As Dictionary(Of String, Object) =
            serializer.Deserialize(Of Dictionary(Of String, Object))(json)
        Dim titleObj As Object = Nothing
        If map.TryGetValue("Title", titleObj) AndAlso titleObj IsNot Nothing Then
            Me.Text = titleObj.ToString()
        End If
    End Sub
End Class

JavaScriptSerializer 位于程序集 System.Web.Extensions。若项目尚无该引用:右键项目 → 添加引用GAC 或浏览框架程序集,加入 System.Web.Extensions(详见 引用 DLL)。

若把 JSON 设为 EmbeddedResource,可用清单流读取(资源名通常为「默认命名空间 + 相对路径,点号分隔」;在项目属性中确认默认命名空间):

C#
using System;
using System.IO;
using System.Reflection;

// 假设默认命名空间为 MyApp,文件为 Data\appsettings.json
string resourceName = "MyApp.Data.appsettings.json";
Assembly asm = Assembly.GetExecutingAssembly();
using (Stream stream = asm.GetManifestResourceStream(resourceName))
{
    if (stream == null)
    {
        throw new InvalidOperationException("找不到嵌入资源: " + resourceName);
    }
    using (StreamReader reader = new StreamReader(stream))
    {
        string json = reader.ReadToEnd();
        // 再按上文方式反序列化
    }
}
VB.NET
Imports System
Imports System.IO
Imports System.Reflection

' 假设默认命名空间为 MyApp,文件为 Data\appsettings.json
Dim resourceName As String = "MyApp.Data.appsettings.json"
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Using stream As Stream = asm.GetManifestResourceStream(resourceName)
    If stream Is Nothing Then
        Throw New InvalidOperationException("找不到嵌入资源: " & resourceName)
    End If
    Using reader As New StreamReader(stream)
        Dim json As String = reader.ReadToEnd()
        ' 再按上文方式反序列化
    End Using
End Using

注意事项与暂不支持

事项 说明
默认行为易踩坑 图片 / JSON 加入后多为 None,既不嵌入也不复制;运行时「找不到文件」时先查属性面板。
「成功行为」文案 属性名中文为「成功行为」(英源为 Build action);下拉选项仍是 None / Content / EmbeddedResource 等英文 ItemType。
强类型资源类 未设置 ResXFileCodeGenerator 时不会出现 Properties.Resources;改完自定义工具后需保存并编译。
清单资源名 嵌入非 .resx 文件时,名称依赖默认命名空间与文件夹;可用反射列出 GetManifestResourceNames() 核对。
Win32 / .rc 资源 本手册不展开本机资源脚本工作流;相关可视化编辑能力暂不支持,待更新完善
卫星程序集 / 多语言 .resx 按区域性拆分本地化资源的完整流程暂不支持,待更新完善;当前以单语言嵌入与 Content 落地为主。

常见资源类型对照

类型 推荐成功行为 复制到输出目录 代码入口(示例)
图片(嵌入) 放入 .resx(自身为 EmbeddedResource) Never Properties.Resources.键名
图片(落地) Content PreserveNewest 或 Always Image.FromFile(…)
JSON(可改配置) Content PreserveNewest 或 Always File.ReadAllText + 反序列化
JSON(随程序固定) EmbeddedResource Never GetManifestResourceStream
空 / 项目 .resx EmbeddedResource(默认) Never 自定义工具生成 Designer 后强类型访问
图标 .ico(窗体 Icon) 可进 .resx,或 Content + 复制 按所选方式 设计器属性或 new Icon(path)
仅归档、不参与运行 None Never (运行时不使用)

相关阅读