C#编写记事本(高仿)_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > C#编写记事本(高仿)

C#编写记事本(高仿)

 2014/9/1 23:12:01  小土亦尘  程序员俱乐部  我要评论(0)
  • 摘要:近一周写的关于记事本的代码,高仿记事本。本人C#入门不久,其中存在代码冗余,但懒得修改了。经测试运行正常。一、主窗体设计及代码1namespaceBestEditor2{3publicpartialclassMain:Form4{5privateboolisTextChanged;6privatestringpath;//记录文件路径(刚新建的文件路径为"",打开的文件路径为原路径)78publicMain()9{10InitializeComponent();11this.Text="无标题
  • 标签:C#

近一周写的关于记事本的代码,高仿记事本。本人C#入门不久,其中存在代码冗余,但懒得修改了。

经测试运行正常。

一、主窗体设计及代码

class="code_img_closed" src="/Upload/Images/2014090123/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('ca647701-b4fd-4e7a-86f0-74f0bea0c317',event)" src="/Upload/Images/2014090123/2B1B950FA3DF188F.gif" alt="" />
  1 namespace BestEditor
  2 {
  3     public partial class Main : Form
  4     {
  5         private bool isTextChanged;
  6         private string path;//记录文件路径(刚新建的文件路径为"",打开的文件路径为原路径)
  7 
  8         public Main()
  9         {
 10             InitializeComponent();
 11             this.Text = "无标题 - 记事本";
 12             path = "";
 13         }
 14 
 15         /// <summary>
 16         /// 初始化窗体时调用
 17         /// </summary>
 18         /// <param name="sender"></param>
 19         /// <param name="e"></param>
 20         private void Main_Load(object sender, EventArgs e)
 21         {
 22             //初始化,撤销、剪切、复制、删除 不可用
 23             撤消UToolStripMenuItem.Enabled = false;
 24             剪切TToolStripMenuItem.Enabled = false;
 25             复制CToolStripMenuItem.Enabled = false;
 26             删除LToolStripMenuItem.Enabled = false;
 27 
 28             if (richTextBoxBoard.Equals(""))
 29             {
 30                 查找FToolStripMenuItem.Enabled = false;
 31                 查找下一个NToolStripMenuItem.Enabled = false;
 32             }
 33             else
 34             {
 35                 查找FToolStripMenuItem.Enabled = true;
 36                 查找下一个NToolStripMenuItem.Enabled = true;
 37             }
 38 
 39             if (Clipboard.ContainsText())
 40                 粘贴PToolStripMenuItem.Enabled = true;
 41             else
 42                 粘贴PToolStripMenuItem.Enabled = false;
 43 
 44             toolStripStatusLabel2.Text = "第 1 行,第 1 列";
 45         }
 46 
 47         private void 新建NToolStripMenuItem_Click(object sender, EventArgs e)
 48         {
 49             //如果输入框文字发生变动
 50             if (isTextChanged)
 51             {
 52                 saveFileDialog1.FileName = "*.txt";
 53                 DialogResult dr = MessageBox.Show("是否将更改保存到 " + this.Text + "?", "记事本", 
 54                     MessageBoxButtons.YesNoCancel);
 55                 if (dr == DialogResult.Yes)
 56                 {
 57                     //获取或设置指定要在 SaveFileDialog 中显示的文件类型和说明的筛选器字符串
 58                     saveFileDialog1.Filter = @"文本文档(*.txt)|*.txt|所有格式|*.txt;*.doc;*.cs;*.rtf;*.sln";
 59                     if (saveFileDialog1.ShowDialog() == DialogResult.OK)
 60                     {
 61                         richTextBoxBoard.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
 62                         richTextBoxBoard.Text = "";
 63                         path = "";
 64                     }
 65                 }
 66                 else if(dr == DialogResult.No)
 67                 {
 68                     richTextBoxBoard.Text = "";
 69                     path = "";
 70                 }
 71             }
 72             else
 73             {
 74                 richTextBoxBoard.Text = "";
 75                 this.Text = "无标题 - 记事本";
 76                 path = "";
 77             }
 78         }
 79 
 80         /// <summary>
 81         /// 输入框发生变化时触发
 82         /// </summary>
 83         /// <param name="sender"></param>
 84         /// <param name="e"></param>
 85         private void richTextBoxBoard_TextChanged(object sender, EventArgs e)
 86         {
 87             isTextChanged = true;
 88         }
 89 
 90         private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
 91         {
 92             if (isTextChanged)
 93             {
 94                 saveFileDialog1.FileName = "*.txt";
 95                 DialogResult dr = MessageBox.Show("是否将更改保存到 " + this.Text + "?", "记事本",
 96                     MessageBoxButtons.YesNoCancel);
 97                 if (dr == DialogResult.Yes)
 98                 {
 99                     //获取或设置指定要在 SaveFileDialog 中显示的文件类型和说明的筛选器字符串
100                     saveFileDialog1.Filter = @"文本文档(*.txt)|*.txt|所有格式|*.txt;*.doc;*.cs;*.rtf;*.sln";
101                     if (saveFileDialog1.ShowDialog() == DialogResult.OK)
102                     {
103                         richTextBoxBoard.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
104                         Text = saveFileDialog1.FileName.Substring(saveFileDialog1.FileName.LastIndexOf("\\")+1)+
105                             " - 记事本";
106                     }
107                 }
108             }
109 
110             openFileDialog1.FileName = "";
111 
112             if (openFileDialog1.ShowDialog() == DialogResult.OK)
113             {
114                 path = openFileDialog1.FileName;
115                 Text = path.Substring(path.LastIndexOf("\\") + 1) + " - 记事本";
116                 Console.WriteLine("path={0}",path);
117                 richTextBoxBoard.LoadFile(path, RichTextBoxStreamType.PlainText);
118                 isTextChanged = false;
119             }
120         }
121 
122         private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
123         {
124             if (!("".Equals(path)))
125             {
126                 richTextBoxBoard.SaveFile(path, RichTextBoxStreamType.PlainText);
127                 isTextChanged = false;
128             }
129             else
130             {
131                 saveFileDialog1.Filter = @"文本文档(*.txt)|*.txt|所有格式|*.txt;*.doc;*.cs;*.rtf;*.sln";
132                 if (saveFileDialog1.ShowDialog() == DialogResult.OK)
133                 {
134                     richTextBoxBoard.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
135                     path = saveFileDialog1.FileName;
136                     this.Text = path.Substring(path.LastIndexOf("\\") + 1) + " - 记事本";
137                     isTextChanged = false;
138                 }
139             }
140         }
141 
142         private void 另存为AToolStripMenuItem_Click(object sender, EventArgs e)
143         {
144             saveFileDialog1.Filter = @"文本文档(*.txt)|*.txt|所有格式|*.txt;*.doc;*.cs;*.rtf;*.sln";
145             if (saveFileDialog1.ShowDialog() == DialogResult.OK)
146             {
147                 richTextBoxBoard.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
148                 path = saveFileDialog1.FileName;
149                 this.Text = path.Substring(path.LastIndexOf("\\") + 1) + " - 记事本";
150                 isTextChanged = false;
151             }
152         }
153 
154         private void 页面设置UToolStripMenuItem_Click(object sender, EventArgs e)
155         {
156             pageSetupDialog1.Document = printDocument1;
157             pageSetupDialog1.ShowDialog();
158         }
159 
160         private void 打印PToolStripMenuItem_Click(object sender, EventArgs e)
161         {
162             printDialog1.Document = printDocument1;
163             printDialog1.ShowDialog();
164         }
165 
166         private void 退出XToolStripMenuItem_Click(object sender, EventArgs e)
167         {
168             this.Close();
169         }
170 
171         private void 撤消UToolStripMenuItem_Click(object sender, EventArgs e)
172         {
173             richTextBoxBoard.Undo();
174         }
175 
176         private void 编辑EToolStripMenuItem_Click(object sender, EventArgs e)
177         {
178             if (richTextBoxBoard.CanUndo)
179                 撤消UToolStripMenuItem.Enabled = true;
180 
181             if (richTextBoxBoard.SelectionLength > 0)
182             {
183                 剪切TToolStripMenuItem.Enabled = true;
184                 复制CToolStripMenuItem.Enabled = true;
185                 删除LToolStripMenuItem.Enabled = true;
186             }
187             else
188             {
189                 剪切TToolStripMenuItem.Enabled = false;
190                 复制CToolStripMenuItem.Enabled = false;
191                 删除LToolStripMenuItem.Enabled = false;
192             }
193 
194             if (richTextBoxBoard.Equals(""))
195             {
196                 查找FToolStripMenuItem.Enabled = false;
197                 查找下一个NToolStripMenuItem.Enabled = false;
198             }
199             else
200             {
201                 查找FToolStripMenuItem.Enabled = true;
202                 查找下一个NToolStripMenuItem.Enabled = true;
203             }
204 
205             if (Clipboard.ContainsText())
206                 粘贴PToolStripMenuItem.Enabled = true;
207             else
208                 粘贴PToolStripMenuItem.Enabled = false;
209         }
210 
211         private void 剪切TToolStripMenuItem_Click(object sender, EventArgs e)
212         {
213             richTextBoxBoard.Cut();
214         }
215 
216         private void 复制CToolStripMenuItem_Click(object sender, EventArgs e)
217         {
218             richTextBoxBoard.Copy();
219         }
220 
221         private void 粘贴PToolStripMenuItem_Click(object sender, EventArgs e)
222         {
223             richTextBoxBoard.Paste();
224         }
225 
226         private void 删除LToolStripMenuItem_Click(object sender, EventArgs e)
227         {
228             richTextBoxBoard.SelectedText = "";
229         }
230 
231         /// <summary>
232         /// 不同窗体之间通讯
233         /// </summary>
234         /// <param name="sender"></param>
235         /// <param name="e"></param>
236         private void 查找FToolStripMenuItem_Click(object sender, EventArgs e)
237         {
238             Search search = new Search();
239             search.Owner = this;
240             search.Show();
241         }
242 
243         private void 查找下一个NToolStripMenuItem_Click(object sender, EventArgs e)
244         {
245             Search search = new Search();
246             search.Owner = this;
247             search.Show();
248         }
249 
250         private void 替换RToolStripMenuItem_Click(object sender, EventArgs e)
251         {
252             Change change = new Change();
253             change.Owner = this;
254             change.Show();
255         }
256 
257         private void 转到GToolStripMenuItem_Click(object sender, EventArgs e)
258         {
259             Goto gt = new Goto();
260             gt.Owner = this;
261             gt.Show();
262         }
263 
264         private void 全选AToolStripMenuItem_Click(object sender, EventArgs e)
265         {
266             richTextBoxBoard.SelectAll();
267         }
268 
269         private void 时间日期DToolStripMenuItem_Click(object sender, EventArgs e)
270         {
271             string front = richTextBoxBoard.Text.Substring(0, richTextBoxBoard.SelectionStart);
272             string back = richTextBoxBoard.Text.Substring(richTextBoxBoard.SelectionStart, 
273                 richTextBoxBoard.Text.Length - richTextBoxBoard.SelectionStart);
274             richTextBoxBoard.Text = front + DateTime.Now.ToString() + back;
275         }
276 
277         private void 自动换行WToolStripMenuItem_Click(object sender, EventArgs e)
278         {
279             if (richTextBoxBoard.WordWrap)
280             {
281                 自动换行WToolStripMenuItem.Checked = false;
282                 richTextBoxBoard.WordWrap = false;
283             }
284             else
285             {
286                 自动换行WToolStripMenuItem.Checked = true;
287                 richTextBoxBoard.WordWrap = true;
288             }
289         }
290 
291         private void 字体FToolStripMenuItem_Click(object sender, EventArgs e)
292         {
293             fontDialog1.ShowDialog();
294             richTextBoxBoard.SelectionFont = fontDialog1.Font;
295         }
296 
297         /// <summary>
298         /// 控制底部状态栏显示与否
299         /// </summary>
300         /// <param name="sender"></param>
301         /// <param name="e"></param>
302         private void 状态栏SToolStripMenuItem_Click(object sender, EventArgs e)
303         {
304             if (状态栏SToolStripMenuItem.Checked)
305             {
306                 状态栏SToolStripMenuItem.Checked = false;
307                 statusStrip1.Visible = false;
308             }
309             else
310             {
311                 状态栏SToolStripMenuItem.Checked = true;
312                 statusStrip1.Visible = true;
313             }
314         }
315 
316         /// <summary>
317         /// 输入框光标位置变化时触发
318         /// </summary>
319         /// <param name="sender"></param>
320         /// <param name="e"></param>
321         private void richTextBoxBoard_SelectionChanged(object sender, EventArgs e)
322         {
323             string[] str = richTextBoxBoard.Text.Split('\r', '\n');
324             int row = 1, column = 1, pos = richTextBoxBoard.SelectionStart;
325 
326             foreach(string s in str)
327                 Console.WriteLine(s);
328             Console.WriteLine("pos={0}",pos);
329 
330             for (int i = 0; pos - str[i].Length > 0; i++)
331             {
332                 pos = pos - str[i].Length - 1;
333                 row = i + 2;
334             }
335             column = pos + 1;
336             toolStripStatusLabel2.Text = "" + row + " 行,第 " + column + "";
337         }
338 
339         private void 关于记事本AToolStripMenuItem_Click(object sender, EventArgs e)
340         {
341             AboutBox ab = new AboutBox();
342             ab.Show();
343         }
344 
345         private void 查看帮助HToolStripMenuItem_Click(object sender, EventArgs e)
346         {
347             //调用系统内部的notepad.chm文件
348         }
349 
350         /// <summary>
351         /// 点击窗体右上角关闭按钮触发
352         /// </summary>
353         /// <param name="sender"></param>
354         /// <param name="e"></param>
355         private void Main_FormClosing(object sender, FormClosingEventArgs e)
356         {
357             if (isTextChanged)
358             {
359                 if (!("".Equals(path)))
360                 {
361                     DialogResult dr = MessageBox.Show("是否将更改保存到"+path+"?","记事本",
362                         MessageBoxButtons.YesNoCancel);
363                     if (dr == DialogResult.Yes)
364                         richTextBoxBoard.SaveFile(path, RichTextBoxStreamType.PlainText);
365                     else if (dr == DialogResult.No)
366                         e.Cancel = false;
367                     else
368                         e.Cancel = true;//不关闭
369                 }
370                 else
371                 {
372                     DialogResult dr = MessageBox.Show("是否将更改保存到 无标题?", "记事本", 
373                         MessageBoxButtons.YesNoCancel);
374                     if (dr == DialogResult.Yes)
375                     {
376                         saveFileDialog1.Filter = @"文本文档(*.txt)|*.txt|所有格式|*.txt;*.doc;*.cs;*.rtf;*.sln";
377                         if (saveFileDialog1.ShowDialog() == DialogResult.OK)
378                             richTextBoxBoard.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
379                         else
380                             e.Cancel = true;
381                     }
382                     else if (dr == DialogResult.No)
383                         e.Cancel = false;
384                     else
385                         e.Cancel = true;
386                 }
387             }
388         }
389     }
390 }
View Code

