2007年6月16日

'--- module ---
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const WM_USER = &H400
Public Const EM_GETPARAFORMAT = WM_USER + 61
Public Const EM_SETPARAFORMAT = WM_USER + 71
Public Const MAX_TAB_STOPS As Long = 32
Public Const PFM_LINESPACING As Long = 256
Public Type PARAFORMAT2
    cbSize                     As Long
    dwMask                     As Long
    wNumbering                 As Integer
    wEffects                   As Integer
    dxStartIndent              As Long
    dxRightIndent              As Long
    dxOffset                   As Long
    wAlignment                 As Integer
    cTabCount                  As Integer
    rgxTabs(MAX_TAB_STOPS - 1) As Long
    dySpaceBefore              As Long
    dySpaceAfter               As Long
    dyLineSpacing              As Long
    sStyle                     As Integer
    bLineSpacingRule           As Byte
    bOutlineLevel              As Byte
    wShadingWeight             As Integer
    wShadingStyle              As Integer
    wNumberingStart            As Integer
    wNumberingStyle            As Integer
    wNumberingTab              As Integer
    wBorderSpace               As Integer
    wBorderWidth               As Integer
    wBorders                   As Integer
End Type


'--- form ---
'设form上有:RichTextBox(rt)
Private Sub Form_Load()
    rt.Text = "welcome to my company,glad" & vbCrLf & "abcdefghijklmnopqrstuvwxyz"
        Dim pf2 As PARAFORMAT2
    Dim retval As Long
    rt.SelStart = Len(rt)
    pf2.cbSize = LenB(pf2)
    pf2.bLineSpacingRule = 4
    pf2.dyLineSpacing = CLng(500 * Rnd) - 70
    pf2.dwMask = PFM_LINESPACING
    retval = SendMessage(rt.hwnd, EM_SETPARAFORMAT, ByVal 0&, pf2)
End Sub


posted @ 2007-06-16 10:25 TangHuawei 阅读(786) | 评论 (2)编辑

2007年3月5日

    新的一年又开始了!
    去年浑浑噩噩也就过去了,今年刚开始就感觉种种压力压在自己的身上,工作上学习的机会不多,自己也不知道该往哪方面去发展,公司做LED,自己对LED条屏那些协议又不是很了解,又没人可以教我,对232通讯也不尽了解,一切都是很陌生的,要我去写软件我还真不知道该怎么去下手,有时很想转行去干别的,要么搞销售,要么跑业务,要么。。。反正一切很容易发财的门路都想,可是又没那个勇气去做,确实挺难的,自己也老大不小了,也快要结婚了,说到结婚得买房子,汽车之类倒先撇到一边不讲了。
    自己天天都在冥思苦想,到底什么才是适合自己的呢?天天也都在为自己加油打气,一定要出人头地,让别人都觉得自己是个有作为有用的人,让自己的家人感到光荣!
      心里美滋滋的,一天给自己一个定位,一天给自己确切的目标,不实现不罢休,辛辛苦苦干上几年,能让老婆,让自己的家人过上好日子!

posted @ 2007-03-05 16:07 TangHuawei 阅读(83) | 评论 (2)编辑

2007年1月12日

 

Windows控件在Web下的引用,首先我们建立一个window控件,项目名称为EditImagePint,然后,

C#.NET windows控件实现水印(图一)

我们把项目下的UserControl1.cs改为ImagePint.cs,切记文件名和构造函数都改!

先制作界面,首先在设计模式下,我们将一个PictureBox拖放到解面上,命名为pictureBox1

C#.NET windows控件实现水印(图二)

C#.NET windows控件实现水印(图三)

下面我们转入代码页,也就是ImagePint.cs

我们需要引用的对象有:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Net;

然后我们写一个函数

private void ImagePint_Load(object sender, System.EventArgs e)
{
/*具体代码我们下面介绍*/
}

这个函数,是为了在web页面使用时候加载使用的.

然后我们看控件自己的生成代码,把
this.Load += new System.EventHandler(this.ImagePint_Load);
加如InitializeComponent()中
#region 组件设计器生成的代码:

 

///
/// 设计器支持所需的方法 - 不要使用代码编辑器
/// 修改此方法的内容。
///
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// ImagePint
//
this.Controls.Add(this.pictureBox1);
this.Name = "ImagePint";
//看到了吗?很明显,先面的是我们加上去的
this.Load += new System.EventHandler(this.ImagePint_Load);
this.ResumeLayout(false);

}
#endregion

有了这些东西,组件就可以在web下使用了,但是既然是水印,就应该有原始图片,和水印图片,及一些其他的参数,这里我们就用公共函数,至于web怎么把值传进去,我们到下面再说

 

#region 公共属性

