关于winform:更新-WinForms-InitializeComponent-的现代代码生成

当你应用 Visual Studio 中的 WinForms Designer 来创立一个 WinForms 表单或用户控件时,它并没有像 XML 或 HTML 那样的非凡定义或文件格式来示意用户界面。从一开始,WinForms 应用的惟一格局就是程序代码。在 WinForms Visual Basic 我的项目中定义的表单或用户控件会被保留到 VB 代码中。在 C# 我的项目中,这就是 C# 代码。这些代码将被搁置在一个专用的 Designer 文件中,该文件位于理论表单代码文件前面,也蕴含管制 UI 的代码。 当你的表单或用户控件须要在 WinForms Designer 中再次关上时,该代码将被解释并依据后果对象图在 Designer 中从新创立表单/用户控件。这就是咱们把保留表单的过程称为 CodeDOM 序列化的起因。这里的 CodeDOM 指的是一种对象模型(Code Document object model,代码文档对象模型),它容许开发人员通过特定类型的对象来定义程序的各个方面或程序的一部分。 尽管 CodeDOM 很灵便,能够比拟容易地进行扩大,并且反对比 Visual Basic 或 C# 更多的语言,然而从现有的代码文件生成 CodeDOM 图是一件齐全不同的事件。尽管 CodeDOM 能够通过现有的编译器实现为特定的语言编写代码文件,但生成的代码格调依然是 .NET 框架刚开始时的格调,在许多状况下曾经不再合乎以后的编码标准。 在 WinForms 中,当你设计一个表单的时候,所有相干的内容都是在每个表单或用户控件的一个办法中生成的。这个办法(还有一些根底构造和初始化代码)叫做 InitializeComponent。 这个办法会被表单的构造函数无条件地调用。在 C# 中,这是非常明显的,你增加到我的项目中的新表单总是具备构造函数和所需的调用: public partial class Form1 : Form { public Form2() { InitializeComponent(); } }在 Visual Basic 中,如果你不显式地增加构造函数 Sub New,Visual Basic 编译器会在后盾主动插入对 InitializeComponent 的调用。但如果你在代码文件中增加了一个构造函数,编辑器也会在 VB 代码中插入对 InitializeComponent 的调用: ...

April 18, 2023 · 2 min · jiezi

关于winform:winform读取文件目录下的信息

