本文基础:

C#+OpenGL编程之OpenGL 纹理载入

C#+OpenGL编程之OpenGL 多重纹理

小桃子The Tao FrameworkTao提供的所有库都是完全开源的。其中的多数库都可以免费用在商业项目中,该框架较其它框架实现更简单、容易,代码也简洁易读。

很遗憾的是这个框架已经不再开发了,作为程序猿不得不想点其他的框架了。

下面的课程,我们将使用另外一个框架,OpenGL DotNet 官方网站:http://www.taylaninan.com/opengl-dotnet

作为我们的开发框架,比起 小桃子的后继者OpenTK更接近C代码风格,要知道,做什么事都要跟随大流。现在市面上的游戏引擎都是C或者C++,而很多OpenGL教程也是基于C或者C++,标新立异等于在装酷。

首先我们实现最早的基础实例吧:

using System;
using System.Collections.Generic;
using System.Text;
using OpenGLDotNet; namespace OpenGLTK
{
///OpenGLDotNet需要修改
///glut32.dll ->freeglut.dll
///GLUT最初是《OpenGL红皮书(第二版)》[注2]中的示例程序。自那以后,GLUT简单、跨平台的特点,使其在各种实际应用中广泛应用。
///目前最后版本GLUT v3.7的历史可追溯至1998年8月,且该项目似乎已经被废弃。它的许可证禁止任何人发布修改后的库代码。
///毋庸置疑GLUT已经很老了,真的需要改善。此外,GLUT的许可证与一些软件发行不兼容(如XFree86的)。
///一个轻量级的,开源的,跨平台的library。支持OpenGL及OpenGL ES,用来管理窗口,读取输入,处理事件等。因为OpenGL没有窗口管理的功能,所以很多热心的人写了工具来支持这些功能,比如早期的glut,现在的freeglut等。
///修改代码位置 GLU.Functions.cs ///找不到glu32.dll解决方法:
///glu32.dll 改为->GLU32.dll,具体文件名大小写可以去 系统目录搜索这个文件我的是server2012
///修改代码位置 GLUT.Functions.cs ///tao->OpenGLDotNet 需要修改的地方
///函数去掉glu和gl部分,例如
///GL.glPopMatrix();->GL.PopMatrix();
///Gl.gl->GL.
///Gl.GL_->GL.GL_
/// Glu.glu->GLU.
///当然你可以修改源代码private ->public
///修改代码位置 GL.CoreDelegates.cs /// <summary>
/// 第二章 Opengl程序框架 C# by 大师♂罗莊
///
/// </summary>
class Examplefirst : IDisposable
{
String title = "第二章 Opengl程序框架";
///窗口大小
internal int windowWidth, windowHeight; //当前帧
internal float currentTime, startTime; //鼠标位置
internal int mouseX, mouseY, button, state;
//键盘按下 internal byte key;
public Examplefirst()
{
GLConfig.Init(, , title, , , , );
GL.Init(true);
GLUT.KeyboardFunc(Keyboard);
GLUT.MouseFunc(Mouse);
GLUT.IdleFunc(Idle);
GLUT.ReshapeFunc(Reshape);
GLUT.MotionFunc(Motion);
GLUT.DisplayFunc(Display);
} /// <summary>
/// glut键盘回调函数
/// </summary>
/// <param name="key"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public virtual void Keyboard(byte key, int x, int y)
{
this.key = key;
} /// <summary>
/// glut鼠标按下与释放回调函数
/// </summary>
/// <param name="button"></param>
/// <param name="state"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public virtual void Mouse(int button, int state, int x, int y)
{ this.button = button;
this.state = state;
this.mouseX = x;
this.mouseY = y;
return;
} /// <summary>
/// glut空闲处理回调函数
/// </summary>
public void Idle()
{
currentTime = System.Environment.TickCount;
Update(currentTime - startTime);
startTime = currentTime;
return;
} /// <summary>
/// glut窗口重置回调函数
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
public void Reshape(int width, int height)
{
windowWidth = width;
windowHeight = height;
//防止除零问题
windowHeight = windowWidth > ? windowHeight : ;
InitGL(windowWidth, windowHeight); } /// <summary>
/// glut鼠标移动回调函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public void Motion(int x, int y)
{
return;
} /// <summary>
/// glut描绘回调函数
/// </summary>
public void Display()
{
//我感觉用这个得重新设置下lookUP才行
iniView(windowWidth, windowHeight);
DrawGLScene(); } /// <summary>
/// 入口点
/// </summary>
public void Run()
{
GLUT.MainLoop();
} /// <summary>
/// 更新用
/// </summary>
public virtual void Update(float milliseconds)
{
if (key == ) // Escape 按下,退出
{
this.Dispose();
}
return;
} /// <summary>
/// 原书的初始化方法,C# by 大师♂罗莊
/// </summary>
/// <param name="windowWidth">窗口宽</param>
/// <param name="windowHeight">窗口高</param>
/// <returns></returns>
Boolean InitGL(int windowWidth, int windowHeight)
{
// 设置视口 viewport
GL.Viewport(, , windowWidth, windowHeight); //启用阴影平滑
GL.ShadeModel(GL.GL_SMOOTH); //启用反走样
GL.Hint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // 设置投影模式 projection matrix
GL.MatrixMode(GL.GL_PROJECTION);
GL.LoadIdentity();
GL.Disable(GL.GL_DITHER);
return true;
}
/// <summary>
/// 初始化视口投影,本例子没有采用原书例子,自定义的视口
/// </summary>
public virtual void iniView(int windowWidth, int windowHeight)
{
GLU.Perspective(, windowWidth / (double)windowHeight, , );
// 选择模型观察矩阵 modelview matrix
GL.MatrixMode(GL.GL_MODELVIEW);
//重置模型观察矩阵
GL.LoadIdentity();
GLU.LookAt(, , , // 眼睛位置
, , , // 观察点
, , ); // 怎么看
} /// <summary>
/// 原书的绘制方法 C# by 大师♂罗莊
/// <param name="currentTime">当前帧</param>
/// </summary>
public virtual void DrawGLScene()
{
// 重置黑色背景
GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL.Clear(GL.GL_COLOR_BUFFER_BIT);
// 画三角形
GL.Translatef(, , );
GL.Begin(GL.GL_TRIANGLES);
GL.Color3f(, , );
GL.Vertex3f(-, , -);
GL.Color3f(, , );
GL.Vertex3f(, , -);
GL.Color3f(, , );
GL.Vertex3f(, , );
GL.End();
GLUT.SwapBuffers();
} public void Dispose()
{
GLUT.KeyboardFunc(null);
GLUT.MouseFunc(null);
GLUT.IdleFunc(null);
GLUT.ReshapeFunc(null);
GLUT.MotionFunc(null);
GLUT.DestroyWindow(GLUT.GetWindow());
}
}
}