//显示宽度
public int ImgWidht
{
get {return _ImgWidth;}
set {_ImgWidth = value;}
}

//显示高度
public int ImgHeight
{
get {return _ImgHeight;}
set {_ImgHeight = value;}
}

//透明度
private int Alpha
{
get {return _Alpha;}
set {_Alpha = value;}
}

//主图片地址
public string ZPicture
{
get {return _ZPicture;}
set {_ZPicture = value;}
}

//水印图片地址
public string FPicture
{
get {return _FPicture;}
set {_FPicture = value;}
}

#endregion

 

下面把完整的代码贡献给大家:

代码拷贝框

[Ctrl+A 全部选择 然后拷贝]

然后我们把这个控件生成一个Release版本,然后把生成的dll文件copy到你的虚拟目录下,然后就是web调用了,我们先建立一个虚拟目录,比如说我们建立的虚拟目录及地址为:
localhost/Object/ImagePrint/
我们就把生成的 EditImagePint.dll 文件copy到这个目录下
并建立一个html文件,把以下的代码放进去:

<object id="print" classid="http://localhost/Object/ImagePrint/
EditImagePint.dll#EditImagePint.ImagePint"
Width="177" Height="144" VIEWASTEXT >
<param name="ImgWidht" value="177">
<param name="ImgHeight" value="144">
<param name="Alpha" value="40">
<param name="ZPicture" value="http://localhost/Object/ImagePrint/my.jpg">
<param name="FPicture" value="http://localhost/Object/ImagePrint/make.jpg">
</object>

看到了把,这些param就是我们的公共属性了:),这样就把值传递进去了

最终显示如下:

C#.NET windows控件实现水印(图四)

转自图中的那位帅哥!

posted @ 2007-01-12 15:38 TangHuawei 阅读(659) | 评论 (1)编辑

一个货币数字转换中文的算法,注意:本文中的算法支持小于1023 (也就是9999亿兆)货币数字转化。

   货币中文说明: 在说明代码之前,首先让我们回顾一下货币的读法。

  10020002.23  读为 壹仟零贰万零贰元贰角叁分
  1020         读为 壹仟零贰拾元整。
  100000       读为 拾万元整
  0.13         读为 壹角叁分

 

  代码:

测试工程
  static void Main(string[] args)
{

Console.WriteLine("请输入金额");
string inputNum = Console.ReadLine();
while (inputNum != "exit")
{

//货币数字转化类
NumCast nc = new NumCast();


if (nc.IsValidated<string>(inputNum))
{
try
{
string chineseCharacter = nc.ConvertToChinese(inputNum);
Console.WriteLine(chineseCharacter);
}
catch (Exception er)
{
Console.WriteLine(er.Message);
}
}
else
{
Console.WriteLine("不合法的数字或格式");
}

Console.WriteLine("\n请输入金额");
inputNum = Console.ReadLine();

}
Console.ReadLine();
}

测试结果如下:

货币转化类(NumCast类)功能介绍

1 常量的规定
 /// <summary>
/// 数位
/// </summary>
public enum NumLevel { Cent, Chiao, Yuan, Ten, Hundred, Thousand, TenThousand, hundredMillon, Trillion };

/// <summary>
/// 数位的指数
/// </summary>
private int[] NumLevelExponent = new int[] { -2, -1, 0, 1, 2, 3, 4, 8, 12 };

/// <summary>
/// 数位的中文字符
/// </summary>
private string[] NumLeverChineseSign = new string[] { "分", "角", "元", "拾", "佰", "仟", "万", "亿", "兆" };

/// <summary>
/// 大写字符
/// </summary>
private string[] NumChineseCharacter = new string[] {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};


/// <summary>
/// 整(当没有 角分 时)
/// </summary>

private const string EndOfInt = "整";

2:数字合法性验证,采用正则表达式验证
 /// <summary>
/// 正则表达验证数字是否合法
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
public bool IsValidated<T>(T Num)
{
Regex reg = new Regex(@"^(([0])|([1-9]\d{0,23}))(\.\d{1,2})?$");
if (reg.IsMatch(Num.ToString()))
{
return true;

}
return false;
}

3: 获取数位 例如 1000的数位为 NumLevel.Thousand

/// <summary>
/// 获取数字的数位 使用log
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
private NumLevel GetNumLevel(double Num)
{
double numLevelLength;
NumLevel NLvl = new NumLevel();
if (Num > 0)
{
numLevelLength = Math.Floor(Math.Log10(Num));
for (int i = NumLevelExponent.Length - 1; i >= 0; i--)
{
if (numLevelLength >= NumLevelExponent[i])
{
NLvl = (NumLevel)i;
break;
}
}
}
else
{
NLvl = NumLevel.Yuan;
}
return NLvl;

}

