2005年11月29日

这几天donews被攻击了,一直不能发东西!

差点儿把这里放弃了!

好在今天可以了……

2005年11月17日
如何利用C#创建和调用DLL

一、写在前面
C# 语言是一种简单但功能强大的编程语言,用于编写企业应用程序。

C# 语言从C和 C++语言演化而来,在语句、表达式和运算符方面使用了许多 C++ 功能。

C# 语言在类型安全性、版本转换、事件和垃圾回收等方面进行了相当大的改进和创新。

C# 语言提供对常用 API 样式(如 .NET 框架、COM、自动化和 C 样式 API 等)的访问。

       什么是动态链接库?DLL三个字母对于你来说一定很熟悉吧,它是Dynamic Link Library 的缩写形式,动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。

和大多数程序员一样,你一定很使用过DLL吧。也曾感受到它的带给你程序设计和编码上的好错吧今天我想和大家探讨一个主题:如何在C#创建和调用DLL(动态链接库), 其实在很大意义上而讲,DLL让我更灵活的组织编写我们的应用程序,作为软件设计者,可一个根据它来达到很高的代码重用效果。下面我来介绍一下在C#中如何创建和调用DLL。

 

二、准备工作

 

我们需要对我们接下来要做的事情做个简单的介绍,在本文我们将利用C#语言创建一个名为 MyDLL.DLL的动态链接库,在这个动态链接库文件中我们将提供两个功能一个是对两个参数交换他们的值,另一个功能是求两个参数的最大公约数。然后创建一个应用程序使用这个DLL。运行并输出结果。

 

三、创建DLL

 

让我们创建以下三个C#代码文件:

1、  MySwap.cs

using System;

namespace MyMethods

{

     public class SwapClass

     {

          public static bool Swap(ref long i,ref long j)

          {

  i = i+j;

  j = i-j;

  i = i-j;

  return true;

          }

     }

}

 

2、  MyMaxCD.cs

using System;

namespace MyMethods

{

     public class MaxCDClass

     {

          public static long MaxCD(long i, long j)

          {

  long a,b,temp;

  if(i>j)

  {

       a = i;

       b = j;

  }

  else

  {

       b = i;

       a = j;

  }

  temp = a % b;

  while(temp!=0)

  {

       a = b;

       b = temp;

       temp = a % b;

  }

  return b;

          }

     }

}

}需要注意的是:我们在制作这两个文件的时候可以用Visual Studio.NET或者其他的文本编辑器,就算是记事本也可以。这两个文件虽然不在同一个文件里面,但是他们是属于同一个namespace(名称空间)这对以后我们使用这两个方法提供了方便。当然他们也可以属于不同的名称空间,这是完全可以的,但只是在我们应用他们的时候就需要引用两个不同的名称空间,所以作者建议还是写在一个名称空间下面比较好。
接下来的任务是把这两个cs文件变成我们需要的DLL文件。方法是这样的:
在安装了Microsoft.NET Framework的操作系统上,我们可以在Windows所在目录下找到Microsoft.NET目录。在这个目录下面提供了C#的编译器,CSC.EXE
运行:csc /target:library /out:MyDLL.DLL MySwap.cs MyMaxCD.cs
完成后可在本目录下面找到我们刚才生成的MyDLL.DLL文件
/target:library 编译器选项通知编译器输出 DLL 文件而不是 EXE 文件。后跟文件名的 /out 编译器选项用于指定 DLL 文件名。
如果/out后面不跟文件名编译器使用第一个文件 (MySwap.cs) 作为 DLL 文件名。生成的文件为MySwap.DLL文件
OK!我们创建动态链接库文件的任务完成了,现在是我们享受劳动成果的时候了,下面我将介绍如何使用我们所创建的动态链接库文件。
 
四、   使用DLL
 
我们简单写一个小程序来测试一下我们刚才写的两个方法是否正确,好吧,跟我来:
MyClient.cs 
using System;

using MyMethods;

//这里我们引用刚才定义的名称空间,如果刚才的两个文件我们写在两个不同的名称空间
class MyClient

{

     public static void Main(string[] args)

     {

         if (args.Length != 2)

         {

 Console.WriteLine("Usage: MyClient <num1> <num2>");

 return;

         }

          long num1 = long.Parse(args[0]);

          long num2 = long.Parse(args[1]);

          SwapClass.Swap(ref num1,ref num2);

// 请注意,文件开头的 using 指令使您得以在编译时使用未限定的类名来引用 DLL 方法

          Console.WriteLine("The result of swap is num1 = {0} and num2 ={1}",num1, num2);

          long maxcd = MaxCDClass.MaxCD(num1,num2);

          Console.WriteLine("The MaxCD of {0} and {1} is {2}",num1, num2, maxcd);

     }

}

若要生成可执行文件 MyClient.exe,请使用以下命令行:

csc /out:MyClient.exe /reference:MyLibrary.DLL MyClient.cs

/out 编译器选项通知编译器输出 EXE 文件并且指定输出文件名 (MyClient.exe)。/reference 编译器选项指定该程序所引用的 DLL 文件。

 

五、执行

 

若要运行程序,请输入 EXE 文件的名称,文件名的后面跟两个数字,例如:

MyClient 123 456

 

六、输出

 

The result of swap is num1 = 456 and num2 = 123

The MaxCD of 456 and 123 is 3

 

七、小结

动态链接具有下列优点:

节省内存和减少交换操作。很多进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows 必须在内存中加载库代码的一个副本。
节省磁盘空间。许多应用程序可在磁盘上共享 DLL 的一个副本。相反,每个用静态链接库生成的应用程序均具有作为单独的副本链接到其可执行图像中的库代码。
升级到 DLL 更为容易。DLL 中的函数更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。
提供售后支持。例如,可修改显示器驱动程序 DLL 以支持当初交付应用程序时不可用的显示器。
支持多语言程序。只要程序遵循函数的调用约定,用不同编程语言编写的程序就可以调用相同的 DLL 函数。程序与 DLL 函数在下列方面必须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应用程序负责清理堆栈,以及寄存器中是否传递了任何参数。
提供了扩展 MFC 库类的机制。可以从现有 MFC 类派生类,并将它们放到 MFC 扩展 DLL 中供 MFC 应用程序使用。
使国际版本的创建轻松完成。通过将资源放到 DLL 中,创建应用程序的国际版本变得容易得多。可将用于应用程序的每个语言版本的字符串放到单独的 DLL 资源文件中,并使不同的语言版本加载合适的资源。
使用 DLL 的一个潜在缺点是应用程序不是独立的;它取决于是否存在单独的 DLL 模块。

