• 【原创】自己动手写工具----XSmartNote [Beta 2.0]


    前面的话

    在上一篇自己动手写工具----XSmartNote中,我简单介绍了这个小玩意儿的大致界面和要实现的功能,看了一下园子里的评论,评价褒贬不一,有人说“现在那么多云笔记的工具”,“极简版evernote”,我想说的是,别人的工具再好用,终究不是自己写的,其实写这个的目的,一方面是锻炼自己的技术能力,在coding的时候,或多或少会遇到一些问题,在解决这些问题的过程中,技术能力就会有所提升;另一方面,写这个东西还有自己个人原因,可以随时记录一些繁杂的知识点,通过给这些知识点打上标签,可以实现归类,那有的人会说,EverNote呢?嗯,如果你用着自己写的软件和用EverNote,哪个会更有成就感呢?好了,不多说,上图上代码!!

    这个小东西基本上实现了上一篇中列出的功能,添加note、note分类、为note加标签、根据标签对note进行筛选等。下面介绍各个功能点

    功能

    添加note

    首先在界面的右上角会提示您目前选择的树结构节点,如果新添加note就必须选择该note的所属目录(左侧的树节点),否则会因为找不到所属目录而导致添加note失败,如下图:

    这样,新增的note就会自动归类为DOT NET文件夹下咯~

     1 private void btn_Save_Click(object sender, EventArgs e)
     2  {
     3      TreeNode node = tv_Folder.SelectedNode;
     4      TipsForm tf = new TipsForm();
     5      if (node == null)
     6      {
     7          return;
     8      }
     9      if (node.Tag.ToString() == Enums.LEAVES.ToString())
    10      {
    11          //同时更新标题和内容
    12          int i = SQLHelper.UpdateContent(node.Name.ToInt(), txt_Title.Text, txt_Content.Text);
    13          //同时重新加载Treeview
    14          BuildTree(this.tv_Folder, GetFolderSet());
    15          if (i > 0)
    16          {
    17              tf.Show("保存成功!");
    18          }
    19      }
    20  }

    由于建立新note时,note的ID就确定了,所以只要根据ID来更新几个字段就可以了。所以上面是更新操作而不是插入操作。

    1  //更新标题及内容
    2  public static int UpdateContent(int id,string title,string content)
    3  {
    4      int result = -1;
    5      StringBuilder cmd = new StringBuilder();
    6      cmd.Append(string.Format("update Table_Content set Content = '{0}',Title='{1}'  where Id={2}",content,title,id));
    7      return NonQuery(cmd, result);
    8  }

    为note分类

    这个比较简单了,只要在添加的时候指定好note的所属目录就可以了,单击目录时,右侧下方的预览区会显示出该目录下的所有note,并且最上方的标签区域显示该目录下所有的note包含的标签~

    为note指定标签

    为note指定标签的过程实际上是向关联note和标签的表中加入数据的过程,这里note和标签是多对多的关系,所以需要单独建立一个关系表。

    为note加标签,是通过自定义控件LabelWithCheck的选中事件触发的,而且LabelWithCheck是在初始化时动态生成并且动态绑定事件的。

     1  public void AddLabelToLocation(FlowLayoutPanel flp, int column, string tag, int Id, bool ischecked,bool registerEvent)
     2  {
     3      //int flag = 0;
     4      int labelCount = flp.Controls.Count;
     5      int lines = labelCount / column;
     6      int left = labelCount % column;
     7      int X = (left * WIDTH) + (left + 1) * MARGIN;
     8      int Y = lines * HEIGHT + (lines + 1) * MARGIN;
     9      LabelWithCheck label = new LabelWithCheck();
    10      //注册事件
    11      if (registerEvent)
    12      {
    13          label.LabelCheckedEvent += Label_LabelCheckedEvent;
    14          //new TipsForm().Show("注册插入数据库事件");
    15      }
    16      else
    17      {
    18          label.LabelCheckedEvent += Label_LabelSelectEvent;
    19          //new TipsForm().Show("注册过滤事件");
    20      }
    21     
    22      label.BackColor = ColorTranslator.FromHtml(ColorManager.ColorConvertor(flagForPanelEdit));
    23      label.Location = new Point(X, Y);
    24      label.LabelText = tag;//存储标签名称
    25      label.Id = Id;//存储标签ID
    26      label.LabelChecked = ischecked;//选中状态
    27      flp.Controls.Add(label);
    28      flagForPanelEdit++;
    29      if (flagForPanelEdit > 19)
    30      {
    31          flagForPanelEdit = 0;
    32      }
    33  }

    下面是自定义控件LabelWithCheck的代码,重绘LabelWithCheck

     1  #region OVERRIDE
     2  protected override void OnPaint(PaintEventArgs e)
     3  {
     4      Graphics g = e.Graphics;
     5      int x = this.Width;
     6      int y = this.Height;
     7      Point leftTop = new Point(0, 0);
     8      Point rightTop = new Point(x - 1, 0);
     9      Point leftBottom = new Point(0, y - 1);
    10      Point rightBottom = new Point(x - 1, y - 1);
    11 
    12      g.DrawLine(new Pen(Color.White), leftTop, rightTop);
    13      g.DrawLine(new Pen(Color.White), leftBottom, rightBottom);
    14      g.DrawLine(new Pen(Color.White), leftTop, leftBottom);
    15      g.DrawLine(new Pen(Color.White), rightTop, rightBottom);
    16      //画上边缘
    17      for (int i = 0; i < x - 1; i += 3)
    18      {
    19          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(i, 0, 2, 1));
    20      }
    21 
    22      //画下边缘
    23      for (int m = 0; m < x - 1; m += 3)
    24      {
    25          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(m, y - 1, 2, 1));
    26      }
    27 
    28      //画左边缘
    29      for (int i = 0; i < y - 1; i += 3)
    30      {
    31          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, i, 1, 2));
    32      }
    33 
    34      //画右边缘
    35      for (int i = 0; i < y - 1; i += 3)
    36      {
    37          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(x - 1, i, 1, 2));
    38      }
    39      base.OnPaint(e);
    40  }
    41  #endregion

    定义LabelWithCheck控件的事件,为note添加标签的时候就触发这个事件,参数中包括了标签的一些信息

     1 #region EVENT
     2 public delegate void LabelWithCheckSelectedHandler(object sender, LabelWithCheckEventArgs e);
     3 public event LabelWithCheckSelectedHandler LabelCheckedEvent;
     4 private void ck_CheckedChanged(object sender, EventArgs e)//checkBox原型
     5 {
     6     if (LabelCheckedEvent != null)
     7     {
     8         LabelCheckedEvent(sender, new LabelWithCheckEventArgs(this._Id,this.LabelText));
     9     }
    10 }
    11 #endregion

     每选择一个LabelWithCheck都会动态添加该控件

    1  private void Label_LabelSelectEvent(object sender, LabelWithCheckEventArgs e)
    2  {
    3      AddLabelToLocation(flowLayoutPanel2,6,e.LabelText,e.Id,false,false); //Stack Overflow 重复绑定重复执行 形成无限循环导致
    4  }

    根据目录和标签筛选

    这一部分还没有仔细地去做,目前只是大概地处理了一下,最近实在太忙了。大概的筛选原则就是右侧上方的两个标签区域的交集,只要符合条件就会在下面的预览区域显示出来,也就是我们想要看到的结果啦~

    上面一排是所选的目录下所有note包含的所有的标签,下面是手工指定的标签,通过筛选条件的就会出现在下面的note预览区域中

    结语

    本来这个小东西早就该完成,但是中间公司又分配了些项目,没有太多的空闲时间,今天抽空把他总结出来,对自己也有个交代。在写这个玩意儿的时候,的确遇到了一些小问题,如左侧树状结构绑定同一张表中带有层级结构的数据,这是第一次接触,但是掌握了方法就OK了;还有自定义控件的动态添加和绑定事件等等。如果您有什么建议,欢迎评论,大神勿拍... ...如果觉得好玩儿,就给个赞吧~~

    2014马上过去了,不得不说时间飞快,祝各位园友在新的一年里,能够实现升职加薪,出任CTO,迎娶白富美,走向人生巅峰

     作者:悠扬的牧笛

     博客地址:http://www.cnblogs.com/xhb-bky-blog/p/4167108.html

     声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。

  • 相关阅读:
    统计nginx日志里访问次数最多的前十个IP
    while 格式化输出 运算符 字符编码
    Python 软件安装
    Python 基础
    Typora 基础的使用方法
    Django ORM (四) annotate,F,Q 查询
    Django 惰性机制
    Django ORM (三) 查询,删除,更新操作
    Django ORM (二) 增加操作
    Django ORM (一) 创建数据库和模型常用的字段类型参数及Field 重要参数介绍
  • 原文地址:https://www.cnblogs.com/xhb-bky-blog/p/4167108.html
Copyright © 2020-2023  润新知