4:判断数字之间是否有跳位,也就是中文中间是否要加零,例如1020 就应该加零。
 /// <summary>
/// 是否跳位
/// </summary>
/// <returns></returns>
private bool IsDumpLevel(double Num)
{
 if (Num > 0)
{
NumLevel? currentLevel = GetNumLevel(Num);
NumLevel? nextLevel = null;
int numExponent = this.NumLevelExponent[(int)currentLevel];

double postfixNun = Math.Round(Num % (Math.Pow(10, numExponent)),2);
if(postfixNun> 0)
nextLevel = GetNumLevel(postfixNun);
if (currentLevel != null && nextLevel != null)
{
if (currentLevel > nextLevel + 1)
{
return true;
}
}
}
return false;

}

5 把长数字分割为两个较小的数字数组,例如把9999亿兆,分割为9999亿和0兆,

因为计算机不支持过长的数字。
 /// <summary>
/// 是否大于兆,如果大于就把字符串分为两部分,
/// 一部分是兆以前的数字
/// 另一部分是兆以后的数字
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
private bool IsBigThanTillion(string Num)
{
bool isBig = false;
if (Num.IndexOf('.') != -1)
{
//如果大于兆
if (Num.IndexOf('.') > NumLevelExponent[(int)NumLevel.Trillion])
{
isBig = true;
}
}
else
{
//如果大于兆
if (Num.Length > NumLevelExponent[(int)NumLevel.Trillion])
{
isBig = true;
}
}
return isBig;
}

/// <summary>
/// 把数字字符串由‘兆’分开两个
/// </summary>
/// <returns></returns>
private double[] SplitNum(string Num)
{
//兆的开始位
double[] TillionLevelNums = new double[2];
int trillionLevelLength;
if (Num.IndexOf('.') == -1)
trillionLevelLength = Num.Length - NumLevelExponent[(int)NumLevel.Trillion];
else
trillionLevelLength = Num.IndexOf('.') - NumLevelExponent[(int)NumLevel.Trillion];
//兆以上的数字
TillionLevelNums[0] = Convert.ToDouble(Num.Substring(0, trillionLevelLength));
//兆以下的数字
TillionLevelNums[1] = Convert.ToDouble(Num.Substring(trillionLevelLength ));
return TillionLevelNums;
}
 

6 是否以“壹拾”开头,如果是就可以把它变为“拾”
  bool isStartOfTen = false;
while (Num >=10)
{
if (Num == 10)
{
isStartOfTen = true;
break;
}
//Num的数位
NumLevel currentLevel = GetNumLevel(Num);

int numExponent = this.NumLevelExponent[(int)currentLevel];
Num = Convert.ToInt32(Math.Floor(Num / Math.Pow(10, numExponent)));
if (currentLevel == NumLevel.Ten && Num == 1)
{
isStartOfTen = true;
break;
}
}
return isStartOfTen;


7 合并大于兆连个数组转化成的货币字符串

/// <summary>
/// 合并分开的数组中文货币字符
/// </summary>
/// <param name="tillionNums"></param>
/// <returns></returns>
private string ContactNumChinese(double[] tillionNums)
{
string uptillionStr = CalculateChineseSign(tillionNums[0], NumLevel.Trillion, true, IsStartOfTen(tillionNums[0]));
string downtrillionStr = CalculateChineseSign(tillionNums[1], null, true,false);
string chineseCharactor = string.Empty;
//分开后的字符是否有跳位
if (GetNumLevel(tillionNums[1] * 10) == NumLevel.Trillion)
{
chineseCharactor = uptillionStr + NumLeverChineseSign[(int)NumLevel.Trillion] + downtrillionStr;
}
else
{
chineseCharactor = uptillionStr + NumLeverChineseSign[(int)NumLevel.Trillion];
if (downtrillionStr != "零元整")
{
chineseCharactor += NumChineseCharacter[0] + downtrillionStr;
}
else
{
chineseCharactor += "元整";
}
}
return chineseCharactor;

}

8:递归计算货币数字的中文
 /// <summary>