2005年11月07日
        在编程中我们常常会遇到“将文件保存到数据库中”这样一个问题,虽然这已不是什么高难度的问题,但对于一些刚刚开始编程的朋友来说可能是有一点困难。其实,方法非常的简单,只是可能由于这些朋友刚刚开始编程不久,一时没有找到方法而已。
        下面介绍一下使用C#来完成此项任务。
        首先,介绍一下保存文件到数据库中。将文件保存到数据库中,实际上是将文件转换成二进制流后,将二进制流保存到数据库相应的字段中。在SQL Server中该字段的数据类型是Image,在Access中该字段的数据类型是OLE对象。
 //保存文件到SQL Server数据库中
 FileInfo fi=new FileInfo(fileName);
 FileStream fs=fi.OpenRead();
 byte[] bytes=new byte[fs.Length];
 fs.Read(bytes,0,Convert.ToInt32(fs.Length));
 SqlCommand cm=new SqlCommand();
 cm.Connection=cn;
 cm.CommandType=CommandType.Text;
 if(cn.State==0) cn.Open();
 cm.CommandText="insert into "+tableName+"("+fieldName+") values(@file)";
 SqlParameter spFile=new SqlParameter("@file",SqlDbType.Image);
 spFile.Value=bytes;
 cm.Parameters.Add(spFile);
 cm.ExecuteNonQuery()
 //保存文件到Access数据库中
 FileInfo fi=new FileInfo(fileName);
 FileStream fs=fi.OpenRead();
 byte[] bytes=new byte[fs.Length];
 fs.Read(bytes,0,Convert.ToInt32(fs.Length));
 OleDbCommand cm=new OleDbCommand();
 cm.Connection=cn;
 cm.CommandType=CommandType.Text;
 if(cn.State==0) cn.Open();
 cm.CommandText="insert into "+tableName+"("+fieldName+") values(@file)";
 OleDbParameter spFile=new OleDbParameter("@file",OleDbType.Binary);
 spFile.Value=bytes;
 cm.Parameters.Add(spFile);
 cm.ExecuteNonQuery()
 代码中的fileName是文件的完整名称,tableName是要操作的表名称,fieldName是要保存文件的字段名称。
 两段代码实际上是一样的,只是操作的数据库不同,使用的对象不同而已。
         接着,在说说将文件从数据库中读取出来,只介绍从SQL Server中读取。
 SqlDataReader dr=null;
 SqlConnection objCn=new SqlConnection();
 objCn.ConnectionString="Data Source=(local);User ID=sa;Password=;Initial Catalog=Test";
 SqlCommand cm=new SqlCommand();
 cm.Connection=cn;
 cm.CommandType=CommandType.Text;
 cm.CommandText="select "+fieldName+" from "+tableName+" where ID=1";
 dr=cm.ExecuteReader();
 byte[] File=null; 
 if(dr.Read())
 {
  File=(byte[])dr[0];
 }
 FileStream fs;
 FileInfo fi=new System.IO.FileInfo(fileName);
 fs=fi.OpenWrite();
 fs.Write(File,0,File.Length);
 fs.Close();
 上面的代码是将保存在数据库中的文件读取出来并保存文fileName指定的文件中。
         在使用上面的代码时,别忘了添加System.Data.SqlClient和System.IO引用。

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
namespace using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;

namespace PickHead
{
///
/// 一个控制摄像头的类
///
public class Pick
{
private const int WM_USER = 0×400;
private const int WS_CHILD = 0×40000000;
private const int WS_VISIBLE = 0×10000000;
private const int WM_CAP_START = WM_USER;
private const int WM_CAP_STOP = WM_CAP_START + 68;
private const int WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
private const int WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;
private const int WM_CAP_SAVEDIB = WM_CAP_START + 25;
private const int WM_CAP_GRAB_FRAME = WM_CAP_START + 60;
private const int WM_CAP_SEQUENCE = WM_CAP_START + 62;
private const int WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
private const int WM_CAP_SEQUENCE_NOFILE =WM_CAP_START+ 63;
private const int WM_CAP_SET_OVERLAY =WM_CAP_START+ 51;
private const int WM_CAP_SET_PREVIEW =WM_CAP_START+ 50;
private const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START +6;
private const int WM_CAP_SET_CALLBACK_ERROR=WM_CAP_START +2;
private const int WM_CAP_SET_CALLBACK_STATUSA= WM_CAP_START +3;
private const int WM_CAP_SET_CALLBACK_FRAME= WM_CAP_START +5;
private const int WM_CAP_SET_SCALE=WM_CAP_START+ 53;
private const int WM_CAP_SET_PREVIEWRATE=WM_CAP_START+ 52;
private IntPtr hWndC;
private bool bStat = false;

private IntPtr mControlPtr;
private int mWidth;
private int mHeight;
private int mLeft;
private int mTop;

///
/// 初始化摄像头
///
/// 控件的句柄
/// 开始显示的左边距
/// 开始显示的上边距
/// 要显示的宽度
/// 要显示的长度
public Pick(IntPtr handle, int left, int top, int width,int height)
{
mControlPtr = handle;
mWidth = width;
mHeight = height;
mLeft = left;
mTop = top;
}

[DllImport("avicap32.dll")]
private static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);

[DllImport("avicap32.dll")]
private static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize );
[DllImport("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);

///
/// 开始显示图像
///
public void Start()
{
if (bStat)
return;

bStat = true;
byte[] lpszName = new byte[100];

hWndC = capCreateCaptureWindowA(lpszName,WS_CHILD|WS_VISIBLE ,mLeft,mTop,mWidth,mHeight,mControlPtr,0);

if (hWndC.ToInt32() != 0)
{
SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0);
SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);
SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0);
SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 66, 0);
SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0);
SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0);
}

return;




}

///
/// 停止显示
///
public void Stop()
{
SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
bStat = false;
}

///
/// 抓图
///
/// 要保存bmp文件的路径
public void GrabImage(string path)
{

IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC,WM_CAP_SAVEDIB,0,hBmp.ToInt64());

}

///
/// 录像
///
/// 要保存avi文件的路径
public void Kinescope(string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC,WM_CAP_FILE_SET_CAPTURE_FILEA,0,hBmp.ToInt64());
SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
}

///
/// 停止录像
///
public void StopKinescope()
{
SendMessage(hWndC, WM_CAP_STOP, 0, 0);
}

}
}

安装摄像头后,一般可以找到一个avicap32.dll文件 这是一个关于设想头的类

using  system;
using  System.Runtime.InteropServices;

