C#-WinForm剪切板监控各类数据

看代码就行,下面是一个简单说实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public partial class Form1 : Form
{

//一些dll的调用
public const int WM_CLIPBOARDUPDATE = 0x031D;
[DllImport("user32.dll", SetLastError = true)]
public static extern bool AddClipboardFormatListener(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RemoveClipboardFormatListener(IntPtr hWnd);


public Form1()
{
InitializeComponent();

//加上这一行
AddClipboardFormatListener(this.Handle);
//RemoveClipboardFormatListener(this.Handle); 销毁
Message mes = new Message();
DefWndProc(ref mes);
}

//监听处理事件
protected override void DefWndProc(ref Message m)
{
if (m.Msg == WM_CLIPBOARDUPDATE)
{
if (Clipboard.ContainsText())
{
//输出剪切板中的文本
Console.WriteLine(Clipboard.GetText());
}
//显示剪贴板中的图片信息
else if (Clipboard.ContainsImage())
{

Console.WriteLine("图片");
//Clipboard.GetImage();
//赋值给imgbox 我这里没有
// pictureBox1.Update();
}
else
{

Console.WriteLine("其他待处理的文件类型");
}
}
else
{
base.DefWndProc(ref m);
}
}
}

html页面显示之前执行js方法

第一种方式是把方法写在head中

让它顺序执行的时候去执行。

第二种方式是使用body的onload方法
第三种方式是使用$(document).ready()

JQuery 中用得最多的要属工厂函数 $() 了,下面我们就来看一下它的初步应用。
大家知道,在 JQuery 中我们可以使用 $(document).ready(); 在其中加入页面加载后的代码,以便做出丰富的页面行为。
它和传统的 JS 中的 onload 有什么区别呢?
onload ready 没有简写方式 具有简写方式 当 HTML 页面所有内容加载完毕后才执行 onload 当 DOM
节点加载完毕后就执行 ready 一个 HTML 页面只能编写一个 onload 一个 HTML 页面允许同时编写多个 ready
传统的 window 的 onload 程序如下:
window.onload = function() { }
它是在整个页面完全被加载之后执行。
这样做最大的一个缺点就是速度问题,onload 中的代码不仅是在构建 DOM 树之后,而且是在所有图像和其它外部资源被完整地加载
并在页面浏览器窗口显示完毕之后才执行。
而 $(document).ready() 最大地优点就是在浏览器构建 DOM 树之后立即执行其中的代码。
(document).ready()的写法比较正式,用得比较多的写法还可以是:(document).ready() 的写法比较正式,用得比较多的写法还可以是:(document).ready()的写法比较正式,用得比较多的写法还可以是:(), 你可以在括号中直接加你的匿名函数,如下:
$(function() { });

$(document).ready(function() { });

$().ready(function(){ });
都是正确的。

白岩松:毁掉一个人最好的方式,就是投其所好

文章转载~

image-20200408184349995

智能手机已经成为了人类不可获取的产品,走到哪里都会不自主的将手机掏出来看一眼,不管有没有人跟你联系。一个普通人一天掏出手机的次数有多少呢?没有经过完全的统计,在工作的时候,一小时能大概能看上6-10次。

这个影响还不是最最深的,白岩松说本想在11点睡觉的,想着掏出手机看十分钟就行。但是上面的内容太精彩了,都是自己喜欢的内容,然后再看时间,发现已经12点多了。我们会沉浸在手机投我们所好的内容上,从而也就有不会有任何的别扭。 别扭,往往时进步的标志。因为我们对某个东西不了解,所以会感到陌生,感到别扭。往往很多别扭会让人进步,因为你解决了别扭,你也就提升了。但是手机是投其所好的,没有了别扭,也就没有了进步,对于一个人而言,没有了进步就是倒退。所以也就有了白岩松的名言:现在手机这种投其所好是毁人的最好方式之一。

别扭是我们进步的阶梯

小时候不敢游泳,因为被水呛到的滋味太难受了,所以下水就成了一件特别别扭的事情。有一次去河边玩的时候,不小心将课本掉到河里面,身边也没有其他朋友。不下水的话,课本不用多久就会沉到水底或者被冲走。最后还是一咬牙跳进了水里,尝试着用狗刨的形式比划了两下,竟让可以浮在水面上。从那之后,便学会了游泳。 不敢下水是因为怕被水呛到,所以下水也就成了一个特别别扭的事情。不下水的话,就不会被水呛到,同时也不会有别扭。但是,不敢面对这种别扭,又怎么能学会游泳呢?去打破这个别扭之后,就是一次全新的提升,就是进步中的一个阶梯。就像玩游戏一样,每过一关就会有一个别扭的BOSS,但打倒这个BOSS却是兴趣最盎然的时刻。

投其所好是无形的甜蜜“杀手”

投其所好的作用是什么呢?投其所好的最大作用就是可以让一个人变的安逸。刘备去了孙权的地盘之后,孙权就投其所好,给他好吃的,好玩的。时间长了,也就迷失在了里面,所以就有了“乐不思蜀”的成语。 现在的手机也正是这样,每次打开之后,它的后台会根据用户的习惯,推荐用户感兴趣的内容。就像一罐罐蜂蜜一样,时刻的将用户包围起来,刚看过一篇文章是喜欢的,马上又有一个视频是自己喜欢的。本想晚上出去跑步的,但是一看手机忘记了时间,也忘记了跑步。本想着读书的,却被手机上的蜂蜜吸引住了,书也就不愿意再看了。 正像白岩松所说的那样:当年轻人都不开始读书的时候,谁读书谁就会杀出一条血路。谁用手机的时间少一点,多给自己一点无聊的时光,伟大的创造就有可能诞生在谁哪里。国外的作家已经说得很明白,手机拿走了人们的无聊,也顺便将与无聊有关的伟大一并拿走。

不想被毁掉,就要逼自己“无聊”

“三体”的作者在谈到自己写作的时候,他有大把的时间是无聊的,而三体就是在这样的无聊时间中诞生的。他将这些无聊的时间串起来,然后开始写,写的时间长了,也就有了三体这本书。其实他也可以不无聊的,比如掏出手机看上一会自己喜欢的内容,无聊的时间或许会很快从他身边溜走。 一家公司的前台,平时工作很简单,空闲时间也比较充足。她不知道做什么,不像另外一个同事去刷手机,她相反的开始去学习如何做PPT。有一次,公司需要提交方案,但做PPT的同事不在,其他人做的也不好。她这个时候就站了出来,主动承担起做PPT的任务。汇报方案结束之后,她被破格提拔到产品部。刷手机的同事,依然还在哪里做着前台。 无论是读书还是学一个技能,是一件挺“无聊”的事情。它不像手机中那些写出来的巧妙的句子,能够博得一笑。更不像那些很有趣的内容,让你将无聊的时光消磨掉。但是,它可以通过日积月累,将知识或者经验加持到你身上,可能现在不会闪光,但是当这些小优点足够多了,也就会有大的光亮了。 比“无聊”更无聊的,是能够坚持 无聊这种事情做起来并不难,但是最难的是能够将这个“无聊”的事情坚持下去,特别是这个无聊在偶尔的时候你根本看不到有一丝价值。就像一些作家一样,写了大半辈子的书,一部也没有火。这种无聊是最熬人的,很多事情就是这样,如果一年能够让你有所收获,很多人都愿意做。如果三年之后才会有收获,或许有不少人都会选择放弃。

这就是在结果上的选择,会高估一年的付出,但会低估三年的收获。能够坚持一年的无聊,但未必能坚持一年没有收获的无聊。就像大作家莫言,在他成名之前的几十年的时间里,收获并不大,换作其他人,可能有人就会选择换行吧。但是他将这个“无聊”坚持去做,也就有了现在知名作家莫言了。 时间对每一个人都是最公平的,它不会看你漂亮让你一天30个小时,也不会看你个子高,让你的一天变成20个小时。但是,你可以选择让你这24个小时是在“投其所好”中度过,或者是在“别扭”中度过。当然,时间也会根据你的选择,给你一个匹配的答案。

C#-WinForm图形界面学习笔记

基础语法笔记

1.Parse 方法用于将字符串类型转换成任意类型
2.Convert 方法是数据类型转换中最灵活的方法,它能够将任意数据类型的值转换成任意数据类型,前提是不要超出指定数据类型的范围。
3.C#正则表达式(Regex类)
正则表达式的符号主要分为元字符和表示重复的字符,分别如下表所示。

Using的用法

1.在文件顶部引用命名空间,如:using System;

2.为命名空间或类型定义别名; :using ElseName = This.Is.Very.Very.Long.NamespaceName;

3.使用using,定义范围,在该范围结束时回收资源。

​ 使用前提:该对象必须继承了IDisposable接口,功能等同于try{}Finally{}。

正则表达式中的 元字符

1 . 匹配除换行符以外的所有字符
2 \w 匹配字母、数字、下画线
3 \s 匹配空白符(空格)
4 \d 匹配数字
5 \b 匹配表达式的开始或结束
6 ^ 匹配表达式的开始
7 $ 匹配表达式的结束

正则表达式中 表示重复的字符
1 * 0次或多次字符
2 ? 0次或1次字符
3 + 1次或多次字符
4 {n} n次字符
5 {n,M} n到M次字符
6 {n, } n次以上字符

此外,在正则表达式中使用|分隔符表示多个正则表达式之间的或者关系,也就是在匹配某一个字符串时满足其中一个正则表达式即可。

例如使用正则表达式来验证身份证信息,第一代身份证是由 15 个数字构成的,第二代身份证是由 18 个数字构成的,正则表达式可以写成 \d{15}|\d{18}

在 C# 语言中使用正则表达式时要用到 Regex 类,该类在 System.Text.RegularExpressions 名称空间中。

在 Regex 类中使用 IsMatch 方法判断所匹配的字符串是否满足正则表达式的要求。

1
2
3
4
5
6
7
8
9
10
11
Console.WriteLine("请输入一个邮箱");
string email = Console.ReadLine();
Regex regex = new Regex(@"^(\w)+(\.\w)*@(\w)+((\.\w+)+)$");
if (regex.IsMatch(email))
{
Console.WriteLine("邮箱格式正确。");
}
else
{
Console.WriteLine("邮箱格式不正确。");
}

更多:http://c.biancheng.net/view/2846.html

定义枚举类型的变量的语法形式如下。

1
2
3
4
5
访问修饰符 enum 变量名 : 数据类型
{
值l,
2,
}

结构体类型

1
2
3
4
5
访问修饰符  struct  结构体名称
{
//结构体成员
}

委托

委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。

委托定义

1
public delegate void MyDelegate();

匿名委托

在 C# 语言中匿名委托是指使用匿名方法注册在委托上,实际上是在委托中通过定义代码块来实现委托的作用,具体的语法形式如下。

1
2
3
4
5
6
7
8
//1. 定义委托
修饰符 delegate 返回值类型 委托名 ( 参数列表 );

//2. 定义匿名委托
委托名 委托对象 = delegate
{
//代码块
};

事件

事件定义的语法形式如下。

1
访问修饰符 event 委托名 事件名 ;

C#委托+回调

线程间安全

//通过委托回调

文件操作

C# Driveinfo:获取计算机驱动器信息

C# Directoryinfo类:文件夹操作

C# Directory类:文件夹操作

C# FileInfo类:文件操作

C# File类:文件操作

C# Path类:文件路径操作

C#流简介

C# StreamReader类:读取文件

C# StreamWriter类:写入文件

C# FileStream类:文件读写

C# BinaryReader类:读取二进制文件

C# BinaryWriter类:写入二进制数据

异常与调试

本章内容:

  1. C# Exception:异常类
  2. C# try catch finally:异常处理
  3. C#自定义异常(throw抛出异常)
  4. C# Debug和Trace:输出调试信息
  5. C#程序调试:VS2015调试程序详解

常用的异常类如下图所示。

异常类继承关系图

常用的系统异常类如下表所示。

异常类 说明
System.OutOfMemoryException 用 new 分配内存失败
System.StackOverflowException 递归过多、过深
System.NullReferenceException 对象为空
Syetem.IndexOutOfRangeException 数组越界
System.ArithmaticException 算术操作异常的基类
System.DivideByZeroException 除零错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Program
{
static void Main(string[] args)
{
//定义存放5个整数的数组
int[] a = new int[5];
try
{
for(int i = 0; i < a.Length; i++)
{
a[i] = int.Parse(Console.ReadLine());
}
for(int i = 0; i < a.Length; i++)
{
Console.Write(a[i] + " ");
}
}
catch(FormatException f)
{
Console.WriteLine("输入的数字格式不正确!");
}
catch(OverflowException o)
{
Console.WriteLine("输入的值已经超出 int 类型的最大值!");
}
catch(IndexOutOfRangeException r)
{
Console.WriteLine("数组越界异常!");
}
}
}

进程与线程

Process 类主要提供对本地和远程进程的访问,并提供对本地进程的启动、停止等操作。

线程及与线程有关的类

与线程有关的类同样也都在 System.Threading 命名空间中,主要的类如下表所示。

类名 说明
Thread 在初始的应用程序中创建其他的线程
ThreadState 指定 Thread 的执行状态,包括开始、运行、挂起等
ThreadPriority 线程在调度时的优先级枚举值,包括 Highest、AboveNormal、Normal、BelowNormal、Lowest
ThreadPool 提供一个线程池,用于执行任务、发送工作项、处理异步I/O等操作
Monitor 提供同步访问对象的机制
Mutex 用于线程间同步的操作
ThreadAbortException 调用Thread类中的Abort方法时出现的异常
ThreadStateException Thead处于对方法调用无效的ThreadState时出现的异常

Thread 类主要用于实现线程的创建以及执行,其常用的属性和方法如下表所示。

属性或方法 说明
Name 属性,获取或设置线程的名称
Priority 属性,获取或设置线程的优先级
ThreadState 属性,获取线程当前的状态
IsAlive 属性,获取当前线程是否处于启动状态
IsBackground 属性,获取或设置值,表示该线程是否为后台线程
CurrentThread 属性,获取当前正在运行的线程
Start() 方法,启动线程
Sleep(int millisecondsTimout) 方法,将当前线程暂停指定的毫秒数
Suspend() 方法,挂起当前线程(已经被弃用)
Join() 方法,阻塞调用线程,直到某个线程终止为止
Interrupt() 方法,中断当前线程
Resume() 方法,继续已经挂起的线程(已经被弃用)
Abort() 方法,终止线程

ThreadStart:创建线程

lock 关键字能保证加锁的线程只有在执行完成后才能执行其他线程。使用 TryEnter() 方法可以给它传送一个超时值,决定等待获得对象锁的最长时间。

Mutex 类也是用于线程同步操作的类,例如,当多个线程同时访问一个资源时保证一次只能有一个线程访问资源。 if(mutex.WaitOne()){} //mutex.ReleaseMutex();

多线程与异步程序设计

1.Thread类及其应用
2.线程优先级和线程调度
3.线程互斥
4.线程同步
5.volatile关键词
6.线程池
7.TAP异步编程模式

C#中@的用法

1.加在字符串前面,字符串中的 \ 失去转义符的作用,直接写字符串而不需要考虑转义字符
2.加在字符串前面,字符串中的 “ 要用 “” 表示
3.加在字符串前面,换行空格都保存着,方便阅读代码
4.用关键字做变量时在关键字前面加@
5.作为sql语句里的一个“标签”,声明此处需要插入一个参数

布局

Anchor:设置一个控件的Anchor为ToplRight当窗口大小改变时,该控件锚定于窗口的右上角即,与父窗口的上边距Top和右边距Right保持不变

Dock:停靠,将控件停靠在一侧或中央

FlowLayoutPanel:

TableLayoutPanel:

AfDockLayout:

当设置Dock属性时,Anchor属性无效

对话框的使用

弹出对话框窗口:
MyDialog dlg=new MyDialog();

dlg.ShowDialog(this);

dlg.Dispose();

其中,
-dlg.Show()作为普通窗口显示
-dlg.ShowDialog()作为对话框窗口显示

Form窗口对象含有非托管资源,需要手工销毁

注:Dispose非托管资源,

FormBorderStyle属性的不同效果

属性 意义
FormBorderStyle.None 0 无边框
FormBorderStyle.FixedSingle 1 固定的单行边框
FormBorderStyle.Fixed3D 2 固定的三维样式边框
FormBorderStyle.FixedDialog 3 固定的对话框样式的粗边框
FormBorderStyle.Sizable 4 可调整大小的边框
FormBorderStyle.FixedToolWindow 5 不可调整大小的工具窗口边框
FormBorderStyle.SizableToolWindow 6 可调整大小的工具窗口边框

窗口顶置

registerForm.TopMost = true;

根据鼠标点击的位置,判断点中了哪一项
int index=listBox1.IndexFromPoint(e.Location);

DataGridView

1
2
3
4
5
6
// 取得当前单元格内容 
Console.WriteLine(DataGridView1.CurrentCell.Value);
// 取得当前单元格的列 Index
Console.WriteLine(DataGridView1.CurrentCell.ColumnIndex);
// 取得当前单元格的行 Index
Console.WriteLine(DataGridView1.CurrentCell.RowIndex);

Tag 绑定对象

Listbox

加入对象调用tostring对象

标准类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    class plist
{
public plist() { }

string path;
string name;
public string Path
{
get { return this.path; }
set { this.path = value; }
}

public string Name
{
get { return this.name; }
set { this.name = value; }
}

public plist(string a, string b)
{
this.name = a;
this.path = b;
}
public override string ToString()
{
return this.name;
}
}

案例:图片查看器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog F = new FolderBrowserDialog();
if (F.ShowDialog() == DialogResult.OK)
{
string dir = F.SelectedPath;
textBox1.Text = dir;
ShowPictureList(dir);
}
}
private void ShowPictureList(string dir)
{
listBox1.Items.Clear();
string[] files = Directory.GetFiles(dir);
foreach (string s in files)
{
if (s.EndsWith(".jpg") || s.EndsWith(".png"))
{
plist p = new plist(Path.GetFileName(s), s);

listBox1.Items.Add(p);
}
}
if (files.Length > 0)
{
listBox1.SetSelected(0,true);
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
plist p = (plist)listBox1.SelectedItem;
if (p == null) return;
pictureBox1.Load(p.Path);
}

多个窗口之间的数据传递

通过静态字段

通过窗体构造函数

多文档窗体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
父窗体
IsMdiContainer设置为True


SForm child = new SForm();
child.MdiParent=this; //建立父子窗体 关系
child.Show();

//窗体显示方式
this.LayoutMdi(System.Windows.Forms.MdiLayout.xxx);

排列:ArrangeLcons
层叠:Cascade
水平:TileVertical
垂直:TileHorizontal

异步TAP模式

winform自定义控件

创建控件

继承于Control类,就可以从头到尾定制一个控件包含以下几个方面:
1控件的显示(绘制)2控件的行为(事件)3控件的数据(属性)

image-20200418152433287

生成解决方案,工具箱自动添加为true

控件的绘制

重写OnPaint()方法,实现控件的绘制

image-20200418153254612

颜色
指定颜色有两种方式:
Color color=Color.White;或者
Color color=Color.FromArgb([可选],255,255,255)

形状的绘制
本章介绍形状的绘制:
DrawArc圆弧 .
DrawBezier贝塞尔曲线
DrawCurve曲线/多个线段
DrawEllipse 椭圆/圆.
DrawLine 直线.
DrawPie扇形
DrawPolygon多边形
DrawRectangle 矩形.

描边与填充
以Draw打头的方法,称为描边/勾线以Fill打头的文件,称为填充/涂色例如,在描边时,需指定一个笔Pen g.DrawRectangle(pen,rect);在填充时,需指定一个刷子Brush g.FillRectangle(brush,rect);

资源释放

Pen与Brush都包含非托管资源,需要Dispose可以使用using写法

1
2
3
using(Brush brush=new SolidBrush(Color.Red)){
g.FillRectangle(brush,rect);
}

常见形状

DrawLine直线
DrawEllipse 椭/圆
DrawPolygon 多边形
DrawRectangle矩形

1直线Line需指定起点和终点
2矩形Rectangle指定矩形的位置和大小,可以使用Inflate()来缩放矩形
3椭圆/圆Ellipse指定该椭圆所在的矩形

平滑模式SmoothingMode 也称为反锯齿效果,可以将线条显示得更平滑l

g.SmoothingMode=SmoothingMode.HighQuality;

线型与填充色

线型:指定Pen的参数,设置线条参数
比如,点画线的绘制

1
2
pen.DashCap=DashCap.Round;
pen.DashPattern=new float[]{10,2,5,1};

填充:
SolidBrush纯色填充
LinearGradientBrush 线性渐变填充
TextureBrush 纹理填充等

背景与前景

背景:填充整个区域的、一般不变化的OnPaintBackground()
按照官方的建议,背景的绘制应该和前景分开

实例:正弦曲线

WinFormAPI支持的三种线条:
-直线IDrawLine
-圆弧、椭圆弧DrawArc
-贝塞尔曲线DrawBezier

像正弦这种特殊的曲线,API并不支持

多段拟和法

1一个回调方法可以同时注册给多个控件

2为了减轻重绘时的闪烁问题,可以使用“双缓冲”
在自定义控件中,启用DoubleBuffer双缓冲特性

image-20200418163850121

文本的绘制

image-20200418161856008

image-20200418162058416

文本的对齐

image-20200418162819073

1此种方法也适用于多行文本的绘制支持自动换行
2将来如果需要更精细的测算,还可以使用Graphics.MeasureString()
可以测算出一段文本所需的显示空间的大小

添加属性0

给控件添加属性:
-添加一个字段,表示要绘制的内容
-添加属性控制
如果属性名称已经存在,则需要override

this.Invalidate();

[ Browsable(truel)]
[ DesignerSerializationVisibility(DesignerSerialization Visibility.Visible)]

练习:请给它再添加一个属性:BorderColor,用于设置边框的颜色。

image-20200418163637307

实例:自定义日历

图片绘制

使用d.DrawImage()可以绘制图片

g.DrawImage(image,rect)

图片缩放:算法实现

图片截取

在绘制图片时,可以截取图片的一部分显示

image-20200418165806501

高级形状绘制

本章介绍一些高级形状的绘制圆弧Arc、扇形Pie路径Path、不规则形状、圆角矩形
-剪辑区域Clip、蒙版
-半透明叠加效果。。

注意:高级形状,并不代表是常用形状

image-20200418170359659
image-20200418170454602

不规则图形:

image-20200418170619963

剪辑区域:

image-20200418171015938

Region类还支持交并补运算

事件

image-20200419151118288

鼠标事件:

重写方法

鼠标事件:public ovefride OnMouse***()
比如:
OnMouseEnter 鼠标进入OnMouseLeave 鼠标移出
OnMouseDown 鼠标按下OnMouseUp鼠标抬起
OnMouseMove 鼠标移动OnMouseWheel鼠标滚轮
OnMouseClick/MouseDoubleClick单击/双击

image-20200419151723401

状态控制

事件参数:

事件的参数,用于携带事件相关的数据
比如,MouseDown事件的参数:
void button1_MouseDown(object sender,MouseEventArgs e)
在EventArgs里包含了鼠标点击的位置、按键等信息。。

定义事件的参数,按以下三步进行
1添加MyClickEventArgs,继承于EventArgs
2在MyButton中:触发事件时,传递事件参数
3在Form1中:在事件处理方法,取出事件参数

案例:拨号面板

键盘事件

OnKeyPress:

char ch=e.KeyChar;

1区分大小写,比如,’a’和’A’是不同的
2如果一直按着,则KeyPress事件会多次触发

输入焦点

有的控件支持焦点,如TextBox有的控件不支持焦点,如Label设置一个控件是否接受焦点:

this.Setftyle(ControlStyles.Selectable,true);

如果自定义控件不接收焦点,则可以设置为false

image-20200419155319329

Winform

跨线程调用invoke

InvokeRequired 判断当前是否在工作线程

image-20200421160053936

定时任务

定时任务的实现方式:
1.创建工作线程,sleep控制时间间隔

2.创建定时器

System.Timers.Timer(基于线程池)

3.System.Threading.Timer(基于线程池)

4.System.Windows.Forms.Timer(基于消息循环)

System.Threading.Timer一个基于线程池的定时器演示:使用定时器实现倒计时效果。。
1创建定时器
2启动定时器/停止定时器
3在定时器回调中,执行定时任务
(回调在工作线程中执行的)
4窗口关闭时,销毁定时器

image-20200421160751699

image-20200421160820681

image-20200421160833933

image-20200421160854893

System.Windows.Forms.Timer:

界面定时器的回调,直接运行在消息循环中
好处:可以直接更新界面
坏处:必须尽快完成,否则界面卡顿

image-20200421161226183

image-20200421161247814

image-20200421161257133

1.界面定时器的好处:可以直接更新UI控件

2.界面定时器的局限:只适合执行轻量级任务,必须尽快完成,不然界面会卡顿。
对于重量级的定时任务,须使用线程定时器。

短消息提示

特点:
1.弹出式窗口
2.短文本,可以折行显示3根据文本长度,自动调整大小
4.约1.5后后,自动消息I

在WinForm中,所有的窗口都用Form实现I比如,
常规窗口Window
对话框窗口Dialog
悬浮窗口FloatWindow
工具提示Tooltip
弹出式窗口Popup(如菜单窗口、下拉列表窗口)

image-20200421164503937

使用Graphics.MeastureString()可以测算文本的尺寸

Graphics g=this.CreateGraphics();

SizeF size=g.MeasureString(str,this.Font,300);

g.Dispose();

注意,临时创建的Graphics用完之后需要手工销毁

窗口背景

实现方法:
1自己绘制一个圆角矩形背景
2将外围区域透明化
this.BackColor=Color.White;
this.TransparencyKey=Color.White;
//指定透明区域的颜色

托盘通知

NotifyIcon 托盘通知程序可以在通知区创建一个通知图标一般地,可以提示一个气泡通知、右键菜单支持。。

卡片式导航

JavaScript DOM/BOM操作笔记总结

之前学习的JS的笔记现在整理发布到到博客,也当是复习知识

什么是DOM?

什么是DOM?

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。

操作元素

JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性

改变元素内容

1
2
3
4
5
element.innerText
从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉

element.innerHTML
起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

获取元素

getElementById……略

通过HTML5新增的方法获取

1
2
3
1.document.getElementeByclasaName('类名');//根据类名返回元素对象集合
2.document.querySelector('选择器'); //根据指定选择器返回第一个元素象
3.document.querySelectorA11('选择器'); //根据指定选择器返回

表单元素操作

利用DOM可以操作如下表单元素的属性:

1
type、value、checked、selected、disabled

样式属性操作

1
2
3
4
5
6
7
8
9
10
11
我们可以通过JS修改元素的大小、颜色、位置等样式。

1.element.style //行内样式操作
2.element.className //类名样式操作

// 在单个语句中设置多个样式
elt.style.cssText = "color: blue; border: 1px solid black";
// 或者
elt.setAttribute("style", "color:red; border: 1px solid blue;");
// 设置特定样式,同时保持其他内联样式值不变
elt.style.color = "blue";

注意:
1.Js里面的样式采取驼峰命名法比如 fontsize、backgroundcolor e
2.Js修改sty1e样式操作,产生的是行内样式,css权重比较高

3.如果样式修改较多,可以采取操作类名方式更改元素样式。
4.clasa因为是个保留字,因此使用className来操作元素类名属性
5.className 会直接更改元素的类名,会覆盖原先的类名。

案例:循环精灵图

案例:显示隐藏文本框内容

案例:判断输入是否符合条件

image-20200305150450394

排他思想

image-20200305150534282

如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
1.所有元素全部清除样式(干掉其他人)
2.给当前元素设百样式(留下我自己)
3.注意顺序不能颠倒,首先干掉其他人,再设置自己

代码:略

案例:image-20200305150602322

image-20200305150609746

自定义属性的操作

1.获取属性值

element.属性 获取属性值。
element.getAttribute(’属性);

区别

element.属性 获取内置属性值(元素本身自带的属性)
element.getAttribute(属性);主要获得自定义的属性(标准)我们程序员自定义的属性

自定义属性值的操作

1
2
element.属性='值'	//设置内置属性值。
element.setattribute('属性','值');

自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(’属性’)获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
H5给我们新增了自定义属性:

设置H5自定义属性:

H5规定自定义属性data-开头做为属性名并且赋值。

1
2
3
4
5
6
比如<div data-index=“1"></div>
或者使用JS设置
element.setAtribute('data-index',2)

//如果自定义属性里面有多个.链接的单词,我们获取的时候采取驼峰命名法
//h5新增的获取自定义属性的方法它只能获取data-开头的

节点操作

为什么需要节点操作

image-20200305151706763

节点概述

image-20200305151756506

一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
·元素节点nodeType为1

·属性节点nodeType为2
·文本节点nodeType为3(文本节点包含文字、空格、换行等)

在实际开发中,节点操作主要操作的是元素节点

节点层级

父节点

1
node.parentNode

子节点

1
2
3
4
parentNode.firstChild 
firstChild返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.lastChild
lastChild返回最后一个子书点,找不到则返回null。同样,也是包含所有的节点。

firstChild第一个子节点不管是文本节点还是元素节点

1
2
3
4
5
6
7
parentNode.firstElementChild 
firstE1ementChi1d 返回第一个子元素节点,找不到则返回null

parentNode.lastElementChi1d
1astE1ementChild返回最后一个子元素节点,找不到则返回null

注意:这两个方法有兼容性问题,TE9以上才支持。

注意元素节点和节点的区别

实际开发中,firstchild和1astchild包含其他节点,操作不方便,而firstElementchild和1astE1ementchi1d又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

dm

兄弟节点

1
2
3
4
5
6
1.node.nextsib1ing 
nextSib1ing返回当前元素的下一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点。

2.node.previouasibling
previousSibling 返回当前元素上一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点。

1
2
3
4
5
6
7
3.node.nextElementsibling 
nextE1ementsibling返回当前元素下一个兄弟元素节点,找不到则返回null

4.node.previousElementsibling
previousE1ementsibling返回当前元素上一个兄弟节点,找不到则返回null

注意:这两个方法有兼容性问题,IE9以上才支持。

如何解决兼容性问题?

封装一个兼容性的函数

image-20200305152905858

创建节点

1
2
3
document.createElement('tagName')

创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。

添加节点

1
2
node.appenchild(chile)	//添加到末尾
node.insertBefore(chile,指定元素) //添加到指定节点的前面

案例:简单版发布留言案例

节点删除

1
2
node.removeChild(child)
//node.removeChild()发放从DOM中删除一个子节点,返回删除的节点.

案例:添加删除按钮

复制节点(克隆节点)

1
2
node.cloneNode()
//方法返回调用该方法的节点的一个副本。也称为克降节点/拷贝节点

注意:
1.如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子
2.如果括号参数为true,则是深应拷贝,会复制节点本身以及里面所有的子节点。

三种动态创建元素的区别

document.write()

element.innerHTL()
document.createElement()

区别
1.document.write 是直接将内容写入页面的内容流,但是文流执行完毕,则它会导致页面全部重绘
2.innerHTL是将内容写入某个Dox节点,不会导致页面全部重绘

3.innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
4.createElement()创建多个元素效率稍低一点点,但是结构更清晰

不同浏览器下,innerHTML 效率要比 createElement 高

DOM重点核心

增删改查 属性操作,事件操作

创建

1.document.write
2.innerHTML
3.createElement

1.appendChild

2.insertBefore

1.removeChild

主要修改dom的元素属性,dom元素的内容、属性,表单的值等
1.修改元素属性:src、href、title等

2.修改普通元素内容:innerHTML、innerText
3.修改表单元素:value、type、disabled等
4.修改元素样式:style、className

主要针对于自定义属性。
1.setAttribute:设置dom的属性值
2.removeAttribute :移除属性

事件操作

给元素注册事件,采取 : 事件源.事件类型=事件处理程序

onclick 鼠标点击左键触发

onmouseover 鼠标经过触发

onmouseout 鼠标离开触发

onfocus 获得鼠标焦点触发

onblur 失去鼠标焦点触发

onmousemove 鼠标移动触发

onmouseup 鼠标标单起触发

onmousedown 鼠标按下触发

注册事件(事件绑定)

给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式和方法监听注册方式

image-20200307144712704

传统方法(略)

attachEvent 事件监听

1
eventTarget.attachEvent(eventNamewithon,callback)

eventrarget.attachEvent()方法将指定的监听器注册到eventrarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。

该方法接收两个参数:
eventNameWithOn:事件类型字符串,比如onclick、onmouseover,这里要带on
callback: 事件处理函数,当目标触发事件时回调函数被调用

计算机生成了可选文字: divs[1].addEventListener(/images/JavaScript%E5%85%A5%E9%97%A8%E7%AC%94%E8%AE%B0%E6%80%BB%E7%BB%93/clip_image001-1583564072529.png)

注册事件兼容性解决方案

image-20200307145054161

兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器

事件删除(解绑事件)

删除事件的方式

1.传统方式

eventTarget.onclick = null;

2.方法监听注册方式

eventTarget.removeEventListener(type,listener[,usecapture]);

DOM事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
比如我们给一个div注册了点击事件:

image-20200307145540000

1.事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。
2.事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。实际开发注重冒泡

image-20200307145703762

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
注意
1.Js代码中只能执行捕获或者冒泡其中的一个阶段。
2.onclick和attachEvent 只能得到冒泡阶段。
3.addEventListener(type,listenert,usecapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
4.实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
5.有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
6.事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。

事件对象

什么是事件对象

1
2
3
eventrarget.onclick=function(eventy){}
eventTarget.addEventListener('click'function(event){})
//这个event 就是事件对象,我们还喜欢的写成e或者evt

官方解释:event对象代表事件的状态,比如键盘按键的状态鼠标的位置、鼠标按钮的状态。

简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法。

这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。

事件对象的兼容性方案

事件对象本身的获取存在兼容问题:
1.标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到。
2.在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找。
解决:

1
e=ell window.event;

阻止事件冒泡

阻止事件冒泡的两种方法

事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点。
事件省泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。

1
2
3
4
//标准写法:利用事件对象里面的stoppropagation()方法
e.stopPropagation()

//非标准写法:IE6-8利用事件对象cancelBubble属性

阻止事件冒泡的兼容性解决方案

1
2
3
4
5
if(e && e.stopPropagation){
e. stopPropagation();
} else{
window.event.cancelBubble=true;
}

事件对象

事件对象的常见属性和方法

image-20200307150845708

事件委托

事件委托
事件委托也称为事件代理,在jQuery里面称为事件委派。
事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用管泡原理影响设置每个子节点。
案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会智泡到ul上,ul有注册事件,就会触发事件监听器。
事件委托的作用
我们只操作了一次DOM,提高了程序的性能。

常用的鼠标事件

1.禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

1
2
3
document.addEventListener('contextmenu'function(e){
e.preventDefault();
})

2.禁止鼠标选中(selectstart 开始选中)

1
2
3
document.addEventListener('selectstart'function(e){
e.preventDefault();
})
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
我是一段不愿意分享的文字
<script>
//1.contextmenu我们可以禁用右键菜单
document.addEventListener('contextmenu'function(e){
e.preventDefault();
})
//2.禁止选中文字selectstart
document.addEventListener('selectstart'function(e){
e.preventDefault();
})
</script>
</body>

常用鼠标事件

event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent 和键盘事件对象 KeyboardEvent。

image-20200307151650282

image-20200307151715792

案例:跟随鼠标的天使

常用键盘事件

image-20200307151828846

注意:
1.如果使用addEventuistener不需要加on
2.onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift等。
3.三个事件的执行顺序是:keydown–keypress—keyup

键盘事件对象

image-20200307152000430

注意:onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写。
在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)Keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCll值

案例:模拟京东按键输入内容 按下s键,光标定位到搜索框

案例:模拟京东快递单查询 输入内容时,文本框上面自动显示大号字的内容

image-20200307152232527

BOM概述

BOM的构成

window对象是浏览器的顶级对象,它具有双重角色。
1.它是Js访问浏览器窗口的一个接口。
2.它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。
注意:window下的一个特殊属性window.name

window对象的常见事件

窗口加载事件

1
2
3
window.onload=function(){}
或者
window.addEventListener("load"function(){});

1.有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面内容全部加载完再去执行处理函数。
2.window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准。

1
document.addEventListener('DOMContentLoaded',function(){})

DOMContentloaded 事件触发时,仅当DOMm载完成,不包括样式表,图片,flash等等。
le9以上才支持
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响户的体验,此时用DOMContentloaded事件比较合适。

调整窗口大小事件

1
2
window.onresize=function(){}
window.addEventListener("resize",function(){});

window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数。

定时器

setTimeout()定时器

1
window.setTimeout(调用函数,[延迟的毫秒数]);

setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
注意:
1.window可以省略。
2.这个调用函数可以 直接写函数,或者 写函数名 或者采取字符’串函数名()’三种形式。第三种不推荐
3.延迟的毫秒数省略默认是0,如果写,必须是毫秒。
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

setTimeout()这个调用函数我们也称为 回调函数calback
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。简单理解:回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。
以前我们讲的element.onclick=function(){}或者element.addEventtistener(“cick”,fm);里面的函数也是回调函数。

案例:5秒后自动关闭的广告

clearTimeout()方法取消了先前通过调用setrimeout()建立的定时器。
注意:
1.window可以省略。

setinterval定时器

1
window.setInterval(回调函数,[间隔的毫秒数]);

setlnterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
注意:
1.window可以省略。
2.这个调用函数可以直接写函数,或者写函数名或者采取字符串’函数名()’三种形式。
3.间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

案例:倒计时

cleanrInterval()方法取消先前通过调用setInterval()建立的定时器

案例:发送短信 60秒之内不能再次点击,防止重复发送

this

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定his到底指向谁,一般情况下this的最终指向的是那个调用它的对象
全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

JS执行机制

同步和异步

为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

他们的本质区别:这条流水线上各个流程的执行顺序不同。

同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS的异步是通过回调函数实现的。一般而言,异步任务有以下三种类型

1、普通事件,如click、resize等

2、资源加载,如load、error等

3、定时器,包括setlnterval、setTimeout等

异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

image-20200307154641274

1.先执行执行栈中的同步任务。
2.异步任务(回调函数)放入任务队列中。
3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

image-20200307154733165

image-20200307154758084

location对象

lovation对象的属性

image-20200307155153056

重点记住:href 和 search

案例:5秒之后自动跳转页面

案例:获取URL参数数据

image-20200307155403870

lovation对象的方法

image-20200307155433000

navigator

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转

image-20200307155557394

history对象

window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

image-20200307155727978

网页特效↓

元素偏移量 offset系列

概述

offset 翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置
获得元素自身的大小(宽度高度)

注意:返回的数值都不带单位
ofset系列常用属性:

image-20200307155937841

offset与style的区别

image-20200307160010928

案例:获取鼠标在盒子的坐标

案例:模态框拖拽

案例:淘宝图片放大镜

image-20200307160135031

元素可视区 client系列

client 翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

image-20200307160241702

案例:淘宝flexible.js源码分析

立即执行函数(function(){})() 主要作用:创建一个独立的作用域

元素滚动sroll系列

scroll 翻译过来就是滚动的,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。

image-20200307160445908

案例:仿淘宝固定右侧边栏

三大系列总结

image-20200307160524222

他们主要用法:
1.offset系列经常用于获得元素位置 offsetLeft offsetTop
2.client经常用于获取元素大小clientWidth clientHeight
3.scroll经常用于获取滚动距离 scrollTop scrolleft
4.注意页面滚动的距离通过window.pagexoffset获得

动画函数封装

缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来思路:
1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
2.核心算法:(目标值-现在的位置)/10做为每次移动的距离步长
3.停止的条件是:让当前盒子位置等于目标位置就停止定时器

演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//ydjl:移动到指定位置  (obj.offsetLeft)
function animate(obj,ydpx) {
//清除定时器 防止每一次调用都产生一个定时器,叠加导致问题(速度变快)
clearInterval(obj.timer);
obj.timer=setInterval(function () {
var step = (ydpx - obj.offsetLeft) / 10; //移动距离
//取整
step = step>0 ? Math.ceil(step) : Math.floor(step);
//判断是否移动到指定位置
if(obj.offsetLeft == ydpx)
{
//清除定时器,停止移动
clearInterval(obj.timer);
}
//修改left实现移动
obj.style.left = obj.offsetLeft + step + 'px';

},15)//移动间隔设置
}


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.boks{
position: absolute;
top: 300px;
left:0;
width: 100px;
height: 100px;
background-color: #ff0011;
}
</style>

</head>
<body>
<button class="yd500">移动500px</button>
<button class="yd800">移动800px</button>
<div class="boks">hezi</div>
</body>
<script>
function animate(obj,ydpx) {
//清除定时器
clearInterval(obj.timer);
obj.timer=setInterval(function () {
var step = (ydpx - obj.offsetLeft) / 10;
step = step>0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == ydpx)
{
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';

},15);
}
var yd500 = document.querySelector(".yd500");
var yd800 = document.querySelector(".yd800");
//盒子
var boks = document.querySelector(".boks");

yd500.addEventListener('click', function() {
// 调用函数
animate(boks, 500); //传递要移动的对象 和 移动位置
})

yd800.addEventListener('click', function() {
// 调用函数
animate(boks, 800); //传递要移动的对象 和 移动位置
})
</script>
</html>

案例:轮播图

节流阀

&& 运算符的运用

mouseenter 和mouseover的区别

mouseenter 鼠标事件
当鼠标移动到元素上时就会触发mouseenter事件
类似mouseover,它们两者之间的差别是
mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会
之所以这样,就是因为mouseenter不会冒泡
跟mouseenter搭配鼠标离开 mouseleave同样不会冒泡

window.sessionStorage

image-20200307161431078

window.localStorage

image-20200307161453888

触屏事件(略)

剩下的为一些特效实现(略~

C++与Java语法上的不同

一、new关键字

1
2
3
4
5
// C++中:
MyClass* a = new MyClass();
delete a;
// Java中:
MyClass a = new MyClass();
  1. C++中new关键字实例化对象之后返回的是一个对象的指针,所以需要定义指针;而Java中定义对象时返回的其实也是一个指针(引用),但是在Java中不需要显示的定义指针。
    不同点
  2. C++中通过new关键字实例化的对象在使用完毕后需要使用delete关键字手动释放内存;而Java中由于垃圾回收机制的存在,我们无需手动释放内存。

二、C++实例化对象的两种方式

1
2
3
4
5
6
// 方式一
MyClass* a = new MyClass();
delete a;
// 方式二
MyClass b(params...); // 该方式将会调用有参数的构造函数
MyClass c; //该方式将会调用无参数的构造函数
  1. 方式一中new关键字做了三件事:首先在堆内存上获得内存空间(类似malloc函数),然后调用类的构造函数,最后返回该内存空间的指针;因为是在堆内存的动态分配的内存空间,所以最后需要调用delete函数释放这一部分内存空间。
  2. 方式二中直接在栈内存上分配了存储空间,类似于基本类型的定义,所以无需手动释放内存空间,其会在作用域生命周期结束时自动调用析构函数释放内存;但是当对象信息量较大时,这种做法会占用很多内存,影响程序效率。

三、C++初始化表达式

1
int a(10); // 等效于 int a = 10;

与java不同,C++除了使用赋值语句初始化变量之外,还可以使用上述初始化表达式对变量进行初始化,其效果相同。

四、C++构造函数后的冒号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 初始化表达式
class MyClass {
public:
const int a;
int b;
MyClass(int aVal, int bVal):a(aVal), b(bVal) {}
};
// 非初始化表达式,无法通过编译,编译时会报以下错误:
// 'const int MyClass::a' should be initialized
class MyClass {
public:
const int a;
int b;
MyClass(int aVal, int bVal) {
a = aVal;
b = bVal;
}
};

这个语法其实就是上述第四点中的初始化表达式,但这里我们看到下面这种赋值方式在构造函数里面会报错,这又是为什么呢?因为这里我们的冒号初始化和赋值语句干的事情不太一样:在冒号初始化时,只有冒号后面有相应变量的初始化表达式,就会在为成员变量分配内存时进行初始化,所以常量a在分配内存时做了初始化操作,之后也没有被改变值,所以不会报错;而在使用赋值语句时,构造函数在执行到函数体时已经为a分配了内存但却没有对其进行初始化,因此就会报should be initialized编译错误了。

这种神奇的写法我第一次见的时候也是惊讶了一波。

五、C++中难以省略的分号;

在上面例子中我们看到了C++类的定义后面也要加分号;我们知道在Java中类定义的大括号后面都无需加分号。
之后查资料发现:
在C++中,除函数,及预编译指令外,其它的语句或代码段结尾都必须要加分号。其中预编译指令是指,以#开头的语句。常见的有,#include ,#define, #ifdef, #if, #elif, #else,#endif等。

六、C++中的::(作用域符)

C++的作用域符::用法有三,一一介绍如下

  1. 全局作用域符
1
2
3
4
5
int a = 3;
void test() {
int a = ::a;
cout << a << endl;
}

这里就是将全局变量a的值通过全局作用域符的方式访问到,然后将其值赋给test函数中的局部变量a。

  1. 类作用域符
1
2
3
4
5
6
7
class MyClass {
public:
void sayHello();
};
void MyClass::sayHello() {
cout << "hello world!" << endl;
}

这里有点类似Java中定义接口和对接口进行实现;首先在类的定义中定义了一个函数sayHello,但是没有具体函数体,然后在类的定义外,通过作用域符,在函数sayHello前加了一个MyClass::,相当于告诉编译器,这个函数就是MyClass类的sayHello方法的具体实现。

  1. 命名空间作用域符
1
std::cout << "hello world!" << endl;

这里std就是命名空间,这样的用法相当于using namespace std;

七、C++中的*、&、->

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass {
public:
int a;
MyClass(int aVal):a(aVal){}
};
int main () {
MyClass obj(5);
MyClass* objPointer = new MyClass(3);
// 常规操作
cout << obj.a << endl;
// 取指针操作
cout << (*objPointer).a << endl;
// ->操作
cout << objPointer->a << endl;
// 取地址操作
cout << (&obj)->a << endl;
// new出来的对象别忘了释放内存哦
delete objPointer;
return 0;
}

在C++中:

  1. *表示访问指针a指向的变量;

  2. &表示取得变量的地址;

  3. .表示访问对象的的成员变量或者函数;(与Java相同)

  4. ->表示访问指针指向的对象的成员变量或者函数;

    指针内容实在太多,这里就不赘述了,有兴趣的童鞋可以参考菜鸟教程

八、C++函数名前或者函数名后的const

  1. 函数名前的const
1
2
3
4
5
6
7
const int getVal() {
const int a = 3;
return a;
}
int main() {
cout << getVal() << endl;
}

就是定义函数的返回类型,规定返回变量类型必须为const。

  1. 函数名后的const(用于类的成员函数中)
1
2
3
4
5
6
7
8
9
10
11
12
class MyClass {
public:
int a;
MyClass(int aVal):a(aVal){}
void sayHello() const {
cout << "a value is: " << a << endl;
}
// 编译报错:assignment of member 'MyClass::a' in read-only object
void changeA() const {
a = 5;
}
};

函数名后面的const表示是该函数为常成员函数,该函数不能修改对象内的任何成员变量,只能发生读操作,不能发生写操作。这样可以对成员变量起到保护作用。

九、delete完成后需要将指针置为NULL

1
2
3
4
5
6
MyClass* a = new MyClass();
delete a;
// 省略下面这句运行时会出现以下错误:
// pointer being freed was not allocated
a = NULL;
delete a;

对一个非空指针delete后,若没有置为NULL,若再次delete的话,有可能出现问题。而C++标准规定:delete空指针是合法的,没有副作用。所以每次delete之后要将指针的值置为NULL。这是一个不得不养成的好习惯.