/// 计算中文字符串
/// </summary>
/// <param name="Num">数字</param>
/// <param name="NL">数位级别 比如1000万的 数位级别为万</param>
/// <param name="IsExceptTen">是否以‘壹拾’开头</param>
/// <returns>中文大写</returns>
public string CalculateChineseSign(double Num, NumLevel? NL ,bool IsDump,bool IsExceptTen)
{
Num = Math.Round(Num, 2);
bool isDump = false;
//Num的数位
NumLevel? currentLevel = GetNumLevel(Num);
int numExponent = this.NumLevelExponent[(int)currentLevel];

string Result = string.Empty;

//整除后的结果
int prefixNum;
//余数 当为小数的时候 分子分母各乘100
double postfixNun ;
if (Num >= 1)
{
prefixNum = Convert.ToInt32(Math.Floor(Num / Math.Pow(10, numExponent)));
postfixNun = Math.Round(Num % (Math.Pow(10, numExponent)), 2);
}
else
{
prefixNum = Convert.ToInt32(Math.Floor(Num*100 / Math.Pow(10, numExponent+2)));
postfixNun = Math.Round(Num * 100 % (Math.Pow(10, numExponent + 2)), 2);
postfixNun *= 0.01;
}

if (prefixNum < 10 )
{
//避免以‘壹拾’开头
if (!(NumChineseCharacter[(int)prefixNum] == NumChineseCharacter[1]
&& currentLevel == NumLevel.Ten && IsExceptTen))
{
Result += NumChineseCharacter[(int)prefixNum];
}
else
{
IsExceptTen = false;
}
//加上单位
if (currentLevel == NumLevel.Yuan )
{
////当为 “元” 位不为零时 加“元”。
if (NL == null)
{
Result += NumLeverChineseSign[(int)currentLevel];
//当小数点后为零时 加 "整"
if (postfixNun == 0)
{
Result += EndOfInt;
}
}
}
else
{
Result += NumLeverChineseSign[(int)currentLevel];
}
 //当真正的个位为零时 加上“元”
if (NL == null && postfixNun < 1 && currentLevel > NumLevel.Yuan && postfixNun > 0)
{
Result += NumLeverChineseSign[(int)NumLevel.Yuan];

}


}
else
{
//当 前缀数字未被除尽时, 递归下去
NumLevel? NextNL = null;
if ((int)currentLevel >= (int)(NumLevel.TenThousand))
NextNL = currentLevel;

Result += CalculateChineseSign((double)prefixNum, NextNL, isDump, IsExceptTen);
if ((int)currentLevel >= (int)(NumLevel.TenThousand))
{
Result += NumLeverChineseSign[(int)currentLevel];
}
}

//是否跳位
// 判断是否加零, 比如302 就要给三百 后面加零,变为 三百零二。
if (IsDumpLevel(Num))
{
Result += NumChineseCharacter[0];
isDump = true;

}

//余数是否需要递归
if (postfixNun > 0)
{
Result += CalculateChineseSign(postfixNun, NL, isDump, false);
}
else if (postfixNun == 0 && currentLevel > NumLevel.Yuan )
{
//当数字是以零元结尾的加上 元整 比如1000000一百万元整
if (NL == null)
{
Result += NumLeverChineseSign[(int)NumLevel.Yuan];
Result += EndOfInt;
}
}

return Result;
}

9:外部调用的转换方法。

 /// <summary>
/// 外部调用的转换方法
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
public string ConvertToChinese(string Num)
{

if (!IsValidated<string>(Num))
{
throw new OverflowException("数值格式不正确,请输入小于9999亿兆的数字且最多精确的分的金额!");
}
string chineseCharactor = string.Empty;
if (IsBigThanTillion(Num))
{
double[] tillionNums = SplitNum(Num);
chineseCharactor = ContactNumChinese(tillionNums);
}
else
{
double dNum = Convert.ToDouble(Num);
chineseCharactor = CalculateChineseSign(dNum, null, true, IsStartOfTen(dNum));
}
return chineseCharactor;
}

  小结:

  个人认为程序的灵魂是算法,大到一个系统中的业务逻辑,小到一个货币数字转中文的算法,处处都体现一种逻辑思想。

  是否能把需求抽象成一个好的数学模型,直接关系到程序的实现的复杂度和稳定性。在一些常用功能中想些不一样的算法,对我们开拓思路很有帮助。

posted @ 2007-01-12 15:34 TangHuawei 阅读(464) | 评论 (1)编辑

我们一般是用鼠标按住窗口的标题栏,然后移动窗口,当窗口没有标题栏时,我们可以用下面的方法来移动窗口:
在 BAS 文件中声明:
Declare Function ReleaseCapture Lib "user32" () As Long
Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" ( _
ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Public Const HTCAPTION = 2
Public Const WM_NCLBUTTONDOWN = &HA1
然后,在 Form_MouseDown 事件中:
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
ReleaseCapture
SendMessage hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&
End Sub

posted @ 2007-01-12 15:29 TangHuawei 阅读(183) | 评论 (0)编辑