namespace  webcam
{
///  
///  avicap  的摘要说明。
///  
public  class  showVideo
{
//  showVideo  calls
[DllImport("avicap32.dll")]  public  static  extern  IntPtr  capCreateCaptureWindowA(byte[]  lpszWindowName,  int  dwStyle,  int  x,  int  y,  int  nWidth,  int  nHeight,  IntPtr  hWndParent,  int  nID);
[DllImport"avicap32.dll")]  public  static  extern  bool  capGetDriverDescriptionA(short  wDriver,  byte[]  lpszName,  int  cbName,  byte[]  lpszVer,  int  cbVer);
[DllImport("User32.dll")]  public  static  extern  bool  SendMessage(IntPtr  hWnd,  int  wMsg,  bool  wParam,  int  lParam);  
[DllImport("User32.dll")]  public  static  extern  bool  SendMessage(IntPtr  hWnd,  int  wMsg,  short  wParam,  int  lParam);  
[DllImport("User32.dll")]  public  static  extern  bool  SendMessage(IntPtr  hWnd,  int  wMsg,  short  wParam,  FrameEventHandler  lParam);  
[DllImport("User32.dll")]  public  static  extern  bool  SendMessage(IntPtr  hWnd,  int  wMsg,  int  wParam,  ref  BITMAPINFO  lParam);
[DllImport("User32.dll")]  public  static  extern  int  SetWindowPos(IntPtr  hWnd,  int  hWndInsertAfter,  int  x,  int  y,  int  cx,  int  cy,  int  wFlags);
[DllImport("avicap32.dll")]public  static  extern  int  capGetVideoFormat(IntPtr  hWnd,  IntPtr  psVideoFormat,  int  wSize  );

//  constants
public  const  int  WM_USER  =  0×400;
public  const  int  WS_CHILD  =  0×40000000;
public  const  int  WS_VISIBLE  =  0×10000000;
public  const  int  SWP_NOMOVE  =  0×2;
public  const  int  SWP_NOZORDER  =  0×4;
public  const  int  WM_CAP_DRIVER_CONNECT  =  WM_USER  +  10;
public  const  int  WM_CAP_DRIVER_DISCONNECT  =  WM_USER  +  11;
public  const  int  WM_CAP_SET_CALLBACK_FRAME  =  WM_USER  +  5;
public  const  int  WM_CAP_SET_PREVIEW  =  WM_USER  +  50;
public  const  int  WM_CAP_SET_PREVIEWRATE  =  WM_USER  +  52;
public  const  int  WM_CAP_SET_VIDEOFORMAT  =  WM_USER  +  45;
  
//  Structures
[StructLayout(LayoutKind.Sequential)]  public  struct  VIDEOHDR
{
[MarshalAs(UnmanagedType.I4)]  public  int  lpData;
[MarshalAs(UnmanagedType.I4)]  public  int  dwBufferLength;
[MarshalAs(UnmanagedType.I4)]  public  int  dwBytesUsed;
[MarshalAs(UnmanagedType.I4)]  public  int  dwTimeCaptured;
[MarshalAs(UnmanagedType.I4)]  public  int  dwUser;
[MarshalAs(UnmanagedType.I4)]  public  int  dwFlags;
[MarshalAs(UnmanagedType.ByValArray,  SizeConst=4)]  public  int[]  dwReserved;
}

[structlayout(layoutkind.sequential)]  public  struct  bitmapinfoheader
{
[MarshalAs(UnmanagedType.I4)]  public  Int32  biSize  ;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biWidth  ;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biHeight  ;
[MarshalAs(UnmanagedType.I2)]  public  short  biPlanes;
[MarshalAs(UnmanagedType.I2)]  public  short  biBitCount  ;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biCompression;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biSizeImage;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biXPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biYPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biClrUsed;
[MarshalAs(UnmanagedType.I4)]  public  Int32  biClrImportant;
}  

[structlayout(layoutkind.sequential)]  public  struct  bitmapinfo
{
[MarshalAs(UnmanagedType.Struct,  SizeConst=40)]  public  BITMAPINFOHEADER  bmiHeader;
[MarshalAs(UnmanagedType.ByValArray,  SizeConst=1024)]  public  Int32[]  bmiColors;
}
  
public  delegate  void  FrameEventHandler(IntPtr  lwnd,  IntPtr  lpVHdr);
  
//  Public  methods
public  static  object  GetStructure(IntPtr  ptr,valueType  structure)
{
return  Marshal.PtrToStructure(ptr,structure.GetType());
}
  
public  static  object  GetStructure(int  ptr,valueType  structure)
{
return  GetStructure(new  IntPtr(ptr),structure);
}
  
public  static  void  Copy(IntPtr  ptr,byte[]  data)
{
Marshal.Copy(ptr,data,0,data.Length);
}
  
public  static  void  Copy(int  ptr,byte[]  data)
{
Copy(new  IntPtr(ptr),data);
}
  
public  static  int  SizeOf(object  structure)
{
return  Marshal.SizeOf(structure);  
}
}

//web  camera  class
public  class  WebCamera
{
//  Constructur
public  WebCamera(IntPtr  handle,  int  width,int  height)
{
mControlPtr  =  handle;
mWidth  =  width;
mHeight  =  height;
}
  
//  delegate  for  frame  callback
public  delegate  void  RecievedFrameEventHandler(byte[]  data);
public  event  RecievedFrameEventHandler  RecievedFrame;
  
private  IntPtr  lwndC;  //  Holds  the  unmanaged  handle  of  the  control
private  IntPtr  mControlPtr;  //  Holds  the  managed  pointer  of  the  control
private  int  mWidth;
private  int  mHeight;
  
private  showVideo.FrameEventHandler  mFrameEventHandler;  //  Delegate  instance  for  the  frame  callback  -  must  keep  alive!  gc  should  NOT  collect  it
  
//  Close  the  web  camera
public  void  CloseWebcam()
{
this.capDriverDisconnect(this.lwndC);
}
  
//  start  the  web  camera
public  void  StartWebCam()
{
byte[]  lpszName  =  new  byte[100];
byte[]  lpszVer  =  new  byte[100];
  
showVideo.capGetDriverDescriptionA(0,  lpszName,  100,lpszVer,  100);
this.lwndC  =  showVideo.capCreateCaptureWindowA(lpszName,  showVideo.WS_VISIBLE  +  showVideo.WS_CHILD,  0,  0,  mWidth,  mHeight,  mControlPtr,  0);
  
if  (this.capDriverConnect(this.lwndC,  0))
{
this.capPreviewRate(this.lwndC,  66);
this.capPreview(this.lwndC,  true);
showVideo.BITMAPINFO  bitmapinfo  =  new  showVideo.BITMAPINFO();  
bitmapinfo.bmiHeader.biSize  =  showVideo.SizeOf(bitmapinfo.bmiHeader);
bitmapinfo.bmiHeader.biWidth  =  352;
bitmapinfo.bmiHeader.biHeight  =  288;
bitmapinfo.bmiHeader.biPlanes  =  1;
bitmapinfo.bmiHeader.biBitCount  =  24;
this.capSetVideoFormat(this.lwndC,  ref  bitmapinfo,  showVideo.SizeOf(bitmapinfo));
this.mFrameEventHandler  =  new  showVideo.FrameEventHandler(FrameCallBack);
this.capSetCallbackOnFrame(this.lwndC,  this.mFrameEventHandler);
showVideo.SetWindowPos(this.lwndC,  0,  0,  0,  mWidth  ,  mHeight  ,  6);
}  
}

//  private  functions
private  bool  capDriverConnect(IntPtr  lwnd,  short  i)
{
return  showVideo.SendMessage(lwnd,  showVideo.WM_CAP_DRIVER_CONNECT,  i,  0);
}

private  bool  capdriverdisconnect(intptr  lwnd)
{
return  showVideo.SendMessage(lwnd,  showVideo.WM_CAP_DRIVER_DISCONNECT,  0,  0);
}
  
private  bool  capPreview(IntPtr  lwnd,  bool  f)
{
return  showVideo.SendMessage(lwnd,  showVideo.WM_CAP_SET_PREVIEW  ,  f,  0);
}

private  bool  cappreviewrate(intptr  lwnd,  short  wms)
{
return  showVideo.SendMessage(lwnd,  showVideo.WM_CAP_SET_PREVIEWRATE,  wMS,  0);
}
  
private  bool  capSetCallbackOnFrame(IntPtr  lwnd,  showVideo.FrameEventHandler  lpProc)
{  
return  showVideo.SendMessage(lwnd,  showVideo.WM_CAP_SET_CALLBACK_FRAME,  0,  lpProc);
}

private  bool  capsetvideoformat(intptr  hcapwnd,  ref  showvideo.bitmapinfo  bmpformat,  int  capformatsize)
{
return  showVideo.SendMessage(hCapWnd,  showVideo.WM_CAP_SET_VIDEOFORMAT,  CapFormatSize,  ref  BmpFormat);
}

private  void  framecallback(intptr  lwnd,  intptr  lpvhdr)
{
showVideo.VIDEOHDR  videoHeader  =  new  showVideo.VIDEOHDR();
byte[]  VideoData;
videoHeader  =  (showVideo.VIDEOHDR)showVideo.GetStructure(lpVHdr,videoHeader);
VideoData  =  new  byte[videoHeader.dwBytesUsed];
showVideo.Copy(videoHeader.lpData  ,VideoData);
if  (this.RecievedFrame  !=  null)
this.RecievedFrame  (VideoData);
}
}

}

