C#中Winform程序中如何实现多维表头【不通过第三方报表程序】
问题:C#中Winform程序中如何实现多维表头。
在网上搜了很多方法,大多数方法对于我这种新手,看的都不是很懂。最后在新浪博客看到了一篇比较易懂的文章:【DataGridView二维表头与合并单元格】
大体的思路如下:
1.新建一个项目:
2.右键项目名称添加一个组件名为:HeaderUnitView.cs
3.点击【单击此处切换到代码视图】代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Design;
using System.Diagnostics; namespace WindowsFormsApplication1
{
public partial class HeaderUnitView : DataGridView
{
private TreeView[] _columnTreeView;
private ArrayList _columnList = new ArrayList();
private int _cellHeight = 17; public int CellHeight
{
get { return _cellHeight; }
set { _cellHeight = value; }
}
private int _columnDeep = 1; private bool HscrollRefresh = false;
/// <summary>
/// 水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误
/// </summary>
[Description("水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误")]
public bool RefreshAtHscroll
{
get { return HscrollRefresh; }
set { HscrollRefresh = value; }
} /// <summary>
/// 构造函数
/// </summary>
public HeaderUnitView()
{
InitializeComponent();
this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
//设置列高度显示模式
} public HeaderUnitView(IContainer container)
{
container.Add(this); InitializeComponent();
} [Description("设置或获得合并表头树的深度")]
public int ColumnDeep
{
get
{
if (this.Columns.Count == 0)
_columnDeep = 1; this.ColumnHeadersHeight = _cellHeight * _columnDeep;
return _columnDeep;
} set
{
if (value < 1)
_columnDeep = 1;
else
_columnDeep = value;
this.ColumnHeadersHeight = _cellHeight * _columnDeep;
}
} [Description("添加合并式单元格绘制的所需要的节点对象")]
public TreeView[] ColumnTreeView
{
get { return _columnTreeView; }
set
{
if (_columnTreeView != null)
{
for (int i = 0; i <= _columnTreeView.Length - 1; i++)
_columnTreeView[i].Dispose();
}
_columnTreeView = value;
}
} [Description("设置添加的字段树的相关属性")]
public TreeView ColumnTreeViewNode
{
get { return _columnTreeView[0]; }
} /// <summary>
/// 设置或获取合并列的集合
/// </summary>
[MergableProperty(false)]
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
[Localizable(true)]
[Description("设置或获取合并列的集合"), Browsable(true), Category("单元格合并")]
public List<string> MergeColumnNames
{
get
{
return _mergecolumnname;
}
set
{
_mergecolumnname = value;
}
}
private List<string> _mergecolumnname = new List<string>(); public ArrayList NadirColumnList
{
get
{
if (_columnTreeView == null)
return null; if (_columnTreeView[0] == null)
return null; if (_columnTreeView[0].Nodes == null)
return null; if (_columnTreeView[0].Nodes.Count == 0)
return null; _columnList.Clear();
GetNadirColumnNodes(_columnList, _columnTreeView[0].Nodes[0], false);
return _columnList;
}
}
///<summary>
///绘制合并表头
///</summary>
///<param name="node">合并表头节点</param>
///<param name="e">绘图参数集</param>
///<param name="level">结点深度</param>
///<remarks></remarks>
public void PaintUnitHeader(
TreeNode node,
System.Windows.Forms.DataGridViewCellPaintingEventArgs e,
int level)
{
//根节点时退出递归调用
if (level == 0)
return; RectangleF uhRectangle;
int uhWidth;
SolidBrush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backColorBrush = new SolidBrush(e.CellStyle.BackColor);
Pen gridLinePen = new Pen(gridBrush);
StringFormat textFormat = new StringFormat(); textFormat.Alignment = StringAlignment.Center; uhWidth = GetUnitHeaderWidth(node); if (node.Nodes.Count == 0)
{
uhRectangle = new Rectangle(e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight * (_columnDeep - node.Level) - 1);
}
else
{
uhRectangle = new Rectangle(
e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight - 1);
} //画矩形
e.Graphics.FillRectangle(backColorBrush, uhRectangle); //划底线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Left
, uhRectangle.Bottom
, uhRectangle.Right
, uhRectangle.Bottom);
//划右端线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Right
, uhRectangle.Top
, uhRectangle.Right
, uhRectangle.Bottom);
////写字段文本 e.Graphics.DrawString(node.Text, this.Font
, new SolidBrush(e.CellStyle.ForeColor)
, uhRectangle.Left + uhRectangle.Width / 2 -
e.Graphics.MeasureString(node.Text, this.Font).Width / 2 - 1
, uhRectangle.Top +
uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.Font).Height / 2);
//递归调用()
if (node.PrevNode == null)
if (node.Parent != null)
PaintUnitHeader(node.Parent, e, level - 1);
}
/// <summary>
/// 获得合并标题字段的宽度
/// </summary>
/// <param name="node">字段节点</param>
/// <returns>字段宽度</returns>
/// <remarks></remarks>
private int GetUnitHeaderWidth(TreeNode node)
{
//获得非最底层字段的宽度 int uhWidth = 0;
//获得最底层字段的宽度
if (node.Nodes == null)
return this.Columns[GetColumnListNodeIndex(node)].Width; if (node.Nodes.Count == 0)
return this.Columns[GetColumnListNodeIndex(node)].Width; for (int i = 0; i <= node.Nodes.Count - 1; i++)
{
uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes[i]);
}
return uhWidth;
} /// <summary>
/// 获得底层字段索引
/// </summary>
///' <param name="node">底层字段节点</param>
/// <returns>索引</returns>
/// <remarks></remarks>
private int GetColumnListNodeIndex(TreeNode node)
{
for (int i = 0; i <= _columnList.Count - 1; i++)
{
if (((TreeNode)_columnList[i]).Equals(node))
return i;
}
return -1;
} /// <summary>
/// 获得底层字段集合
/// </summary>
/// <param name="alList">底层字段集合</param>
/// <param name="node">字段节点</param>
/// <param name="checked">向上搜索与否</param>
/// <remarks></remarks>
private void GetNadirColumnNodes(
ArrayList alList,
TreeNode node,
Boolean isChecked)
{
if (isChecked == false)
{
if (node.FirstNode == null)
{
alList.Add(node);
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
}
if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
else
{
if (node.FirstNode != null)
{
GetNadirColumnNodes(alList, node.FirstNode, false);
return;
}
}
}
else
{
if (node.FirstNode == null)
{
return;
}
else
{
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
} if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
}
}
/// <summary>
/// 滚动
/// </summary>
/// <param name="e"></param>
protected override void OnScroll(ScrollEventArgs e)
{
bool scrollDirection = (e.ScrollOrientation == ScrollOrientation.HorizontalScroll);
base.OnScroll(e);
if (RefreshAtHscroll && scrollDirection)
this.Refresh();
} /// <summary>
/// 列宽度改变的重写
/// </summary>
/// <param name="e"></param>
protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
{
Graphics g = Graphics.FromHwnd(this.Handle);
float uwh = g.MeasureString(e.Column.HeaderText, this.Font).Width;
if (uwh >= e.Column.Width) { e.Column.Width = Convert.ToInt16(uwh); }
base.OnColumnWidthChanged(e);
} /// <summary>
/// 单元格绘制(重写)
/// </summary>
/// <param name="e"></param>
/// <remarks></remarks>
protected override void OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
{
try
{
if (e.RowIndex > -1 && e.ColumnIndex > -1)
{
DrawCell(e);
}
else
{
//行标题不重写
if (e.ColumnIndex < 0)
{
base.OnCellPainting(e);
return;
} if (_columnDeep == 1)
{
base.OnCellPainting(e);
return;
} //绘制表头
if (e.RowIndex == -1)
{
if (e.ColumnIndex >= NadirColumnList.Count) { e.Handled = true; return; }
PaintUnitHeader((TreeNode)NadirColumnList[e.ColumnIndex]
, e
, _columnDeep);
e.Handled = true;
}
}
}
catch
{ }
} #region 合并单元格
/// <summary>
/// 画单元格
/// </summary>
/// <param name="e"></param>
private void DrawCell(DataGridViewCellPaintingEventArgs e)
{
if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet)
{
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
Brush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor);
SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
int cellwidth;
//上面相同的行数
int UpRows = 0;
//下面相同的行数
int DownRows = 0;
//总行数
int count = 0;
if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -1)
{
cellwidth = e.CellBounds.Width;
Pen gridLinePen = new Pen(gridBrush);
string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? "" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim();
if (!string.IsNullOrEmpty(curValue))
{
#region 获取下面的行数
for (int i = e.RowIndex; i < this.Rows.Count; i++)
{
if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
{
//this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected; DownRows++;
if (e.RowIndex != i)
{
cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
}
}
else
{
break;
}
}
#endregion
#region 获取上面的行数
for (int i = e.RowIndex; i >= 0; i--)
{
if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
{
//this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
UpRows++;
if (e.RowIndex != i)
{
cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
}
}
else
{
break;
}
}
#endregion
count = DownRows + UpRows - 1;
if (count < 2)
{
return;
}
}
if (this.Rows[e.RowIndex].Selected)
{
backBrush.Color = e.CellStyle.SelectionBackColor;
fontBrush.Color = e.CellStyle.SelectionForeColor;
}
//以背景色填充
e.Graphics.FillRectangle(backBrush, e.CellBounds);
//画字符串
PaintingFont(e, cellwidth, UpRows, DownRows, count);
if (DownRows == 1)
{
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
count = 0;
}
// 画右边线
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom); e.Handled = true;
}
}
/// <summary>
/// 画字符串
/// </summary>
/// <param name="e"></param>
/// <param name="cellwidth"></param>
/// <param name="UpRows"></param>
/// <param name="DownRows"></param>
/// <param name="count"></param>
private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count)
{
SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
int cellheight = e.CellBounds.Height; if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1));
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1));
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1));
}
else
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
}
}
#endregion
}
}
4.为窗体Form1添加控件(组件)HeaderUnitView:
5.控件的设置:
A、通过属性设置
(1)设置ColumnHeadersHeightSizeMode属性为:DisableResizing
(2)编辑列
(3)设置ColumnDeep属性为:2;设置CellHeight和ColumnHeadersHeight属性 (设置一个值)
(4)设置ColumnTreeView属性,添加TreeView
(5)设置ColumnTreeViewNode属性,为TreeView添加节点。
(6)设置RefreshAtHscroll属性为True。
(7)利用DataGridView方法绑定所要显示的数据即可
B、通过代码设置
//添加列
DataGridViewTextBoxColumn tcDM = newDataGridViewTextBoxColumn();
tcDM.HeaderText = "班级代码";
tcDM.Name = "DM";
//tcDM.DataPropertyName = "DM";
tcDM.ReadOnly = true;
//tcDM.SortMode =DataGridViewColumnSortMode.NotSortable;
//tcDM.DefaultCellStyle.Alignment =DataGridViewContentAlignment.MiddleCenter;
dgv.Columns.Add(tcDM); DataGridViewTextBoxColumn tcMC = newDataGridViewTextBoxColumn();
tcMC.HeaderText = "班级名称";
tcMC.Name = "MC";
tcMC.ReadOnly = true;
dgv.Columns.Add(tcMC);
DataGridViewTextBoxColumn tcNan = newDataGridViewTextBoxColumn();
tcNan.HeaderText = "男";
tcNan.Name = "Nan";
tcNan.ReadOnly = true;
dgv.Columns.Add(tcNan);
DataGridViewTextBoxColumn tcNv = newDataGridViewTextBoxColumn();
tcNv.HeaderText = "女";
tcNv.Name = "Nv";
tcNv.ReadOnly = true;
dgv.Columns.Add(tcNv);
//增加TreeView
TreeView tv = new TreeView();
TreeNode tnDM = new TreeNode("班级代码");
tv.Nodes.Add(tnDM);
TreeNode tnMC = new TreeNode("班级名称");
tv.Nodes.Add(tnMC);
TreeNode tnSex = new TreeNode("性别");
tv.Nodes.Add(tnSex);
TreeNode tnNan = new TreeNode("男");
tnSex.Nodes.Add(tnNan);
TreeNode tnNv = new TreeNode("女");
tnSex.Nodes.Add(tnNv);
dgv.ColumnTreeView = new TreeView[] { tv };
//设置其他属性
dgv.AutoGenerateColumns =false; //不自动增加列
dgv.RowHeadersVisible =false; //行头不可见
dgv.AllowUserToAddRows = false;
dgv.RowTemplate.DefaultCellStyle.Alignment =DataGridViewContentAlignment.MiddleCenter;
dgv.ColumnHeadersHeightSizeMode =DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dgv.ColumnDeep = 2;
dgv.CellHeight = 25;
dgv.ColumnHeadersHeight = 50;
dgv.RefreshAtHscroll = true;
三、添加一条数据
dgv.Rows.Add(); //添加行
dgv.Rows[0].Cells["DM"].Value= "2003001";
dgv.Rows[0].Cells["MC"].Value= "网络一班"; ;
dgv.Rows[0].Cells["Nan"].Value= "26人";
dgv.Rows[0].Cells["Nv"].Value= "18人";
四、合并单元格
headerUnitView1.MergeColumnNames.Add("Column11");//Column11需要合并单元格的列
如果有三层表头就把ColumnDeep改成3,,依次...
C#中Winform程序中如何实现多维表头【不通过第三方报表程序】的更多相关文章
- C#中WinForm窗体事件的执行次序
C#中WinForm窗体事件的执行次序如下: 当 Windows Form 应用程序启动时,会以下列顺序引发主要表单的启动事件: System.Windows.Forms.Control ...
- 在DevExpress程序中使用Winform分页控件直接录入数据并保存
一般情况下,我们都倾向于使用一个组织比较好的独立界面来录入或者展示相关的数据,这样处理比较规范,也方便显示比较复杂的数据.不过在一些情况下,我们也可能需要直接在GridView表格上直接录入或者修改数 ...
- 在Winform程序中设置管理员权限及为用户组添加写入权限
在我们一些Winform程序中,往往需要具有一些特殊的权限才能操作系统文件,我们可以设置运行程序具有管理员权限或者设置运行程序的目录具有写入的权限,如果是在操作系统里面,我们可以设置运行程序以管理员身 ...
- 【转】C#中WinForm程序退出方法技巧总结
C#中WinForm程序退出方法技巧总结 一.关闭窗体 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.Ex ...
- C#将exe运行程序嵌入到自己的winform窗体中
以下例子是将Word打开,然后将它嵌入到winform窗体中,效果如下图:C将exe运行程序嵌入到自己的winform窗体中 - kingmax_res - iSport注意:该方法只适用于com的e ...
- C#中WinForm程序退出方法技巧总结(转)
本文实例总结了C#中WinForm程序退出方法技巧.分享给大家供大家参考.具体分析如下: 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit ...
- (转)在Winform程序中设置管理员权限及为用户组添加写入权限
本文转载自:http://www.cnblogs.com/wuhuacong/p/5645172.html 在我们一些Winform程序中,往往需要具有一些特殊的权限才能操作系统文件,我们可以设置运行 ...
- WinForm程序中两份mdf文件问题的解决
在项目中用程序中嵌入mdf文件的方式来进行SQLServer数据库开发非常方便,用来发布开源项目等很方便,点击就可以运行,免部署,特别是在教学中用起来更加方便,老师不用先将数据库文件detach再发给 ...
- C#中WinForm程序退出方法技巧总结
C#中WinForm程序退出方法技巧总结 一.关闭窗体 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.Ex ...
随机推荐
- spring mvc静态资源访问的配置
如果我们使用spring mvc来做web访问请求的控制转发,那么默认所有访问都将被DispatcherServlet独裁统治.比如我现在想访问的欢迎页index.html根本无需任何业务逻辑处理,仅 ...
- android之Notification通知
我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的. pac ...
- Git&Repo 命令大全 ***
首先理解几个基本概念: origin:默认远程版本库: master:默认开发分支: 查看本地更新状态: git status jiangzhaowei@ubuntu$ git status # On ...
- PL/SQL 训练04--事务
--pl/sql通过SQL和ORACLE数据库紧密的整合在一起--在pl/sql中可以执行任何操作语句(DML语句),包括INSERT,UPDATE,DELETE,MERGE,也包括查询语句--可否执 ...
- mysql 常见参数
my.cnf[client] 对mysql的所有客端都生效的[mysql] 只对mysql这个命令有效了[mysqd][mysqld_multi] 多实例启动[mysqld_safe][mysqldN ...
- JS,JQUERY 常用笔记
JSON.parse() 转成数组对象 JSON.stringify() 转成JSON字符串
- 前端自动化之gulp
前端自动化之gulp 前题:1.安装好nodejs环境,或者nvm 2.安装npm包管理工具 简介: 可以自动的将开发阶段的代码进行压缩.合并.编译.加密等处理,生成项目提交的代码. 使用: gulp ...
- 升级到Win10 周年更新版
尝试过强制刷更新,但是没用,最近微软才跟我的机器推送周年更新,于是更新. 花费了些时间更新,之前网上有的那些诗句,亲眼看看还是蛮有意思的. 但是更新完了后,explorer 一直出错,有闪退(闪屏)一 ...
- web页面在ios下不支持fixed可用absolute替代的方案
本文引用出处:http://www.cnblogs.com/PeunZhang/p/3553020.html. 对于 ios4 和 android2.2 以下不支持 position:fixed 的问 ...
- node.js开发指南读书笔记(1)
3.1 开始使用Node.js编程 3.1.1 Hello World 将以下源代码保存到helloworld.js文件中 console.log('Hello World!'); console.l ...