Windows强大的功能及与用户友好的交互环境使用户操作简单,方便易用。可以说是进出自如。但在要求用户回答问题时,最典型的例子就是当出现有"确定","取消","是","否"等消息框时,总要求用户明确的给出一个回答,然后程序才继续下去。但有时在一些特别的环境下(如多用户共享资源),必须在一定时间内作出回答(否则其他用户有可能因得不到所需的资源而出现系统死锁),才能保证系统的正常运行;或者当要求用户选择时,系统可以根据默认设置来自动选择以继续运行程序。那么就要让程序会自动替用户选择某一个回答。可能吾乃一井底之蛙,在如此大的视窗里从来就没有见过这类东东。那么如何实现呢?且继续看下文。
  
  一、在VFP6.0中的实现
  首先建立一空表单,再加入一时间控制,再加三个按键,其Name属性都按默认,即:Form1,Timer1,Command1,Command2和Command3。在属性窗口中设置属性:Form1.Caption = "自动选择功能演示程序"Timer1.Interval = 1000 && 1000毫秒,即1秒其次建立各控制的事件:
  Form1.Init事件:
  thisform.AddProperty("TimeSetup", 10) &&定义执行自动选择的时间变量Timer1.Timer事件:
  thisform.command1.caption = "自动选择" + str(thisform.TimeSetup) + "秒"thisform.TimeSetup = thisform.TimeSetup - 1if thisform.TimeSetup < 0thisform.command1.click()endifCommand1.Click事件:
  = messagebox("自动选择或人工选择Command1")thisform.TimeSetup = 10
  Command2.Click事件:
  = messagebox("人工选择Command2")thisform.TimeSetup = 10
  Command3.Click事件:
  thisform.release()
  按Ctrl+E执行程序,之后就看你的了。
  
  二、在VB6.0中实现
  首先建立一个标准EXE,加入一时间控制,再加三个按键,其Name属性都按默认,即:Form1,Timer1,Command1,Command2和Command3。在属性窗口中设置属性:
  Form1.Caption = "自动选择功能演示程序"Timer1.Interval = 1000 && 1000毫秒,即1秒
  其次建立各控制的事件代码:
  在代码窗口的“通用”中输入下行Private time As Integer 注释:定义执行自动选择的时间变量
  Private Sub Command1_Click()MsgBox ("自动选择或人工选择command1")time = 10End Sub
  Private Sub Command2_Click()MsgBox ("人工选择command2.")time = 10End Sub
  Private Sub Command3_Click()Unload MeEnd Sub
  Private Sub Form_Load()time = 10 注释:预设定10秒End Sub
  Private Sub Timer1_Timer()Command1.Caption = "自动选择" & time & "秒"time = time - 1If time < 0 ThenCommand1_ClickEnd IfEnd Sub
  按F5,然后就在一边乐吧。

posted @ 2007-01-12 15:28 TangHuawei 阅读(172) | 评论 (0)编辑

复选框内包含了检查符号,表示男

复选框内未包含检查符号,表示女


    我们来改进一下复选框。选中性别复选框,单击在属性表“事件/单击”右边的生成器按钮,选择代码生成器,就出现了代码的编辑窗口。写入如下程序:

Private Sub 性别_Click()

    注释:根据复选框的值显示男或女

    If (Me![性别] = -1) Then       注释:如果“是”就把标签改成“男”
      Me![性别标签].Caption = "男"
    End If

    If (Me![性别] = 0) Then        注释:如果“否”就把标签改成“女”
      Me![性别标签].Caption = "女"
    End If

End Sub

    以上这段程序能在单击复选框时自动改编标签显示的内容。为了在移动记录时正确显示性别,还需要在窗体的“事件/成为当前”里把这段程序再写一遍。

Private Sub Form_Current()

    注释:根据复选框的值显示男或女

    If (Me![性别] = -1) Then       注释:如果“是”就把标签改成“男”
      Me![性别标签].Caption = "男"
    End If

    If (Me![性别] = 0) Then        注释:如果“否”就把标签改成“女”
      Me![性别标签].Caption = "女"
    End If

End Sub

posted @ 2007-01-12 15:27 TangHuawei 阅读(149) | 评论 (0)编辑

文/袁磊  


一、引言
局域网中,往往有定时监视同一组内机器的屏幕的需要。比如:在工业控制中,某车间有多条生产线,每条生产线有一台或几台计算机实时监控该生产线的工序参数的波动;同时,需要有一台计算机(可以称之为屏幕监视服务器)来定时循环地显示各监视器的屏幕,以达到及时发现异常情况的目的。再如学校等公共机房,为了提高机器的有效使用率,屏幕监视亦具有良好的效用。本文将介绍如何用VB来实现屏幕监视的功能。

二、VB实现屏幕监视的原理
本文把被监视的机器称为客户机,监视屏幕的机器称为服务器(程序中服务器的名称为Monitor)。首先在客户机上把显示器的屏幕作为一个窗口,并且把该窗口作为图像加在VB工程中的窗体上,而后把该图像在服务器上保存为图像文件。在服务器上则在窗体中循环加载图像文件,实现动态的、可选择地显示各个图像。

