在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
PS色调均化滤镜的快捷实现(C#源代码)。photoshop色调均化功能通常是在进行修片处理前期比较常用的功能之一,其对扩展图像的对比度,增强视觉效果有一定的作用。在很多课本或者文章中,也称这种处理为灰度均衡化、直方图均衡化等等。算法原理都是对原始图像统计其直方图,然后通过累计分布函数,重新隐射直方图数据,使每个色阶的的分布概率都往一致的方向调整。我看到的网络上的代码,抑或是一些教材中的代码,对这个过程的描述都是相当的冗余,要么是代码累赘,效率低下,要么是萝莉啰唆,很是难受。 在给出我的代码之前,还需要说明一些问题。对于灰度图像,由于只有一个通道,这个问题不明显,对于常见的24位图像,由于有RGB三个通道,那就存在是每个通道都单独均衡还是三通道联合计算直方图,然后利用相同的映射表在隐射RGB数据了,经过我的测试,在Photoshop中,是取的后者。 for (Y = 0; Y < Height; Y++)
{
Pointer = Scan0 + Y * Stride; // 定位到每个扫描行的第一个像素,以避免溶于数据的影响
for (X = 0; X < Width; X++)
{
HistGram[*Pointer]++; // Blue
HistGram[*(Pointer + 1)]++; // Green
HistGram[*(Pointer + 2)]++; // Red
Pointer += 3; // 移向下一个像素
}
}
Num = 0;
for (Y = 0; Y < 256; Y++)
{
Num = Num + HistGram[Y];
Lut[Y] = (byte)((float)Num / (Width * Height * 3) * 255); // 计算映射表
}
for (Y = 0; Y < Height; Y++)
{
Pointer = Scan0 + Y * Stride;
for (X = 0; X < Width * 3; X += 3) // 也可以这样写
{
Pointer[X] = Lut[Pointer[X]];
Pointer[X + 1] = Lut[Pointer[X + 1]];
Pointer[X + 2] = Lut[Pointer[X + 2]];
}
}
算法部分就是这么简单的二十几行代码,代码清晰,执行效率又特别高,数码相机中常见的4000*3000的照片100ms内就可以处理完。 一副图像如果执行了一次色调均化,那么再次执行色调均化应该不会有任何像素发生变换了。 从广义上讲,色调均化可以看成是直方图匹配的一个特例,即匹配的直方图分布为一条水平线。 一些书中的色调均化是对各通道分别进行校正的,似乎这样处理的效果容易导致图像整体颜色不搭配,比如经典的Lena图:
原图 PS的色调均化 郎锐课本上的效果 C#版色调均化代码:https://files.cnblogs.com/Imageshop/HistGramEqualize.rar
[06] 调整图像
C#
〇、目录一、前言 二、工具准备 三、T4代码生成预热 (二) 多文件生成 (一) 生成准备 (二) 生成实体相关相似代码 五、源码下载 六、系列导航 一、前言经过前面EF的《第一篇》与《第二篇》,我们的数据层功能已经较为完善了,但有不少代码相似度较高,比如负责实体映射的 EntityConfiguration,负责仓储操作的IEntityRepository与EntityRepository。而且每添加一个实体类型,就要手动去添加一套相应的代码,也是比较累的工作。如果能有一个根据实体类型自动生成这些相似度较高的代码的解决方案,那将会减少大量的无聊的工作。 VS提供的“文本模板”(俗称T4)功能,就是一个较好的解决方案。要添加一个实体类型,只要把实体类型定义好,然后运行一下定义好的T4模板,就可以自动生成相应的类文件。 二、工具准备为了更好的使用 T4模板 功能,我们需要给VS安装如下两个插件:
三、T4代码生成预热(一) 单文件生成:HelloWorld.cs下面,我们先来体验一个最简单的T4代码生成功能,输出一个最简单的类文件。 首先,在 GMF.Demo.Core.Data中 添加一个名为 T4 的文件夹,用于存放生成本工程内的代码的T4模板文件。并在其中添加一个名为 HelloWorld.tt的“文本模板”的项。 HelloWorld.tt定义如下: 1 <#@ template debug="false" hostspecific="false" language="C#" #> 2 <#@ assembly name="System.Core" #> 3 <#@ import namespace="System.Linq" #> 4 <#@ import namespace="System.Text" #> 5 <#@ import namespace="System.Collections.Generic" #> 6 <#@ output extension=".cs" #> 7 using System; 8 9 namespace GMF.Demo.Core.Data.T4 10 { 11 public class HelloWorld 12 { 13 private string _word; 14 15 public HelloWorld(string word) 16 { 17 _word = word; 18 } 19 } 20 } 直接保存文件(T4的生成将会在保存模板,模板失去焦点等情况下自动触发生成。),将会在模板的当前位置生成一个同名的类文件: HelloWorld.cs的内容如下: 1 using System; 2 3 namespace GMF.Demo.Core.Data.T4 4 { 5 public class HelloWorld 6 { 7 private string _word; 8 9 public HelloWorld(string word) 10 { 11 _word = word; 12 } 13 } 14 } 这样,我们的HelloWorld之旅就结束了,非常简单。 (二) 多文件生成当前位置方案的方案只能生成如下所示的代码: 生成的文件会与T4模板在同一目录中,这里就不详述了,可以参考 蒋金楠 一个简易版的T4代码生成"框架" 。 本项目的多文件需要生成到指定文件夹中,但又想对T4模板进行统一的管理,T4文件夹里放置T4模板文件,但生成的映射文件EntityConfiguration将放置到文件夹Configurations中,仓储操作的文件IEntityRepository与EntityRepository将放置到Repositories文件夹中。且生成的代码文件应能自动的添加到解决方案中,而不是只是在文件夹中存在。 要实现此需求,一个简单的办法就是通过 T4 Toolbox 来进行生成。想了解 T4 Toolbox 的细节,可以自己使用 ILSpy 来对 T4Toolbox.dll 文件进行反编译来查看源代码,如果是通过 T4 Toolbox 是通过VS的插件来安装的,将在“C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\dca4f0lt.jdx”文件夹中(我的机器上)。下面,我们直接进行多文件生成的演示。 首先,添加一个名为 HelloWorldTemplate.tt 的 T4 Toolbox 的代码模板。 此模板将继承于 T4 Toolbox 的 CSharpTemplate 类: 1 <#+ 2 // <copyright file="HelloWorldTemplate.tt" company="郭明锋@中国"> 3 // Copyright © 郭明锋@中国. All Rights Reserved. 4 // </copyright> 5 6 public class HelloWorldTemplate : CSharpTemplate 7 { 8 private string _className; 9 10 public HelloWorldTemplate(string className) 11 { 12 _className = className; 13 } 14 15 public override string TransformText() 16 { 17 #> 18 using System; 19 20 namespace GMF.Demo.Core.Data.T4 21 { 22 public class <#=_className #> 23 { 24 private string _word; 25 26 public <#=_className #>(string word) 27 { 28 _word = word; 29 } 30 } 31 } 32 <#+ 33 return this.GenerationEnvironment.ToString(); 34 } 35 } 36 #> 模板类中定义了一个 className 参数,用于接收一个表示要生成的类名的值。所有生成类的代码都以字符串的形式写在重写的 TransformText 方法中。 再定义一个T4模板文件 HelloWorldMulti.tt,用于调用 上面定义的代码模板进行代码文件的生成。 1 <#@ template debug="false" hostspecific="false" language="C#" #> 2 <#@ assembly name="System.Core" #> 3 <#@ import namespace="System.IO" #> 4 <#@ import namespace="System.Linq" #> 5 <#@ import namespace="System.Text" #> 6 <#@ import namespace="System.Collections.Generic" #> 7 <#@ include file="T4Toolbox.tt" #> 8 <#@ include file="HelloWorldTemplate.tt" #> 9 <# 10 string curPath = Path.GetDirectoryName(Host.TemplateFile); 11 string destPath = Path.Combine(curPath, "outPath"); 12 if(!Directory.Exists(destPath)) 13 { 14 Directory.CreateDirectory(destPath); 15 } 16 string[] classNames = new[]{"HelloWorld1", "HelloWorld2", "HelloWorld3"}; 17 foreach(string className in classNames) 18 { 19 HelloWorldTemplate template = new HelloWorldTemplate(className); 20 string fileName = string.Format(@"{0}\{1}.cs", destPath, className); 21 template.Output.Encoding = Encoding.UTF8; 22 template.RenderToFile(fileName); 23 } 24 #> 以上是整个T4模板的执行方,在执行方中,要引用所有需要用到的类库文件,命名空间,包含的模板文件等。 最后,文件的生成是调用 T4 Toolbox 的Template基类中定义的 RenderToFile(string filename)方法来生成各个文件的,输入的参数为生成文件的文件全名。在这里,生成将如下所示: outPPath文件夹中生成了 HelloWorld1.cs、HelloWorld2.cs、HelloWorld3.cs 文件,而 HelloWorldMulti.tt 所在文件夹中也会生成一个空的 HelloWorldMulti.cs 类文件。 四、生成数据层实体相关相似代码(一) 生成准备我们的生成代码是完全依赖于业务实体的,所以,需要有一个类来对业务实体的信息进行提取封装。 1 namespace GMF.Component.Tools.T4 2 { 3 /// <summary> 4 /// T4实体模型信息类 5 /// </summary> 6 public class T4ModelInfo 7 { 8 /// <summary> 9 /// 获取 模型所在模块名称 10 /// </summary> 11 public string ModuleName { get; private set; } 12 13 /// <summary> 14 /// 获取 模型名称 15 /// </summary> 16 public string Name { get; private set; } 17 18 /// <summary> 19 /// 获取 模型描述 20 /// </summary> 21 public string Description { get; private set; } 22 23 public IEnumerable<PropertyInfo> Properties { get; private set; } 24 25 public T4ModelInfo(Type modelType) 26 { 27 var @namespace = modelType.Namespace; 28 if (@namespace == null) 29 { 30 return; 31 } 32 var index = @namespace.LastIndexOf('.') + 1; 33 ModuleName = @namespace.Substring(index, @namespace.Length - index); 34 Name = modelType.Name; 35 var descAttributes = modelType.GetCustomAttributes(typeof(DescriptionAttribute), true); 36 Description = descAttributes.Length == 1 ? ((DescriptionAttribute)descAttributes[0]).Description : Name; 37 Properties = modelType.GetProperties(); 38 } 39 } 40 } 另外,通过模板生成的代码,与我们手写的代码有如下几个区别:
基于以上几个区别,我提出如下解决方案,来解决生成代码的修改问题
(二) 生成实体相关相似代码1. 生成实体映射配置类实体映射配置类模板 EntityConfigurationTemplate.tt 定义: 1 <#+ 2 // <copyright file="EntityConfigurationTemplate.tt" company="郭明锋@中国"> 3 // Copyright © 郭明锋@中国. All Rights Reserved. 4 // </copyright> 5 6 public class EntityConfigurationTemplate : CSharpTemplate 7 { 8 private T4ModelInfo _model; 9 10 public EntityConfigurationTemplate(T4ModelInfo model) 11 { 12 _model = model; 13 } 14 15 /// <summary> 16 /// 获取 生成的文件名,根据模型名定义 17 /// </summary> 18 public string FileName 19 { 20 get 21 { 22 return string.Format("{0}Configuration.generated.cs", _model.Name); 23 } 24 } 25 26 public override string TransformText() 27 { 28 #> 29 //------------------------------------------------------------------------------ 30 // <auto-generated> 31 // 此代码由工具生成。 32 // 对此文件的更改可能会导致不正确的行为,并且如果 33 // 重新生成代码,这些更改将会丢失。 34 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类实现 <#= _model.Name #>ConfigurationAppend 分部方法。 35 // </auto-generated> 36 // 37 // <copyright file="<#= _model.Name #>Configuration.generated.cs"> 38 // Copyright(c)2013 GMFCN.All rights reserved. 39 // CLR版本:4.0.30319.239 40 // 开发组织:郭明锋@中国 41 // 公司网站:http://www.gmfcn.net 42 // 所属工程:GMF.Demo.Core.Data 43 // 生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #> 44 // </copyright> 45 //------------------------------------------------------------------------------ 46 47 using System; 48 using System.Data.Entity.ModelConfiguration; 49 using System.Data.Entity.ModelConfiguration.Configuration; 50 51 using GMF.Component.Data; 52 using GMF.Demo.Core.Models; 53 54 55 namespace GMF.Demo.Core.Data.Configurations 56 { 57 /// <summary> 58 /// 实体类-数据表映射——<#= _model.Description #> 59 /// </summary> 60 internal partial class <#= _model.Name #>Configuration : EntityTypeConfiguration<<#= _model.Name #>>, IEntityMapper 61 { 62 /// <summary> 63 /// 实体类-数据表映射构造函数——<#= _model.Description #> 64 /// </summary> 65 public <#= _model.Name #>Configuration() 66 { 67 <#= _model.Name #>ConfigurationAppend(); 68 } 69 70 /// <summary> 71 /// 额外的数据映射 72 /// </summary> 73 partial void <#= _model.Name #>ConfigurationAppend(); 74 75 /// <summary> 76 /// 将当前实体映射对象注册到当前数据访问上下文实体映射配置注册器中 77 /// </summary> 78 /// <param name="configurations">实体映射配置注册器</param> 79 public void RegistTo(ConfigurationRegistrar configurations) 80 { 81 configurations.Add(this); 82 } 83 } 84 } 85 <#+ 86 return this.GenerationEnvironment.ToString(); 87 } 88 } 89 #> 生成模板调用方 EntityCodeScript.tt 定义 1 <#@ template language="C#" debug="True" #> 2 <#@ output extension="cs" #> 3 <#@ Assembly Name="System.Core" #> 4 <#@ Assembly Name="$(SolutionDir)\GMF.Component.Tools\bin\Debug\GMF.Component.Tools.dll" #> 5 <#@ import namespace="System.IO" #> 6 <#@ Import Namespace="System.Linq" #> 7 <#@ Import Namespace="System.Text" #> 8 <#@ import namespace="System.Reflection" #> 9 <#@ Import Namespace="System.Collections.Generic" #> 10 <#@ Import Namespace="GMF.Component.Tools" #> 11 <#@ Import Namespace="GMF.Component.Tools.T4" #> 12 <#@ include file="T4Toolbox.tt" #> 13 <#@ include file="Include\EntityConfigurationTemplate.tt" #> 14 <# 15 string currentPath = Path.GetDirectoryName(Host.TemplateFile); 16 string projectPath =currentPath.Substring(0, currentPath.IndexOf(@"\T4")); 17 string solutionPath = currentPath.Substring(0, currentPath.IndexOf(@"\GMF.Demo.Core.Data")); 18 19 string modelFile= Path.Combine(solutionPath, @"GMF.Demo.Core.Models\bin\Debug\GMF.Demo.Core.Models.dll"); 20 byte[] fileData= File.ReadAllBytes(modelFile); 21 Assembly assembly = Assembly.Load(fileData); 22 IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => typeof(Entity).IsAssignableFrom(m) && !m.IsAbstract); 23 foreach(Type modelType in modelTypes) 24 { 25 T4ModelInfo model = new T4ModelInfo(modelType); 26 //实体映射类 27 EntityConfigurationTemplate config = new EntityConfigurationTemplate(model); 28 string path = string.Format(@"{0}\Configurations", projectPath); 29 config.Output.Encoding = Encoding.UTF8; 30 config.RenderToFile(Path.Combine(path, config.FileName)); 31 } 32 #> 调用方通过反射从业务实体程序集 GMF.Demo.Core.Models.dll 中获取所有基类为 Entity 的并且不是抽象类的实体类型信息,再调用模板逐个生成实体配置类文件。 例如,生成的登录记录信息(LoginLog)的映射文件 LoginLogConfiguration.generated.cs 如下: 1 //------------------------------------------------------------------------------ 2 // <auto-generated> 3 // 此代码由工具生成。 4 // 对此文件的更改可能会导致不正确的行为,并且如果 5 // 重新生成代码,这些更改将会丢失。 6 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类实现 LoginLogConfigurationAppend 分部方法。 7 // </auto-generated> 8 // 9 // <copyright file="LoginLogConfiguration.generated.cs"> 10 // Copyright(c)2013 GMFCN.All rights reserved. 11 // CLR版本:4.0.30319.239 12 // 开发组织:郭明锋@中国 13 // 公司网站:http://www.gmfcn.net 14 // 所属工程:GMF.Demo.Core.Data 15 // 生成时间:2013-06-16 17:45 16 // </copyright> 17 //------------------------------------------------------------------------------ 18 19 using System; 20 using System.Data.Entity.ModelConfiguration; 21 using System.Data.Entity.ModelConfiguration.Configuration; 22 23 using GMF.Component.Data; 24 using GMF.Demo.Core.Models; 25 26 27 namespace GMF.Demo.Core.Data.Configurations 28 { 29 /// <summary> 30 /// 实体类-数据表映射——登录记录信息 31 /// </summary> 32 internal partial class LoginLogConfiguration : EntityTypeConfiguration<LoginLog>, IEntityMapper 33 { 34 /// <summary> 35 /// 实体类-数据表映射构造函数——登录记录信息 36 /// </summary> 37 public LoginLogConfiguration() 38 { 39 LoginLogConfigurationAppend(); 40 } 41 42 /// <summary> 43 /// 额外的数据映射 44 /// </summary> 45 partial void LoginLogConfigurationAppend(); 46 47 /// <summary> 48 /// 将当前实体映射对象注册到当前数据访问上下文实体映射配置注册器中 49 /// </summary> 50 /// <param name="configurations">实体映射配置注册器</param> 51 public void RegistTo(ConfigurationRegistrar configurations) 52 { 53 configurations.Add(this); 54 } 55 } 56 } 要配置登录信息与用户信息的 N:1 关系,只需要添加一个分部类 LoginLogConfiguration,并实现分类方法 LoginLogConfigurationAppend 即可。 1 namespace GMF.Demo.Core.Data.Configurations 2 { 3 partial class LoginLogConfiguration 4 { 5 partial void LoginLogConfigurationAppend() 6 { 7 HasRequired(m => m.Member).WithMany(n => n.LoginLogs); 8 } 9 } 10 } 2. 生成实体仓储接口实体映射配置类模板 EntityConfigurationTemplate.tt 定义: 1 <#+ 2 // <copyright file="IEntityRepositoryTemplate.tt" company="郭明锋@中国"> 3 // Copyright © 郭明锋@中国. All Rights Reserved. 4 // </copyright> 5 6 public class IEntityRepositoryTemplate : CSharpTemplate 7 { 8 private T4ModelInfo _model; 9 10 public IEntityRepositoryTemplate(T4ModelInfo model) 11 { 12 _model = model; 13 } 14 15 /// <summary> 16 /// 获取 生成的文件名,根据模型名定义 17 /// </summary> 18 public string FileName 19 { 20 get 21 { 22 return string.Format("I{0}Repository.generated.cs", _model.Name); 23 } 24 } 25 26 public override string TransformText() 27 { 28 #> 29 //------------------------------------------------------------------------------ 30 // <auto-generated> 31 // 此代码由工具生成。 32 // 对此文件的更改可能会导致不正确的行为,并且如果 33 // 重新生成代码,这些更改将会丢失。 34 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。 35 // </auto-generated> 36 // 37 // <copyright file="I<#= _model.Name #>Repository.generated.cs"> 38 // Copyright(c)2013 GMFCN.All rights reserved. 39 // CLR版本:4.0.30319.239 40 // 开发组织:郭明锋@中国 41 // 公司网站:http://www.gmfcn.net 42 // 所属工程:GMF.Demo.Core.Data 43 // 生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #> 44 // </copyright> 45 //------------------------------------------------------------------------------ 46 47 using System; 48 49 using GMF.Component.Data; 50 using GMF.Demo.Core.Models; 51 52 53 namespace GMF.Demo.Core.Data.Repositories 54 { 55 /// <summary> 56 /// 数据访问层接口——<#= _model.Description #> 57 /// </summary> 58 public partial interface I<#= _model.Name #>Repository : IRepository<<#= _model.Name #>> 59 { } 60 } 61 62 <#+ 63 return this.GenerationEnvironment.ToString(); 64 } 65 } 66 #> 相应的,在调用方 EntityCodeScript.tt 中添加模板调用代码(如下 11-15 行所示): 1 foreach(Type modelType in modelTypes) 2 { 3 T4ModelInfo model = new T4ModelInfo(modelType); 4 5 //实体映射类 6 EntityConfigurationTemplate config = new EntityConfigurationTemplate(model); 7 string path = string.Format(@"{0}\Configurations", projectPath); 8 config.Output.Encoding = Encoding.UTF8; 9 config.RenderToFile(Path.Combine(path, config.FileName)); 10 11 //实体仓储操作接口 12 IEntityRepositoryTemplate irep= new IEntityRepositoryTemplate(model); 13 path = string.Format(@"{0}\Repositories", projectPath); 14 irep.Output.Encoding = Encoding.UTF8; 15 irep.RenderToFile(Path.Combine(path, irep.FileName)); 16 }
生成的登录记录信息仓储操作接口 ILoginLogRepository.generated.cs: 1 //------------------------------------------------------------------------------ 2 // <auto-generated> 3 // 此代码由工具生成。 4 // 对此文件的更改可能会导致不正确的行为,并且如果 5 // 重新生成代码,这些更改将会丢失。 6 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。 7 // </auto-generated> 8 // 9 // <copyright file="ILoginLogRepository.generated.cs"> 10 // Copyright(c)2013 GMFCN.All rights reserved. 11 // CLR版本:4.0.30319.239 12 // 开发组织:郭明锋@中国 13 // 公司网站:http://www.gmfcn.net 14 // 所属工程:GMF.Demo.Core.Data 15 // 生成时间:2013-06-16 17:56 16 // </copyright> 17 //------------------------------------------------------------------------------ 18 19 using System; 20 21 using GMF.Component.Data; 22 using GMF.Demo.Core.Models; 23 24 25 namespace GMF.Demo.Core.Data.Repositories 26 { 27 /// <summary> 28 /// 数据访问层接口——登录记录信息 29 /// </summary> 30 public partial interface ILoginLogRepository : IRepository<LoginLog> 31 { } 32 } 如果 IRepository<T> 中定义的仓储操作不满足登录记录仓储操作的需求,只需要添加一个相应的分部接口,在其中进行需求的定义即可。这里当前没有额外的需求,就不需要额外定义了。 3. 生成实体仓储实现实体仓储操作的实现与仓储操作接口类似,这里略过。 完成生成后,代码结构如下所示: 如果添加了或者删除了一个实体,只需要重新运行一下调用模板 EntityCodeScript.tt 即可重新生成新的代码。 五、源码下载六、系列导航
如果您看完本篇文章感觉不错,请点击一下右下角的“推荐”来支持一下博主,谢谢!
作者:郭明锋 出处:http://www.cnblogs.com/guomingfeng 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 EntityFramework
EntityFramework
更有效率的使用Visual Studio(二)没想到上一篇文章有这么多人喜欢,多谢大家支持。继续~ 很多比较通用的快捷键的默认设置其实是有一些缩写在里面的,这个估计也是MS帮助我们记忆。比如说注释代码的快捷键是Ctrl + E + C,我们如果知道它是 Ctrl + Edit + Comment Code 的缩写不是更好记么?我也会尽量YY把快捷键和功能联系起来来帮助我自己记忆。另外很多功能在VS中有多个快捷键可以实现,我猜是为了防止一些快捷键冲突所设计的吧,我一般只会去记好记的,冲突了再说。 三、继续更有效率的编辑器 3.1 更有效的编辑(补充) a. 注释代码:Ctrl + E(Edit) + C(Comment), Ctrl + K + C(Comment)。打开文件类型不同行为可能不同,在cs文件类型中会将选中行的代码注释,cpp中会将选中的内容进行注释。 反注释代码:Ctrl + E(Edit) + U(Uncomment), Ctrl + K + U(Uncomment) b. 调整格式选中代码格式:Ctrl + E(Edit) + F(Format)。 c. 调整整个文档代码格式:Ctrl + E(Edit) + D(Document Format)。 3.2 更有效率的搜索: a. Incremental Search(增量搜索,不知道翻译得恰不恰当):Ctrl + I(Incremental) (移动到下一个匹配按Ctrl + I, 移动到上一个Shift + Ctrl + I)。按住快捷键然后输入要查询的字符串,VS会马上定位到而不需要想Ctrl + F那种确认的过程,可以通过我截的图中看到效果。我一般如果只是想在当前文档进行简单搜索的话一般会使用这个搜索,遇到是一些比较复杂的搜索条件才去动用弹框搜索。 b. Ctrl + F(Find):在Visual Studio 2012中其实这个功能已经和Increment Search很相似了,你会发现在VS2012+里使用Ctrl + F和上面的效果是一样的,都是输入即可看到搜索结果。不过与Increment Search不同的是,这个搜索可以指定更多的条件,如是否匹配大小写、是否整词搜索、是否用正则表达式以及搜索的范围。 c. 在文件中查找:Ctrl + Shift + F,这个可以实现的搜索功能与Ctrl + F 一模一样,唯一不同就是这个可以将你搜索的结果输出到查找结果窗口中,而不是一个一个显示出来。这个比较合适搜一些比较多匹配的东西,然后在输出的结果窗口中在肉眼筛选。 四、更有效的导航: 1. 快速打开Solution Explorer:Ctrl + W(Windows)+ S(Solution)、Ctrl + Alt + L。当你在写代码想打开工程中另一个文件时就可以用这个快速打开解决方案窗口选择文件。 2. 打开当前打开文件列表:Ctrl+Alt+Down。这个很好用,但是这个快捷键在很多电脑上都会翻转屏幕,囧。如果实在要用这个功能,可以通过自定义快捷键来实现。 3. 快速将焦点移到类列表(这个名词纯属YY,见图便知我指的是啥):Ctrl +F2。 4. 内部文件切换:Ctrl + Tab。这个不仅在VS中,很多软件中都是这个功能。 5. 全屏:Shift + Alt + Enter。可以让你进入全屏无干扰模式,本人很喜欢这个功能。 五、更有效的智能感知 智能感知本来就很智能,但是很多时候我们想强制的调出一些提示来看一下的时候这些功能就爽。很多功能语言描述可能比较累,而且由于我语文不好很可能你还看不懂,所以我会附图。 1. 列出成员。Ctrl + K + L(List Member), Ctrl + J。我们知道当我们需要访问对象方法的时候按.VS会自动提示出有哪些方法,但是有时候我们需要在.操作符已经存在的情况下再查看。以前我会把点删掉然后再点一次,我承认我当时很傻,后来知道这个快捷键以后就好多了。 2. 列出选项(表述不明确,具体看后面描述)。Ctrl + . 或者Ctrl + Shift +F10。当我们用到一些类型在我们工程引用的程序集里但是没有在当前当前文件引用的命名空间内时,或者我们写了一个不存在的函数时,那行代码会有错误提示,并且在左下角有一个小符号。如图:。我们鼠标移到符号附近会出现一些帮助,可以自动帮助我们添加引用或者生成函数。这个快捷键就是在不移动鼠标的情况下让其出现这个提示。 六、其他 1. 任务列表(Task List),可以通过View->Task List打开这个窗口。很多人可能不知道这个功能,我觉得挺有用。写代码的时候我往往会遇到这种情况,某一些代码我现在不确定需求或者觉得可能会有问题将来需要改善,我会加上注释://TODO:reason。相信很多人会有同样的习惯,这个任务列表的功能就是让我们可以看到我们当前工程中有多少个TODO项。当然不局限于TODO这个词,可以自定义词汇。我一般会在commit之前看一下这个列表看看还有没有需要改的地方。这个还可以直接添加一些任务,具体使用自己用一下就知道了。
七、插件 这里在推荐两个插件:C# outline 和Smart Paster。 1. C# Outline Visual Studio默认的outline是只有在函数级别的,但是很多时候有一些循环条件很长也需要缩起来看比较方便。于是就有了这个插件。效果如下: Before outline-> After outline-> 2. Smart Paster 这个插件可以将文字粘帖为注释、和string字符串和StringBuilder。特别是对于粘贴多行的文字的时候很有用。 八、推荐资料 1. Favorite Visual Studio keyboard shortcuts:Stackoverflow 上一群人在讨论自己最喜欢的快捷键,可以去里面看看或许你会看到一些你意想不到的快捷键。 2. Visual Studio 程序员箴言:这本书介绍了很多关于VS方面的知识。 3. 可以多看看VS菜单栏上那些没用过东西,或许你会发现一些对你很有用的东西。 总结 这些只是对我来说最有用的一些技巧,强烈推荐大家可以去看看我推荐的那些资料去探索一些更加适合你的习惯的一些功能。因为当你不知道有这个功能的存在的情况下你根本就想不到要去找这么一个功能。 容我再罗嗦几句。我们绝对没有必要去死记硬背很多很多快捷键然后装逼,因为并非所有的快捷键所有人都需要。很大程度上一些功能的使用是取决于你的工作习惯,同时我也不推荐你去记一些你觉得你都不会用到的快捷键,没意义,浪费时间。这也就是为什么我只列出一些对我工作效率有切身帮助的一些快捷键,而不是把Visual Studio中所有的快捷键都列出来,因为那样子的话就没意义了! 所以我强烈建议你们只去记你觉得有用的那些东西。 经验总结
快捷键
四:江 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论