winform读取文件目录下的信息private void button1_Click(object sender, System.EventArgs e) { //浏览文件夹 this.folderBrowserDialog1.ShowDialog(); if(this.folderBrowserDialog1.SelectedPath.Trim()!="") this.textBox1.Text=this.folderBrowserDialog1.SelectedPath.Trim();}private void button2_Click(object sender, System.EventArgs e) { //显示指定文件夹下的文件 if(this.textBox1.Text.Trim()=="") return; this.listBox1.Items.Clear(); string[] MyFiles=System.IO.Directory.GetFiles(this.textBox1.Text); this.listBox1.Items.AddRange(MyFiles); //foreach(string File in MyFiles) // this.listBox1.Items.Add(File);}

October 26, 2021 · 1 min · jiezi

关于winform:应用的工具栏太难看这个控件帮你提升应用颜值

点击获取工具>>Toolbar Form是XtraForm的扩大版本,容许您将bar items 间接增加到表单标题栏中。 下图阐明了一个示例Toolbar Form,在表单标题栏中带有不同类型的bar items(惯例按钮、编辑项、查看项和外观菜单)。 ToolbarForm是XtraForm类的后辈,并共享其所有性能。 将表单转换为工具栏表单要将规范或任何DevExpress form转换为工具栏表单,请调用智能标记菜单并抉择 "Convert to Toolbar Form" 选项。 暗藏表单题目能够显示没有题目的Toolbar Form(Form.Text属性),为此请禁用ShowText设置。 以下"Visual Studio Inspired UI Demo" DevExpress demo屏幕截图阐明了没有可见题目的Toolbar Form。 在设计时将Bar Items增加到Form Title Bar中能够应用向床柜工具栏增加bar items的办法来填充Toolbar Form的标题栏:表单在其标题栏的两端都有两个能够包容我的项目的区域,单击 "[Add]" 按钮创立一个新的我的项目。 您能够在设计时拖放我的项目来重新排列它们,而后从一个标题栏区域挪动到另一个标题栏区域。 在Code. Satellite控件中创立Toolbar FormsToolbar Form具备两个必须的从属控件 - ToolbarFormControl和ToolbarFormManager。 ToolbarFormControl - 表单的标题栏,显示增加到其ToolbarFormControl.TitleItemLinks汇合的条形我的项目,应用BarItem.Alignment属性抉择此我的项目停靠在ToolbarFormControl的左边缘还是右边缘。ToolbarFormManager - 表单的外部BarManager,在ToolbarFormControl中显示的集体工具栏我的项目。要将现有表单转换为Toolbar Forms或在代码中创立新的工具栏表单,您须要手动创立这些组件。 C# `ToolbarForm myForm = new ToolbarForm();myForm.Size = new Size(800, 600);myForm.Text = "Toolbar Form";ToolbarFormManager tfcManager = new ToolbarFormManager() { Form = myForm };ToolbarFormControl tfcHeader = new ToolbarFormControl() { ToolbarForm = myForm, Manager = tfcManager};myForm.Controls.Add(tfcHeader);myForm.ToolbarFormControl = tfcHeader; ...

January 7, 2021 · 2 min · jiezi

关于winform:如何将WinFormsWPF项目转换为NET-Core

Telerik UI for WinForms和WPF套件通过Visual Studio扩大提供了.NET Core Project Converter,此工具能够将应用.NET Framework 4.8(或更低版本)的客户端我的项目转换为.NET Core我的项目,以简化迁徙。 telerik技术团队领有近20年的.NET Framework开发教训,生成并正在创立大量的桌面应该程序。.NET Core的诞生带来了一个新时代,即便某些开发人员可能抉择持续应用.NET Framework进行进一步开发,但其余开发人员仍偏向于新趋势。 那么所有针对.NET Framework的现有Telerik WinForms / WPF我的项目都将如何解决? 是否能够将它们转换为.NET Core?在咱们次要的桌面产品中,Telerik UI for WinForms和Telerik UI for WPF始终致力于为客户解决各种问题,同时也能够将现有我的项目转化为.NET Core。 自R2 2020版本起,这两个套件都通过Telerik WinForms和WPF Visual Studio Extensions在Visual Studio 2019中提供了工具,这些工具会将应用.NET Framework 4.8(或更低版本)的客户端我的项目转换为.NET Core我的项目,以简化迁徙。 仅当解决方案在VS2019中加载并且蕴含任何.NET Framework Telerik我的项目时,菜单项才可见。 .NET Core Project Converter是基于Try-Convert工具和Microsoft提供的.NET可移植性分析器,以帮忙.NET开发人员将其我的项目移植到.NET Core。 请记住,即便转换可能胜利,咱们也不保障我的项目将被编译或失常运行,并且您可能须要微调输入。 .NET Core Project Converter Wizard容许您将Telerik .NET Framework我的项目转换为Telerik .NET Core我的项目,第一步是显示正告页面,以告知用户运行向导后将进行哪些更新和哪些内容不会更新。 Converter向导列出了所有检测到的.NET Framework我的项目,并在下拉列表中列出了所有可用的.NET Core 3.1发行版: ...

December 22, 2020 · 1 min · jiezi

关于winform:WinForm界面开发轻松实现菜单列表的动态个性化配置管理

点击获取工具>>在咱们个别的利用零碎外面,因为零碎是面向不同类型的用户,咱们所看到的菜单会越来越多,多一点的甚至上百个,然而咱们理论工作接触的菜单可能就是那么几个,那么对于这种宏大的菜单体系,寻找起来十分不便。因而对菜单的个性化配置就显得尤为重要,本文就是基于这样的理念,提供用户对可见菜单进行一个动静配置,只选本人喜爱、罕用的菜单显示进去即可,菜单的配置存储在数据库外面,在不同的客户端体验都是一样。本文次要介绍实现这样的性能的一个残缺思路,局部代码逻辑可供参考。 一、 菜单列表的动静个性化配置的过程在咱们有些软件外面,咱们可能在界面上顶部搁置菜单,也可能在界面的左侧搁置树形列表菜单,这种状况都有可能,本篇摘取其中之一,左侧菜单进行一个介绍菜单的配置解决。 例如咱们在左侧依据用户权限展现相干的菜单信息,动静生成整个列表展现,大抵的界面成果如下所示。 而后在性能列表上提供一个右键的菜单进行菜单的刷新、配置管理,如下界面所示。 通过配置性能,咱们让用户进入一个配置管理界面,在其中配置显示本人感兴趣的菜单,而后进行保留即可,保留后同时刷新界面的性能菜单显示。 以上几个界面成果就是为了介绍整个菜单配置管理的个别过程,之所以把界面成果放在后面介绍,就是可能让咱们有一个相似原型设计形式的感性认识,理解了相干的处理过程,咱们就能够着手通过编码的形式来实现这个解决逻辑了。 二、菜单动静个性化配置的性能实现下面介绍了大略的界面成果,有了参考,咱们能够把它的实现思路通过代码实现进去。 1. 参数的数据存储 首先咱们须要理解,用户配置能够通过XML保留在本地,也能够通过数据库存储保留在服务器,后者在分布式的客户端的时候,能够处处一样,这样就不会造成体验上的差别,因而咱们这里采纳存储在数据库的计划。 这个配置管理组件SettingsProvider.net应用起来也是比拟不便的,能够抉择存储在本地的对象,也能够抉择存储在数据库的存储对象。 首先咱们先定义一个存储的参数类,这个是应用这个组件所必须的存储对象信息,如下代码所示。 `/// <summary>/// 用来管制人员治理显示菜单的参数配置/// </summary>public class UserMenuParameter{[DefaultValue("")][Description("用户ID")]public string UserID { get; set; } [Description("用户设置可见的菜单")]public Dictionary<string, bool> VisibleDict { get; set; }}` 须要获取或存储这个对象信息的时候,咱们初始化几个治理类,如下代码所示。 `//参数存储所需的相干对象private SettingsProvider settings;private ISettingsStorage store;private UserMenuParameter parameter;` 而后在配置管理界面窗体外面,初始化这几个对象,如下代码所示。 `// PortableStorage: 在运行程序目录创立一个setting的文件记录参数数据// DatabaseStorage:在数据库TB_UserParameter表存储用户配置参数store = new DatabaseStorage(LoginUserInfo.ID);settings = new SettingsProvider(store);parameter = settings.GetSettings<UserMenuParameter>();` 这样咱们就能够依据用户的ID,获取对应记录的信息并转换为相干的对象了,如果咱们须要把批改的信息写会到存储介质外面,代码如下所示。 `try{parameter = settings.GetSettings<UserMenuParameter>();parameter.VisibleDict = dict;parameter.UserID = LoginUserInfo.ID;settings.SaveSettings<UserMenuParameter>(parameter); ProcessDataSaved(sender, e);//触发内部事件 ...

December 7, 2020 · 1 min · jiezi

关于winform:NEWWinForm界面开发设计时正式支持NET-5

点击获取工具>> 早在往年7月,官网技术团队发表对DevExpress控件进行性能加强,使其反对最新的.NET 5 Preview。 然而只管技术团队始终在致力确保WinForms控件与.NET 5兼容但在Visual Studio中对设计器的反对却是另一回事。 当初.NET 5已与Visual Studio 2019 v16.8一起正式公布,当初该探讨如何应用DevExpress WinForms v20.2的设计时工具了。 只管WinForms平台尚未齐全解决重要的设计时问题,但Microsoft在思考.NET 5的开发人员方面获得了较好的停顿,例如,您能够调用控件的智能标记菜单... 应用控件的设计器 并利用独立的设计器对话框来设置简单的属性,例如技术团队最近全面批改的编辑器输出标记的Mask Settings对话框。 基本操作为了开发一个新的WinForms应用程序,该应用程序以DevExpress控件为指标面向.NET 5,您应该执行以下操作: 应用VS Installer中选中的“.NET Core development tools”选项来装置Visual Studio 2019 version 16.9 Preview 1。依照本帮忙文章中的阐明注册非凡的领先体验NuGet feed:装置Visual Studio的NuGet Package Manager。通过独自的Feed散发.NET 5控件,Microsoft仍必须施行一些细节,这些细节对于残缺设计时反对至关重要。留神:目前,NuGet feed是获取针对.NET 5优化的最新DevExpress WinForms控件的惟一办法。通过Download Manager中提供的经典.NET Core安装程序散发的DevExpress WinForms v20.2控件,也能够在.NET Core下运行.NET 5,但不足设计时反对。 在Visual Studio中,确保您的应用程序面向.NET 5.0。跳转到“Project | Manage NuGet Packages...”,抉择您在步骤2中注册的Feed,而后装置具备所需本地化区域性的预公布软件包,每个软件包都蕴含所有可用的DevExpress WinForms控件。 装置选定的程序包后,您能够从Visual Studio工具箱中增加DevExpress控件。 已知问题只管下面提到的设计时性能仿佛表明.NET 5已准备就绪且可用(实际上可用于Visual Studio中的根本WinForms控件),但规范WinForms设计器界面依然存在重要的局限性/问题,这些问题意味着设计器目前尚不齐全反对咱们简单的WinForms控件。当然,Microsoft将在将来的Visual Studio构建中加强这些接口,随后将提供DevExpress WinForms设计时反对。 目前,咱们尚无无关何时筹备好进行此类更改的领导,因而咱们无奈为用户提供确切的公布时间表。一些尚未为.NET 5提供最佳的设计时体验示例: ...

December 4, 2020 · 1 min · jiezi

关于winform:WinForm应用界面开发框架下的布局调整操作简单实用

点击获取工具>>在本文中,咱们形容LayoutControl如何调整其子控件的大小,一旦相熟了次要概念,就应该可能使其适应您的计划。 概念:LayoutControl调整我的项目的大小,以便思考到这些我的项目及其子项的大小限度,它们会填充所有可用区域。若要限度某些控件的大小并在此大小大于可用的可见区域时显示滚动条,请指定 Control.MinimumSize属性。 若要限度我的项目的最大大小并容许LayoutControl自在调整其余我的项目的大小,能够指定Control.MaximumSize并增加Empty Space Items ,以便它们占据调整大小后残余的空白区域。 要自在调整控件的大小,您能够删除Size Constraints并增加Empty Space Items,以便它们填充空白区域。 请留神以下几点: 某些DevExpress编辑器和控件(如TextEdit,SimpleButton等)和某些规范WinForms控件无奈通过设计自在调整大小。如果Control.MinimumSize / Control.MaximumSize属性的宽度和/或高度设置为0,则能够自在调整控件的大小。应用v20.2设计时和运行时自定义表格会主动突出显示已达到其最小/最大大小(因而无奈进一步调整大小)的我的项目。 在设计时,当聚焦控件或LayoutControl时,将显示尺寸图标,这些图标批示对控件施加了哪些尺寸限度。 示例:暗藏LayoutControl中的滚动条 利用大小限度时,LayoutControl将显示滚动条,因而请确保: 未设置Control.MinimumSize 属性。相应我的项目的 LayoutControlItem.SizeConstraintsType 属性未设置为Custom,也未指定其 LayoutControlItem.MinSize。控件的大小不能在设计时设置 确保我的项目没有因为尺寸限度而被锁定。因为布局控件会调整其我的项目的大小,以便它们能够占据所有可用区域,因而要调整我的项目的大小,有必要将Empty Space Items增加到指标布局我的项目的相应一侧。 调整组或标签组的大小 在指标组外部和/或内部的相应一侧增加一个Empty Space Item来调整其大小。 调整我的项目题目的大小 您能够将TextAlignMode设置为以下任一值: AutoSize使LayoutControl将我的项目题目的大小调整为最小宽度,以使文本整体显示。CustomSize而后将TextSize属性设置为所须要的大小值。更改控件与其题目之间的间隔 您能够应用TextToControlDistance属性来治理间隔。 当CheckEdit.Text蕴含长文本时,避免应用CheckEdit减少LayoutItem的大小 将控件增加到LayoutControl时,将创立一个具备Default Size Constraints的新布局我的项目。更改LayoutControl中CheckEdit的文本时,将更新LayoutControlItem.MinSize和MaxSize属性来限度我的项目的可能大小。为防止这种状况,请将CheckEdit增加到LayoutControl,并将CheckEdit LayoutItem的大小束缚设置为FreeSizing,而后批改CheckEdit的文本。

October 19, 2020 · 1 min · jiezi

NetC常用系统操作获取系统文件设置开机启动等

获取常用系统文件目录static void Main(string[] args){ //1、通过Environment.GetFolderPath()获取 string pathFavorites = Environment.GetFolderPath(Environment.SpecialFolder.Favorites);//获取我的收藏路径 Console.WriteLine("Favorites:" + pathFavorites); string pathDesktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);//获取桌面路径 Console.WriteLine("Desktop:" + pathDesktop); string pathMyDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);//获取我的文档路径 Console.WriteLine("MyDocuments:" + pathMyDocuments); string pathMyPictures = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);//获取我的图片路径 Console.WriteLine("MyPictures:" + pathMyPictures); string pathMyVideos = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);//获取我的视频路径 Console.WriteLine("MyVideos:" + pathMyVideos); string pathDownloads = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\Downloads";//获取下载路径(这个没有找到,所以需要配合UserProfile来拼接了) Console.WriteLine("Downloads:" + pathDownloads); //2、通过环境变量获取 string tempPath = Environment.GetEnvironmentVariable("TEMP"); Console.WriteLine("TEMP:" + tempPath); Console.ReadKey();}设置开机启动private string registryName = "BootTestDemo";//启动项的名称private void btnSubmit_Click(object sender, EventArgs e){ if (this.ckBootEntry.Checked) { string filePath = Environment.CurrentDirectory + "\\PowerBootDemo.exe"; SetBoot(this.registryName, filePath); } else { DeleteBoot(this.registryName); } MessageBox.Show("Success");}/// <summary>/// 检测注册项是否存在/// </summary>/// <param name="key"></param>/// <returns></returns>private bool CheckExisting(string key){ string[] allNames = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run").GetValueNames(); foreach (var item in allNames) { if (item.Equals(key)) { return true; } } return false;}/// <summary>/// 设置启动项/// </summary>private void SetBoot(string key, string path){ if (CheckExisting(this.registryName)) return;//检测是否存在 Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");//在系统启动的注册表中创建子项 registryKey.SetValue(key, path);//为子项进行赋值}/// <summary>/// 删除启动项/// </summary>public void DeleteBoot(string key){ if (!CheckExisting(this.registryName)) return;//检测是否存在 Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run"); registryKey.DeleteValue(key, false);}//PS:如果记不住这么长的路径可以直接打开系统注册表编辑器来翻看(cmd执行:regedit)。持续更新.... ...

September 10, 2019 · 1 min · jiezi

Winform-WebSocketSharp客户端连接JAVA-WebSocket-服务端的消息推送桌面弹框提醒

WebSocketSharp 请参考官网 https://github.com/sta/websoc...坑: ws.OnMessage += (sender, e) => { BalloonForm balloon = new BalloonForm("标题", "内容", "底部"); balloon.Visible = false; balloon.ShowDialog();//此处弹窗必须使用模式对话框,否则窗体打开里面控件样式不显示,鼠标一直显示加载状态 } 弹窗代码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace xxxx.page{ public class BalloonForm : Form { private System.ComponentModel.IContainer components = null; private Label title; private Label textContent; private Label staticTime; private Timer timer1; private Timer timer2; private Timer timer3; public int StayTime = 5000; private int heightMax, widthMax; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.title = new Label(); this.textContent = new Label(); this.staticTime = new Label(); this.timer1 = new Timer(this.components); this.timer2 = new Timer(this.components); this.timer3 = new Timer(this.components); this.SuspendLayout(); // // title // this.title.AutoSize = true; this.title.Location = new Point(10, 10); this.title.Name = "title"; this.title.TabIndex = 0; this.title.Text = "标题"; // // textContent // this.textContent.AutoSize = true; this.textContent.Location = new Point(30, 40); this.textContent.Font= new Font("宋体",12, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134))); this.textContent.Name = "textContent"; this.textContent.TabIndex = 0; this.textContent.Text = "内容"; // // staticTime // this.staticTime.AutoSize = true; this.staticTime.Location = new Point(120, 90); this.staticTime.Name = "staticTime"; this.staticTime.TabIndex = 0; this.staticTime.Text = "开始时间"; // // timer1 // this.timer1.Interval = 10; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // timer2 // this.timer2.Interval = 10; this.timer2.Tick += new System.EventHandler(this.timer2_Tick); // // timer3 // this.timer3.Interval = 10; this.timer3.Tick += new System.EventHandler(this.timer3_Tick); // // BalloonForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.White; this.ClientSize = new System.Drawing.Size(200, 120); this.Controls.Add(this.title); this.Controls.Add(this.textContent); this.Controls.Add(this.staticTime); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "BalloonForm"; this.Opacity = 1; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "BalloonForm"; this.TopMost = true; this.Load += new System.EventHandler(this.BalloonForm_Load); //this.ResumeLayout(false); //this.PerformLayout(); } #endregion public string BalloonText { get { return this.title.Text; } set { this.title.Text = value; } } public Color BalloonBackColor { get { return this.BackColor; } set { this.BackColor = value; } } public Color BalloonForeColor { get { return this.title.ForeColor; } set { this.title.ForeColor = value; } } public BalloonForm(string title,string textContent,string staticTime) { //方法一:不进行跨线程安全检查 CheckForIllegalCrossThreadCalls = false; InitializeComponent(); this.title.Text = title; this.textContent.Text = textContent; this.staticTime.Text = staticTime; this.HeightMax = 120;//窗体滚动的高度 this.WidthMax = 260;//窗体滚动的宽度 this.ScrollShow(); } private void timer1_Tick(object sender, EventArgs e) { ScrollUp(); } private void timer2_Tick(object sender, EventArgs e) { timer2.Enabled = false; timer3.Enabled = true; } private void timer3_Tick(object sender, EventArgs e) { ScrollDown(); } public int HeightMax { set { heightMax = value; } get { return heightMax; } } public int WidthMax { set { widthMax = value; } get { return widthMax; } } public void ScrollShow() { this.Width = widthMax; this.Height = 0; this.Show(); this.timer1.Enabled = true; } private void ScrollUp() { if (Height < heightMax) { this.Height += 3; this.Location = new Point(this.Location.X, this.Location.Y - 3); } else { this.timer1.Enabled = false; this.timer2.Enabled = true; } } private void ScrollDown() { if (Height > 3) { this.Height -= 3; this.Location = new Point(this.Location.X, this.Location.Y + 3); } else { this.timer3.Enabled = false; this.Close(); } } private void BalloonForm_Load(object sender, EventArgs e) { Screen screen = Screen.PrimaryScreen; ;//获取屏幕变量 this.Location = new Point(screen.WorkingArea.Width - widthMax - 20, screen.WorkingArea.Height - 38);//WorkingArea为Windows桌面的工作区 this.timer2.Interval = StayTime; } }}

June 11, 2019 · 3 min · jiezi

C-Winfrom在x32和x64环境中读取Excel

1.OleDb读取(必须装Office,Office版本不同,参数设置不一样) 2.Microsoft.Office.Interop.Excel读取(支持win7 x64)win7 x32中报 .无法将类型为“System.__ComObject”的 COM 对象强制转换为接口类型“Excel.Application”。此操作失败的原因是对 IID 为“{000208D5-0000-0000-C000-000000000046}”的接口的 COM 组件调用 QueryInterface 因以下错误而失败: 不支持此接口 (异常来自 HRESULT:0x80004002 (E_NOINTERFACE))。在网上找解决方法:4位系统下,有些组件(微软的)只有32位版本,64位的应用程序调用不了32位的COM组件,返回的结果就是没有注册类别。 在64位系统中,VS2008默认会生成64位的程序,你可以改变程序的部署平台为×86来生成32位的程序。解决方法:在“解决方案”-》“开发项目的名称”,鼠标右击,单击“属性”-》“生成”-》“目标平台”,把“AnyCPU”改成“×86”,重新编译程序即可。 (问题没有解决) .Microsoft.Office.Interop.Excel;的嵌入互操作类型改为false报错如下: 未能加载文件或程序集“Interop.Office, Version=99.1.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。系统找不到指定的文件。3.NPOI读取Excel 可支持(目前没有发现环境问题)

May 24, 2019 · 1 min · jiezi

CNET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区。 文章目录C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf创建Windows服务程序及服务的安装和卸载 (1)在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务) (2)C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案 (3)前言在上一篇文章《在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)》的最后,我给大家抛出了一个遗留的问题--在将TopshelfDemoService程序作为Windows服务安装的情况下,由它守护并启动的客户端程序是没有UI界面的。到这里,我们得分析为什么会出现这个问题,为什么在桌面应用程序模式下可以显示UI界面,而在服务模式下没有UI界面? 分析问题(Session 0 隔离)通过查阅资料,这是由于Session 0 隔离作用的结果。那么什么又是Session 0 隔离呢? 在Windows XP、Windows Server 2003 或早期Windows 系统时代,当第一个用户登录系统后服务和应用程序是在同一个Session 中运行的。这就是Session 0 如下图所示: 但是这种运行方式提高了系统安全风险,因为服务是通过提升了用户权限运行的,而应用程序往往是那些不具备管理员身份的普通用户运行的,其中的危险显而易见。 从Vista 开始Session 0 中只包含系统服务,其他应用程序则通过分离的Session 运行,将服务与应用程序隔离提高系统的安全性。如下图所示: 这样使得Session 0 与其他Session 之间无法进行交互,不能通过服务向桌面用户弹出信息窗口、UI 窗口等信息。这也就是为什么刚才我说那个图已经不能通过当前桌面进行截图了。 潜在的问题解决方案在了解了Session 0 隔离之后,给出一些有关创建服务程序以及由服务托管的驱动程序的建议: 1、与应用程序通信时,使用RPC、命名管道等C/S模式代替窗口消息2、如果服务程序需要UI与用户交互的话,有两种方式:①用WTSSendMessage来创建一个消息框与用户交互②使用一个代理(agent)来完成跟用户的交互,服务程序通过CreateProcessAsUser创建代理。 并用RPC或者命名管道等方式跟代理通信,从而完成复杂的界面交互。3、应该在用户的Session中查询显示属性,如果在Session 0中做这件事,将会得到不正确的结果。4、明确地使用Local或者Global为命名对象命名,Local/为Session/<n>/BaseNamedObject/,Global/为BaseNamedObject/5、将程序放在实际环境中测试是最好的方法,如果条件不允许,可以在XP的FUS下测试。在XP的FUS下能工作的服务程序将很可能可以在新版系统中工作,注意XP的FUS下的测试不能检测到在Session 0下跟视频驱动有关的问题 本文我们的服务程序将通过CreateProcessAsUser创建代理来实现Session 0隔离的穿透。 在项目[TopshelfDemoService]中创建一个静态扩展帮助类ProcessExtensions.cs,代码如下: using System;using System.Runtime.InteropServices;namespace TopshelfDemoService{ /// <summary> /// 进程静态扩展类 /// </summary> public static class ProcessExtensions { #region Win32 Constants private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400; private const int CREATE_NO_WINDOW = 0x08000000; private const int CREATE_NEW_CONSOLE = 0x00000010; private const uint INVALID_SESSION_ID = 0xFFFFFFFF; private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; #endregion #region DllImports [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] private static extern bool CreateProcessAsUser( IntPtr hToken, String lpApplicationName, String lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandle, uint dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")] private static extern bool DuplicateTokenEx( IntPtr ExistingTokenHandle, uint dwDesiredAccess, IntPtr lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle); [DllImport("userenv.dll", SetLastError = true)] private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, bool bInherit); [DllImport("userenv.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hSnapshot); [DllImport("kernel32.dll")] private static extern uint WTSGetActiveConsoleSessionId(); [DllImport("Wtsapi32.dll")] private static extern uint WTSQueryUserToken(uint SessionId, ref IntPtr phToken); [DllImport("wtsapi32.dll", SetLastError = true)] private static extern int WTSEnumerateSessions( IntPtr hServer, int Reserved, int Version, ref IntPtr ppSessionInfo, ref int pCount); #endregion #region Win32 Structs private enum SW { SW_HIDE = 0, SW_SHOWNORMAL = 1, SW_NORMAL = 1, SW_SHOWMINIMIZED = 2, SW_SHOWMAXIMIZED = 3, SW_MAXIMIZE = 3, SW_SHOWNOACTIVATE = 4, SW_SHOW = 5, SW_MINIMIZE = 6, SW_SHOWMINNOACTIVE = 7, SW_SHOWNA = 8, SW_RESTORE = 9, SW_SHOWDEFAULT = 10, SW_MAX = 10 } private enum WTS_CONNECTSTATE_CLASS { WTSActive, WTSConnected, WTSConnectQuery, WTSShadow, WTSDisconnected, WTSIdle, WTSListen, WTSReset, WTSDown, WTSInit } [StructLayout(LayoutKind.Sequential)] private struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId; } private enum SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous = 0, SecurityIdentification = 1, SecurityImpersonation = 2, SecurityDelegation = 3, } [StructLayout(LayoutKind.Sequential)] private struct STARTUPINFO { public int cb; public String lpReserved; public String lpDesktop; public String lpTitle; public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars; public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } private enum TOKEN_TYPE { TokenPrimary = 1, TokenImpersonation = 2 } [StructLayout(LayoutKind.Sequential)] private struct WTS_SESSION_INFO { public readonly UInt32 SessionID; [MarshalAs(UnmanagedType.LPStr)] public readonly String pWinStationName; public readonly WTS_CONNECTSTATE_CLASS State; } #endregion // Gets the user token from the currently active session private static bool GetSessionUserToken(ref IntPtr phUserToken) { var bResult = false; var hImpersonationToken = IntPtr.Zero; var activeSessionId = INVALID_SESSION_ID; var pSessionInfo = IntPtr.Zero; var sessionCount = 0; // Get a handle to the user access token for the current active session. if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref sessionCount) != 0) { var arrayElementSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); var current = pSessionInfo; for (var i = 0; i < sessionCount; i++) { var si = (WTS_SESSION_INFO)Marshal.PtrToStructure(current, typeof(WTS_SESSION_INFO)); current += arrayElementSize; if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive) { activeSessionId = si.SessionID; } } } // If enumerating did not work, fall back to the old method if (activeSessionId == INVALID_SESSION_ID) { activeSessionId = WTSGetActiveConsoleSessionId(); } if (WTSQueryUserToken(activeSessionId, ref hImpersonationToken) != 0) { // Convert the impersonation token to a primary token bResult = DuplicateTokenEx(hImpersonationToken, 0, IntPtr.Zero, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary, ref phUserToken); CloseHandle(hImpersonationToken); } return bResult; } public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true) { var hUserToken = IntPtr.Zero; var startInfo = new STARTUPINFO(); var procInfo = new PROCESS_INFORMATION(); var pEnv = IntPtr.Zero; int iResultOfCreateProcessAsUser; startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO)); try { if (!GetSessionUserToken(ref hUserToken)) { throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed."); } uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW); startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE); startInfo.lpDesktop = "winsta0\\default"; if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false)) { throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed."); } if (!CreateProcessAsUser(hUserToken, appPath, // Application Name cmdLine, // Command Line IntPtr.Zero, IntPtr.Zero, false, dwCreationFlags, pEnv, workDir, // Working directory ref startInfo, out procInfo)) { iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error(); throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed. Error Code -" + iResultOfCreateProcessAsUser); } iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error(); } finally { CloseHandle(hUserToken); if (pEnv != IntPtr.Zero) { DestroyEnvironmentBlock(pEnv); } CloseHandle(procInfo.hThread); CloseHandle(procInfo.hProcess); } return true; } }}修改ProcessHelper.cs为如下代码: ...

May 24, 2019 · 4 min · jiezi

新的尝试!ComponentOne WinForm 和 .NET Core 3.0

在微软 Build 2018 开发者大会上,.NET 团队公布了 .NET Core 的下一个主要版本 .NET Core 3.0 的规划蓝图:.NET Core 3将开始支持Windows桌面应用程序,包括Windows Form、Windows Presentation Framework(WPF)和UWP XAML。届时在 .NET Core 3上将能运行Windows桌面应用程序,在享受 .NET Core新架构优势便利的同时,兼容老的 .net应用。目前为止,.Net Core 3.0 的首个预览版已正式发布,而正式版本也将在今年全面推出。作为经典的全功能 .NET控件集,ComponentOne技术团队一直专注于行业未来的发展方向,2019年 ComponentOne 将继续增强产品功能、增加新的控件并全面兼容 .Net Core 3.0。在此之前,ComponentOne 技术团队一直致力于研究框架和库的变化和兼容性。因此,在 .Net Core 3.0正式版中使用任何 ComponentOne 控件将不需要进行任何更改(由于某些类缺少,有些控件当前在 .Net Core 3.0 预览版中不起作用。要了解未解决的问题,请跳至本博客的最后一部分)。现在,我们将以 ComponentOne 其中一个Demo为例,看看如何将它移植到 .NET Core 3.0 中,此步骤与GitHub上的步骤类似。先决条件安装 .NET Core 3.0 SDK。选择适当您的平台下载安装程序(如果您使用的是64位操作系统,请使用x64;如果您使用的是32位操作系统,请选择x86)。本Demo是使用VS2019运行的,您可以在此处下载预览版。安装ComponentOne WinForms Edition(在此处获取免费试用版)。如果已安装本程序,则可以跳过此步骤。运行步骤第1步考虑到VS2019预览版中的工具有限,缺少WinForms的项目模板,我们将使用命令提示符创建一个新项目。打开命令提示符并运行以下命令:dotnet new winform -o TestWFCore上述代码会创建一个名为TestWFCore的新项目。该项目位于c: Users(YourAccount)下通过命令提示符导航到项目目录cd TestWFCore第2步通过命令提示符添加Windows兼容包,如下所示:dotnet add package Microsoft.Windows.Compatibility第3步使用dotnet run运行应用程序以确保项目正常工作。dotnet run你将看到:Hello .NET Core!现在我们可以在Visual Studio中打开它。Visual Studio中的项目第4步我们将在.Net Core 3.0中运行现有示例,我们将在此位置进行移植“ComboBoxItemModes”输入示例:〜 Documents ComponentOne Samples WinForms C1Input CS ComboBoxItemModes将上述示例中的所有csharp文件链接到此项目。同时包含licences.licx,它位于Properties文件夹下。将licenses.licx文件标记为嵌入资源。大多数现有项目都包含Properties文件夹中的AssemblyInfo.cs文件。新项目样式使用不同的方法,并在构建过程中生成相同的程序集属性。要禁用该行为,可以添加属性GenerateAssemblyInfo:<PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <UseWindowsForms>true</UseWindowsForms> <generateassemblyinfo>false</generateassemblyinfo></PropertyGroup>第5步添加C1.Win.Input程序集的参考。第6步修改program.cs文件以创建Form1的实例并运行该应用程序。这类似于任何WinForms应用程序。 class Program { static void Main() { Application.Run(new Form1()); } }第7步构建并运行应用程序:Demo 示例下载按照上述步骤,我们创建了一个简单的示例,用于在 .NET Core 3.0 中运行不同的 ComponentOne 控件,段尾提供了 Demo 的下载示例。在运行示例之前,请查看自述文件。您将在以下位置找到 .NET Core 3.0 项目文件:〜 DotNetCore3Sample WinForms CS DotNetCore3 DotNetCore3.NET Core 3示例.NET Core 3.0预览中的问题目前,由于 .NET Core 3.0 预览版尚未移植 WinForms 类,FlexGrid、TrueDbGrid、ThemeController和Command在 .NET Core 3.0 预览版中运行时会出现bug。这些bug会在下一个预览版中得到修复:https://github.com/dotnet/cor…最后伴随着 .NET Core 3.0的到来,以及 WinForm 和 WPF 的开源,ComponentOne 也将迎来更多改变,针对桌面应用程序、.NET Core Web API,ComponentOne将推出一系列全新控件和增强功能。期待 ComponentOne 2019 将带给您更多惊喜!ComponentOne EnterpriseComponentOne是一款专注于企业应用高性能开发的 .NET 全功能控件套包,包含300余种控件,支持7大平台,涵盖7大功能模块。较于市面上其他同类产品,ComponentOne更加轻盈,功能更加强大,20多年的开发经验,将为您的应用系统带来更为安全的使用体验。纯中文操作界面,一对一技术支持,厂商级的技术服务,共同造就了这款国际顶级控件套包。 ...

January 17, 2019 · 1 min · jiezi

“Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!

概述Material Design设计规范的受欢迎程度和实用性已经引起了 ComponentOne 技术团队的重视。ComponentOne Enterprise 2018V3 版本将全面支持Material specs的功能集。 在此之前,我们已经在ASP.NET MVC和JavaScript控件中添加了 Material 支持。 随着Material Design的日益普及,我们的桌面用户也将可以使用, ComponentOne For WinForm在2018V3中针对材料设计规范增加了全新的主题设计。将材料主题添加到 WinForm 应用程序ComponentOne For WinForm Edition中添加了全新的Material和Material Dark主题。 这些主题即可作为 ComponentOne 主题,也可应用于 WinForm 平台以及大多数常用的Microsoft 框架中。 这两个主题提供两种不同的配色方案,但遵循相同的材料原则和颜色规格,甚至可以作为未来材料主题的基本元素。 与Material Dark相比,Material主题是一个更为轻松的主题。以下是 ComponentOne 控件在默认主题和Material主题中的外观比较:使用WinForm Material Theme Designer创建新主题Material Design颜色系统由主要颜色和次要颜色组成。 这些颜色反映了您的应用程序的主题和样式。 ComponentOne中提供的 Material Designer是一个交互式设计器,可让您为Material主题选择主要和次要风格样式。您可以保存主题并在以后直接将其应用于WinForm应用程序。WinForms Material Designer要更改主题的配色方案,请按照以下简单步骤操作:运行Material Theme Designer示例。单击“设置”选项卡,然后根据您的品牌/主题选择模板和强调颜色。使用C1控件预览主题的外观。单击cog图标以打开应用程序菜单。单击“保存主题”将主题保存在首选位置。请参阅材料主题设计器:将Material Themes应用于WinForm 应用程序材料主题设计器可以在 WinForm 应用程序的设计阶段和运行阶段启动。 您可以在设计时使用“主题控制器”对话框或通过修改“App.config”文件来应用主题。 要在运行时启动,请使用C1ThemeController静态类来应用主题。使用主题控制器对话框在Visual Studio的表单设计器中打开应用程序中的表单。从设计器的工具箱中,拖动C1ThemeController并将其放在表单上。将出现ThemeController对话框。这使您可以选择:应用程序范围的默认主题,当前控制器的默认主题,所有支持控件的主题已经在表单上。在弹出的对话框中,主题最初被指定为“(none)”,适用于表单上已有的控件。这样做可以防止无意中更改这些控件上的属性设置。单击对话框中的全部(默认)按钮,以便在所有控件上设置默认主题。注意:如果您已经自定义了一些控件,则会忽略此控件,并且不会还原默认主题。从可用内置主题列表中选择“材质”。您还可以选择使用Material Theme Designer创建的材质主题。单击上面提到的全部(默认)按钮,在窗体上的所有支持控件上设置默认主题。单击确定按钮以关闭对话框并将指定的主题应用于窗体上的控件。使用App.config文件确保您的产品路径下包含C1.Win.C1Themes.dll。 您可以在App.Config中添加以下应用程序设置以应用基本主题:<configuration> <appSettings> <add key=“C1ApplicationTheme” value=“Material”/> </appSettings></configuration>使用代码确保您的产品路径下包含C1.Win.C1Themes.dll。在加载前在您的应用程序中添加以下代码。C1Theme theme = C1.Win.C1Themes.C1ThemeController.GetThemeByName(“Material”,false);C1ThemeController.ApplyThemeToControlTree(control, theme);自定义材质主题(高级)C1Theme Designer应用程序允许为WinForm Edition中的任何控件轻松设计新主题。 它还允许您编辑/修改现有主题以实现您选择的外观,或与应用程序主题匹配。 您可以进一步使用此应用程序将Material主题调整到控件允许的最精细级别。主题是一个带有.c1theme扩展名的XML文件,它由一组属性及其值组成(它决定了控件的外观)。 主题在内部划分为对应于不同控件的不同部分。 所有其他控件都可以访问“基本主题属性”部分。 此部分包含子部分“材质”,该部分存储可以更改为创建不同材质主题的“材质”属性。例如,下面让我们尝试更改FlexGrid的材质主题,其中标题是主要颜色。如何使用WinForms Material Theme Designer1、 从ComponentOne开始菜单打开ComponentOne主题设计器。 按Ctrl + N或文件>新建。 选择“材质”作为新主题的基本主题。2、 单击BTP编辑器按钮(1)。 这将打开一个新的基本主题属性编辑器。 选择“材料”属性(2)。 在这里,您可以看到材质中使用的不同颜色:3、 转到主题树并展开C1FlexGrid节点。4、 展开C1FlexGrid>样式>固定节点。 此节点将保存固定(标题)单元格的样式。5、 选择ForeColo下拉列表以打开颜色选择器。6、 您可以在选择器下拉列表中选择“参考”选项卡以选择主要颜色。7、 您可以保存此主题并按照“在应用程序中应用材料主题”部分中的说明使用它。 您的FlexGrid现在应该具有基于主要颜色设置的标题颜色。欢迎您下载体验 ComponentOne Enterprise,并与我们分享您是如何设计桌面应用程序以及Material主题如何与您的应用程序协同工作的宝贵经验。ComponentOne Enterprise | 下载试用ComponentOne是一款专注于企业应用高性能开发的 .NET 全功能控件套包,包含300余种控件,支持7大平台,涵盖7大功能模块。较于市面上其他同类产品,ComponentOne更加轻盈,功能更加强大,20多年的开发经验,将为您的应用系统带来更为安全的使用体验。纯中文操作界面,一对一技术支持,厂商级的技术服务,共同造就了这款国际顶级控件套包。您对ComponentOne 产品的任何技术问题,都有技术支持工程师提供1对1专业解答,点击此处即可发帖提问>> 技术支持论坛 ...

December 18, 2018 · 1 min · jiezi