具体调用如下:

using  system;
using  System.Drawing;
using  System.Collections;
using  System.ComponentModel;
using  System.Windows.Forms;
using  System.Data;
using  webcam;

namespace  webcam
{
///  
///  Form1  的摘要说明。
///  
public  class  Form1  :  System.Windows.Forms.Form
{
private  System.Windows.Forms.Panel  panelPreview;
private  System.Windows.Forms.Button  b_play;
private  System.Windows.Forms.Button  b_stop;
///  
///  必需的设计器变量。
///  
private  System.ComponentModel.Container  components  =  null;
WebCamera  wc;

public  form1()
{
//
//  Windows  窗体设计器支持所必需的
//
InitializeComponent();

//
//  TODO:  在  InitializeComponent  调用后添加任何构造函数代码
//
}

///  
///  清理所有正在使用的资源。
///  
protected  override  void  Dispose(  bool  disposing  )
{
if(  disposing  )
{
if  (components  !=  null)  
{
components.Dispose();
}
}
base.Dispose(  disposing  );
}

#region  windows  窗体设计器生成的代码
///  
///  设计器支持所需的方法  -  不要使用代码编辑器修改
///  此方法的内容。
///  
private  void  InitializeComponent()
{
this.b_play  =  new  System.Windows.Forms.Button();
this.panelPreview  =  new  System.Windows.Forms.Panel();
this.b_stop  =  new  System.Windows.Forms.Button();
this.SuspendLayout();
//  
//  b_play
//  
this.b_play.Location  =  new  System.Drawing.Point(280,  368);
this.b_play.Name  =  "b_play";
this.b_play.TabIndex  =  0;
this.b_play.Text  =  "&Play";
this.b_play.Click  +=  new  System.EventHandler(this.button1_Click);
//  
//  panelPreview
//  
this.panelPreview.Location  =  new  System.Drawing.Point(8,  8);
this.panelPreview.Name  =  "panelPreview";
this.panelPreview.Size  =  new  System.Drawing.Size(344,  272);
this.panelPreview.TabIndex  =  1;
//  
//  b_stop
//  
this.b_stop.Enabled  =  false;
this.b_stop.Location  =  new  System.Drawing.Point(360,  368);
this.b_stop.Name  =  "b_stop";
this.b_stop.TabIndex  =  2;
this.b_stop.Text  =  "&Stop";
this.b_stop.Click  +=  new  System.EventHandler(this.b_stop_Click);
//  
//  Form1
//  
this.AutoScaleBaseSize  =  new  System.Drawing.Size(6,  14);
this.ClientSize  =  new  System.Drawing.Size(464,  413);
this.Controls.Add(this.b_stop);
this.Controls.Add(this.panelPreview);
this.Controls.Add(this.b_play);
this.MaximizeBox  =  false;
this.MinimizeBox  =  false;
this.Name  =  "Form1";
this.Text  =  "GoodView  test  Web  Camera";
this.Load  +=  new  System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);

}
#endregion

///  
///  应用程序的主入口点。
///  
[STAThread]
static  void  Main()  
{
Application.Run(new  Form1());
}

private  void  form1_load(object  sender,  system.eventargs  e)
{
b_play.Enabled  =  false;
b_stop.Enabled  =  true;
panelPreview.Size  =  new  Size(330,330);
wc  =  new  WebCamera(  panelPreview.Handle,panelPreview.Width,panelPreview.Height);
wc.StartWebCam();
}

private  void  button1_click(object  sender,  system.eventargs  e)
{
b_play.Enabled  =  false;
b_stop.Enabled  =  true;
panelPreview.Size  =  new  Size(330,330);
wc  =  new  WebCamera(  panelPreview.Handle,panelPreview.Width,panelPreview.Height);
wc.StartWebCam();
}

private  void  b_stop_click(object  sender,  system.eventargs  e)
{
b_play.Enabled  =  true;
b_stop.Enabled  =  false;
wc.CloseWebcam();
}
}
}

–    c#中调用windows  api的要点
在.Net  Framework  SDK文档中,关于调用Windows  API的指示比较零散,并且其中稍全面一点的是针对Visual  Basic  .net讲述的。本文将C#中调用API的要点汇集如下,希望给未在C#中使用过API的朋友一点帮助。另外如果安装了Visual  Studio  .net的话,在C:\\Program  Files\\Microsoft  Visual  Studio  .NET\\FrameworkSDK\\Samples\\Technologies\\Interop\\PlatformInvoke\\WinAPIs\\CS目录下有大量的调用API的例子。
一、调用格式
using  System.Runtime.InteropServices;  //引用此名称空间,简化后面的代码

//使用DllImportAttribute特性来引入api函数,注意声明的是空方法,即方法体为空。
[DllImport("user32.dll")]
public  static  extern  ReturnType  FunctionName(type  arg1,type  arg2,…);
//调用时与调用其他方法并无区别

可以使用字段进一步说明特性,用逗号隔开,如:
[  DllImport(  "kernel32",  EntryPoint="GetVersionEx"  )]  
DllImportAttribute特性的公共字段如下:
1、CallingConvention  指示向非托管实现传递方法参数时所用的  CallingConvention  值。  
    CallingConvention.Cdecl  :  调用方清理堆栈。它使您能够调用具有  varargs  的函数。
    CallingConvention.StdCall  :  被调用方清理堆栈。它是从托管代码调用非托管函数的默认约定。
2、CharSet  控制调用函数的名称版本及指示如何向方法封送  String  参数。
    此字段被设置为  CharSet  值之一。如果  CharSet  字段设置为  Unicode,则所有字符串参数在传递到非托管实现之前都转换成  Unicode  字符。这还导致向  DLL  EntryPoint  的名称中追加字母“W”。如果此字段设置为  Ansi,则字符串将转换成  ANSI  字符串,同时向  DLL  EntryPoint  的名称中追加字母“A”。大多数  Win32  API  使用这种追加“W”或“A”的约定。如果  CharSet  设置为  Auto,则这种转换就是与平台有关的(在  Windows  NT  上为  Unicode,在  Windows  98  上为  Ansi)。CharSet  的默认值为  Ansi。CharSet  字段也用于确定将从指定的  DLL  导入哪个版本的函数。CharSet.Ansi  和  CharSet.Unicode  的名称匹配规则大不相同。对于  Ansi  来说,如果将  EntryPoint  设置为“MyMethod”且它存在的话,则返回“MyMethod”。如果  DLL  中没有“MyMethod”,但存在“MyMethodA”,则返回“MyMethodA”。对于  Unicode  来说则正好相反。如果将  EntryPoint  设置为“MyMethod”且它存在的话,则返回“MyMethodW”。如果  DLL  中不存在“MyMethodW”,但存在“MyMethod”,则返回“MyMethod”。如果使用的是  Auto,则匹配规则与平台有关(在  Windows  NT  上为  Unicode,在  Windows  98  上为  Ansi)。如果  ExactSpelling  设置为  true,则只有当  DLL  中存在“MyMethod”时才返回“MyMethod”。