二、查找子窗体设计及代码

 1 namespace BestEditor
 2 {
 3     public partial class Search : Form
 4     {
 5         private RichTextBox rtb = new RichTextBox();
 6 
 7         public Search()
 8         {
 9             InitializeComponent();
10         }
11 
12         /// <summary>
13         /// 初始化时得到主窗口的通讯数据
14         /// </summary>
15         /// <param name="sender"></param>
16         /// <param name="e"></param>
17         private void Search_Load(object sender, EventArgs e)
18         {
19             Main main = (Main)this.Owner;
20             this.rtb = main.richTextBoxBoard;
21         }
22 
23         /// <summary>
24         /// 取消
25         /// </summary>
26         /// <param name="sender"></param>
27         /// <param name="e"></param>
28         private void button2_Click(object sender, EventArgs e)
29         {
30             this.Close();
31         }
32 
33         private void button1_Click(object sender, EventArgs e)
34         {
35             string str = rtb.Text;//文件内容
36             string subSearch = textBox1.Text;//查找内容
37             string initString = subSearch;
38             int pos = rtb.SelectionStart;//光标位置
39             
40             if (!checkBox1.Checked)
41             {
42                 str = str.ToLower();
43                 subSearch = subSearch.ToLower();
44             }
45 
46             if (radioButton1.Checked)//向上查找
47             {
48                 if (rtb.SelectionLength > 0)
49                     pos = pos + rtb.SelectionLength - 1;
50                 
51                 str = str.Substring(0, pos);
52                 if (subSearch != "" && (pos = str.LastIndexOf(subSearch, pos)) != -1)
53                 {
54                     //输入框得到焦点并选中查找的内容
55                     rtb.Focus();
56                     rtb.SelectionStart = pos;
57                     rtb.SelectionLength = subSearch.Length;
58                 }
59                 else
60                     MessageBox.Show("找不到\"" + initString + "\"", "记事本", 
61                         MessageBoxButtons.OK, MessageBoxIcon.Information);
62             }
63             else
64             {
65                 if (rtb.SelectionLength > 0)
66                     pos = pos + 1;
67                 if (subSearch != "" && (pos = str.IndexOf(subSearch, pos)) != -1)
68                 {
69                     rtb.Focus();
70                     rtb.SelectionStart = pos;
71                     rtb.SelectionLength = subSearch.Length;
72                 }
73                 else
74                     MessageBox.Show("找不到\"" + subSearch + "\"", "记事本",
75                         MessageBoxButtons.OK, MessageBoxIcon.Information);
76             }
77         }
78     }
79 }
View Code

