编程爱好者电子杂志 2001年第七期出版日期: 2001年9月9日
欢迎光临编程爱好者网站: http://www.programfan.com
【杂志网站】【编辑信箱】【提问信箱】【过刊查询】【杂志订退】
本 期 内 容
编 者 絮 语
由于本人工作繁忙等原因,导致本刊一直无法正常发送,甚至一度从周刊变成了月刊,为此,很对不起广大喜爱本刊的朋友们。为此,我下定决心,再累再忙,也不能让大家等。从今天开始,本刊恢复为周刊,没有意外情况,每周日发送,请大家监督。也希望大家能一起参与到杂志中的各个栏目里来。谢谢!
编 程 爱 好 者 网 站 最 新 更 动
更多文章,尽在编程爱好者网站
● 利用C++ Builer编制控制台程序 2001-9-8 (点击数:14)
● 在Web页面中执行Windows程序 2001-9-8 (点击数:20)
● ASP备份数据库 2001-9-8 (点击数:10)
● VB中字符串中文的问题 2001-9-8 (点击数:15)
● 在TextBox中查找和继续查找 2001-9-8 (点击数:14)
● 在ASP中优化数据库处理 2001-9-8 (点击数:6)
● 利用VB控制窗口显示风格 2001-9-5 (点击数:28)
● 用程序模拟键盘和鼠标键盘 2001-9-5 (点击数:44)
● VB编程如何控制I/O口 2001-9-5 (点击数:72)
● 在VB中引用.dbf及索引文件 2001-9-5 (点击数:30)
● 在VB应用软件中实现动画效果 2001-9-5 (点击数:41)
● 怎样实现动画背景旗帜 2001-9-5 (点击数:25)
● 得到95和NT中正在运行的进程 2001-9-5 (点击数:51)
● 用Java程序生成文本的捷径 2001-9-5 (点击数:25)
● 在JSP中写text文件 2001-9-4 (点击数:26)
● 浅谈足球游戏的人工智能 2001-9-4 (点击数:53)
● 即时战略游戏将领指挥AI方案设想 2001-9-4 (点击数:37)
● 如何在VC5下定制多媒体真彩封页 2001-9-4 (点击数:20)
● 在程序中实现网站链接和发送邮件 2001-9-4 (点击数:41)
● DirectInput 鼠标编程入门 2001-9-4 (点击数:32)
● win32asm原理 2001-9-4 (点击数:66)
● VB与VC混合编程中处理消息的方法 2001-9-4 (点击数:63)
● 掀起硬盘主引导扇区的神秘面纱 2001-9-4 (点击数:73)
● 谈用Delphi程序获取拨号连接的动态IP地址 2001-9-2 (点击数:27)
● Delphi开发用DOA运行存储过程 2001-9-2 (点击数:40)
● Windows API函数使用技巧 2001-9-2 (点击数:84)
● 如何使Delphi得的程序有大小两种图标状态 2001-9-2 (点击数:36)
● DELPHI下的多线程程序设计 2001-9-2 (点击数:48)
● 利用VB制作MP3播放列表 2001-9-2 (点击数:41)
● 用VC++制作动画窗口的实例 2001-9-2 (点击数:64)
● Delphi编程:完全控制桌面的实现 2001-9-2 (点击数:54)
用 Java 保存位图文件
摘要
虽然 Java 提供了几种打开图像的机制,但保存图像并不是它的强项。这篇技巧将讲述如何将图像保存在 24 位位图文件中。另外,Jean-Pierre 还提供了将图像文件写入位图文件所需的全部代码。
这篇技巧是 "在 Java 应用程序中加载位图文件的逐步指南" 的补充,那篇技巧说明了在 Java 应用程序中加载位图文件的过程。本月我再提供一篇教程,说明如何将图像保存在 24 位位图文件中,其中还包含将图像对象写入位图文件的代码片断。
如果您在 Microsoft Windows 环境中工作,那么创建位图文件的功能将为您提供许多方便。例如,在我的上一个项目中,我必须将 Java 与 Microsoft Access 对接。Java 程序允许用户在屏幕上绘图。这幅图随后被打印到 Microsoft Access 报表中。由于 Java 不支持 OLE,我的唯一选择就是创建该图的一个位图文件,并通知 Microsoft Access 报表在何处能找到这个位图文件。如果您写过向剪贴板发送图像的应用程序,则这个技巧可能对您有用 -- 尤其是当您将这个信息传递给另一个应用程序时。
位图文件的格式
位图文件格式支持 4 位 RLE(行程长度编码)以及 8 位和 24 位编码。因为我们只处理 24 位格式,所以下面我们查看一下该文件的结构。
位图文件分为三个部分。我已将它们列在下面。
第 1 部分:位图文件的标头
标头包含位图文件的类型大小信息和版面信息。结构如下(摘自 C 语言结构定义):
typedef struct tagBITMAPFILEHEADER {
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
下面是对这个清单中的代码元素的说明:
bfType:指定文件类型,其值始终为 BM。
bfSize:指定整个文件的大小(以字节为单位)。
bfReserved1:保留 -- 必须为 0。
bfReserved2:保留 -- 必须为 0。
bfOffBits:指定从 BitmapFileHeader 到图像首部的字节偏移量。
现在您已经明白位图标头的用途就是标识位图文件。读取位图文件的每个程序都使用位图标头来进行文件验证。
第 2 部分:位图信息标头
随后的标头称为信息标头,其中包含图像本身的属性。
下面说明如何指定 Windows 3.0(或更高版本)设备独立位图 (DIB) 的大小和颜色格式:
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
以上代码清单的每个元素说明如下:
biSize:指定 BITMAPINFOHEADER 结构所需的字节数。
biWidth:指定位图的宽度(以象素为单位)。
biHeight:指定位图的高度(以象素为单位)。
biPlanes:指定目标设备的位面数。这个成员变量的值必须为 1。
biBitCount:指定每个象素的位数。其值必须为 1、4、8 或 24。
biCompression:指定压缩位图的压缩类型。在 24 位格式中,该变量被设置为 0。
biSizeImage:指定图像的大小(以字节为单位)。如果位图的格式是 BI_RGB,则将此成员变量设置为 0 是有效的。
biXPelsPerMeter:为位图指定目标设备的水平分辨率(以“象素/米”为单位)。应用程序可用该值从最符合当前设备特征的资源群组中选择一个位图。
biYPelsPerMeter:为位图指定目标设备的垂直分辨率(以“象素/米”为单位)。
biClrUsed:指定位图实际所用的颜色表中的颜色索引数。如果 biBitCount 设为 24,则 biClrUsed 指定用来优化 Windows 调色板性能的参考颜色表。
biClrImportant:指定对位图的显示有重要影响的颜色索引数。如果此值为 0,则所有颜色都很重要。
现在已定义了创建图像所需的全部信息。
第 3 部分:图像
在 24 位格式中,图像中的每个象素都由存储为 BRG 的三字节 RGB 序列表示。每个扫描行都被补足到 4 位。为了使这个过程稍复杂一点,图像是自底而上存储的,即第一个扫描行是图像中的最后一个扫描行。下图显示了标头 (BITMAPHEADER) 和 (BITMAPINFOHEADER) 以及部分图像。各个部分由垂线分隔:
0000000000 4D42 B536 0002 0000 0000 0036 0000 | 0028
0000000020 0000 0107 0000 00E0 0000 0001 0018 0000
0000000040 0000 B500 0002 0EC4 0000 0EC4 0000 0000
0000000060 0000 0000 0000 | FFFF FFFF FFFF FFFF FFFF
0000000100 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
*
现在,我们开始检视代码
现在我们已经知道了 24 位位图文件的结构,下面就是您期待已久的内容:用来将图像对象写入位图文件的代码。
import java.awt.*;
import java.io.*;
import java.awt.image.*;
public class BMPFile extends Component {
file://--- 私有常量
private final static int BITMAPFILEHEADER_SIZE = 14;
private final static int BITMAPINFOHEADER_SIZE = 40;
file://--- 私有变量声明
file://--- 位图文件标头
private byte bitmapFileHeader [] = new byte [14];
private byte bfType [] = {'B', 'M'};
private int bfSize = 0;
private int bfReserved1 = 0;
private int bfReserved2 = 0;
private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
file://--- 位图信息标头
private byte bitmapInfoHeader [] = new byte [40];
private int biSize = BITMAPINFOHEADER_SIZE;
private int biWidth = 0;
private int biHeight = 0;
private int biPlanes = 1;
private int biBitCount = 24;
private int biCompression = 0;
private int biSizeImage = 0x030000;
private int biXPelsPerMeter = 0x0;
private int biYPelsPerMeter = 0x0;
private int biClrUsed = 0;
private int biClrImportant = 0;
file://--- 位图原始数据
private int bitmap [];
file://--- 文件部分
private FileOutputStream fo;
file://--- 缺省构造函数
public BMPFile() {
}
public void saveBitmap (String parFilename, Image parImage, int
parWidth, int parHeight) {
try {
fo = new FileOutputStream (parFilename);
save (parImage, parWidth, parHeight);
fo.close ();
}
catch (Exception saveEx) {
saveEx.printStackTrace ();
}
}
/*
* saveMethod 是该进程的主方法。该方法
* 将调用 convertImage 方法以将内存图像转换为
* 字节数组;writeBitmapFileHeader 方法创建并写入
* 位图文件标头;writeBitmapInfoHeader 创建
* 信息标头;writeBitmap 写入图像。
*
*/
private void save (Image parImage, int parWidth, int parHeight) {
try {
convertImage (parImage, parWidth, parHeight);
writeBitmapFileHeader ();
writeBitmapInfoHeader ();
writeBitmap ();
}
catch (Exception saveEx) {
saveEx.printStackTrace ();
}
}
/*
* convertImage 将内存图像转换为位图格式 (BRG)。
* 它还计算位图信息标头所用的某些信息。
*
*/
private boolean convertImage (Image parImage, int parWidth, int parHeight) {
int pad;
bitmap = new int [parWidth * parHeight];
PixelGrabber pg = new PixelGrabber (parImage, 0, 0, parWidth, parHeight,
bitmap, 0, parWidth);
try {
pg.grabPixels ();
}
catch (InterruptedException e) {
e.printStackTrace ();
return (false);
}
pad = (4 - ((parWidth * 3) % 4)) * parHeight;
biSizeImage = ((parWidth * parHeight) * 3) + pad;
bfSize = biSizeImage + BITMAPFILEHEADER_SIZE +
BITMAPINFOHEADER_SIZE;
biWidth = parWidth;
biHeight = parHeight;
return (true);
}
/*
* writeBitmap 将象素捕获器返回的图像转换为
* 所需的格式。请记住:扫描行在位图文件中是
* 反向存储的!
*
* 每个扫描行必须补足为 4 个字节。
*/
private void writeBitmap () {
int size;
int value;
int j;
int i;
int rowCount;
int rowIndex;
int lastRowIndex;
int pad;
int padCount;
byte rgb [] = new byte [3];
size = (biWidth * biHeight) - 1;
pad = 4 - ((biWidth * 3) % 4);
if (pad == 4) // <==== 错误修正
pad = 0; // <==== 错误修正
rowCount = 1;
padCount = 0;
rowIndex = size - biWidth;
lastRowIndex = rowIndex;
try {
for (j = 0; j < size; j++) {
value = bitmap [rowIndex];
rgb [0] = (byte) (value & 0xFF);
rgb [1] = (byte) ((value >> 8) & 0xFF);
rgb [2] = (byte) ((value >> 16) & 0xFF);
fo.write (rgb);
if (rowCount == biWidth) {
padCount += pad;
for (i = 1; i <= pad; i++) {
fo.write (0x00);
}
rowCount = 1;
rowIndex = lastRowIndex - biWidth;
lastRowIndex = rowIndex;
}
else
rowCount++;
rowIndex++;
}
file://--- 更新文件大小
bfSize += padCount - pad;
biSizeImage += padCount - pad;
}
catch (Exception wb) {
wb.printStackTrace ();
}
}
/*
* writeBitmapFileHeader 将位图文件标头写入文件中。
*
*/
private void writeBitmapFileHeader () {
try {
fo.write (bfType);
fo.write (intToDWord (bfSize));
fo.write (intToWord (bfReserved1));
fo.write (intToWord (bfReserved2));
fo.write (intToDWord (bfOffBits));
}
catch (Exception wbfh) {
wbfh.printStackTrace ();
}
}
/*
*
* writeBitmapInfoHeader 将位图信息标头
* 写入文件中。
*
*/
private void writeBitmapInfoHeader () {
try {
fo.write (intToDWord (biSize));
fo.write (intToDWord (biWidth));
fo.write (intToDWord (biHeight));
fo.write (intToWord (biPlanes));
fo.write (intToWord (biBitCount));
fo.write (intToDWord (biCompression));
fo.write (intToDWord (biSizeImage));
fo.write (intToDWord (biXPelsPerMeter));
fo.write (intToDWord (biYPelsPerMeter));
fo.write (intToDWord (biClrUsed));
fo.write (intToDWord (biClrImportant));
}
catch (Exception wbih) {
wbih.printStackTrace ();
}
}
/*
*
* intToWord 将整数转换为单字,返回值
* 存储在一个双字节数组中。
*
*/
private byte [] intToWord (int parValue) {
byte retValue [] = new byte [2];
retValue [0] = (byte) (parValue & 0x00FF);
retValue [1] = (byte) ((parValue >> 8) & 0x00FF);
return (retValue);
}
/*
*
* intToDWord 将整数转换为双字,返回值
* 存储在一个 4 字节数组中。
*
*/
private byte [] intToDWord (int parValue) {
byte retValue [] = new byte [4];
retValue [0] = (byte) (parValue & 0x00FF);
retValue [1] = (byte) ((parValue >> 8) & 0x000000FF);
retValue [2] = (byte) ((parValue >> 16) & 0x000000FF);
retValue [3] = (byte) ((parValue >> 24) & 0x000000FF);
return (retValue);
}
}
小结
这就是所要做的全部工作。我确信您将会发现这个类很有用,因为到 JDK 1.1.6 为止,Java 不支持用任何常用的格式保存图像。JDK 1.2 将支持创建 JPEG 图像,但不支持创建位图。所以这个类仍将填补 JDK1.2 中的空白。
Delphi中保存图像列表
蔡健
最近在做项目时遇到将图像列表(TImageList)中一系列的图像保存到指定的文件或二进制流中,以便在需要时进行动态恢复的情况。于是在Delphi的帮助中查找TImageList类相关的属性、方法,遗憾的是Delphi在TImageList中并未提供SaveToFile和SaveToStream方法,所以针对TImageList目前的限制,必须采取其它的办法来扩展TImageList的功能,以满足实际项目的需要。
解决方法
方法一:
使用API函数ImageList_Write和ImageList_Read。二者都需要指定一个类型为IStream的参数,前者的作用是将指定句柄的图像列表保存到类型为IStream的二进制流中;后者是从类型为IStream的二进制流中读出原先保存的图像列表,并且返回指向这个图像列表的句柄。IStream是一个OLE对象,它在Delphi中的声明为TStreamAdapter = class(TInterfacedObject, IStream),意为TStreamAdapter是从TInterfacedObject继承下来的操纵 IStream接口的对象。通过TStreamAdapter对象可以实现Delphi内部TStream对象对ISTream接口对象的操纵。
方法二:
从TImageList继承一个子类TImageListEx,实现自定义的SaveToFileEx和SaveToStreamEx方法。在默认情况下TImageList中保存的图像是由普通图像及其掩码图像组合而成,所以必须调用其基类TCustomImageList的Protected部分提供的GetImages(Index: Integer; Image, Mask: TBitmap)方法,以获得图像列表中指定索引号的位图及其掩码位图,之后分别保存到自定义的文件或二进制流中,此外还需提供LoadFromFileEx和LoadFromStreamEx方法从自定义的文件或二进制流中恢复图像集合。
实现步骤
自定义的TImageListEx控件在Public部分一并实现了对上述两种方法的封装。
TImageListEx类源代码如下:
unit ImageListEx;
interface
uses Windows, SysUtils, Classes, Graphics, Controls, Commctrl, ImgList, Consts;
type
TImageListEx = class(TImageList)
public
procedure LoadFromFile(const FileName: string);//实现API方式保存
procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(const FileName: string);
procedure SaveToStream(Stream: TStream);
procedure LoadFromFileEx(const FileName: string);//实现自定义方式保存
procedure LoadFromStreamEx(Stream: TStream);
procedure SaveToFileEx(const FileName: string);
procedure SaveToStreamEx(Stream: TStream);
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('ImageListEx', [TImageListEx]);
end;
{ TImageListEx }
procedure TImageListEx.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
procedure TImageListEx.LoadFromFileEx(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
LoadFromStreamEx(Stream);
finally
Stream.Free;
end;
end;
procedure TImageListEx.LoadFromStream(Stream: TStream);
var
SA: TStreamAdapter;
begin
SA := TStreamAdapter.Create(Stream);
try
Handle := ImageList_Read(SA);//将当前图像列表的句柄指向从二进制流中得到的句柄
if Handle = 0 then
raise EReadError.CreateRes(@SImageReadFail);
finally
SA.Free;
end;
end;
procedure TImageListEx.LoadFromStreamEx(Stream: TStream);
var
Width, Height: Integer;
Bitmap, Mask: TBitmap;
BinStream: TMemoryStream;
procedure LoadImageFromStream(Image: TBitmap);
var
Count: DWORD;
begin
Image.Assign(nil);
Stream.ReadBuffer(Count, SizeOf(Count));//首先读出位图的大小
BinStream.Clear;
BinStream.CopyFrom(Stream, Count);//接着读出位图
BinStream.Position := 0;//流指针复位
Image.LoadFromStream(BinStream);
end;
begin
Stream.ReadBuffer(Height, SizeOf(Height));
Stream.ReadBuffer(Width, SizeOf(Width));
Self.Height := Height;
Self.Width := Width;//恢复图像列表原来的高度、宽度
Bitmap := TBitmap.Create;
Mask := TBitmap.Create;
BinStream := TMemoryStream.Create;
try
while Stream.Position <> Stream.Size do
begin
LoadImageFromStream(Bitmap);//从二进制流中读出位图
LoadImageFromStream(Mask);//从二进制流中读出掩码位图
Add(Bitmap, Mask);//将位图及其掩码位图合并添加到图像列表中
end;
finally
Bitmap.Free;
Mask.Free;
BinStream.Free;
end;
end;
procedure TImageListEx.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
procedure TImageListEx.SaveToFileEx(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStreamEx(Stream);
finally
Stream.Free;
end;
end;
procedure TImageListEx.SaveToStream(Stream: TStream);
var
SA: TStreamAdapter;
begin
SA := TStreamAdapter.Create(Stream);
try
if not ImageList_Write(Handle, SA) then//将当前图像列表保存到二进制流中
raise EWriteError.CreateRes(@SImageWriteFail);
finally
SA.Free;
end;
end;
procedure TImageListEx.SaveToStreamEx(Stream: TStream);
var
I: Integer;
Width, Height: Integer;
Bitmap, Mask: TBitmap;
BinStream: TMemoryStream;
procedure SetImage(Image: TBitmap; IsMask: Boolean);
begin
Image.Assign(nil);//清除上一次保存的图像,避免出现图像重叠
with Image do
begin
if IsMask then Monochrome := True;//掩码位图必须使用单色
Height := Self.Height;
Width := Self.Width;
end;
end;
procedure SaveImageToStream(Image: TBitmap);
var
Count: DWORD;
begin
BinStream.Clear;
Image.SaveToStream(BinStream);
Count := BinStream.Size;
Stream.WriteBuffer(Count, SizeOf(Count));//首先保存位图的大小
Stream.CopyFrom(BinStream, 0);//接着保存位图
end;
begin
Height := Self.Height;
Width := Self.Width;
Stream.WriteBuffer(Height, SizeOf(Height));//保存原图像列表的高度
Stream.WriteBuffer(Width, SizeOf(Width));//保存将原图像列表的宽度
Bitmap := TBitmap.Create;
Mask := TBitmap.Create;
BinStream := TMemoryStream.Create;
try
for I := 0 to Count - 1 do//遂一保存图像列表中的图像
begin
SetImage(Bitmap, False);
SetImage(Mask, True);
GetImages(I, Bitmap, Mask);//取得指定索引号的位图及其掩码位图
SaveImageToStream(Bitmap);//保存位图到二进制流中
SaveImageToStream(Mask);//保存掩码位图到二进制流中
end;
finally
Bitmap.Free;
Mask.Free;
BinStream.Free;
end;
end;
end.
下面示范在Delphi中的使用方法:
首先在Delphi中新建一个项目,然后在Form1上放置一个ImageListEx控件,一个TreeView控件和四个Button控件。将TreeView控件的Images属性与ImageListEx相关联,在ImageListEx中任意添加几幅图像,在TreeView中添加相应数量的项目,项目的ImageIndex属性分别对应于ImageListEx中图像的索引号。现在TreeView中每个项目之前已经能够显示出相应的图标。
最后,在Button1的OnClick事件中写上:
ImageListEx1.SaveToFile('C:\CJ.dat');
ImageListEx1.SaveToFileEx('C:\CJEx.dat');
在Button2的OnClick事件中写上:ImageListEx1.Clear;
在Button3的OnClick事件中写上:ImageListEx1.LoadFromFile('C:\CJ.dat');
在Button4的OnClick事件中写上:ImageListEx1.LoadFromFileEx('C:\CJEx.dat');
运行程序,首先单击Button1,之后单击Button2,最后任意单击Button3或Button4,可以看到程序能够将图像列表中的图像保存到指定的文件中,可以从指定的文件中正确的恢复并显示。
结束语
本文介绍的内容已用于解决本人在实际项目中遇到的情况,也希望同样遇到此问题的程序员能够从中找到答案。以上代码在 Delphi5.0、Windows2000 Server 中调试运行通过。
如何在程序中获得其他程序的图标
两种方法:
(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,
(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.
Example(1):
在程序窗口左上角显示 NotePad图标.
void CSampleView:
OnDraw(CDC * pDC)
{
if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,
&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
{
pDC ->DrawIcon(10,10,stFileInfo.hIcon)
}
}
Example(2):同样功能,Use ExtractIcon Function
void CSampleView:: OnDraw(CDC *pDC)
{
HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
("NotePad.exe"),0)
if (hIcon &&hIcon!=(HICON)-1)
pDC->DrawIcon(10,10,hIcon)
}
说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点.
用VFP在INTERNET上制作数据库动态查询
要在INTERNET上制作数据库动态查询,关键的问题是在INTERNET上建立与数据库的连接,在INTERNET上与数据库建立连接有很多方法,如CGI、ASP、JDK等,在这里介绍一种利用VFP6.0简单编程语句及HTML的标准格式相结合建立FOXPRO数据库连接的方法,这一方法对于我国早期大量DBASE数据库开发人员引入INTERNET编程具有莫大的帮助。它的最基本思想是利用FOXPRO的过程返回一个文件(并非一般的过程或函数返回的是狭义值)HTML文件。这样客户端浏览器提供参数在服务器请求获取数据时,服务器端根据客户端提供参数在服务器端运行FOXPRO的过程返回给客户端一个HTML格式文档,这样客户端浏览器把HTML格式文档翻译成我们所见到到数据网页。
环境:WIN98操作系统、WEB个人服务器系统、ASP服务器系统、VFP6.0。(这些软件的安装方法比较简单、依软件的安装程序提示做即可)。
如下详述一例说明其制作过程:
首先在c盘建一目录gd,并创建一数据表tt.dbf(以前称数据库)字段为code及item,并输入数据。
一、VFP6.0中制作DLL
在VFP6.0中的项目管理器中新建一个项目文件GD.PJX,然后在项目管理器中的类标签中新建一个类gd.vcx,其派生于custom类,然后在主菜单类选项中进入类信息对话框,选上类为OLE公共,按确定按钮退出,然后在主菜单类选项中进入新建方法程序中添加一个名为li可视性为公共的方法程序,按关闭退出,然后按鼠标右键,进入gd.vcx(gd)属性对话框,在方法程序中找到li并双击鼠标进入其程序编辑窗口,并输入如下内容:
lparameters ivar,inifile,iniflag
set default to c:\gd
use tt
set textmerge on
set textmerge to li_hua_01.htm
$#@60;table$#@62;
scan
$#@60;tr$#@62;$#@60;td$#@62;$#@60;$#@60;alltrim(code)$#@62;$#@62;$#@60;/td$#@60;/td$#@62;$#@60;$#@60;alltrim(item)$#@62;$#@62;$#@60;/td$#@62;$#@60;/tr$#@62;
endscan
$#@60;table$#@62;
set textmerge off
set textmerge to
create cursor temp (mm m)
append blank
append memo mm from li_hua_01.htm
vr=temp.mm
use in temp
close database all
erase li_hua_01.htm
return vr
然后关闭保存这一方法程序及关闭保存gd.vcx(gd)类设计器,在gd的项目管理器中单 啵∩狭郼om dll,按确定,这样就完成了gd.dll的制作,并在机中注册了这一类库。
二、制作ASP文档
在WEB个人服务器系统设置C:\gd这一目录为可运行。并在此目录创建一ASP文档(gd.asp),内容为:
$#@60;HTML$#@62;
$#@60;HEAD$#@62;
数据库查询网页
$#@60;/HEAD$#@62;
$#@60;BODY $#@62;
$#@60;%SET gd=server.createobject("gd.gd")%$#@62;
$#@60;%=gd.li%$#@62;
$#@60;/BODY$#@62;
$#@60;/HTML$#@62;
这样你在浏览器键入hyperlink http://你的计算机名/gd http://你的计算机名/gd的虚拟目录/gd.asp即可看到数据库的数据,上面的例只是介绍其制作的基本思想和方法,只要了解其基本思想和方法并用你们的丰富的vfp编程技术,你们可制作出丰富多彩的动态的数据库网页。
用VB5 Winsock控件创建TCP\IP客户机服务器程序
随着Windows 95中文版和Windows NT Server 4.0中文版的流行, Microsoft公司推出了相应平台上的开发软件: Visual Basic 5.0 中文企业 版。它为Windows环境下的网络开发提供了强大的工具,Winsock控件就是其中之一。
Winsock控件建立在TCP、UDP协议的基础上,完成与远程计算机的通信。即使对TCP/IP不太熟悉的用户,使用该控件也可以在十几分钟内创建一个简单的客户机/服务器程序。下面我们对Winsock控件的事件、方法、属性按其在程序中出现的顺序分别作详细的介绍,以便更好地理解程序源代码。
服务器程序的实现过程是:
(1)服务器程序必须设置好LocalPort属性,作为侦听端口,该值为一个整数(只要是一个其它TCP/IP应用程序没有使用过的值即可)。
(2)使用Listen方法进入侦听状态,等待客户机程序的连接请求。
(3)客户机程序发出连接请求,使服务器程序产生ConnectionRequest事件,该事件得到一个参数requestID。
(4)服务器程序用Accept方法接受客户机程序的requestID请求。这样,服务器程序就可以用SendData方法发送数据了。Accept方法必须用上一步得到的requestID作为其参数。
(5)当服务器程序接收到数据时,产生DataArrival事件,参数BytesTotal包含接收到的数据字节数。在该事件中,可以用GetData方法接收数据。
(6)如果接受到Close事件,则用Close方法关闭TCP/IP连接。
客户机程序的实现过程是:
(1) 客户程序设置Remotehost属性,以便指定运行服务器程序的主机 名,该字符串可在“控制面板|网络|标识|计算机名”中查到。
(2) 设置RemotePort属性,以便指定服务器程序的侦听端口。
(3)使用Connect方法,向服务器提出连接请求。
(4)服务器接受客户机程序的请求,客户机程序产生Connect事件,就可以用SendData方法发送数据了。
(5)当客户机程序接收到数据时,产生DataArrival事件,参数BytesTotal包含接收到的数据字节数。在该事件中,可以用GetData方法接收数据。
(6)如果接受到Close事件,则用Close方法关闭连接。
Winsock控件还有两个重要的属性,即Protocol和State。Protocol设定使用的协议是TCP还是UDP:取值sckTCPProtocol表示TCP, 取值sckUDPProtocol则表示UDP。因为Winsock控件的缺省设置是sckTCPProtocol,所以程序中并没有使用Protocol属性。State属性反映的是当前TCP/IP的连接状态,取值如表1所示。
表1 Winsock控件的State属性及其描述
常数 值 描述
sckClosed 0 缺省值,关闭。
SckOpen 1 打开。
SckListening 2 侦听
sckConnectionPending 3 连接挂起
sckResolvingHost 4 识别主机。
sckHostResolved 5 已识别主机
sckConnecting 6 正在连接。
sckConnected 7 已连接。
sckClosing 8 同级人员正在关闭连接。
sckError 9
错误。
先在一台计算机上运行服务器程序,此时窗口上只有一个“退出”按钮。 再在另一台计算机上运行客户机程序,在“连接”按钮右边的文本框中输入服务器 的主机名后单击“连接”按钮。如果连接成功,则服务器和客户机程序窗口都会出现两个文本框。这时,两端都可以在上面的文本框中输入文字,这些文字会立即在下面的文本框中出现。
服务器程序使用的控件如下:
(1)Command1:退出按钮;
(2)textsend:发送数据文本框;
(3)Winsockserver: 服务器Winsock;
(4)textget :接收数据文本框。
服务器程序的界面如图所示。
服务器程序的源代码如下:
Private Sub Command1_Click()
End
End Sub
Private Sub Form_Load()
textsend.Visible = False
textget.Visible = False
Winsockserver.LocalPort = 1001
Winsockserver.Listen
End Sub
Private Sub textsend_Change()
Winsockserver.SendData textsend.Text
End Sub
Private Sub Winsockserver_Close()
Winsockserver.Close
End
End Sub
Private Sub Winsockserver_ConnectionRequest(ByVal requestID As Long)
textsend.Visible = True
textget.Visible = True
If Winsockserver.State <> sckClosed Then Winsockserver.Close
Winsockserver.Accept requestID
End Sub
Private Sub Winsockserver_DataArrival(ByVal bytesTotal As Long)
Dim tmpstr As String
Winsockserver.GetData tmpstr
textget.Text = tmpstr
End Sub
客户机程序使用的控件如下:
(1)Command1:退出按钮;
(2)Command2:连接按钮;
(3)Winsockclient:客户Winsock;
(4)Text1:主机名文本框;
(5)Textsend:发送数据文本框;
(6)Textget:接收数据文本框; 客户机程序的界面如图所示。
客户机程序的源代码如下:
Private Sub Command1_Click()
End
End Sub
Private Sub Command2_Click()
Winsockclient.Connect
End Sub
Private Sub Form_Load()
textsend.Visible = False
textget.Visible = False
Winsockclient.RemotePort = 1001
Winsockclient.RemoteHost = "sccdsz"
End Sub
Private Sub Text1_Change()
Winsockclient.RemoteHost = Text1.Text
End Sub
Private Sub textsend_Change()
Winsockclient.SendData textsend.Text
End Sub
Private Sub Winsockclient_Close()
Winsockclient.Close
End
End Sub
Private Sub winsockclient_Connect()
textsend.Visible = True
textget.Visible = True
Command2.Visible = False
End Sub
Private Sub winsockclient_DataArrival(ByVal bytesTotal As Long)
Dim tmpstr As String
Winsockclient.GetData tmpstr
textget.Text = tmpstr
End Sub
(中国银行成都分行电脑处 宋卫华 610061)
最 新 网 友 作 品
如果您也有自己满意的作品,并希望发布推广的话,十分欢迎您能在这里发布。
您可以通过发布作品页面来递交您的作品。也可以直接将您作品的介绍以及下载地址、您的网址、联系方法等相关信息发给我。如果您尚未有自己的网上空间来发布作品的话,可以直接通过EMAIL寄给我,本站竭诚为您提供发布的空间。如有疑问可以与我联系。
● GetFlash v.0.8.21 Beta 测试版! (更新日期:2001年9月7日 点击数:6)
GetFlash v.0.8.21 Beta 测试版!
有的时候看到网页上精美的 Flash 动画想收藏到自己的硬盘上来,却苦于无从下手。 ……
● 网易Flash 新闻广告杀手 (更新日期:2001年9月7日 点击数:8)
网易的新闻报道的确很不错,可是现在在看的时候总让人觉得不爽!
现在好端端的新闻之间插了一个 Flash 广告,不仅看的时候 ……
● IE 梦工厂系列 之I 如虎添翼 (更新日期:2001年9月7日 点击数:8)
IE 梦工厂系列 之I 如虎添翼
想像金山毒霸那样在你的IE工具栏里添加一个属于你自己的按钮吗?
想像网络蚂蚁那样在你的IE右键弹出上 ……
● 窗口最前V0.1 (更新日期:2001年9月7日 点击数:48)
topmostv0.1是针对当前大多数软件中缺少将本窗口放置到最前(topmost)的功能,运行topmostv0.1可以在所有窗口的系统菜单中添加一个“窗口最 ……
● 超文档保存管理工具(Sharp Tips Manager) (更新日期:2001年9月6日 点击数:17)
保存管理各种文档,支持HTML(包括图像),TXT,RTF等. 支持在IE中直接保存,可只保存选中的部分(包括图像); 支持拖放保存,粘贴保存. http:// ……
● 文摘集中营2.0 (更新日期:2001年9月2日 点击数:90)
现在网上的东东实在是太多了,每上一次网就会掏到许多文摘,对它们的管理又是麻烦事,Artical Assembly(文摘集中营)为我们解决了这一困难,它可以将.t ……
《编程爱好者》订退方法
请在下面的文本框内输入您订阅本刊的邮件地址,并按右面的订阅按钮即可。如果您觉得这份刊物还不错的话,欢迎把它推荐给您的朋友。
欢迎订阅
不知道您看了这期刊物有什么想法或者是意见,欢迎向我提出来。
本人感激不尽,我的联系方法如下:
Homepage: http://www.programfan.com
E-mail: pfan2000@163.net
OICQ: 15987743
Copyright© 1999-2001 Programfan.com. All Rights Reserved
站长:yaozheng E-mail: pfan2000@163.net OICQ: 15987743
<scrIPTvar tc_user="yaozheng";var tc_class="2";
<scrIPT src="http://stat.t2t2.com/stat.js"