GDI绘制时钟效果,与系统时间保持同步,基于Winform
2018年工作之余,想起来捡起GDI方面的技术,特意在RichCodeBox项目中做了两个示例程序,其中一个就是时钟效果,纯C#开发。这个CSharpQuartz是今天上午抽出一些时间,编写的,算是偷得浮生半日休闲吧。先来看看效果图吧:

这是直接在Winform的基础上进行绘制的。接下来,我对时钟进行了封装,封装成一个名为CSharpQuartz的类,效果如下:

这是把时钟封装后,实现的一种效果,CSharpQuartz内部开辟了一个线程,与系统时间,保持同步,每秒刷新一次。所采用的技术也就是GDI和多线程及事件委托。把时钟封装成对象后,还为其添加了OnChanged事件,用于对象提供外部
处理之用。接下来就简单的说下,做次小程序的一些准备工作吧。
这也是最近偶尔听到有朋友问怎样做时钟的事,想来,其实也简单的,只是需要一些耐心和细心,这里主要还利用一些三角函数进行计算。上图看似很简单,其实也有很多小细节需要注意。我就把大致绘制的过程简单说下:
首先,我们需要定义一个圆,来作为时钟的轮廓,这里是通过设置时钟的直径及winform的宽高,来计算出时钟在窗体居中的位置。绘制圆的代码就更简单了
float w = 300f, h = 300f;
float x = (this.Width - w) / 2;
float y = (this.Height - h) / 2; float d = w;//直径
float r = d / 2;//半径 graphics.DrawEllipse(pen, new RectangleF(x, y, w, h));//绘制圆
接下来,我们需要计算圆的一周遍布的12个时间点。然后把这些时间点和圆心连在一起,就形成了上图我们看到的不同时间点的线段。圆心的查找非常简单,圆心的坐标点,其实就是x轴+半径r,y轴+半径r:
PointF pointEclipse = new PointF(x + r, y + r);
开始分表绘制12个点与圆心的连线,我这里是以9点为起点,此时,脑海中呈现这样的画面

时针一圈12格,每格也就是 Math.PI/6

比如我们计算10点在圆上的坐标P10.