三、替换子窗体设计及其代码

  1 namespace BestEditor
  2 {
  3     public partial class Change : Form
  4     {
  5         private RichTextBox rtb = new RichTextBox();
  6 
  7         public Change()
  8         {
  9             InitializeComponent();
 10         }
 11 
 12         private void Change_Load(object sender, EventArgs e)
 13         {
 14             Main main = (Main)this.Owner;
 15             this.rtb = main.richTextBoxBoard;
 16             button1.Enabled = false;
 17             button2.Enabled = false;
 18             button3.Enabled = false;
 19         }
 20 
 21         /// <summary>
 22         /// 查找下一个
 23         /// </summary>
 24         /// <param name="sender"></param>
 25         /// <param name="e"></param>
 26         private void button1_Click(object sender, EventArgs e)
 27         {
 28             string str = rtb.Text;
 29             string subSearch = textBox1.Text;
 30             string initString = subSearch;
 31             int pos = rtb.SelectionStart;
 32 
 33             if (!checkBox1.Checked)
 34             {
 35                 str = str.ToLower();
 36                 subSearch = subSearch.ToLower();
 37             }
 38 
 39             if (rtb.SelectionLength > 0)
 40                 pos = pos + 1;
 41             if ((pos = str.IndexOf(subSearch, pos)) != -1)
 42             {
 43                 rtb.Focus();
 44                 rtb.SelectionStart = pos;
 45                 rtb.SelectionLength = subSearch.Length;
 46             }
 47             else
 48                 MessageBox.Show("找不到\"" + initString + "\"", "记事本", 
 49                     MessageBoxButtons.OK, MessageBoxIcon.Information);
 50         }
 51 
 52         private void textBox1_TextChanged(object sender, EventArgs e)
 53         {
 54             bool flag = textBox1.Text != "";
 55             button1.Enabled = flag;
 56             button2.Enabled = flag;
 57             button3.Enabled = flag;
 58         }
 59 
 60         /// <summary>
 61         /// 取消
 62         /// </summary>
 63         /// <param name="sender"></param>
 64         /// <param name="e"></param>
 65         private void button4_Click(object sender, EventArgs e)
 66         {
 67             this.Close();
 68         }
 69 
 70         /// <summary>
 71         /// 替换
 72         /// </summary>
 73         /// <param name="sender"></param>
 74         /// <param name="e"></param>
 75         private void button2_Click(object sender, EventArgs e)
 76         {
 77             string str = rtb.Text;
 78             string subSearch = textBox1.Text;
 79             string initString = subSearch;
 80             string changeTo = textBox2.Text;
 81             string front;
 82             string dest;
 83             string back;
 84             int pos = rtb.SelectionStart;
 85 
 86             if (!checkBox1.Checked)
 87             {
 88                 str = str.ToLower();
 89                 subSearch = subSearch.ToLower();
 90             }
 91 
 92             if (rtb.SelectionLength > 0)
 93             {
 94                 if (rtb.SelectedText.Equals(subSearch))
 95                 {
 96                     //将文本框字符串分段,替换后再组合
 97                     front = rtb.Text.Substring(0,pos);
 98                     dest = changeTo;
 99                     back = rtb.Text.Substring(pos + subSearch.Length, rtb.Text.Length - pos - subSearch.Length);
100                     rtb.Text = front + dest + back;
101                 }
102                 pos = pos + 1;
103             }
104 
105             if ((pos = str.IndexOf(subSearch, pos)) != -1)
106             {
107                 rtb.Focus();
108                 rtb.SelectionStart = pos;
109                 rtb.SelectionLength = subSearch.Length;
110             }
111             else
112                 MessageBox.Show("找不到\"" + initString + "\"", "记事本",
113                     MessageBoxButtons.OK, MessageBoxIcon.Information);
114         }
115 
116         /// <summary>
117         /// 全部替换
118         /// </summary>
119         /// <param name="sender"></param>
120         /// <param name="e"></param>
121         private void button3_Click(object sender, EventArgs e)
122         {
123             string str = rtb.Text;
124             string subSearch = textBox1.Text;
125             string changeTo = textBox2.Text;
126             string front;
127             string dest;
128             string back;
129             int pos = 0;
130 
131             if (!checkBox1.Checked)
132             {
133                 str = str.ToLower();
134                 subSearch = subSearch.ToLower();
135             }
136 
137             while ((pos=str.IndexOf(subSearch,pos))!=-1)
138             {
139                 front = rtb.Text.Substring(0, pos);
140                 dest = changeTo;
141                 back = rtb.Text.Substring(pos + subSearch.Length, rtb.Text.Length - pos - subSearch.Length);
142                 rtb.Text = front + dest + back;
143                 if (!checkBox1.Checked)
144                     str = rtb.Text.ToLower();
145             }
146         }
147     }
148 }
View Code