三、客户机程序的编制与设置
1、启动VB,创建缺省工程,将窗体的Visible属性改为False,并在窗体上添加一Timer控件,名称为Timer1,其Interval属性设为30000(采样间隔为30秒)。
2、API函数的声明(可通过API Text Viewer加入)
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
3、全局变量的声明
Dim ComputerName As String '本机名称,用来区分不同的机器所生成的图像。
4、再添加以下代码
Private Sub Form_Load()
Dim sBuffer As String
Dim lSize As Long
sBuffer = Space$(255)
lSize = Len(sBuffer)
Call GetComputerName(sBuffer, lSize)
ComputerName = Trim(Left$(sBuffer, lSize))
Call iniPara 'iniPara函数定义在后
End Sub
为了防止程序被终止,添加如下语句:
Private Sub Form_Unload(Cancel As Integer)
Shell "C:\Windows\System\Client.exe" '调用本程序所生成的可执行文件
End Sub
Private Sub Timer1_Timer()
Dim swnd, sdc, hd
swnd = GetDesktopWindow()
sdc = GetDC(swnd)
hd = BitBlt(Me.hdc, 0, 0, Me.Width, Me.Height, sdc, 0, 0, &HCC0020)
SavePicture Me.Image, "\\Monitor\D$\ClientScreen\image" & ComputerName & ".bmp"
hd = ReleaseDC(swnd, sdc)
Call iniPara
End Sub
当发现有异常情况时,往往需要缩短采样间隔,下面iniPara函数可实现改变定时器的Interval属性的功能。
Private Function iniPara() '读取服务器上的Client.ini文件,初使化定时器的间隔。
Dim sBuffer As String
Dim lSize As Long
Dim TimerInterval As Integer '采样间隔
Open "\\Monitor\D$\ClientScreen\Client.ini" For Input As #1
Line Input #1, sBuffer
lSize = InStr(1, sBuffer, "=")
Timer1.Interval = Val(Mid(sBuffer, lSize + 1))
Close (1)
End Function
编译生成可执行文件Client.exe,将其放在文件夹C:\Windows\System下,并把该程序设为开机即启动。

四、服务器程序的编制与设置
启动VB,创建缺省工程,将窗体的WindowState属性改为2-maximized,并在窗体上添加一Timer控件,名称为Timer1,其Interval属性设为6000(采样间隔为6秒);在窗体上增添一Image控件,名称为Image1,调整至合适尺寸,将其Stretch属性改为True,添加如下代码:
Const iNumClient = 5 '客户机的数量
Dim sClientName(1 To iNumClient) As String '存放客户机名称的数组
Dim i As Integer
然后在Form_Load中把sClientName逐个赋值为客户机的名称,再添加如下代码:
Private Sub Timer1_Timer()
i = i + 1
If (i > iNumClient) Then i = 1
Image1.Picture = LoadPicture("D:\ClientScreen\image" & sClientName(i) & " .bmp")
End Sub
编译生成可执行文件Server.exe,将其放在文件夹D:\ClientScreen下,并在该文件夹下新建一文本文件Client.ini,里面记录着客户机的采样间隔,格式为“任意字符串(不能包含等号)=时间(毫秒)”,比如:
ClientInterval=60000
即表示客户机的采样间隔为60秒。
再把服务器的D盘共享为D$,访问类型为“完全”。
下面的工作就是待各客户机运行一段时间后,在服务器就可以一览众客户机的屏幕了。

五、结束语
该程序比较简洁,使用方便,达到了“一机多显示器”的效果。当然,本程序仅仅是梗概,还很不完善,功能也不多,在实际应用中可逐步完善。
本程序是在VB6.0企业版下实现的。

posted @ 2007-01-12 15:25 TangHuawei 阅读(532) | 评论 (2)编辑