OpenGL DotNet也非十全十美,需要我们修改源代码:

1、首先一个问题就是使用glut32.dll,这个库已经是上个世纪的库了,我们需要修改GLU.Functions.cs 里面把glut32.dll改为freeglut.dll

2、找不到glu32.dll,这个要大家自己去windows目录看文件名大小写,在我的2012上面文件名为GLU32.dll

然后就可以把桃子框架代码移植过来了。

上面的代码就和C很相似了,使用GLUT函数实现窗口管理,代码量从160行升至220行。

下面我们移植下多重纹理吧。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using OpenGLDotNet; namespace OpenGLTK
{
/// <summary>
/// 自制的纹理载入类 C# by 大师♂罗莊
/// </summary>
class TextureLoad : IDisposable
{
public uint[] ID = new uint[];
Bitmap image;
public bool Load(String fileName)
{
///原则上材质只应该在初始化时候载入一次,否则会影响性能
if (image != null)
{
return true;
}
FileInfo file = new FileInfo(fileName);
if (file.Exists == false)
{
MessageBox.Show("无法载入" + fileName);
return false;
}
try
{
if (file.Extension.ToUpper() == ".TGA")
{
///http://blog.csdn.net/zgke/article/details/4667499
///C# 载入TGA 类,自行参考,这里不再列出
ImageTGA tga = new ImageTGA(fileName);
image = tga.Image;
}
else
{
image = new Bitmap(fileName);
} }
catch (System.ArgumentException)
{
MessageBox.Show("无法载入" + fileName);
return false;
} if (image != null)
{
image.RotateFlip(RotateFlipType.RotateNoneFlipY);
System.Drawing.Imaging.BitmapData bitmapdata;
Rectangle rect = new Rectangle(, , image.Width, image.Height); ///Nearest Linear MipMapped三个纹理实现,本文暂时不考虑
//bitmapdata = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//GL.GenTextures(3, this.texture); //// Create Nearest Filtered Texture
//GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[0]);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
//GL.TexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGB, image.Width, image.Height, 0, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
//// Create Linear Filtered Texture
//GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[1]);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
//GL.TexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGB, image.Width, image.Height, 0, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
//// Create MipMapped Texture
//GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[2]);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
//GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_NEAREST);
//GL.uBuild2DMipmaps(GL.GL_TEXTURE_2D, (int)GL.GL_RGB, image.Width, image.Height, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
//image.UnlockBits(bitmapdata); /** 生成纹理对象名称 */
GL.GenTextures(, ID); /** 创建纹理对象 */
GL.BindTexture(GL.GL_TEXTURE_2D, ID[]); /** 控制滤波 */
GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR);
GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR);
GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_REPEAT);
GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_REPEAT); bitmapdata = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
/** 创建纹理 */
GLU.Build2DMipmaps(GL.GL_TEXTURE_2D, (int)GL.GL_RGB, image.Width,
image.Height, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE,
bitmapdata.Scan0);
image.UnlockBits(bitmapdata);
}
return true;
} public void FreeImage()
{
/** 释放内存 */
if (image != null)
{
image.Dispose();
}
}
public void Dispose()
{
FreeImage();
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using OpenGLDotNet; namespace OpenGLTK
{
/// <summary>
/// 第四章 OpenGl 多重纹理载入 C# by 大师♂罗莊
/// </summary>
class OpenGLMultiTexture : Examplefirst
{
TextureLoad[] m_texture = new TextureLoad[];
bool multitexturing=false;
/** 检查是否支持扩展 */
string title = "第四章 OpenGl 多重纹理载入"; public OpenGLMultiTexture()
: base()
{
for (int i = ; i < ; i++)
{
m_texture[i] = new TextureLoad();//对象数组必须初始化
}
LoadTexture();
GLUT.SetWindowTitle(title);
/** 初始化 */
if (!initMultiTexture())//和原来不一样,GL.GetString这个函数不能放入动画事件
{
MessageBox.Show("您的硬件和驱动不支持多重纹理");
return;
} } /// <summary>
/// 检查多重纹理支持
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
bool isExtensionSupported(string input)
{
string extension = GL.GetString(GL.GL_EXTENSIONS); return extension.IndexOf(input)>=;
} bool initMultiTexture()
{
/** 检查是否支持扩展 */
if (isExtensionSupported("GL_ARB_multitexture"))
{
return true;
}
else
return false;
} /** 载入纹理数据 */
bool LoadTexture()
{
/// 文件名
String[] fileName = new String[] { "wall.bmp", "lightmap.bmp", "bitmap.bmp", "fog.bmp" }; /// 载入四幅位图
for (int i = ; i < ; i++)
{
if (m_texture[i].Load(Path.Combine(Application.StartupPath, @"Image\" + fileName[i]).ToString()) == false) /**< 载入位图文件 */
{
MessageBox.Show("无法载入" + fileName[i]);
return false;
} }
return true; } /// <summary>
/// 初始化视口投影,恢复原书的视口
/// </summary>
public override void iniView(int windowWidth, int windowHeight)
{
GLU.Perspective(45.0f, windowWidth / windowHeight, 1.0f, 100.0f);
GL.MatrixMode(GL.GL_MODELVIEW);
GL.LoadIdentity();
GLU.LookAt(, , , // 眼睛位置
, , , // 观察点
, , ); // 怎么看 } /** 用户自定义的卸载函数 */
public new void Dispose()
{
base.Dispose();
for (int i = ; i < ; i++)
{
m_texture[i].FreeImage();
GL.DeleteTextures(, m_texture[i].ID);
}
}
float wrap = ; /**< 用于雾的流动 */ public override void Keyboard(byte key, int x, int y)
{
if (key == ) // Escape 按下,退出
{
this.Dispose();
} /////** 当按下空格时,开启多重纹理 */
if (key == 0x20)
{
multitexturing = true;//开启
}
else
{
multitexturing = false;//按下其他键关闭
}
}
/// <summary>
/// 重载
/// </summary>
/// <param name="currentTime"></param>
public override void Update(float milliseconds)
{
wrap += milliseconds /; //动画 速度请自己调节
Display(); }
/// <summary>
/// 重载,使用Draw方法绘图
/// </summary>
/// <param name="mouseX"></param>
/// <param name="currentTime"></param>
public override void DrawGLScene()
{
Draw();
GLUT.SwapBuffers();
} /** 绘制函数 */
void Draw()
{
/** 用户自定义的绘制过程 */
GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
GL.LoadIdentity(); GL.Translatef(0.0f, 0.0f, -10.0f); /** 激活纹理0,并绑定纹理 */
GL.ActiveTextureARB(GL.GL_TEXTURE0_ARB);
GL.Enable(GL.GL_TEXTURE_2D);
GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[].ID[]); /** 激活纹理1,并绑定纹理 */
GL.ActiveTextureARB(GL.GL_TEXTURE1_ARB); /** 如果多重纹理启用,则启用该纹理 */
if (multitexturing)
GL.Enable(GL.GL_TEXTURE_2D);
else
GL.Disable(GL.GL_TEXTURE_2D); GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[].ID[]); /** 绘制一个四方形墙面 */
GL.PushMatrix();
GL.Translatef(-2.5f, 0f, 0f);
GL.Scalef(2.0f, 2.0f, 2.0f);
GL.Begin(GL.GL_QUADS); /** 左上点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 1.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f, 1.0f);
GL.Vertex3f(-, , ); /** 左下点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 0.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f, 0.0f);
GL.Vertex3f(-, -, ); /** 右下点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 0.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f, 0.0f);
GL.Vertex3f(, -, ); /** 右上点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 1.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f, 1.0f);
GL.Vertex3f(, , ); GL.End(); /**< 绘制结束 */
GL.PopMatrix(); /** 激活纹理0,并绑定纹理 */
GL.ActiveTextureARB(GL.GL_TEXTURE0_ARB);
GL.Enable(GL.GL_TEXTURE_2D);
GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[].ID[]); /** 激活纹理1,并绑定纹理 */
GL.ActiveTextureARB(GL.GL_TEXTURE1_ARB); /** 如果多重纹理启用,则启用该纹理 */
if (multitexturing)
GL.Enable(GL.GL_TEXTURE_2D);
else
GL.Disable(GL.GL_TEXTURE_2D);
GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[].ID[]); GL.Translatef(2.5f, , );
GL.Scalef(2.0f, 2.0f, 2.0f);
GL.Begin(GL.GL_QUADS); /** 左上点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 1.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f - wrap, 1.0f);
GL.Vertex3f(-, , ); /** 左下点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 0.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f - wrap, 0.0f);
GL.Vertex3f(-, -, ); /** 右下点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 0.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f - wrap, 0.0f);
GL.Vertex3f(, -, ); /** 右上点 */
GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 1.0f);
GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f - wrap, 1.0f);
GL.Vertex3f(, , );
GL.End();
}
}
}