四、转到子窗体设计及其代码

 1 namespace BestEditor
 2 {
 3     public partial class Goto : Form
 4     {
 5         private RichTextBox rtb = new RichTextBox();
 6 
 7         public Goto()
 8         {
 9             InitializeComponent();
10         }
11 
12         private void Goto_Load(object sender, EventArgs e)
13         {
14             Main main = (Main)this.Owner;
15             this.rtb = main.richTextBoxBoard;
16         }
17 
18         private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
19         {
20             if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != 13)
21             {
22                 e.Handled = true;
23                 MessageBox.Show("只能接收数字","记事本",MessageBoxButtons.OK,MessageBoxIcon.Error);
24             }
25         }
26 
27         private void button2_Click(object sender, EventArgs e)
28         {
29             this.Close();
30         }
31 
32         /// <summary>
33         /// 确定
34         /// </summary>
35         /// <param name="sender"></param>
36         /// <param name="e"></param>
37         private void button1_Click(object sender, EventArgs e)
38         {
39             int row = int.Parse(textBox1.Text);
40             int pos = 0;
41             string[] str = rtb.Text.Split('\r', '\n');
42             
43             if (row < 1|| row > str.Length)
44                 MessageBox.Show("行数超出范围", "记事本 - 跳行", MessageBoxButtons.OK);
45             else
46             {
47                 for (int i = 1; i < row; i++)
48                     pos = pos + str[i-1].Length + 1;
49                 this.Close();
50                 rtb.Focus();
51                 rtb.SelectionStart = pos;
52             }
53         }
54     }
55 }
View Code

五、“关于”对话框

直接插入“关于”对话框即可

 

Ps:

编写过程中有参考到以下代码:http://blog.csdn.net/mathewsking/article/details/3645753,在此谢谢博主的思路启发!

发表评论
用户名: 匿名