在看电影或电视时我们有时会看到有些片名一个一个的字由大到小打印到屏幕上(或是片名整齐的由大到小打印到屏幕上),俗语称"打屏"。并且有时文字颜色会不断变化,出现霓虹灯效果,闪烁亮晶晶,煞是好看。
如果你是用VB6来开发软件的话,假如能把它应用到你的软件封面中,让软件的名字唰唰唰照打在屏幕上,那种感觉是不是有点......像炎热的夏天喝了一杯冰水呢。那么在VB6中如何实现这种效果呢? OK!赶快拔出你的屠龙刀VB6,LET GO!跟我来吧!(怎么觉得有点牛刀杀小鸡的味道^_^)

  首先启动VB6,新建一个标准EXE工程,添加两个TIMER控件到窗体上,设TIMER1的Interval属性为1(用于启动文字打屏),TIMER2的Enabled属性为False、Interval属性为319(用于文字颜色闪烁速度);再添加五个LABEL控件LABEL1、LABEL2、LABEL3、LABEL4、LABEL5到窗体上,然后按着Ctrl键将它们五个选中,设它们的BackStyle属性为0-Transparent、Font属性为隶书72号字型(当然也可选其他字体)、ForeColor属性等于&H000080FF&(字体颜色为深黄色)、Visible属性为False(让它们都不可见),再将五个LABEL控件按顺序分别排列在窗体的中间位置。排在什么位置都行,只要整齐就行,但注意不能将五个LABEL控件重叠在一起。再保存工程。

  接下来在Form_Load()事件中加入代码:

  Dim t As Long '定义变量
  Me.BackColor = &H80000012 '初始化窗体颜色为黑色
  Me.WindowState = 2 '初始化窗体为全屏运行
  '初始化打屏文字
  Label1.Caption = "文"
  Label2.Caption = "字"
  Label3.Caption = "演"
  Label4.Caption = "示"
  Label5.Caption = "!"
  
  在Timer1_Timer()事件中加入以下代码:

  打屏效果控制
  定义文字的字体大小
  Label8.FontSize = 960
  Label9.FontSize = 960
  Label10.FontSize = 960
  Label11.FontSize = 960
  Label12.FontSize = 960
通过循环语句制造文字由大到小的效果,当文字大小小于或等于72时停止循环
  Label8.Visible = True
  
  For t = 1 To 120
  
  Label8.FontSize = Label8.FontSize - 8
  If Label8.FontSize < = 72 Then
  Label8.FontSize = 72
  Label9.Visible = True
  Exit For
  End If
  Next t
  
  For t = 1 To 120
  
  Label9.FontSize = Label9.FontSize - 8
  If Label9.FontSize < = 72 Then
  Label9.FontSize = 72
  Label10.Visible = True
  Exit For
  End If
  Next t

 

  For t = 1 To 120
  
  Label10.FontSize = Label10.FontSize - 8
  If Label10.FontSize < = 72 Then
  Label10.FontSize = 72
  Label11.Visible = True
  Exit For
  End If
  Next t
  
  For t = 1 To 120
  
  Label11.FontSize = Label11.FontSize - 8
  If Label11.FontSize < = 72 Then
  Label11.FontSize = 72
  Label12.Visible = True
  Exit For
  End If
  Next t
For t = 1 To 120
  
  Label12.FontSize = Label12.FontSize - 8
  If Label12.FontSize < = 72 Then
  Label12.FontSize = 72
  Timer1.Enabled = False
  Timer2.Enabled = True
  Exit For
  End If
  Next t
  
  再在Timer2_Timer() 事件中加入字体霓虹灯效果的代码:
  霓虹灯效果设置

  Dim x As Integer, y As Integer, z As Integer '定义变量

  设置字体颜色的随机效果
  x = Int(Rnd * (255))
  y = Int(Rnd * (255))
  z = Int(Rnd * (255))
  Label8.ForeColor = RGB(x, y, z)
  x = Int(Rnd * (255))
  y = Int(Rnd * (255))
  z = Int(Rnd * (255))
  Label9.ForeColor = RGB(x, y, z)
  x = Int(Rnd * (255))
  y = Int(Rnd * (255))
  z = Int(Rnd * (255))
  Label10.ForeColor = RGB(x, y, z)
  x = Int(Rnd * (255))
  y = Int(Rnd * (255))
  z = Int(Rnd * (255))
  Label11.ForeColor = RGB(x, y, z)
  x = Int(Rnd * (255))
  y = Int(Rnd * (255))
  z = Int(Rnd * (255))
  Label12.ForeColor = RGB(x, y, z)
  
  最后不要忘了在Form_Click()事件中加入"Unload Me"的语句,以释放资源。好了!睁大你长时间用眼睛亲吻电脑显示屏而血红的双眼,伸出由于长期抚摸键盘而进化得象香蕉的手指按F5键运行,哇!......大功告成!

posted @ 2007-01-12 15:24 TangHuawei 阅读(224) | 评论 (0)编辑

VB“破解”有时间限制的程序

张 胜
--------------------------------------------------------------------------------