10点所在的点,与x轴的夹角呈30度。那么10点在x上的坐标应该是,x1=x+r-r*Cos(30),以此类推,不难求出12个点的位置,具体代码如下:
/// <summary>
/// <![CDATA[画时刻线 这里是以9点这个时间坐标为起点 进行360度]]>
/// </summary>
/// <param name="graphics"><![CDATA[画布]]></param>
/// <param name="x"><![CDATA[圆x坐标]]></param>
/// <param name="y"><![CDATA[圆y坐标]]></param>
/// <param name="r"><![CDATA[圆x坐标]]></param>
private void DrawQuartzLine(Graphics graphics, float x, float y, float r)
{
//圆心
PointF pointEclipse = new PointF(x + r, y + r);
float labelX, labelY;//文本坐标
float angle = Convert.ToSingle(Math.PI / 6);//角度 30度
Font font = new Font(FontFamily.GenericSerif, 12);
float _x, _y;//圆上的坐标点
using (Brush brush = new System.Drawing.SolidBrush(Color.Red))
{
using (Pen pen = new Pen(Color.Black, 0.6f))
{
//一天12H,将圆分为12份
for (int i = 0; i <= 11; i++)
{
PointF p10;//圆周上的点
float pAngle = angle * i;
float x1, y1; //三、四象限
if (pAngle > Math.PI)
{
if ((pAngle - Math.PI) > Math.PI / 2)//钝角大于90度
{
//第三象限
x1 = Convert.ToSingle(r * Math.Cos(Math.PI * 2 - pAngle));
y1 = Convert.ToSingle(r * Math.Sin(Math.PI * 2 - pAngle));
_x = x + r - x1;
_y = y + r + y1;
labelX = _x - 8;
labelY = _y;
}
else
{
//第四象限
x1 = Convert.ToSingle(r * Math.Cos(pAngle - Math.PI));
y1 = Convert.ToSingle(r * Math.Sin(pAngle - Math.PI));
_x = x + r + x1;
_y = y + r + y1;
labelX = _x;
labelY = _y;
}
}
//一、二象限
else if (pAngle > Math.PI / 2)//钝角大于90度
{
//第一象限
x1 = Convert.ToSingle(r * Math.Cos(Math.PI - pAngle));
y1 = Convert.ToSingle(r * Math.Sin(Math.PI - pAngle));
_x = x + r + x1;
_y = y + r - y1;
labelX = _x;
labelY = _y - 20;
}
else
{
//第二象限
x1 = Convert.ToSingle(r * Math.Cos(pAngle));
y1 = Convert.ToSingle(r * Math.Sin(pAngle));
_x = x + r - x1;
_y = y + r - y1;
labelX = _x - 15;
labelY = _y - 20;
}
//上半圆 分成12份,每份 30度
if (i + 9 > 12)
{
graphics.DrawString((i + 9 - 12).ToString(), font, brush, labelX, labelY);
}
else
{
if (i + 9 == 9)
{
labelX = x - 13;
labelY = y + r - 6;
}
graphics.DrawString((i + 9).ToString(), font, brush, labelX, labelY);
}
p10 = new PointF(_x, _y);
graphics.DrawLine(pen, pointEclipse, p10);
}
}
}
}
为了辅助计算,我又添加了x轴与y轴的线,就是我们在效果图中看到的垂直于水平两条线段。
/// <summary>
/// <![CDATA[绘制象限]]>
/// </summary>
/// <param name="graphics"><![CDATA[画布]]></param>
/// <param name="x"><![CDATA[圆x坐标]]></param>
/// <param name="y"><![CDATA[圆y坐标]]></param>
/// <param name="r"><![CDATA[圆半径]]></param>
private void DrawQuadrant(Graphics graphics, float x, float y, float r)
{
float w = r * 2;
float extend = 100f;
using (Pen pen = new Pen(Color.Black, 1))
{
#region 绘制象限
PointF point1 = new PointF(x - extend, y + r);//
PointF point2 = new PointF(x + w + extend, y + r); PointF point3 = new PointF(x + r, y - extend);//
PointF point4 = new PointF(x + r, y + w + extend); graphics.DrawLine(pen, point1, point2); graphics.DrawLine(pen, point3, point4);
#endregion 绘制象限
} }
接下来,该绘制指针(时、分、秒),就是我们效果图中看到的,红绿蓝,三条长短不一的线段,秒针最长,这是和本地系统时间同步,所以要根据当前时间,计算出指针所在的位置。
/// <summary>
/// <![CDATA[绘制时、分、秒针]]>
/// </summary>
/// <param name="graphics"><![CDATA[画布]]></param>
/// <param name="x"><![CDATA[圆x坐标]]></param>
/// <param name="y"><![CDATA[圆y坐标]]></param>
/// <param name="r"><![CDATA[圆半径]]></param>
private void DrawQuartzShot(Graphics graphics, float x, float y, float r)
{
if (this.IsHandleCreated)
{
this.Invoke(new Action(() =>
{
//当前时间
DateTime dtNow = DateTime.Now;
int h = dtNow.Hour;
int m = dtNow.Minute;
int s = dtNow.Second;
float ha = Convert.ToSingle(Math.PI * 2 / 12);//每小时所弧度 360/12格=30
float hm = Convert.ToSingle(Math.PI * 2 / 60);
float hs = Convert.ToSingle(Math.PI * 2 / 60);
float x1, y1, offset = 60f;
using (Pen pen = new Pen(Color.Green, 4))
{
//时针
h = h >= 12 ? h - 12 : h;
double angle = h * ha;//当前时针所占弧度
x1 = x + r + Convert.ToSingle(Math.Sin(angle) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = y + r - Convert.ToSingle(Math.Cos(angle) * (r - offset));
//圆心
PointF pointEclipse = new PointF(x + r, y + r);
PointF pointEnd = new PointF(x1, y1); graphics.DrawLine(pen, pointEclipse, pointEnd);//画45度角 //分针
using (Pen penYellow = new Pen(Color.Red, 2))
{
offset = 30;
//分
double angelMinutes = hm * m;//每分钟弧度
x1 = x + r + Convert.ToSingle(Math.Sin(angelMinutes) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = y + r - Convert.ToSingle(Math.Cos(angelMinutes) * (r - offset));
graphics.DrawLine(penYellow, pointEclipse, new PointF(x1, y1));//画45度角
} //秒针
using (Pen penYellow = new Pen(Color.Blue, 2))
{
offset = 20;
//分
double angelSeconds = hs * s;//每秒钟弧度
x1 = x + r + Convert.ToSingle(Math.Sin(angelSeconds) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = y + r - Convert.ToSingle(Math.Cos(angelSeconds) * (r - offset));
graphics.DrawLine(penYellow, pointEclipse, new PointF(x1, y1));//画45度角
} } this.lblTime.Text = string.Format("当前时间:{0}:{1}:{2}", h, m, s);
})); }
}
最后,开辟一个线程,来同步更新时针的状态。
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Quartz_Load(object sender, EventArgs e)
{
timer = new Thread(() =>
{
if (_graphics == null)
{
_graphics = this.CreateGraphics();
_graphics.SmoothingMode = SmoothingMode.HighQuality; //高质量
_graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
}
while (true)
{
_graphics.Clear(this.BackColor);
DrawCaller(_graphics);
System.Threading.Thread.Sleep(1000);
}
});
timer.IsBackground = true;
}
每秒钟,更新一次,其实就是重绘。
完成了以上几个步骤,我们就完成GDI绘制时钟的工作,后来,把它封装成一个名为CSharpQuartz的对象,具体代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; /*=================================================================================================
*
* Title:C#开发的简易时钟
* Author:李朝强
* Description:模块描述
* CreatedBy:lichaoqiang.com
* CreatedOn:
* ModifyBy:暂无...
* ModifyOn:
* Company:河南天一文化传播股份有限公司
* Blog:http://www.lichaoqiang.com
* Mark:
*
*** ================================================================================================*/
namespace WinformGDIEvent.Sample
{ /// <summary>
/// <![CDATA[CSharpQuarz GDI时钟]]>
/// </summary>
public class CSharpQuartz : IDisposable
{ /// <summary>
/// 定时器
/// </summary>
private Thread timer = null; /// <summary>
/// X坐标
/// </summary>
public float X { get; private set; } /// <summary>
/// Y坐标
/// </summary>
public float Y { get; private set; } /// <summary>
/// 半径
/// </summary>
private float r; /// <summary>
/// 画布
/// </summary>
private Graphics Graphics = null; /// <summary>
/// 直径
/// </summary>
public float Diameter { get; private set; } /// <summary>
///
/// </summary>
public Form CurrentWinform { get; private set; } /// <summary>
///
/// </summary>
private EventHandler _OnChanged; /// <summary>
/// 事件,时钟状态更新后,当前频次1秒钟
/// </summary>
public event EventHandler OnChanged
{
add
{
this._OnChanged += value;
}
remove
{
this._OnChanged -= value;
}
} /// <summary>
/// 构造函数
/// </summary>
CSharpQuartz()
{
//
timer = new Thread((() =>
{
if (Graphics == null)
{
Graphics = CurrentWinform.CreateGraphics();//创建画布
Graphics.SmoothingMode = SmoothingMode.HighQuality; //高质量
Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
}
while (true)
{
//清除画布颜色,以窗体底色填充
Graphics.Clear(CurrentWinform.BackColor);
DrawCaller();//绘制时钟
//事件
if (_OnChanged != null) _OnChanged(this, null);
System.Threading.Thread.Sleep(1000);
}
}));
timer.IsBackground = true;
} /// <summary>
/// <![CDATA[构造函数]]>
/// </summary>
/// <param name="x"><![CDATA[圆x坐标]]></param>
/// <param name="y"><![CDATA[圆y坐标]]></param>
/// <param name="d"><![CDATA[圆直径]]></param>
public CSharpQuartz(Form form, float x, float y, float d)
: this()
{
this.CurrentWinform = form;
this.X = x;
this.Y = y;
this.Diameter = d;
r = d / 2;
} /// <summary>
///
/// </summary>
public void Start()
{
if (timer.IsAlive == false) timer.Start();//启动工作线程
} /// <summary>
/// 终止
/// </summary>
public void Stop()
{
if (timer.IsAlive == true) timer.Abort();//终止工作线程
} /// <summary>
/// <![CDATA[调用绘图]]>
/// </summary>
private void DrawCaller()
{
Graphics.SmoothingMode = SmoothingMode.HighQuality; //高质量
Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
using (Pen pen = new Pen(Color.Red, 2))
{
if (this.CurrentWinform.IsHandleCreated)
{
this.CurrentWinform.Invoke(new Action(() =>
{
//绘制圆
Graphics.DrawEllipse(pen, new RectangleF(X, Y, Diameter, Diameter)); //绘制象限
DrawQuadrant(); //绘制时、分、秒等针
DrawQuartzShot(); //绘制时刻线
DrawQuartzLine(); //写入版本信息
WriteVersion();
}));
}
}
} /// <summary>
/// <![CDATA[绘制象限]]>
/// </summary>
private void DrawQuadrant()
{
#region 绘制象限
float w = Diameter;
float extend = 100f;
using (Pen pen = new Pen(Color.Black, 1))
{ PointF point1 = new PointF(X - extend, Y + r);//
PointF point2 = new PointF(X + w + extend, Y + r); PointF point3 = new PointF(X + r, Y - extend);//
PointF point4 = new PointF(X + r, Y + w + extend); Graphics.DrawLine(pen, point1, point2); Graphics.DrawLine(pen, point3, point4); }
#endregion 绘制象限
} /// <summary>
/// <![CDATA[绘制时、分、秒针]]>
/// </summary>
private void DrawQuartzShot()
{
//当前时间
DateTime dtNow = DateTime.Now;
int h = dtNow.Hour;
int m = dtNow.Minute;
int s = dtNow.Second;
float ha = Convert.ToSingle(Math.PI * 2 / 12);//每小时所弧度 360/12格=30
float radian = Convert.ToSingle(Math.PI * 2 / 60);//分秒偏移弧度
float x1, y1, offset = 60f;
using (Pen pen = new Pen(Color.Green, 4))
{
//时针
h = h >= 12 ? h - 12 : h;
double angle = h * ha;//当前时针所占弧度
x1 = X + r + Convert.ToSingle(Math.Sin(angle) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = Y + r - Convert.ToSingle(Math.Cos(angle) * (r - offset));
//圆心
PointF pointEclipse = new PointF(X + r, Y + r);
PointF pointEnd = new PointF(x1, y1); Graphics.DrawLine(pen, pointEclipse, pointEnd);//画45度角 //分针
using (Pen penYellow = new Pen(Color.Red, 2))
{
offset = 30;//与分针长度成反比
//分
double angelMinutes = radian * m;//每分钟弧度
x1 = X + r + Convert.ToSingle(Math.Sin(angelMinutes) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = Y + r - Convert.ToSingle(Math.Cos(angelMinutes) * (r - offset));
Graphics.DrawLine(penYellow, pointEclipse, new PointF(x1, y1));//画45度角
} //秒针
using (Pen penYellow = new Pen(Color.Blue, 2))
{
offset = 20;
//分
double angelSeconds = radian * s;//每秒钟弧度
x1 = X + r + Convert.ToSingle(Math.Sin(angelSeconds) * (r - offset));//通过调整offset的大小,可以控制时针的长短
y1 = Y + r - Convert.ToSingle(Math.Cos(angelSeconds) * (r - offset));
Graphics.DrawLine(penYellow, pointEclipse, new PointF(x1, y1));//画45度角
}
}
} /// <summary>
/// <![CDATA[绘制时刻线]]>
/// </summary>
private void DrawQuartzLine()
{
//圆心
PointF pointEclipse = new PointF(X + r, Y + r);
float labelX, labelY;//文本坐标
float angle = Convert.ToSingle(Math.PI / 6);//角度 30度
using (Font font = new Font(FontFamily.GenericSerif, 12))
{
float _x, _y;//圆上的坐标点
using (Brush brush = new System.Drawing.SolidBrush(Color.Red))
{
using (Pen pen = new Pen(Color.Black, 0.6f))
{
//一天12H,将圆分为12份
for (int i = 0; i <= 11; i++)
{
PointF p10;//圆周上的点
float pAngle = angle * i;
float x1, y1; //三、四象限
if (pAngle > Math.PI)
{
if ((pAngle - Math.PI) > Math.PI / 2)//钝角大于90度
{
//第三象限
x1 = Convert.ToSingle(r * Math.Cos(Math.PI * 2 - pAngle));
y1 = Convert.ToSingle(r * Math.Sin(Math.PI * 2 - pAngle));
_x = X + r - x1;
_y = Y + r + y1;
labelX = _x - 8;
labelY = _y;
}
else
{
//第四象限
x1 = Convert.ToSingle(r * Math.Cos(pAngle - Math.PI));
y1 = Convert.ToSingle(r * Math.Sin(pAngle - Math.PI));
_x = X + r + x1;
_y = Y + r + y1;
labelX = _x;
labelY = _y;
}
}
//一、二象限
else if (pAngle > Math.PI / 2)//钝角大于90度
{
//第一象限
x1 = Convert.ToSingle(r * Math.Cos(Math.PI - pAngle));
y1 = Convert.ToSingle(r * Math.Sin(Math.PI - pAngle));
_x = X + r + x1;
_y = Y + r - y1;
labelX = _x;
labelY = _y - 20;
}
else
{
//第二象限
x1 = Convert.ToSingle(r * Math.Cos(pAngle));
y1 = Convert.ToSingle(r * Math.Sin(pAngle));
_x = X + r - x1;
_y = Y + r - y1;
labelX = _x - 15;
labelY = _y - 20;
}
//上半圆 分成12份,每份 30度
if (i + 9 > 12)
{
Graphics.DrawString((i + 9 - 12).ToString(), font, brush, labelX, labelY);
}
else
{
if (i + 9 == 9)
{
labelX = X - 13;
labelY = Y + r - 6;
}
Graphics.DrawString((i + 9).ToString(), font, brush, labelX, labelY);
}
p10 = new PointF(_x, _y);
Graphics.DrawLine(pen, pointEclipse, p10);
}
}
}
}
} /// <summary>
/// <![CDATA[写入版本信息]]>
/// </summary>
private void WriteVersion()
{
PointF point = new PointF(X + r / 4, Y + r - 30);
using (Font font = new Font(FontFamily.GenericSansSerif, 18))
{
using (Brush brush = new SolidBrush(Color.Black))
{
this.Graphics.DrawString("Quartz", font, brush, point);
}
}
} /// <summary>
/// <![CDATA[释放]]>
/// </summary>
/// <param name="isDispose"></param>
private void Dispose(bool isDispose)
{
if (isDispose)
{
timer.Abort();
this.Graphics.Dispose();
}
} /// <summary>
///
/// </summary>
public void Dispose()
{
this.Dispose(true);
}
}
}
winfom调用示例
/// <summary>
///
/// </summary>
private CSharpQuartz sharpQuartz = null; /// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CSharpQuartzSample_Load(object sender, EventArgs e)
{
float w = 300f, h = 300f;
float x = (this.Width - w) / 2;
float y = (this.Height - h) / 2;
sharpQuartz = new CSharpQuartz(this, x, y, w);
sharpQuartz.OnChanged += SharpQuartz_OnChanged;
sharpQuartz.Start();
} /// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SharpQuartz_OnChanged(object sender, EventArgs e)
{
if (lblTime.IsHandleCreated)
{
lblTime.Invoke(new Action(() =>
{
lblTime.Text = DateTime.Now.ToString("当前时间:HH:mm:ss");
}));
}
}
这就是我们开篇第一张效果图,带有Quartz字样的,至此,关于GDI绘制时钟与系统时间同步的小程序就这样完成。时间仓促,某些计算方法买来得及仔细推敲,不足之处,大家多提意见。
GDI绘制时钟效果,与系统时间保持同步,基于Winform的更多相关文章
- 如何解决Ubuntu与Windows双系统时间不同步
导读 不知道有没朋友跟我一样是 Ubuntu 和 Windows 双系统?今天有朋友问到我,当他从 Ubuntu 系统重新启动到 Windows 时,会发现 Windows 中的时间变了,他问我有没办 ...
- [2014.5.22][UBUNTU]Ubuntu与Windows系统时间不同步的问题
安装Ubuntu+Windows双系统时会遇到Windows和Ubuntu系统时间不同步的问题,这是由于Windows系统默认读取主板bios等硬件系统时间作为OS的当地时间;而MAc,Linux类的 ...
- linux 修改系统时间 同步网络时间
一.date命令 date -s time 修改系统时钟时间为time 设置时间和日期 例如:将系统日期设定成2018年6月8日的命令 命令 : "date -s 06/08/2018&q ...
- Gentoo解决Windows双系统时间不同步的问题
升级后的gentoo不再使用/etc/conf.d/clock,而是使用/etc/conf.d/hwclock来设置和时间相关了. 在/etc/conf.d/hwclock文件中设置系统时间为本地时间 ...
- centos 系统时间的同步
1.当你的网站架构涉及到多台服务器的时候,服务器之间的时间必须得同步,这样就涉及到了程序的时间的准确性问题,特别是跟时间相关的操作和系统本身的定时任务. 2.时间同步工具:ntpdate,安装方式:y ...
- 【转载】linux系统时间自动同步:ntp
NTP基本介绍 NTP(Network TimeProtocol,网络时间协议),使用来使本地机器与服务端机器时间保持同步的一种协议.如果我们只有一台机器那么只需要安装NTP客户端ntpdate这个包 ...
- 解决Ubuntu与Windows双系统时间不同步问题
目录 1.Windows修改法 1.1设置UTC 1.2恢复LocalTime 2.Ubuntu修改法 2.1设置LocalTime 2.2恢复UTC 切换系统后,往往发现时间差了8小时.这恰恰是北京 ...
- 解决:Win 10 + Mint 18双系统时间不同步,更换系统启动项顺序
1.win10 & mint 18双系统时间同步: 先打开终端下更新一下时间,确保时间无误: sudo apt-get install ntpdate sudo ntpdate time.wi ...
- 修改linux系统时间和同步
date 查看当前时间 date -s 15:14:13 修改时间 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 修改时区 yes cront ...
随机推荐
- c语言中的转义序列
c中的输出函数printf()可以带以下的转义序列,不同的转义序列会得到不同的结果. 1.\a:警报 2.\b:退格(光标回退一格)3.\f:换页4.\n:换行(光标去到下一行的起始处)5.\r:回车 ...
- python中星号的意义(**字典,*列表或元组)
传递实参和定义形参(所谓实参就是调用函数时传入的参数,形参则是定义函数是定义的参数)的时候,你还可以使用两个特殊的语法:*.** . 调用函数时使用* ,** test(*args)中 * 的作用:其 ...
- java多线程(一)-概述
最近这段在看java多线程编程方面的东西.所以特写了几篇文章,来总结和回顾一下自己所学习到的相关知识.因为水平有限,文章中总结不全面甚至理解错误的地方,欢迎读者指点批评. 我们平时所接触到的程序,都是 ...
- android之monkey测试
本文同时发表于本人个人网站 www.yaoxiaowen.com monkey测试算是android自动化测试当中最简单的一种工具了.虽然简单,不过对于测试app的稳定健壮,减少崩溃还是比较有用的.所 ...
- Lucene.net(4.8.0) 学习问题记录二: 分词器Analyzer中的TokenStream和AttributeSource
前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...
- 微信小程序之注册和入门
一.注册 首先,在微信公众平台mp.weixin.qq.com上注册一个帐号. 小程序开放个人开发者申请注册,个人用户可访问微信公众平台,扫码验证个人身份后即可完成小程序帐号申请并进行代码开发. 这里 ...
- sqlalchemy 踩过的坑
记录下Sqlalchemy遇到的问题,不定时更新. 设置主键为非自增 sqlalchemy 在sql server中默认主键是自增的,如果在数据库设置的主键不是自增的,这个时候插入就会出现异常: 提示 ...
- php 常量const
常量使用关键词const修饰,一经定义,不能改变 常量的使用规则 定义后,应该马上赋初始值 不能用public.private.protected修饰 在本类,可用self::name 类名::na ...
- JQuery 网页瞄点
$("html,body").animate({ scrollTop: $("#Content1").offset().top }, 3000); 代码说明:h ...
- 【转】Install libimobiledevice on Mac OSX
About the App App name: libimobiledevice App description: Library to communicate with iOS devices na ...