3、entrypoint  指示要调用的  dll  入口点的名称或序号。  
    如果你的方法名不想与api函数同名的话,一定要指定此参数,例如:
[DllImport("user32.dll",CharSet="CharSet.Auto",EntryPoint="MessageBox")]
public  static  extern  int  MsgBox(IntPtr  hWnd,string  txt,string  caption,  int  type);

4、exactspelling  指示是否应修改非托管  dll  中的入口点的名称,以与  charset  字段中指定的  charset  值相对应。如果为  true,则当  dllimportattribute.charset  字段设置为  charset  的  ansi  值时,向方法名称中追加字母  a,当  dllimportattribute.charset  字段设置为  charset  的  unicode  值时,向方法的名称中追加字母  w。此字段的默认值是  false。  
5、PreserveSig  指示托管方法签名不应转换成返回  HRESULT、并且可能有一个对应于返回值的附加  [out,  retval]  参数的非托管签名。  
6、SetLastError  指示被调用方在从属性化方法返回之前将调用  Win32  API  SetLastError。  true  指示调用方将调用  SetLastError,默认为  false。运行时封送拆收器将调用  GetLastError  并缓存返回的值,以防其被其他  API  调用重写。用户可通过调用  GetLastWin32Error  来检索错误代码。

二、参数类型:
1、数值型直接用对应的就可。(DWORD  ->  int  ,  WORD  ->  Int16)
2、API中字符串指针类型  ->  .net中string
3、API中句柄  (dWord)    ->  .net中IntPtr
4、API中结构      ->  .net中结构或者类。注意这种情况下,要先用StructLayout特性限定声明结构或类
公共语言运行库利用StructLayoutAttribute控制类或结构的数据字段在托管内存中的物理布局,即类或结构需要按某种方式排列。如果要将类传递给需要指定布局的非托管代码,则显式控制类布局是重要的。它的构造函数中用LayoutKind值初始化  StructLayoutAttribute  类的新实例。  LayoutKind.Sequential  用于强制将成员按其出现的顺序进行顺序布局。
LayoutKind.Explicit  用于控制每个数据成员的精确位置。利用  Explicit,  每个成员必须使用  FieldOffsetAttribute  指示此字段在类型中的位置。如:
[StructLayout(LayoutKind.Explicit,  Size=16,  CharSet=CharSet.Ansi)]
public  class  MySystemTime  
{
        [FieldOffset(0)]public  ushort  wYear;  
        [FieldOffset(2)]public  ushort  wMonth;
        [FieldOffset(4)]public  ushort  wDayOfWeek;  
        [FieldOffset(6)]public  ushort  wDay;  
        [FieldOffset(8)]public  ushort  wHour;  
        [FieldOffset(10)]public  ushort  wMinute;  
        [FieldOffset(12)]public  ushort  wSecond;  
        [FieldOffset(14)]public  ushort  wMilliseconds;  
}
下面是针对API中OSVERSIONINFO结构,在.net中定义对应类或结构的例子:
/**********************************************
*  API中定义原结构声明
*  OSVERSIONINFOA  STRUCT
*    dwOSVersionInfoSize      DWORD            ?
*    dwMajorVersion                DWORD            ?
*    dwMinorVersion                DWORD            ?
*    dwBuildNumber                  DWORD            ?
*    dwPlatformId                    DWORD            ?
*    szCSDVersion                    BYTE  128  dup  (?)
*  OSVERSIONINFOA  ENDS
*
*  OSVERSIONINFO    equ    <OSVERSIONINFOA>
*********************************************/

//.net中声明为类
[  StructLayout(  LayoutKind.Sequential  )]      
public  class  OSVersionInfo  
{      
        public  int  OSVersionInfoSize;
        public  int  majorVersion;  
        public  int  minorVersion;
        public  int  buildNumber;
        public  int  platformId;

        [  marshalas(  unmanagedtype.byvaltstr,  sizeconst=128  )]        
        public  String  versionString;
}
//或者
//.net中声明为结构
[  StructLayout(  LayoutKind.Sequential  )]    
public  struct  OSVersionInfo2  
{
        public  int  OSVersionInfoSize;
        public  int  majorVersion;  
        public  int  minorVersion;
        public  int  buildNumber;
        public  int  platformId;

        [  marshalas(  unmanagedtype.byvaltstr,  sizeconst=128  )]        
        public  String  versionString;
}

此例中用到mashalas特性,它用于描述字段、方法或参数的封送处理格式。用它作为参数前缀并指定目标需要的数据类型。例如,以下代码将两个参数作为数据类型长指针封送给  windows  api  函数的字符串  (lpstr):  
        [MarshalAs(UnmanagedType.LPStr)]
String  existingfile;
        [MarshalAs(UnmanagedType.LPStr)]
String  newfile;

注意结构作为参数时候,一般前面要加上ref修饰符,否则会出现错误:对象的引用没有指定对象的实例。
[  DllImport(  "kernel32",  EntryPoint="GetVersionEx"  )]  
public  static  extern  bool  GetVersionEx2(  ref  OSVersionInfo2  osvi  );  

三、如何保证使用托管对象的平台调用成功?
        如果在调用平台  invoke  后的任何位置都未引用托管对象,则垃圾回收器可能将完成该托管对象。这将释放资源并使句柄无效,从而导致平台invoke  调用失败。用  HandleRef  包装句柄可保证在平台  invoke  调用完成前,不对托管对象进行垃圾回收。
        例如下面:
                FileStream  fs  =  new  FileStream(  "a.txt",  FileMode.Open  );
                StringBuilder  buffer  =  new  StringBuilder(  5  );
                int  read  =  0;
                ReadFile(fs.Handle,  buffer,  5,  out  read,  0  );  //调用Win  API中的ReadFile函数
由于fs是托管对象,所以有可能在平台调用还未完成时候被垃圾回收站回收。将文件流的句柄用HandleRef包装后,就能避免被垃圾站回收:
[  DllImport(  "Kernel32.dll"  )]
public  static  extern  bool  ReadFile(  
    HandleRef  hndRef,  
    StringBuilder  buffer,  
    int  numberOfBytesToRead,  
    out  int  numberOfBytesRead,  
    ref  Overlapped  flag  );
……
……
                FileStream  fs  =  new  FileStream(  "HandleRef.txt",  FileMode.Open  );
                HandleRef  hr  =  new  HandleRef(  fs,  fs.Handle  );
                StringBuilder  buffer  =  new  StringBuilder(  5  );
                int  read  =  0;
                //  platform  invoke  will  hold  reference  to  HandleRef  until  call  ends
                ReadFile(  hr,  buffer,  5,  out  read,  0  );

——————————————————————————–
  
–    作者:Bestone
–    发布时间:2004-12-7  15:45:59

–    

api函数是构筑windws应用程序的基石,每一种windows应用程序开发工具,它提供的底层函数都间接或直接地调用了windows  api函数,同时为了实现功能扩展,一般也都提供了调用windowsapi函数的接口,  也就是说具备调用动态连接库的能力。visual  c#和其它开发工具一样也能够调用动态链接库的api函数。.net框架本身提供了这样一种服务,允许受管辖的代码调用动态链接库中实现的非受管辖函数,包括操作系统提供的windows  api函数。它能够定位和调用输出函数,根据需要,组织其各个参数(整型、字符串类型、数组、和结构等等)跨越互操作边界。  