你是否经常遇到有时间限制的程序?我等懒人尤其对此特别反感,可惜囊中羞涩,只好反复修改其系统日期而使自己多用几次此软件——实在是辛苦!于是使用“Anyday32”,可惜也太麻烦了;再后使用“时光倒流”,也不好用,而且——居然还有Bugs!......看样子只好自己动手做“VB软件DIY”了。
一、问题所在
有时间限制的程序大都是依靠在启动过程中检测系统日期,再与其记录的第一次使用日期(放于注册表或特殊文件中)进行对比检测是否试用期已到,若试用期已到,可能会在注册表中作一定的标记,使下次程序不可用。
二、解决问题
我们一般可以通过修改系统时间来使用此类程序,当然在其作过过期标志后可能此“大法”就无效了;也有一些程序的检测细化到了小时,那我们只能将时间也一块改了。
三、DIY中的思路及注意事项
我们可以在自己的程序中先修改系统日期,再启动相应的有时间限制的程序,过一段时间后再将系统日期改回来。
注意:在等待外部程序检测系统日期的等待过程中,系统日期已经改变,那么我们改回的系统日期将是错误的!因此我们要进行一定的检测,以防止此类错误的发生。
四、开始软件DIY
这里我们为方便控制,使用Access数据库进行软件编制。
数据库中表的设计
字段名
类型
长度
备注

程序名称
Text
20
程序的标识,以便于管理

启动程序
Text
255
实际启动的程序

启动日期
Date/Time
8
应改回的系统日期


窗体及控件设计:  
名称
类型
设置

Form1
窗体
BorderStyle=1

Command1
command
Caption="执行(&R)"

Command2
command
Caption="退出(&Q)"

Check1   
CheckBox
Caption="启动程序后自动关闭本软件"

Timer1
Timer
Enabled=False;Interval=5000

Data1
Data
DatabaseName=数据库路径及名称

RecordSource=数据表名称

CommonDialog1
CommonDialog
Filter="请选择您想要启动的程序 (*.*)"

DBGrid1
DBGrid
AllowaddNew=True;AllowDelete=True;DataSource=Data1


CommonDialog和DBGrid控件需要另外加载,其中还需在DBGrid的属性页中进行一定的数据库挂接和设置,要在其属性页中“布局”中的第二列的“按钮”选中。
以下是本小软件的源代码:
Option Explicit
注释:启动外部应用程序的API函数定义
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Dim OldDate As Date 注释:保存系统日期

Private Sub Command1_Click()
If Not Data1.Recordset.EOF Then 注释:若数据库正在添加记录则不动作
Date = Data1.Recordset(2) 注释:改系统时间
Call ShellExecute(0, vbNullString, Data1.Recordset(1), vbNullString, vbNullString, vbOK) 注释:启动外部程序
Me.Enabled = False 注释:屏蔽其他操作
Timer1.Enabled = True 注释:启动延时记时器
End If
End Sub

Private Sub Command2_Click()
End 注释:关闭本系统
End Sub

Private Sub DBGrid1_BeforeUpdate(Cancel As Integer)
If MsgBox("记录改变吗?", vbYesNo + vbQuestion) <> vbYes Then Cancel = True 注释:是否更新数据库控制
End Sub

Private Sub DBGrid1_ButtonClick(ByVal ColIndex As Integer)
On Error GoTo errdeal 注释:打开错误监测
CommonDialog1.CancelError = True 注释:系统对话框错误控制
CommonDialog1.ShowOpen 注释:打开系统对话框
If CommonDialog1.filename <> "" Then DBGrid1.Text = CommonDialog1.filename 注释:写入要启动的程序信息
errdeal:
End Sub

Private Sub Form_Load()
OldDate = Date 注释:保存系统时间
Call Parameter 注释:获取系统启动时的参数
End Sub

Private Sub Timer1_Timer()’五秒钟后恢复
If Format(Time, "HH:MM:SS") < "00:00:05" Then OldDate = OldDate + 1 注释:防止在接近零时时的日期恢复错误
Date = OldDate 注释:恢复系统时间
Me.Enabled = True 注释:恢复正常操作
Timer1.Enabled = False 注释:屏蔽延时记时器
If Check1.Value = 1 Then End 注释:是否关闭本系统
End Sub

Private Sub Parameter() 注释:系统参数处理
If Command <> "" Then
注释:查找相应的启动程序
Data1.RecordSource = "Select * From [StartProgram] Where [程序名称]=注释:" & Trim(Command) & "注释:"
Data1.Refresh
If Not (Data1.Recordset.EOF And Data1.Recordset.BOF) Then
Me.Hide 注释:隐藏本系统
Check1.Value = 1 注释:设置关闭标志
Command1_Click 注释:激活本系统的执行事件
Else
注释:未找到处理
MsgBox "没有此启动程序!", 16, Me.Caption 注释:错误提示
End 注释:关闭
End If
End If
End Sub
五、小 结
本小软件可启动多个有时间限制的程序,也可以通过命令参数(格式是:本程序名 要启动的程序名称)一次启动一个程序,可用于作相应的快捷方式(和Anyday32类似),让你放心去使用。
程序编完了,但还需你的完善和润色,遇到问题自己解决——我是软件DIY人!

posted @ 2007-01-12 15:20 TangHuawei 阅读(355) | 评论 (0)编辑