• WinForm 问题集锦


    【1】重用项目窗体解决方案:

    1. 把FmMain.cs 和 FmMain.Designer.cs 和 FmMain .resx 三个文件复制到程序目录下;

    2. 在vs里面添加现有项, 选择FmMain.cs, 不用选择其它文件, 完成操作后重新打开窗口。

    【2】无法读写注册表解决方案

      程序读写注册表是,通过代码将以下注册表路径下的Enabled值修改为0:

      HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaFipsAlgorithmPolicy

      实现代码如下:

    public void SetFipsAlgorithmPolicyValue()
    {
        string keyName = @"HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaFipsAlgorithmPolicy";
        if (Convert.ToBoolean(Registry.GetValue(keyName, "Enabled", null)))
        {
            Registry.SetValue(keyName, "Enabled", 0, RegistryValueKind.DWord);
        }
    }

    【3】WinForm设置窗体控件双缓冲代码:

    using System.Windows.Forms;
    class ListViewEx:ListView
    {
        public ListViewEx()
        {
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
            UpdateStyles();
        }
    }

    【4】MSDN推荐的Lock对象:自定义类推荐用私有的只读静态对象

         通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。而自定义类推荐用私有的只读静态对象,比如:private static readonly object obj = new object();为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就可以执行lock锁定的代码片段。

    【5】C#匹配a标签各个参数的正则表达式:

    string regex = "(?is)<a[^>]*(style=["'])?(?<style>[^"']*?)["'][^>]*(href=["'])?(?<url>[^"']*?)["'][^>]*>(?<text>[\w\W]*?)</a>";

         需求改变,以上的正则表达式也需要进行适当修改

         [^"] 不是表示双引号的任意字符 ,* 表示重复0到多次, 表示转义
         所以 ([^"]*) 是匹配非双引号字符组成的字符串

    Q:经常看见的正则前面的 (?i) (?s) (?m) (?is) (?im) 是什么意思?
    A: 称为内联匹配模式,通常用内联匹配模式代替使用枚举值RegexOptions指定的全局匹配模式,写起来更简洁。
        (?i) 表示所在位置右侧的表达式开启忽略大小写模式
        (?s) 表示所在位置右侧的表达式开启单行模式。
        更改句点字符 (.) 的含义,以使它与每个字符(而不是除 之外的所有字符)匹配。
        注意:(?s)通常在匹配有换行的文本时使用
        (?m) 表示所在位置右侧的表示式开启指定多行模式。
        更改 ^ 和 $ 的含义,以使它们分别与任何行的开头和结尾匹配,
        而不只是与整个字符串的开头和结尾匹配。
        注意:(?m)只有在正则表达式中涉及到多行的“^”和“$”的匹配时,才使用Multiline模式。
        上面的匹配模式可以组合使用,比如(?is),(?im)。
        另外,还可以用(?i:exp)或者(?i)exp(?-i)来指定匹配的有效范围。

    【6】解决错误:System.ArgumentException: 另一个 SqlParameterCollection 中已包含 SqlParameter 的方案

    错误详细信息

          System.ArgumentException: 另一个 SqlParameterCollection 中已包含 SqlParameter。
    具体原因

          声明的SqlParameter数组,而在循环的内部,每一次执行ExecuteNonQuery都由该方法内部的IDbCommand.Parameters.Add(IDbDataParameter)将SqlParameter数组添加到IDbCommand的IDataParameterCollection中。而Framework机制限制两个IDataParameterCollection指向同一个对象。虽然ExecuteNonQuery方法内部声明了一个IDbCommand的临时对象,理论上讲,这个包含了IDataParameterCollection的IDbCommand对象会在ExecuteNonQuery方法结束时从内存中释放。但是实际上可能是由于垃圾回收机制并没有将IDbCommand临时对象即时的回收,而且该对象绑定的Parameter集合也存在,就像一个DropDownList添加Item一样。所以在下一次操作执行的时候,会导致两个IDataParameterCollection指向同一个对象,引发程序异常。
    解决方案一

          在每次操作时,重新生成对象,但这样会产生大量的垃圾变量,不可取。
    解决方案二

          将使用完之后的Command命令的Parameters集合清空。

    调用代码如下:

    SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    cmd.Parameters.Clear();

    【7】C#内存释放的几个方法对比:

    image

    而Close与Dispose这两种方法的区别在于,调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象被销毁了,不能再被使用。

    在实现Dispose方法的时候,一定要加上“GC.SuppressFinalize( this )”语句,避免再让GC调用对象的析构函数。

    【8】C# 去掉标题栏实现用鼠标移动窗体

    // 移动窗体
    const int WM_NCLBUTTONDOWN = 0xA1;
    const int HT_CAPTION = 0x2;
    [DllImport("user32.dll")]
    static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    
    // 窗体上鼠标按下时
    protected override void OnMouseDown(MouseEventArgs e)
    {
          if (e.Button == MouseButtons.Left & this.WindowState==FormWindowState.Normal)
          {
              // 移动窗体
              this.Capture = false;
              SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
          }
    }

    【9】改变DataGridView某行背景颜色以及字体颜色

    改变某行背景颜色:

    dgv_SelectEvent.Rows[行号].DefaultCellStyle.BackColor = System.Drawing.Color.Blue;

    改变某行的字体颜色:
    this.dataGridView1.Rows[行号].Cells[列号].Style.Font或ForeColor;

    【10】C#退出应用程序办法 

    Application.Exit();//好像只在主线程可以起作用,而且当有线程,或是阻塞方法的情况下,很容易失灵
    this.Close();//只是关闭当前窗体。
    Application.ExitThread();//退出当前线程上的消息循环,并关闭该线程上的所有窗口。 也会失灵
    Environment.Exit(0); //前面三种方法都不能很好的退出程序,此方法可以完全退出程序,这个要强制得多。
    Process.GetCurrentProcess().Kill();//此方法完全奏效,绝对是完全退出。
     
     
    【11】让一个线程一直运行
    如果你不想CPU一直负载,也不想让线程运行一次就结束,那么可以使用线程阻塞。system.threading 命名空间中有 AutoResetEvent 类。waitone可以让线程挂起等待信号,信号来了,继续往下走。set给出信号,让你wait的线程继续执行。
    public AutoResetEvent are = new AutoResetEvent(false);
    
    whiletrue)
    {
        are.waitone();
        if( shutdown )
        {
            break;
        }
        //你的程序处理过程
    }
    写另外一个方法,方法中调用are.set(),调用一次set,你的线程就会运行一次,如果要退出,将shudown这个bool型设置为true。
  • 相关阅读:
    微信Jssdk 认证签名
    枚举的变换
    mysql 事务
    Java中的堆和栈
    mysql-索引
    mysql-事务隔离 为什么你改了我还看不见
    mysql 一次更新语句是如何执行的
    mysql-一条sql的执行过程
    随笔
    设计模式之装饰者
  • 原文地址:https://www.cnblogs.com/feiyuhuo/p/5020785.html
Copyright © 2020-2023  润新知