From 6f35f13674d0fef60c4d6d6baa0f6b56207e2544 Mon Sep 17 00:00:00 2001
From: sc <2401809606@qq.com>
Date: Tue, 23 Sep 2025 01:35:05 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.config | 6 ++
App.xaml | 9 ++
App.xaml.cs | 17 ++++
IniFile.cs | 52 ++++++++++
MainWindow.xaml | 142 +++++++++++++++++++++++++++
MainWindow.xaml.cs | 163 +++++++++++++++++++++++++++++++
Properties/AssemblyInfo.cs | 52 ++++++++++
Properties/Resources.Designer.cs | 71 ++++++++++++++
Properties/Resources.resx | 117 ++++++++++++++++++++++
Properties/Settings.Designer.cs | 30 ++++++
Properties/Settings.settings | 7 ++
StatisticsUI.csproj | 104 ++++++++++++++++++++
StatisticsUI.sln | 25 +++++
sunlight_logo.ico | Bin 0 -> 16958 bytes
14 files changed, 795 insertions(+)
create mode 100644 App.config
create mode 100644 App.xaml
create mode 100644 App.xaml.cs
create mode 100644 IniFile.cs
create mode 100644 MainWindow.xaml
create mode 100644 MainWindow.xaml.cs
create mode 100644 Properties/AssemblyInfo.cs
create mode 100644 Properties/Resources.Designer.cs
create mode 100644 Properties/Resources.resx
create mode 100644 Properties/Settings.Designer.cs
create mode 100644 Properties/Settings.settings
create mode 100644 StatisticsUI.csproj
create mode 100644 StatisticsUI.sln
create mode 100644 sunlight_logo.ico
diff --git a/App.config b/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App.xaml b/App.xaml
new file mode 100644
index 0000000..31d7333
--- /dev/null
+++ b/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/App.xaml.cs b/App.xaml.cs
new file mode 100644
index 0000000..3be5ab5
--- /dev/null
+++ b/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace ProcessManagGUI
+{
+ ///
+ /// App.xaml 的交互逻辑
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/IniFile.cs b/IniFile.cs
new file mode 100644
index 0000000..536b47d
--- /dev/null
+++ b/IniFile.cs
@@ -0,0 +1,52 @@
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace StatisticsUI
+{
+ internal class IniFile
+ {
+ public class IniFiles
+ {
+ public string path;
+ [DllImport("kernel32")] //返回0表示失败,非0为成功
+ private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
+ [DllImport("kernel32")] //返回取得字符串缓冲区的长度
+ private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
+ ///
+ /// 保存ini文件的路径
+ /// 调用示例:var ini = IniFiles("C:\file.ini");
+ ///
+ ///
+ public IniFiles(string iniPath)
+ {
+ this.path = iniPath;
+ }
+ ///
+ /// 写Ini文件
+ /// 调用示例:ini.IniWritevalue("Server","name","localhost");
+ ///
+ /// [缓冲区]
+ /// 键
+ /// 值
+ public void IniWritevalue(string Section, string Key, string value)
+ {
+ WritePrivateProfileString(Section, Key, value, this.path);
+ }
+ ///
+ /// 读Ini文件
+ /// 调用示例:ini.IniWritevalue("Server","name");
+ ///
+ /// [缓冲区]
+ /// 键
+ /// 值
+ public string IniReadvalue(string Section, string Key)
+ {
+ StringBuilder temp = new StringBuilder(255);
+
+ int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
+ return temp.ToString();
+ }
+
+ }
+ }
+}
diff --git a/MainWindow.xaml b/MainWindow.xaml
new file mode 100644
index 0000000..99461f9
--- /dev/null
+++ b/MainWindow.xaml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
new file mode 100644
index 0000000..e9a60f5
--- /dev/null
+++ b/MainWindow.xaml.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+
+namespace StatisticsUI
+{
+ ///
+ /// MainWindow.xaml 的交互逻辑
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+
+ private static IniFile.IniFiles Configini = new IniFile.IniFiles(Convert.ToString(System.AppDomain.CurrentDomain.BaseDirectory) + "ProcessManageConfigini.ini");
+ private static string SQLIP = Configini.IniReadvalue("SQL_SERVER", "SQL1"); //读配置文件
+ private static string SQLNAME = Configini.IniReadvalue("SQL_SERVER", "SQL2");
+ private static string SQMOD = Configini.IniReadvalue("SQL_SERVER", "SQL3");
+ private static string SQLUSER = Configini.IniReadvalue("SQL_SERVER", "SQL4");
+ private static string SQLPASWORD = Configini.IniReadvalue("SQL_SERVER", "SQL5");
+ private static DataTable DyelotsBulkedRecipe = new DataTable();
+ private static DataTable Machine = new DataTable();
+ private static DataTable Gram = new DataTable();
+ private static DataTable Machine_Gram = new DataTable();
+ SqlConnection conn_SC;
+ string Connstr_SC;
+ public static string DataGridStatistics_ProductCode = null;
+ public static string date_start_time;
+ public static string date_end_time;
+ public static string query_start = null;//全局变量开始时间
+ public static string query_end = null;//全局变量结束时间
+ public static int type = 0;//全局变量结束时间
+
+ private void DataGridStatistics_MouseDoubleClick(object sender, MouseButtonEventArgs e)//数据表双击事件
+ {
+ int rownum = DataGridStatistics.SelectedIndex;//获取鼠标选中行并定义变量
+ if (rownum != -1)//判断鼠标定位是否有效
+ {
+ /*定位选中行及指定列单元格文本信息*/
+ DataGridStatistics_ProductCode = (DataGridStatistics.Columns[0].GetCellContent(DataGridStatistics.Items[rownum]) as TextBlock).Text;//定位第0列,原料代码
+ }
+ }
+
+ private void Button_Click(object sender, RoutedEventArgs e)
+ {
+ query_start = this.query_date_start.Text;//传递开始日期
+ date_start_time = this.query_date_start_time.Text;//传递开始时间
+ query_end = this.query_date_end.Text;//传递结束日期
+ date_end_time = this.query_date_end_time.Text;//传递结束时间
+ string t = DateTime.Now.ToString("yyyy-MM-dd");
+ int query_endT = DateTime.Compare(Convert.ToDateTime(query_end), Convert.ToDateTime(t)); //比较结束时间及当期,小于-1 等于0 大于1
+ if (query_endT == 0) query_end = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"); //如果结束时间为空则填入当天时间加1天
+ if (query_end == DateTime.Now.ToString("yyyy-MM-dd")) query_end = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd");
+ int query_TimeCompare = DateTime.Compare(Convert.ToDateTime(query_start), Convert.ToDateTime(query_end)); //比较开始结束时间,小于-1 等于0 大于1
+ if (query_TimeCompare == 1)//判断查询时间是否有效,等于1无效
+ {
+ MessageBox.Show("SC:无效查询时间", "错误");//返回无效时间弹窗
+ }
+ else
+ {
+ string DyelotsBulkedRecipe_sql;
+ string Machine_sql;
+ if (this.stuff_ProductType.Text == "染料") type = 1;//原料类型
+ if (this.stuff_ProductType.Text == "助剂") type = 2;
+ if (this.stuff_ProductType.Text == "粉体助剂") type = 3;
+ if (this.stuff_ProductType.Text == "全部原料")
+ {
+ DyelotsBulkedRecipe_sql =
+ "SELECT [ProductCode],[ProductName],SUM(DispenseGrams)/1000 as TotalDispenseGrams,COUNT(*) as PrescriptionCount " +
+ "FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] where Created > '" + query_start + " " +
+ date_start_time + "' AND Created < '" + query_end + " " + date_end_time + "'AND DispenseGrams IS NOT NULL" +
+ " GROUP BY [ProductCode],[ProductName] ORDER BY TotalDispenseGrams DESC ";
+ Machine_sql =
+ "SELECT m.Name AS MachineName," +
+ "COUNT(DISTINCT d.Dyelot) AS DyelotCount," +
+ "ISNULL(SUM(dbr.DispenseGrams)/1000, 0) AS TotalDispenseGrams," +
+ "COUNT(DISTINCT CASE WHEN dbr.Dyelot IS NOT NULL AND dbr.DispenseResult = 301" +
+ "THEN CONCAT(dbr.Dyelot, '|', ISNULL(dbr.ReDye, ''), '|', ISNULL(CAST(dbr.StepNumber AS NVARCHAR(10)), ''))" +
+ "END ) AS UniqueRecipeCount FROM Machines m LEFT JOIN Dyelots d ON m.Name = d.Machine " +
+ "LEFT JOIN DyelotsBulkedRecipe dbr ON d.Dyelot = dbr.Dyelot GROUP BY m.Name ORDER BY m.Name";
+ }
+ else
+ {
+ DyelotsBulkedRecipe_sql =
+ "SELECT [ProductCode],[ProductName],SUM(DispenseGrams)/1000 as TotalDispenseGrams,COUNT(*) as PrescriptionCount " +
+ "FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] where Created >= '" + query_start + " " + date_start_time + "' AND Created < '" +
+ query_end + " " + date_end_time + "'AND ProductType='"+ type + "'AND DispenseGrams IS NOT NULL" +
+ " GROUP BY [ProductCode],[ProductName] ORDER BY TotalDispenseGrams DESC ";
+ Machine_sql =
+ "SELECT m.Name AS MachineName," +
+ "COUNT(DISTINCT d.Dyelot) AS DyelotCount," +
+ "ISNULL(SUM(CASE WHEN dbr.ProductType = '"+type+"' THEN dbr.DispenseGrams END)/1000, 0) AS TotalDispenseGrams," +
+ "COUNT(DISTINCT CASE WHEN dbr.Dyelot IS NOT NULL AND dbr.DispenseResult = 301 AND dbr.ProductType = '"+type+
+ "'THEN CONCAT(dbr.Dyelot, '|', ISNULL(dbr.ReDye, ''), '|', ISNULL(CAST(dbr.StepNumber AS NVARCHAR(10)), ''))" +
+ "END ) AS UniqueRecipeCount FROM Machines m LEFT JOIN Dyelots d ON m.Name = d.Machine " +
+ "AND d.CreationTime >= '" + query_start + " " + date_start_time + "' AND d.CreationTime < '" + query_end +
+ " " + date_end_time + "' LEFT JOIN DyelotsBulkedRecipe dbr ON d.Dyelot = dbr.Dyelot AND dbr.Created>='" + query_start +
+ " " + date_start_time + "' AND dbr.Created < '" + query_end + " " + date_end_time + "' GROUP BY m.Name ORDER BY m.Name";
+ }
+ conn_SC.OpenAsync(); //连接数据库
+ Machine.Clear();
+ DyelotsBulkedRecipe.Clear();
+ SqlDataAdapter DyelotsBulkedRecipe_ = new SqlDataAdapter(DyelotsBulkedRecipe_sql, Connstr_SC);
+ SqlDataAdapter Machine_ = new SqlDataAdapter(Machine_sql, Connstr_SC);
+ try
+ {
+ // DyelotsBulkedRecipe.Clear();
+ DyelotsBulkedRecipe_.Fill(DyelotsBulkedRecipe);
+ DataGridStatistics.ItemsSource = DyelotsBulkedRecipe.DefaultView;
+ // DyelotsBulkedRecipe.Clear();
+
+ //Machine.Clear();
+ Machine_.Fill(Machine);
+ DataGridStatistics_mac.ItemsSource = Machine.DefaultView;
+ // Machine.Clear();
+
+ }
+ catch (Exception ex)
+ {
+ }
+ finally
+ {
+ conn_SC.Close();
+ }
+ }
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ Connstr_SC = "server=" + SQLIP + ";database=" + SQLNAME + ";User ID=" + SQLUSER + ";Password=" + SQLPASWORD;
+ conn_SC = new SqlConnection(Connstr_SC);
+
+ Gram.Columns.Add("ProductCode", typeof(string));
+ Gram.Columns.Add("ProductName", typeof(string));
+ Gram.Columns.Add("TotalDispenseGrams", typeof(string));
+ Gram.Columns.Add("PrescriptionCount", typeof(string));
+
+ Machine_Gram.Columns.Add("MachineName", typeof(string));
+ Machine_Gram.Columns.Add("TotalDispenseGrams", typeof(string));
+ Machine_Gram.Columns.Add("DyelotCount", typeof(string));
+ Machine_Gram.Columns.Add("UniqueRecipeCount", typeof(string));
+ }
+ }
+}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f035443
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,52 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("ProcessManagGUI")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ProcessManagGUI")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+//若要开始生成可本地化的应用程序,请设置
+//.csproj 文件中的 CultureYouAreCodingWith
+//在 中。例如,如果你使用的是美国英语。
+//使用的是美国英语,请将 设置为 en-US。 然后取消
+//对以下 NeutralResourceLanguage 特性的注释。 更新
+//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //主题特定资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //或应用程序资源字典中找到时使用)
+ ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //、应用程序或任何主题专用资源字典中找到时使用)
+)]
+
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..e74ffe4
--- /dev/null
+++ b/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本: 4.0.30319.42000
+//
+// 对此文件的更改可能导致不正确的行为,如果
+// 重新生成代码,则所做更改将丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace ProcessManagGUI.Properties
+{
+
+
+ ///
+ /// 强类型资源类,用于查找本地化字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// 返回此类使用的缓存 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProcessManagGUI.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Properties/Resources.resx b/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..77c91b2
--- /dev/null
+++ b/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace ProcessManagGUI.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/StatisticsUI.csproj b/StatisticsUI.csproj
new file mode 100644
index 0000000..68fbcff
--- /dev/null
+++ b/StatisticsUI.csproj
@@ -0,0 +1,104 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9D677FAF-CB71-49A1-B327-060E16D45E17}
+ WinExe
+ ProcessManagGUI
+ ProcessManagGUI
+ v4.7.2
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/StatisticsUI.sln b/StatisticsUI.sln
new file mode 100644
index 0000000..4624a11
--- /dev/null
+++ b/StatisticsUI.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36511.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatisticsUI", "StatisticsUI.csproj", "{9D677FAF-CB71-49A1-B327-060E16D45E17}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9D677FAF-CB71-49A1-B327-060E16D45E17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9D677FAF-CB71-49A1-B327-060E16D45E17}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9D677FAF-CB71-49A1-B327-060E16D45E17}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9D677FAF-CB71-49A1-B327-060E16D45E17}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {2B17EF6F-2576-43B7-91BC-F480E72D06C9}
+ EndGlobalSection
+EndGlobal
diff --git a/sunlight_logo.ico b/sunlight_logo.ico
new file mode 100644
index 0000000000000000000000000000000000000000..2fe61312eed7e661886cee8880fdaf311b415270
GIT binary patch
literal 16958
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
literal 0
HcmV?d00001