下面以c#为例简单介绍调用api的基本过程:    
动态链接库函数的声明    
 动态链接库函数使用前必须声明,相对于VB,C#函数声明显得更加罗嗦,前者通过  Api  Viewer粘贴以后,可以直接使用,而后者则需要对参数作些额外的变化工作。  

 动态链接库函数声明部分一般由下列两部分组成,一是函数名或索引号,二是动态链接库的文件名。    
   譬如,你想调用User32.DLL中的MessageBox函数,我们必须指明函数的名字MessageBoxA或MessageBoxW,以及库名字User32.dll,我们知道Win32  API对每一个涉及字符串和字符的函数一般都存在两个版本,单字节字符的ANSI版本和双字节字符的UNICODE版本。  

 下面是一个调用API函数的例子:    
[DllImport("KERNEL32.DLL",  EntryPoint="MoveFileW",  SetLastError=true,    
CharSet=CharSet.Unicode,  ExactSpelling=true,    
CallingConvention=CallingConvention.StdCall)]    
public  static  extern  bool  MoveFile(String  src,  String  dst);    

 其中入口点EntryPoint标识函数在动态链接库的入口位置,在一个受管辖的工程中,目标函数的原始名字和序号入口点不仅标识一个跨越互操作界限的函数。而且,你还可以把这个入口点映射为一个不同的名字,也就是对函数进行重命名。重命名可以给调用函数带来种种便利,通过重命名,一方面我们不用为函数的大小写伤透脑筋,同时它也可以保证与已有的命名规则保持一致,允许带有不同参数类型的函数共存,更重要的是它简化了对ANSI和Unicode版本的调用。CharSet用于标识函数调用所采用的是Unicode或是ANSI版本,ExactSpelling=false将告诉编译器,让编译器决定使用Unicode或者是Ansi版本。其它的参数请参考MSDN在线帮助.  

 在C#中,你可以在EntryPoint域通过名字和序号声明一个动态链接库函数,如果在方法定义中使用的函数名与DLL入口点相同,你不需要在EntryPoint域显示声明函数。否则,你必须使用下列属性格式指示一个名字和序号。  

