一、聊天窗体案例 ' ?/ i4 `0 n; Q2 v, O
1、聊天窗体的要求? 6 ~ e Q5 [4 q0 L: p
(1)由两个文本框组以及两个按钮组成(一个只读框,一个输入框与取消按钮,一个发送按钮), r. r' d) ]! L) l5 a
(2)只读框就是只读,并且没有焦点,并且消息发送多了以后会自动往下滚动,并且有滚动条
9 N. P5 s$ l9 W( k" A: L* f# w (3)输入框就是有焦点,可以输入消息
# M$ h1 R( Z1 y5 {! v# k" Y (4)取消按钮就是按下按钮后输入框中的内容消失
9 f) Q3 A L% U (5)发送按钮就是点击或者按下Enter键后发送输入框中的内容$ r! v( ^1 C1 M3 W
2、C#如何实现
6 l. I* e9 Y$ G2 S9 H3 d+ D# W (1)将窗体居中(2种方法)
; I7 D$ l, |* @; \. \ ①使用CenterToScreen()方法/ H0 C8 Q* e% B2 b& a; w
this.CenterToScreen();//使窗体再当前显示器中居中
②使用公式
3 j/ o- {& G3 [& w8 a 要想使窗体居中,就必须计算窗体左边缘与容器工作区左边缘之间距离以及控件上边缘与容器工作区上边缘之间的距离
8 ~+ k9 X( d7 Q7 a this.Left = Screen.PrimaryScreen.WorkingArea.Width / 2 - this.Width/2;
//控件左边缘与容器工作区左边缘之间的距离=显示器工作区域的宽度/2-控件的宽度/2
this.Top = Screen.PrimaryScreen.WorkingArea.Height / 2 - this.Height/2;
//控件行编译与容器工作区上边缘之间的距离=显示器工作区域的高度/2-控件的高度/21
(2)给窗体一个名字,以及大小,背景颜色0 z8 T" L- a' _2 l2 A8 s1 r/ P6 }; e
this.Text = "与吴京正在聊天中.....";
this.Size = new Size(680, 500);
this.BackColor = Color.PowderBlue;
(3)插入只读框textbox并设置大小,并且只读" A& h) G" @" i
那么该如何设置大小呢,它的宽是可以拉动的,但是高不行,所以必须设置Multiline这个属性才可以设置高度,然后,只读的话就是ReadOnly这个属性。
4 o8 g# o, m3 U) p- A1 d textBox1.Multiline = true;//设置可以多行显示
textBox1.Size = new Size(630, 250);
textBox1.ReadOnly = true;//设置控件中的文本内容只读
(4)插入输入框textbox,并设置大小 o& X$ z4 B$ ^: H S3 u
textBox2.Multiline = true;//设置textbox2可以多行显示
textBox2.Size = new Size(textBox1.Width, 100);
此时,我们发现一个问题,就是鼠标的焦点跑到了只读框中,所以此时就应该使用TabIndex这个属性来将鼠标的默认焦点给输入框,它的值是0就是打开
) f9 v% m9 ^3 ~$ g8 `0 S* n# h- Y textBox2.TabIndex = 0;//获取textbox2的默认焦点
(5)插入两个按钮,一个叫取消,一个叫发送,并且他们的大小都是一样的,背景颜色和字体颜色也是一样的
& `5 q; q+ g6 x% H //buttom1的属性
button1.Size = new Size(60, 30);//设置button1的宽为60像素高为30像素
button1.Text = "取消";//设置button1的文本内容
button1.ForeColor = Color.White;//设置字体颜色
button1.BackColor = Color.MediumSeaGren;//设置背景颜色
(6)按下发送,输入框中的内容发送给了只读框,并且输入框中的内容消失,此时,鼠标的焦点还在输入框中,但是按下空格发送或者直接发送,不能发送,并且鼠标焦点还在,而且是在输入框最左边的位置。6 B* O. I0 C8 j! N1 x
①这里我们要用到if判断它是不是空字符或者是空格,如果是就不发送,否则就发送,必须在发送按钮下进行。
) h; |2 j' t7 G string.IsNullOrWhiteSpace 表示指示指定的字符串是null、空还是仅由空白字符组成。- M% N7 Q; M+ V* N9 Z; g. n1 s
Focus() 表示获取输入后的焦点。
* [; S' m4 k( \0 z6 w; D) m) Q 实现发送功能实则就是把输入框中的内容赋值给只读框。然后发送完后输入框中的内容消失,可以用空的字符串代替
Q; r2 {- M7 ~2 U1 O if (string.IsNullOrWhiteSpace(textBox2.Text))//判断textbox2中输入的内容是否为空或者空格
{
textBox2.Focus();//获取输入焦点
textBox2.Text = "";//假如输入空格就将textbox2中的内容清空
}
else
{
textBox1.Text+= "挪威的森林 2024415986" + DateTime.Now + "\r\n" + "\r\n" + textBox2.Text + "\r\n" + "\r\n";
textBox2.Text = "";//内容发送给textbox1后清空textbox2中的内容
}
//+号表示链接上次发发送的内容,"\r\n"表示换行
(7)此时,我们发现一个问题,就是当只读框中的内容超出范围后,它就不再显示, R3 L2 x. c& ?: A" j# ?
那么,该如何解决这个问题呢?这里我们可以引入一个属性和一个方法7 ?* X" [7 O' `, \, {8 s
①SelectionStart 表示获取文本范围的起始点 或者 Select来获取文本范围
5 V5 J5 ^( |* a ?8 o9 m& R4 D ②ScrollToCaret() 表示将控件内容滚动到当前插入符号位置
3 D, M; ?) J+ N; I# Z, w 通过这两行代码就可以解决这个问题,必须在只读框中写1 O% c5 R! Y; S* ~6 e- @* N s
textBox1.SelectionStart = textBox1.TextLength;//获取textbox1中的文本范围的起始点
textBox1.ScrollToCaret();//将控件内容滚动到插入符号位置
(8)按下发送后取消输入框中的内容, |; D1 o6 r# P
这个就可以用空的字符串来代替,但是必须在取消按钮的事件当中写* J9 o' g, R% Z9 p, j" X
//取消后触发的事件
private void button1_Click(object sender, EventArgs e)
{
textBox2.Text = "";
}
9)按下Enter键发送内容, R. C; r" W( s& @1 P
这里要使用到一个方法,AcceptButton这个属性,但是这个属性只有在窗体中才能找到。AcceptButton 表示获取或设置当前用户按Enter键时所单击的窗体上的按钮$ U7 W2 K8 m+ \3 k' C
this.AcceptButton = this.button2;//按下Enter键触发button2中的事件
二、窗体抖动 3 n+ i& L5 ?' r2 p. t; p7 h
1、窗体抖动的原理
6 X ^' w: c; a H, ^$ z5 l 实质就是:窗体位置的改变和快速移动。
& n' S% d1 T9 o6 {" R 第一步:
/ b) v2 E) Z( g4 y4 A+ Y( G( z 使窗体在显示器中居中,并设置窗体的文本- y3 s- f; k, a/ C
this.CenterToScreen();//使窗体在当前显示器中居中
this.Text = "抖一抖";
第二步:
- ~( R: b9 w6 F# J- H+ Y 插入按钮,并设置按钮的大小和文本内容
" w% B# a; }& g( H! j/ A& h6 q this.button1.Size = new Size(80, 40);
button1.Text = "抖一抖";
第三步:
& J3 @3 r u W; Y2 [: P 就是设置窗体的位置了,那么它位置的改变就是从窗体居中后的位置左上角的位置开始顺时针移动改变。% m5 `( a, }# _+ k' @
那么它改变的规律是什么?
" F D7 C. c; Y- l 是先从初始的位置(就是剧中后左上角的位置往右移动=》再往下=》往左=》往左=》往上=》往上=》往右=》往右=》往下=》往左。最终回到初始位置,要用到location这个属性。但是,每次移动后都要让他停留几毫秒,所以,就要用到线程这个概念。 M# T% J( G, A; \+ w, o: a
那么,什么是线程?Thread线程是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是行程中的实际运作单位。Thread.Sleep(); 表示当前线程挂起指定的毫秒数。
# Y- _- G; C2 ]& R, I Thread.Sleep(20);//线程控制20毫秒
但是,位置改变一圈后回到初始位置不是抖动,所以,必须使用for循环让他多次移动来实现抖动的效果
' d( d8 d4 v+ L6 @6 K- u 源码如下:8 \4 ] ~! n5 E; a2 v3 `% M
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 窗体抖动
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.CenterToScreen();//使窗体在当前显示器中居中
this.Text = "抖一抖";
this.button1.Size = new Size(80, 40);
button1.Text = "抖一抖";
this.AcceptButton = this.button1;
}
private void Form1_douyidou(object sender, EventArgs e)
{
for (int i = 0; i < 2; i++)
{
//①往右
this.Location = new Point(this.Left + 10, this.Top);
Thread.Sleep(20);//线程控制20毫秒
//②往下
this.Location = new Point(this.Left, this.Top + 10);
Thread.Sleep(20);
//③往左
this.Location = new Point(this.Left - 10, this.Top);
Thread.Sleep(20);
//④往左
this.Location = new Point(this.Left - 10, this.Top);
Thread.Sleep(20);
//⑤往上
this.Location = new Point(this.Left, this.Top - 10);
Thread.Sleep(20);
//⑥往上
this.Location = new Point(this.Left, this.Top - 10);
Thread.Sleep(20);
//⑦往右
this.Location = new Point(this.Left + 10, this.Top);
Thread.Sleep(20);
//⑧往右
this.Location = new Point(this.Left + 10, this.Top);
Thread.Sleep(20);
//⑨往下
this.Location = new Point(this.Left, this.Top + 10);
Thread.Sleep(20);
//十一往左
this.Location = new Point(this.Left - 10, this.Top);
Thread.Sleep(20);
}
}
}
}