移植只要改改几个地方就很方便了。

这里我再次提醒大家,因为我们用到非托管库,freeglut.dll。需要把这个DLL拷贝到应用程序目录,由于系统分32位和64位,而默认VS生成项目模板是Any CPU,也就是32、64位自适应的EXE,而OpenGLDotNet和tao 自带freeglut.dll都是32位。

需要自己设置为X86 32位EXE,或者自行下载freeglut 编译一个64位DLL,然后做两个版本EXE。

C#+OpenGL编程之再见小桃子(The Tao Framework)的更多相关文章

  1. OpenGL编程(一)渲染一个指定颜色的背景窗口

    上次已经搭好了OpenGL编程的环境.已经成功运行了第一个程序.可只是照搬书上的代码,并没弄懂其中的原理.这次通过一个小程序来解释使用GLUT库编写OpenGL程序的过程. 程序的入口 与其他程序一样 ...

  2. OpenGL编程指南(第七版)

    OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...

  3. 编译opengl编程指南第八版示例代码通过

    最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...

  4. 在 Mac OS X Yosemite 10.10.5 上配置 OpenGL 编程环境

    这个教程主要参考了youtube上的视频 Getting Started in OpenGL with GLFW/GLEW in Xcode 6 ,这个视频有点问题,不能照搬.本人通过自己摸(瞎)索( ...

  5. 用MFC实现OpenGL编程

    一.OpenGL简介 众所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他们的图形工作站上开发高质量图像的接口.但最近几年它成为一个非常优秀的开放式 ...

  6. [ZZ]面向对象编程,再见!

    面向对象编程,再见!- 机器学习算法与自然语言处理 https://mp.weixin.qq.com/s/icXBlVOOYLvDnER7cEeCeg https://medium.com/@csca ...

  7. [转]VS 2012环境下使用MFC进行OpenGL编程

    我就不黏贴复制了,直接给出原文链接:VS 2012环境下使用MFC进行OpenGL编程 其它好文链接: 1.OpenGL系列教程之十二:OpenGL Windows图形界面应用程序

  8. VS15 openGL 编程指南 配置库 triangle例子

    最近去图书馆借了一本书<OpenGL编程指南(原书第八版)>,今天倒腾了一天才把第一个例子运行出来. 所以,给大家分享一下,希望能快速解决配置问题. 一.下载需要的库文件 首先,我们需要去 ...

  9. Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤

    http://blog.csdn.net/vagrxie/article/details/4602961 Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤 wri ...

随机推荐

  1. Android 6.0权限管理

    Android 6.0权限管理 关于权限管理 Android6.0 发布之后,Android 的权限系统被重新设计.在 23 之前 App 的权限只会在用户安装的时候询问一次,App一旦安装后就可以使 ...

  2. Eclipse下link方式安装插件

    一.eclipse安装位置和存放文件位置 eclipse安装位置:D:\ProgramFile\eclipse存放文件:D:\mydep 二.下载插件 这里下载的是PropertiesEditor解压 ...

  3. iOS设计模式简介

    开闭原则: 一个模块的修改,对拓展开放而对修改关闭. 举个例子:有一个类在项目中很多地方被使用了,但是由于需求,想对这个类进行拓展,这里可以使用继承拓展出子类,可以对子类进行修改,尽量不要修改原来的类 ...

  4. python super

    http://hi.baidu.com/thinkinginlamp/item/3095e2f52c642516ce9f32d5 Python中对象方法的定义很怪异,第一个参数一般都命名为self(相 ...

  5. 编译时:virtual memory exhausted: Cannot allocate memory

    一.问题 当安装虚拟机时系统时没有设置swap大小或设置内存太小,编译程序会出现virtual memory exhausted: Cannot allocate memory的问题,可以用swap扩 ...

  6. 编译流程,C开发常见文件类型名

    编译流程 我们常说的编译是一个整体的概念,是指从源程序到可执行程序的整个过程,实际上,C语言编译的过程可以进一步细分为预编译->编译->汇编->链接 预编译是把include关键字所 ...

  7. JavaScript吸顶灯的实现

    吸顶灯是各站点常用的一个功能,它有两个特性 向下滚动到div位置时,该div一直固定在页面的顶部 向上滚动到div原有位置时,div又恢复到文档中的原位置 div可能是一个“分类菜单”,也可能是一个“ ...

  8. Web Storage API : LocalStroage

    这是一篇详细介绍详细介绍详细介绍_(:з」∠)_ 背景: 当你访问一个页面,并不是丢到服务器,等待用户访问就可以了的.从输入网址到显示网页的全过程,可以参考这里 简单来说,在输入url按下回车键后,首 ...

  9. 用VB实现点名程序

    用vb实现点名程序主要是随机变量的产生和数据的读取和存储以及计时器程序的设计,读取的文件命名为data.txt,书写格式为第一行为总人数下面的每行为一个人名,在应用时最好把data文件和程序文件放在一 ...

  10. puppet学习笔记(一)

    之前搞了一个月zabbix,基本上是能熟练使用了,不过在后来部署的时候发现这玩意在部署的时候机子少还行,机子多了手动安装手会残的.第一反应是用puppet,后来师父直接用puppet搞定了.索性自己也 ...