[dllimport("dllname",  entrypoint="functionname")]    
[DllImport("dllname",  EntryPoint="#123")]    
值得注意的是,你必须在数字序号前加“#”    
下面是一个用MsgBox替换MessageBox名字的例子:    
[C#]    
using  System.Runtime.InteropServices;    

public  class  win32  {    
[DllImport("user32.dll",  EntryPoint="MessageBox")]    
public  static  extern  int  MsgBox(int  hWnd,  String  text,  String  caption,  uint  type);    
}    
许多受管辖的动态链接库函数期望你能够传递一个复杂的参数类型给函数,譬如一个用户定义的结构类型成员或者受管辖代码定义的一个类成员,这时你必须提供额外的信息格式化这个类型,以保持参数原有的布局和对齐。  

c#提供了一个structlayoutattribute类,通过它你可以定义自己的格式化类型,在受管辖代码中,格式化类型是一个用structlayoutattribute说明的结构或类成员,通过它能够保证其内部成员预期的布局信息。布局的选项共有三种:  

布局选项    
描述    
LayoutKind.Automatic    
为了提高效率允许运行态对类型成员重新排序。    
注意:永远不要使用这个选项来调用不受管辖的动态链接库函数。    
LayoutKind.Explicit    
对每个域按照FieldOffset属性对类型成员排序    
LayoutKind.Sequential    
对出现在受管辖类型定义地方的不受管辖内存中的类型成员进行排序。    
传递结构成员    
下面的例子说明如何在受管辖代码中定义一个点和矩形类型,并作为一个参数传递给User32.dll库中的PtInRect函数,    
函数的不受管辖原型声明如下:    
BOOL  PtInRect(const  RECT  *lprc,  POINT  pt);    
注意你必须通过引用传递Rect结构参数,因为函数需要一个Rect的结构指针。    
[C#]    
using  System.Runtime.InteropServices;    

[structlayout(layoutkind.sequential)]    
public  struct  Point  {    
public  int  x;    
public  int  y;    
}    

[structlayout(layoutkind.explicit]    
public  struct  Rect  {    
[FieldOffset(0)]  public  int  left;    
[FieldOffset(4)]  public  int  top;    
[FieldOffset(8)]  public  int  right;    
[FieldOffset(12)]  public  int  bottom;    
}    

class  win32api  {    
[DllImport("User32.dll")]    
public  static  extern  Bool  PtInRect(ref  Rect  r,  Point  p);    
}    
类似你可以调用GetSystemInfo函数获得系统信息:    
?  using  System.Runtime.InteropServices;    
[StructLayout(LayoutKind.Sequential)]    
public  struct  SYSTEM_INFO  {    
public  uint  dwOemId;    
public  uint  dwPageSize;    
public  uint  lpMinimumApplicationAddress;    
public  uint  lpMaximumApplicationAddress;    
public  uint  dwActiveProcessorMask;    
public  uint  dwNumberOfProcessors;    
public  uint  dwProcessorType;    
public  uint  dwAllocationGranularity;    
public  uint  dwProcessorLevel;    
public  uint  dwProcessorRevision;    
}    


[DllImport("kernel32")]    
static  extern  void  GetSystemInfo(ref  SYSTEM_INFO  pSI);    

system_info  psi  =  new  system_info();    
GetSystemInfo(ref  pSI);    

类成员的传递    
同样只要类具有一个固定的类成员布局,你也可以传递一个类成员给一个不受管辖的动态链接库函数,下面的例子主要说明如何传递一个sequential顺序定义的MySystemTime类给User32.dll的GetSystemTime函数,  函数用C/C++调用规范如下:  

void  getsystemtime(systemtime*  systemtime);    
不像传值类型,类总是通过引用传递参数.    
[C#]    
[StructLayout(LayoutKind.Sequential)]    
public  class  MySystemTime  {    
public  ushort  wYear;    
public  ushort  wMonth;    
public  ushort  wDayOfWeek;    
public  ushort  wDay;    
public  ushort  wHour;    
public  ushort  wMinute;    
public  ushort  wSecond;    
public  ushort  wMilliseconds;    
}    
class  Win32API  {    
[DllImport("User32.dll")]    
public  static  extern  void  GetSystemTime(MySystemTime  st);    
}    
回调函数的传递:    
从受管辖的代码中调用大多数动态链接库函数,你只需创建一个受管辖的函数定义,然后调用它即可,这个过程非常直接。    
如果一个动态链接库函数需要一个函数指针作为参数,你还需要做以下几步:    
首先,你必须参考有关这个函数的文档,确定这个函数是否需要一个回调;第二,你必须在受管辖代码中创建一个回调函数;最后,你可以把指向这个函数的指针作为一个参数创递给DLL函数,.  

回调函数及其实现:    
回调函数经常用在任务需要重复执行的场合,譬如用于枚举函数,譬如Win32  API  中的EnumFontFamilies(字体枚举),  EnumPrinters(打印机),  EnumWindows  (窗口枚举)函数.  下面以窗口枚举为例,谈谈如何通过调用EnumWindow  函数遍历系统中存在的所有窗口  

分下面几个步骤:    
1.  在实现调用前先参考函数的声明    
BOOL  EnumWindows(WNDENUMPROC  lpEnumFunc,  LPARMAM  IParam)    
显然这个函数需要一个回调函数地址作为参数.    
2.  创建一个受管辖的回调函数,这个例子声明为代表类型(delegate),也就是我们所说的回调,它带有两个参数hwnd和lparam,第一个参数是一个窗口句柄,第二个参数由应用程序定义,两个参数均为整形。  

  当这个回调函数返回一个非零值时,标示执行成功,零则暗示失败,这个例子总是返回True值,以便持续枚举。    
3.  最后创建以代表对象(delegate),并把它作为一个参数传递给EnumWindows  函数,平台会自动地  把代表转化成函数能够识别的回调格式。  

[c#]    
using  System;    
using  System.Runtime.InteropServices;    

public  delegate  bool  callback(int  hwnd,  int  lparam);    

public  class  enumreportapp  {    

[dllimport("user32")]    
public  static  extern  int  EnumWindows(CallBack  x,  int  y);    

public  static  void  main()    
{    
CallBack  myCallBack  =  new  CallBack(EnumReportApp.Report);    
EnumWindows(myCallBack,  0);    
}    

public  static  bool  report(int  hwnd,  int  lparam)  {    
Console.Write("窗口句柄为");    
Console.WriteLine(hwnd);    
return  true;    
}    
}    

指针类型参数传递:    
 在Windows  API函数调用时,大部分函数采用指针传递参数,对一个结构变量指针,我们除了使用上面的类和结构方法传递参数之外,我们有时还可以采用数组传递参数。  

 下面这个函数通过调用GetUserName获得用户名    
BOOL  GetUserName(    
LPTSTR  lpBuffer,  //  用户名缓冲区    
LPDWORD  nSize  //  存放缓冲区大小的地址指针    
);    
     
[DllImport("Advapi32.dll",    
EntryPoint="GetComputerName",    
ExactSpelling=false,    
SetLastError=true)]    
static  extern  bool  GetComputerName  (    
[MarshalAs(UnmanagedType.LPArray)]  byte[]  lpBuffer,    
   [MarshalAs(UnmanagedType.LPArray)]  Int32[]  nSize  );    
 这个函数接受两个参数,char  *  和int  *,因为你必须分配一个字符串缓冲区以接受字符串指针,你可以使用String类代替这个参数类型,当然你还可以声明一个字节数组传递ANSI字符串,同样你也可以声明一个只有一个元素的长整型数组,使用数组名作为第二个参数。上面的函数可以调用如下:  

byte[]  str=new  byte[20];    
Int32[]  len=new  Int32[1];    
len[0]=20;    
GetComputerName  (str,len);    
MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));    
 最后需要提醒的是,每一种方法使用前必须在文件头加上:    
 using  System.Runtime.InteropServices;    

计算机类中文核心期刊

计算机类中文核心期刊简介在实际工作中,常有些读者在职称评审、投稿、申报项目时,需要查找计算机类中文权威、核心期刊目录或编辑部地址、联系方式等,现汇编、整理了这份“计算机类中文核心期刊简介”,供参考。

计算机类中文核心期刊目录如下:

1.《软件学报》 (月刊) EI、ISTIC收录
主办单位:中国计算机学会 中国科学院软件研究所
地址:北京8718信箱 北京海淀区中关村《软件学报》编辑委员会
邮编:100080
邮发代号:82-367
E-mail:jos@iscas.ac.cn
http://www.jos.org.cn http://www.jos.org.cn

2.《计算机学报》 (月刊) EI、ISTIC收录
主办单位:中国计算机学会 中国科学院计算技术研究所
地址:北京2704信箱 中国科学院计算技术研究所 《计算机学报》编辑部
邮编:100080
邮发代号:2-833
E-mail: cjc@ict.ac.cn
http://www.ict.ac.cn/cjc/cjc.html cjc@ict.ac.cn http://www.ict.ac.cn/cjc/cjc.html

3.《计算机研究与发展》 (月刊) ISTIC收录
主办单位:中国科学院计算技术研究所 中国计算机学会
地址:北京2704信箱 中国科学院计算技术研究所 《计算机研究与发展》 编辑委员会
邮编:100080
邮发代号:2-654 E-mail:crad@ict.ac.cn
http:// crad.ict.ac.cn

4.《计算机工程 (半月刊)》 ISTIC收录
主办单位:华东计算技术研究所 上海市计算机学会
地址:上海市漕河泾桂林路418号 《计算机工程》编辑部
邮编:200233
邮发代号:4-310
E-mail:hdsce@china.com
http://www.jsjc.chinajournal.net.cn http://www.jsjc.chinajournal.net.cn

5.《自动化学报》 (双月刊) EI、ISTIC收录
主办单位:中国自动化学会 中国科学院自动化研究所
地址:北京中关村中国科学院自动化所《自动化学报》编辑部
邮编:100080
邮发代号:2-180
E-mail:aas@iamail.ia.ac.cn http://www.chinainfo.gov.cn/periodical/zdhxb http://www.chinainfo.gov.cn/periodical/zdhxb

6 .《模试识别与人工智能》 (季刊) ISTIC收录
主办单位:中国自动化学会 国家智能计算机研究开发中心
地址:合肥1130信箱 中国科学院合肥智能机械研究所 《模式识别与人工智能》编辑部
邮编230031
邮发代号:26-69
E-mail:bjb@mail.iim.ac.cn

7.《小型微型计算机系统》 (月刊) ISTIC收录
主办单位:中科院沈阳计算技术研究所 地址:沈阳市和平区三好街100号 中科院沈阳计算技术研究所 《小型微型计算机系统》编辑部
邮编:110004
邮发代号:8-108
E-mail:xwjxt@sict.ac.cn
http://www. sict.ac.cn

8.《计算机科学》 (月刊) ISTIC收录
主办单位:国家科技部西南信息中心
地址:重庆市渝中区胜利路132号 《计算机科学》杂志社
邮编:400013
邮发代号:78-68
E-mail:jsjkx@swic.ac.cn

9.《计算机应用与软件》(月刊)
主办单位:上海市计算技术研究所 上海计算机软件技术开发中心
地址:上海市愚园路546号 《计算机应用与软件》编辑部
邮编:200040
邮发代号:4-379

10.《数值计算与计算机应用》 (季刊) ISTIC收录
主办单位:中国科学院计算数学与科学工程计算研究所
地址:北京市2719信箱 《数值计算与计算机应用》编辑部
邮编:100080
邮发代号:2-413
E-mail:SZJS@chinajournal.net.cn http://www.chinainfo.gov.cn/periodical http://www.chinainfo.gov.cn/periodical

11.《计算机工程与应用》 (旬刊) ISTIC收录
主办单位:华北计算技术研究所
地址:北京市北四环中路211号 北京619信箱26分箱《计算机工程与应用》杂志社
邮编:100083
邮发代号:82-605
投稿信箱: tjit@public2.bat.net.cn
                 cea@163bj.com
http://www.chinainfo.gov.cn/periodical/ tjit@public2.bat.net.cn cea@163bj.com
http://www.chinainfo.gov.cn/periodical/

12.《计算机应用研究》 (月刊) ISTIC收录
主办单位:四川省电子计算机应用研究中心
地址:成都市人民南路4段11号附1号 《计算机应用研究》杂志社
邮编:610041
邮发代号:62-68
E-mail:SRCCA@SICHUAN.NET.CNSRCCA@SICHUAN.NET.CN

13.《计算机工程与科学》 (双月刊) ISTIC收录
主办单位:国防科技大学计算机学院
地址:湖南长沙砚瓦池正街47号 《计算机工程与科学》编辑部
邮编:410073
邮发代号:42-153
E-mail:cchunxi@163.net
             cchunxi@163.net

14.《中文信息学报》 (双月刊) ISTIC收录
主办单位:中国科学院软件研究所 中国中文信息学会
地址:北京8718信箱 《中文信息学报》编辑部
邮编:100080
E-mail:cips@admin.iscas.ac.cn

15.《计算机应用》 (月刊) ISTIC收录
主办单位:中科院成都计算机应用研究所 四川省计算机学会
地址:成都市人民南路四段九号 成都237信箱《计算机应用》编辑部
邮编:610041
邮发代号:62-110
E-mail:bjb@computerapplications.com.cn   http://www.computerapplications.com.cn

16.《计算机辅助设计与图形学学报》 (月刊) ISTIC收录
主办单位:中国计算机学会
地址:北京2704信箱 中国科学院计算技术研究所
邮编:100080
邮发代号:82-456
E-mail:jcad@ict.ac.cn
http://jcad.ict.ac.cn
http://jcad.ict.ac.cn

17.《计算机科学与技术》(英文版) (双月刊) SCIE、EI收录
主办单位:中国科学院计算技术研究所
地址:北京2704信箱
邮编:100080
邮发代号:2-578
E-mail:jcst@ict.ac.cn
http://jcst.ict.ac.cn
http://jcst.ict.ac.cn

18.《计算机工程与设计》 (月刊)
主办单位:中国航天科工集团二院706所
地址:北京142信箱406分箱 《计算机工程与设计》编辑部
邮编:100854
邮发代号:82-425
E-mail:ced@httx.com.cn
           ced@httx.com.cn

19.《 微电子学与计算机》 (月刊)
主办单位:中国航天科技集团公司西安微电子技术研究所
地址:西安市81号信箱 《 微电子学与计算机》编辑部
邮编:710054
邮发代号:52-16
说明:检索系统摘引情况选定三个系统,即SCI(科学引文索引)、EI(工程索引)和 ISTIC (中国科技期刊引证报告统计源期刊),未注明者为非统计源期刊, 参照1999年度的数据。
2005年11月05日

本人为贵州大学计算机应用技术在读研究生(详见我的个人简历),有大量网上在线时间,所以面向社会各界人士提供以下服务:

1、计算机应用在线答疑(通过QQ等交流),提供计算机应用方面的问题解决方案、解决问题(如确实需要,可上门服务,具体再议)。一般问题,价格按小时计;如有特殊情况,价格再议。先付一半做定金,问题解决后,再付另一半。如无法解决,如数退款。

2、为公司或个人开发软件,如MIS等。建设网站。如果项目实在太大,我可以找人一起做,保证按时交付。价格视具体项目而定。

服务范围:

第一项服务只要方便在线交流就好。

第二项服务最好在贵阳市范围内。(因为涉及到需求分析,需要面对面交流等问题)

欢迎与我联系,洽谈业务!

联系方式:

QQ:28725056           Email:lovercn@gmail.com

手机:13595153901




基 本 信 息
名: 王先生 别:
出生日期: 1983年01月30日 居 住 地: 贵阳市贵州大学花溪北区
工作年限: 一年以上 口: 山东
编: 550025
电子邮件: lovercn@gmail.com             手       机:          13595153901
QQ: 28725056
留言: http://blog.donews.com/meson/contact.aspx
自 我 评 价
务实、善于协同“作战”
求 职 意 向
工作性质: 兼职
希望行业: 计算机
期望工资: 面议
目标职能: 技术支持工程师,软件工程师,网络工程师
工 作 经 验

2005/03–2005/08:济南创博科技公司

所属行业:

通讯/电信

系统集成部

系统集成/支持

负责为联通等提供技术支持(主要为增值业务,如彩信、秘书台等)


2004/09–2005/01:中智伟业股份有限公司

所属行业:

计算机

技术

软件工程师

机顶盒内软件开发
使用Linux下的C语言
参与浏览器的开发、移植,主要负责用户界面部分


2003/01–2003/07:山东建筑工程学院

所属行业:

计算机

空调系

网页设计/制作

网站设计、开发,及日常维护。

项 目 经 验
2005/02–2005/04:机顶盒软件开发
软件环境: Linux,C
硬件环境: 先在pc上实现,再向机顶盒移植
开发工具: gcc等
项目描述: 机顶盒软件开发,主要为浏览器部分。从网络接受一定格式的文件信息,然后还原在机顶盒内。初步实现用机顶盒浏览网页、听歌曲等功能,暂不实现交互。先在linux下实现,然后向机顶盒移植,显示接口暂用framebuffer代替。
责任描述: 参与对文件的接受、还原部分。主要做用户接口部分。


2004/01–2004/07:使用.NET技术实现分布式网站系统的资源发布
软件环境: Microsoft Visual Studio .NET
开发工具: vb.net+sql server
项目描述: 基于分布式和.NET技术的视频点播系统,是分布式网站系统的一种应用实例。我们所提出并开发的系统共包括三个部分(一级服务器端、二级服务器端、客户端),此系统充分利用了分布式的特点,平衡了服务器的压力;同时又充分利用了带宽,平衡了网络负载。
责任描述: 我所负责开发的中心站(一级服务器端),主要有四个模块,分别为:
主界面模块
数据库配置模块
登录模块
文件管理模块
数据库内容写文本文件模块
教 育 经 历
2005/09–至今: 贵州大学 计算机应用 硕士
多媒体技术方向


2000/09–2004/07: 山东建筑工程学院 计算机科学与技术 本科
主修课程:C语言程序设计、离散数学、电路与电子学、数字逻辑、汇编语言、数据结构、计算机组成原理、编译原理、面向对象程序设计(C++)、多媒体技术、人工智能、数据库原理、操作系统、系统结构、专业英语、计算机辅助设计、管理信息系统、电子商务与电子政务、计算机网络、软件工程、算法分析与设计、单片机设计及应用、接口技术
(如需要可提供成绩单)
证 书
2003/10 校级三好学生


2003/07 大学英语四级 合格
语 言 能 力
英语 良好
IT 技 能
技能名称 熟练程度 使用时间


C/C++ 精通 12月
SQL Server 熟练

5月

2005年07月18日

<p>

class Elevator{
      boolean running = true;
      void shutDown(){
    running = false;
      }
}

class FrontDesk{
      private final int EVENING = 8;
      Elevator NorthElevator,SouthElevator;

     FrontDesk(){
    NorthElevator = new Elevator();
    SouthElevator = new Elevator();
      }

      void maintenance(int time){
    if(time == EVENING)
   NorthElevator.shutDown();
      }
     
      void displayStatus(){
    System.out.print("North Elevator is ");
           if(!(NorthElevator.running))
     System.out.print("not ");
    System.out.println("running!");
           if(!(SouthElevator.running))
   System.out.print("not ");
    System.out.println("running!");
      }
}

public class Hotel{
    public static void main(String args[]){
    FrontDesk lobby;
   lobby = new FrontDesk();
   System.out.println("it’s 7:00.time to check the elevators.");
   lobby.maintenance(7);
   lobby.displayStatus();

   System.out.println();
   System.out.println("it’s 8:00.time to check the elevators.");
   lobby.maintenance(8);
   lobby.displayStatus();
     }
}

Running Result:

C:\Documents and Settings\Administrator\桌面\javatest>java Hotel
it’s 7:00.time to check the elevators.
North Elevator is running!
running!

it’s 8:00.time to check the elevators.
North Elevator is not running!
running!

<p>