2005年08月31日


Macromedia家族新成员——Macromedia Studio 8预计将在九月中旬上市,现在可以通过Macromedia的在线商店预购。详情请参阅《Macromedia Studio 8开始网上预订送背包》。

Macromedia Studio 8 家族成员包括:

Dreamweaver 8

Flash Professional 8

Fireworks 8

Contribute

Flash Paper

图形与网页设计者使用Flash创建网页动画或其它网页内容已经有许多年的历史,这些生动的内容为用户提供了更丰富的网络浏览体验。然而即使在今天宽带如此普及的情况下,一些体积较大的文件经常会需要较长的下载时间,这是现在的Internet用户所不愿忍受的。于是Macromedia在新版本的Flash 8中引入了几种高级技术,使得即使是内容较多的动画在最终完成时也只生成较小的文件。下面介绍一下新版的Flash 8中几大重要的新功能。

一、实时渲染滤镜

其中一种非常棒的技术是,Macromedia减轻了Flash Player 8的渲染工作,在Flash文件中使用标签,Flash Player 8现在可以在用户与Flash文件交互时实时渲染滤镜。

这意味着Macromedia已经能够合并内建的滤镜效果,象阴影、模糊、内外发光、倒角、渐变倒角、颜色调整,以获得更丰富的用户体验。这些滤镜或可视效果能够被应用到影片剪辑(MovieClips)和文本域,当在网页中运行时,通过播放器渲染并显现出来。

二、运行时位图缓冲

Macromedia通过另外的方式将Flash和Flash player捆绑在一起以提高性能。另一种新功能叫做位图缓冲,允许设计者将任何影片剪辑符号指定为一个位图,在使用Flash player运行时获得缓冲,以提高影片播放速度。

影片剪辑符号可以使用属性检查器或ActionScript指定为位图,这些指令在运行时传给播放器,节省了通常情况下处理器用来计算矢量图形的时间。

即便对象作为位图被缓冲,对象的矢量数据仍然被保留了下来,允许设计者在任何时候将其转换回矢量对象。

三、FlashType字体渲染引擎

Flash 8同时允许用户使用FlashType字体渲染引擎对字体作更多的控制。FlashType允许设计者对字体拥有与Flash项目中其它元素同样多的控制。

Flash包含字体渲染的预置,为动画文本提供等同于静态文本的高质量优化。新的渲染引擎使得文本即使使用较小的字体看上去也会更加清晰,这一功能是Flash的一大重要改进。

四、自定义淡入淡出功能

动画设计者将会享受新的自定义淡入淡出功能所带来的乐趣,这一功能允许设计者直观地控制所有的动作补间属性。新增的曲线图功能提供对位置、旋转、大小、颜色及滤镜的独立控制,使用它能够精确控制动画对象的速率。

五、全新的视频编码技术

Macromedia在以前版本的Flash中,就已经试图通过引入Flash视频来扩展交互式Web体验。Flash 8继续这一目标,采用了一种新的视频编码,并扩展了面向Web的视频解码选项。

除了在Flash Player中加入新的视频解码器之外,Macromedia同时在Flash Professional中加入了一个独立的视频解码器。设计者现在可以选择使用Sorenson Spark编码或新的On2 VP6编码。新的On2 VP6编码的目标是在提供一种丰富的交互式体验的同时使文件大小保持最小,与Apple支持的视频编码H-264类似。

新的视频工具也为开发者提供了优化视频内容质量和文件大小的高级选项。

在Flash 8中的视频现在允许将提示点嵌入自定义metadata(元数据),使用嵌入的提示点,图形或动画的事件能够在播放期间动态触发。

使用新的On2 VP6编码,开发者能够解码视频中的一个8位Alpha通道,这个Alpha通道可实时合成到任何其它Flash内容之上。覆盖的视频以透明或半透明Alpha通道的方式合成。

现在在一个对话框中有一个集中的视频工作流程,这个对话框提供所有配置Flash视频所能够用到的选项,不管它是Flash Communication Server流视频,还是通过HTTP或其它方式下载的外部FLV文件。

六、其它引人注目的功能

此外Flash 8还有一些比较吸引人注意的新功能,在此列举如下。

SWF元数据

脚本助手(以前叫做“普通模式”)

对象绘制模型

交互式Mobile设备模拟器

改进的视频播放组件

增强的文本工具

增强的描边属性

高级渐变控制

多SWF打包发布成EXE问题?
多SWF打包发布成EXE问题?

做一个FLASH中有 index.swf 1.swf 2.swf 3.swf 4.swf 5.swf 6.swf 7.swf 8.swf 9.swf 这样10个SWF文件 其中index.swf 有调用 其它的SWF文件..

我想把他们发布成一个 EXE 文件请问我应该怎么做?

我想要的最终效果是.10个swf打包成一个 .exe 文件.能正常调用执行.

这种功能用flash是不好做的,当然要使用第三方软件。

不过这个软件很普及,几乎人人都用——WINRAR!! 怎么做?跟我来——

1、准备好你的所有swf文件和一个你中意的ICO图标文件——它就是你打包后的图标。

按此在新窗口浏览图片
我这里,main.swf是主文件(最好用flash player 导成exe 文件,但是…),其它是main调用的文件。

2、选中所有文件,右击选择"winrar 添加到压缩文件…"

按此在新窗口浏览图片

把A选中,在B处写上你EXE文件的名字

3、更改设置

按此在新窗口浏览图片

选C——点D——出现下图

按此在新窗口浏览图片

在常规里设置好,解压后调用的主文件名。(很关键,名字不要错,注意选解压后的!!)

再选择“模式”标签,E——F——G 一个都不能少,

这里设置文件的解压到"临时文件夹",过程中不出现任何提示窗,复盖旧文件(也是为防止出现提示的)
按此在新窗口浏览图片

再选择“文本和图标”标签,设好图标

按此在新窗口浏览图片

4、开始压缩吧!!

压缩后的文件图标是自定义的,解压到机子的临时文件夹(中间不会出现任何的窗口或提示!!),解压后自动调用main文件。

使用时就像是双击了我们的压缩文件直接执行main文件的感觉一样(当然这与你机子的性能和文件大小有相当关系,否则会等相当一段时间才会开始)!!!如果你把FLash Player的图标导入,加在压缩文件里……会和真的播放器一样的,以假乱真!!

再没有多个swf文件烦心了。而且在关闭显示文件后,临时文件夹中的内容会全部删!!开心。

5、但是——这种方法极意被恶意者利用,比如在里面加上一个木马软件,先期调用了,而我们只看flash去了,也不晓得…………后果……
在EXE属性里可以看到压缩文件的注释,如果里面写明了调用EXE文件……就有些可疑!如果是我,不会冒然使用的。


6、声明
请不要利用这个东东搞&*#$@……
请不要不查毒直接调用不明EXE文件……
请不要想用这种方法保护作品,一点做用不起……
但是压缩时加上密码,也是一种防君子偷偷使用的一种方法。

2005年08月15日

 表单的验证一直是网页设计者头痛的问题,表单验证类 Validator就是为解决这个问题而写的,旨在使设计者从纷繁复杂的表单验证中解放出来,把精力集中于网页的设计和功能上的改进上。

  Validator是基于javascript技术的伪静态类和对象的自定义属性,可以对网页中的表单项输入进行相应的验证,允许同一页面中同时验证多个表单,熟悉接口之后也可以对特定的表单项甚至仅仅是某个字符串进行验证。因为是伪静态类,所以在调用时不需要实例化,直接以"类名+.语法+属性或方法名"来调用。此外,Validator还提供3种不同的错误提示模式,以满足不同的需要。

  Validator目前可实现的验证类型有:

  1.是否为空;
  2.中文字符;
  3.双字节字符
  4.英文;
  5.数字;
  6.整数;
  7.实数;
  8.Email地址;
  9.使用HTTP协议的网址;
  10.电话号码;
  11.货币;
  12.手机号码;
  13.邮政编码;
  14.身份证号码;
  15.QQ号码;
  16.日期;
  17.符合安全规则的密码;
  18.某项的重复值;
  19.两数的关系比较;
  20.判断输入值是否在(n, m)区间;
  21.输入字符长度限制(可按字节比较);
  22.对于具有相同名称的单选按钮的选中判断;
  23.限制具有相同名称的多选按钮的选中数目;
  24.自定义的正则表达式验证;

  运行环境(客户端):

  在Windows Server 2003下用IE6.0+SP1和Mozilla Firefox 1.0测试通过;
  在Lunix RedHat 9下的Netscape测试通过;

  对于客户端的表单验证,这个基于javascript编写的Validator基本上都可以满足,具体可以下载CHM文件:
  Validator.CHM下载

  

 <title>表单验证类 Validator v1.0</title>
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;
   color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overflow:auto;}
form{display:inline}
</style>
<table align="center">
<form name="theForm" id="demo" action="" method="get"
  onSubmit="return Validator.Validate(this,2)">
<tr>
<td>真实姓名:</td><td><input name="Name" dataType="Chinese"
     msg="真实姓名只允许中文"></td>
</tr>
<tr>
<td>英文名:</td><td><input name="Nick" dataType="English" require="false"
               msg="英文名只允许英文字母"></td>
</tr>
<tr>
<td>主页:</td><td><input name="Homepage" require="false"
              dataType="Url" msg="非法的Url"></td>
</tr>
<tr>
<td>密码:</td><td><input name="Password" dataType="SafeString"
                msg="密码不符合安全规则" type="password"></td>
</tr>
<tr>
<td>重复:</td><td><input name="Repeat" dataType="Repeat"
                to="Password" msg="两次输入的密码不一致" type="password"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email" dataType="Email" msg="信箱格式不正确"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email" dataType="Repeat" to="Email"
                 msg="两次输入的信箱不一致"></td>
</tr>
<tr>
<td>QQ:</td><td><input name="QQ" require="false" dataType="QQ"
                msg="QQ号码不存在"></td>
</tr>
<tr>
<td>身份证:</td><td><input name="Card" dataType="IdCard"
                  msg="身份证号码不正确"></td>
</tr>
<tr>
<td>年龄:</td><td><input name="Year" dataType="Range"
                 msg="年龄必须在18~28之间" min="18" max="28"></td>
</tr>
<tr>
<td>年龄1:</td><td><input name="Year1" require="false" dataType="Compare"
            msg="年龄必须在18以上" to="18" operator="GreaterThanEqual"></td>
</tr>
<tr>
<td>电话:</td><td><input name="Phone" require="false"
                 dataType="Phone" msg="电话号码不正确"></td>
</tr>
<tr>
<td>手机:</td><td><input name="Mobile" require="false"
                dataType="Mobile" msg="手机号码不正确"></td>
</tr>
<tr>
<td>生日:</td><td><input name="Birthday" dataType="Date" format="ymd"
                 msg="生日日期不存在"></td>
</tr>
<tr>
<td>邮政编码:</td><td><input name="Zip" dataType="Custom" regexp="^[1-9]\d{5}$"
                   msg="邮政编码不存在"></td>
</tr>
<tr>
<td>邮政编码:</td><td><input name="Zip1" dataType="Zip" msg="邮政编码不存在"></td>
</tr>
<tr>
<td>操作系统:</td><td><select name="Operation" dataType="Require"
   msg="未选择所用操作系统" ><option value="">选择您所用的操作系统
   </option><option value="Win98">Win98</option>
   <option value="Win2k">Win2k</option><option value="WinXP">WinXP</option>
   </select></td>
</tr>
<tr>
<td>所在省份:</td><td>广东<input name="Province" value="1" type="radio">
              陕西<input name="Province" value="2" type="radio">  
              浙江<input name="Province" value="3" type="radio">
              江西<input name="Province" value="4" type="radio"
              dataType="Group" msg="必须选定一个省份" ></td>
</tr>
<tr>
<td>爱好:</td><td>运动<input name="Favorite" value="1" type="checkbox">
            上网<input name="Favorite" value="2" type="checkbox">
            听音乐<input name="Favorite" value="3" type="checkbox">
            看书<input name="Favorite" value="4" type="checkbox""
           dataType="Group" min="2" max="3" msg="必须选择2~3种爱好"></td>
</tr>
<td>自我介绍:</td><td><textarea name="Description" dataType="Limit"
     max="10" msg="自我介绍内容必须在10个字之内">中文是一个字
   </textarea></td>
</tr>
<td>自传:</td><td><textarea name="History" dataType="LimitB" min="3"
    max="10" msg="自传内容必须在[3,10]个字节之内">
    中文是两个字节t</textarea></td>
</tr>
<tr>
<td colspan="2"><input name="Submit" type="submit" value="确定提交">
    <input onClick="Validator.Validate(document.getElementById('demo'))
  " value="检验模式1" type="button">
   <input onClick="Validator.Validate(document.getElementById('demo'),2)
   " value="检验模式2" type="button">
    <input onClick="Validator.Validate(document.getElementById('demo'),3)
  " value="检验模式3" type="button"></td>
</tr>
</form>
</table>
<script>
/*************************************************
    Validator v1.0
    cody by 我佛山人
    wfsr@cunite.com
    http://www.cunite.com
*************************************************/
Validator = {
    Require : /.+/,
    Email : /^\w+([-+.]\w+)*@\w+([-.]\\w+)*\.\w+([-.]\w+)*$/,
    Phone : /^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/,
    Mobile : /^((\(\d{3}\))|(\d{3}\-))?13\d{9}$/,
    Url : /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/,
    IdCard : /^\d{15}(\d{2}[A-Za-z0-9])?$/,
    Currency : /^\d+(\.\d+)?$/,
    Number : /^\d+$/,
    Zip : /^[1-9]\d{5}$/,
    QQ : /^[1-9]\d{4,8}$/,
    Integer : /^[-\+]?\d+$/,
    Double : /^[-\+]?\d+(\.\d+)?$/,
    English : /^[A-Za-z]+$/,
    Chinese : /^[\u0391-\uFFE5]+$/,
    UnSafe : /^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\
           ?\\\/\'\"]*)|.{0,5})$|\s/,
    IsSafe : function(str){return !this.UnSafe.test(str);},
    SafeString : "this.IsSafe(value)",
    Limit : "this.limit(value.length,getAttribute('min'),
           getAttribute('max'))",
    LimitB : "this.limit(this.LenB(value), getAttribute('min'),
            getAttribute('max'))",
    Date : "this.IsDate(value, getAttribute('min'), getAttribute('format'))",
    Repeat : "value == document.getElementsByName(getAttribute('to'))[0].value",
    Range : "getAttribute('min') < value && value < getAttribute('max')",
    Compare : "this.compare(value,getAttribute('operator'),getAttribute('to'))",
    Custom : "this.Exec(value, getAttribute('regexp'))",
    Group : "this.MustChecked(getAttribute('name'), getAttribute('min'),
          getAttribute('max'))",
    ErrorItem : [document.forms[0]],
    ErrorMessage : ["以下原因导致提交失败:\t\t\t\t"],
    Validate : function(theForm, mode){
        var obj = theForm || event.srcElement;
        var count = obj.elements.length;
        this.ErrorMessage.length = 1;
        this.ErrorItem.length = 1;
        this.ErrorItem[0] = obj;
        for(var i=0;i<count;i++){
            with(obj.elements[i]){
                var _dataType = getAttribute("dataType");
                if(typeof(_dataType) == "object"
             || typeof(this[_dataType]) == "undefined") continue;
                this.ClearState(obj.elements[i]);
                if(getAttribute
         ("require") == "false" && value == "") continue;
                switch(_dataType){
                    case "Date" :
                    case "Repeat" :
                    case "Range" :
                    case "Compare" :
                    case "Custom" :
                    case "Group" :
                    case "Limit" :
                    case "LimitB" :
                    case "SafeString" :
                        if
                       (!eval(this[_dataType]))    
                      {
                 this.AddError(i, getAttribute("msg"));
                        }
                        break;
                    default :
                        if
                    (!this[_dataType].test(value)){
                this.AddError(i, getAttribute("msg"));
                        }
                        break;
                }
            }
        }
        if(this.ErrorMessage.length > 1){
            mode = mode || 1;
            var errCount = this.ErrorItem.length;
            switch(mode){
            case 2 :
                for(var i=1;i<errCount;i++)
                    this.ErrorItem[i].style.color
                                = "red";
            case 1 :
                alert(this.ErrorMessage.join("\n"));
                this.ErrorItem[1].focus();
                break;
            case 3 :
                for(var i=1;i<errCount;i++){
            try{
                var span = document.createElement("SPAN");
                span.id = "__ErrorMessagePanel";
                span.style.color = "red";
                this.ErrorItem[i].parentNode.appendChild(span);
                span.innerHTML = this.ErrorMessage[i].replace(/\d+:/,"*");
                    }
                    catch(e){alert(e.description);}
                }
                this.ErrorItem[1].focus();
                break;
            default :
                alert(this.ErrorMessage.join("\n"));
                break;
            }
            return false;
        }
        return true;
    },
    limit : function(len,min, max){
        min = min || 0;
        max = max || Number.MAX_VALUE;
        return min <= len && len <= max;
    },
    LenB : function(str){
        return str.replace(/[^\x00-\xff]/g,"**").length;
    },
    ClearState : function(elem){
        with(elem){
            if(style.color == "red")
                style.color = "";
            var lastNode = parentNode.childNodes
                     [parentNode.childNodes.length-1];
            if(lastNode.id == "__ErrorMessagePanel")
                parentNode.removeChild(lastNode);
        }
    },
    AddError : function(index, str){
        this.ErrorItem[this.ErrorItem.length]
              = this.ErrorItem[0].elements[index];
        this.ErrorMessage[this.ErrorMessage.length]
              = this.ErrorMessage.length + ":" + str;
    },
    Exec : function(op, reg){
        return new RegExp(reg,"g").test(op);
    },
    compare : function(op1,operator,op2){
        switch (operator) {
            case "NotEqual":
                return (op1 != op2);
            case "GreaterThan":
                return (op1 > op2);
            case "GreaterThanEqual":
                return (op1 >= op2);
            case "LessThan":
                return (op1 < op2);
            case "LessThanEqual":
                return (op1 <= op2);
            default:
                return (op1 == op2);
        }
    },
    MustChecked : function(name, min, max){
        var groups = document.getElementsByName(name);
        var hasChecked = 0;
        min = min || 1;
        max = max || groups.length;
        for(var i=groups.length-1;i>=0;i--)
            if(groups[i].checked) hasChecked++;
        return min <= hasChecked && hasChecked <= max;
    },
    IsDate : function(op, formatString){
        formatString = formatString || "ymd";
        var m, year, month, day;
        switch(formatString){
            case "ymd" :
                m = op.match(new RegExp
             ("^\\s*((\\d{4})|(\\d{2}))([-./])(\\d{1,2})\\4(\\d{1,2})\\s*$"));
                if(m == null ) return false;
                day = m[6];
                month = m[5]--;
                year = (m[2].length == 4) ?
                 m[2] : GetFullYear(parseInt(m[3], 10));
                break;
            case "dmy" :
                m = op.match(new RegExp
           ("^\\s*(\\d{1,2})([-./])(\\d{1,2})\\2((\\d{4})|(\\d{2}))\\s*$"));
                if(m == null ) return false;
                day = m[1];
                month = m[3]--;
                year = (m[5].length == 4) ?
               m[5] : GetFullYear(parseInt(m[6], 10));
                break;
            default :
                break;
        }
        var date = new Date(year, month, day);
return (typeof(date) == "object" &&
       year == date.getFullYear() && month == date.getMonth()
                    && day == date.getDate());
        function GetFullYear(y){return ((y<30 ? "20" : "19") + y)|0;}
    }
}
</script>

三、DW的站点定义

上一节我们在IIS里把站点根目录定义在E:\Work,现在进到这个目录下新建一文件夹并命名为geustbook。

打开DW,在"Site"菜单下找到"Manage Sites…"项单击,见下图:

 

打开"Manage Site"对话框,点"New …",在出来的下拉菜单里选"Site"定义新站点:

 

跟着新站点定义向导一步一步来定义我们的留言板站点。在站点名称上填上geustbook:

 

点"Next>"继续下一步的后台技术选择,这里我们选择用VBScript作脚本的ASP:

 

点"Next>"继续下一步的站点文件夹设置,因为我们现在是在本地测试,而且gustbook文件夹在E:\Work\guestbook,所以设置如下:

 

点"Next>"继续下一步的设置DW的测试URL:

 

点"Next>"继续下一步,因为我们在本机测试,不需要远程服务器参与,所以选择"No":

 

点"Next>"继续下一步,这里显示的是我们刚才所填的信息,目的是要我们确认一下,如果发现有错,可以点"<Back"返回修改设置,确认无误后就可以点"Done",我们的站点定义就完成了。

 

细心一点的朋友也许会发现,在站点定义对话框上有两个标签:"Base"和"Advanced",其实用途是一样的,只不过"Base"是一步一步的向导模式,而"Advanced"是给对DW有一定了解的朋友用的高级模式,有兴趣的朋友可以自行切换到"Advanced"模式看看。

二、数据库设计
先构想一下,一个功能齐全的留言本应该有哪些内容需要保存?访客名字(Name)、访客主页(Homepage)、访客QQ(QQ)、访客信箱(Email)、访客形象(ICON)、访客IP(IP)、留言内容(Content)、留言时间(Date)—-这是访客的有关信息,如果主人要回复留言呢?好,再加上回复(Reply)和回复时间(RDate),嗯……再想想有没有漏掉什么?对了,还有主人的管理帐号:用户名(Username)、密码(Password)。
要保存这么多信息,数据库应该怎么设计?访客的留言是不断增加的,而主人的管理帐号固定不变,所以应该分开两个表,一个保存所有访客的留言和访客的资料信息,另一个则保存主人的管理帐号。OK,现在可以开始设计数据库了。打开ACCESS(在微软的Office软件中有)软件,新建一空白数据库,ACCESS会提示先保存数据库,定位到你的留言本所在文件夹(笔者是在站点根目录下建了一个guestbook文件夹),保存为data.mdb:

 
然后双击"使用设计器创建表",完成后如图:

 
为了优化数据库,有些字段需要作点设置:
ID:设为主键,确定数据唯一性以保证在管理时能准确定位到相应记录
Name:字段大小设为15(很少有人的名字有这么长的吧?)
Email:字段大小为20(也很少有Email地址的长度超过这个数字)
ICON:字段大小为6(看完后面的教程就明白为什么设这么小了)
IP:字段大小为15(可以算出来,四个三位长的数字再加三个小数点)
Homepage:字段大小为30(很多朋友还在用二级甚至三级的域名,所以放宽一点)
Date:默认值为Now ()(用Now()取得插入新记录时系统的时间)

关闭表窗口,会提示是否保存对表的修改,选"是",然后把表名改为main,同理创建表admin,以保存管理帐号:

 

最后还需要一个记录IP对应地址的表,这个IP库可以在网上搜索一下,或者到http://x-lover.com/temp/ip.mdb下载,然后打开数据库data.mdb
,在"文件"菜单下选择"获取外部数据>>导入",再在弹出的对话框里选择刚才下载的数据库,导入,选择address表,确定,现在数据库data.mdb中应该有这样的三个表:

 

至此,准备工作全部完成。

程序运行配置完了,废话不多说,直接开始我们的DW MX 2004的体验之旅吧。

9月份设计界最热的消息莫过于Macromedia公司的Studio MX 2004了,朋友们都很关心新版软件的新特性,那么就让我通过这个留言本的教程跟大家一起体验Studio MX 2004中的Dreamweaver MX 2004(以下简称DW2004)吧。
一、IIS(Internet 信息服务)安装配置
这里以Windows Server 2003(以下简称Win2003)为例。因为Win2003是服务器级的操作系统,所以自带有IIS6.0,其它版本的系统可以在"添加或删除程序>>添加/删除Windows组件"对话框中把"Internet 信息服务(IIS)"前的勾选中,点"下一步"进行安装就行了(注:在这之前应把系统安装盘放到光驱)。

 
IIS装好之后再作一下简单的配置。定位到"开始>>管理工具>>Internet 信息服务(IIS)管理器",打开IIS管理器。在"本地计算机>>网站>>默认网站"上右键单击,在快捷菜单里选"属性"(或者直接在操作菜单下选"属性"),弹出如下对话框:

 

切换到"主目录"标签(图2),重新选择网站根目录(笔者选择的是E盘下的Work目录),默认是"系统盘:\Inetpub\wwwroot",因为系统盘不宜放太多的非系统文件,所以在这里重设默认网站要目录,如果嫌麻烦可以跳过这步。再切换到"文档"标签,通过"添加"、"删除"、"上移"、"下移",把站点的默认文档设置如图所示:

 
可能有些朋友会疑惑,设置默认内容文档有什么作用?细心的朋友应该会发现,在浏览一些大网站的首页时用它的一级域名就行了,并不需要指定请求页的文件名,这就是设置了默认内容文档的缘故,它的作用就是在浏览器请求没有指定文档的名称时,将默认文档提供给浏览器。要得到更详尽的解释说明,可以点击图3中的"帮助"。之所以有这步,是因为网站的默认内容页中没有index.asp,不大符合国人习惯。

⑨回复页(reply.asp)

先做好一个这样的回复页:

 

然后建立记录集:

 

 

再在"Application"工具组里找到"Record Update Form Wizard"(如图85),弹出跟"Record Insertion Form Wizard"类似"Record Update Form Wizard"对话框:

 

在"Form fields"中删掉"ID"和"Date",修改其余的"Label"为中文,"Content"、"Reply“的"Display as"为"Text area",参考图51、52所示的方法给"Content"和"Reply"加上"Encode – Server.HTMLEncode"格式化,"RDate"的"Display as"为"Hidden field","Default value"为"<%=Date%>",调整下界面后的效果:

 

最后不要忘了也给回复页加上页面保护:

 

⑧删除记录页(delete.asp)

参照图70的做法,另存出一页delete.asp,并修改如下:

 

 

再单击"HTML"工具组中的"Refresh"项(图80),弹出"Refresh"对话框,设置如下:

 

 

点击服务器行为面板上的"Command"命令,在弹出的对话中设置如下:

 

参照75、76的方法,给delete.asp页也添加页面保护

⑦登陆页(login.asp)

有管理页,当然就有登陆页,只有验证通过后才能进入到管理页进行管理。还是用老方法,随便用一个之前做好的页面(比如insert.asp)另存为login.asp,然后删除有服务器行为和一些不必要的表格:

 

光标定位到第三行的单元格,然后通过“Forms"工具组的按钮和表格完成如下表单的制作:

 

"用户"输入框代码:<input name="Username" type="text">
"密码"输入框代码:<input name="Password" type="password">

表单制作完成后应用服务器行为面板上的"Log In User"命令:

 

在弹出的"Log in User"对话框里设置如下:

 

保存后在IE里测试,不过别忘了先在数据库中添加管理员帐号:

 

这样只有当输入用户名admin和密码admin后才跳转到admin.asp页,否则一直在login.asp页,不过,现在直接输入admin.asp看看,是不是不登陆也可以直接进入管理页?这就对了,因为我们没有对admin.asp添加页面保护,重新打开admin.asp,在服务器行为面板上给页面应用"Restrict Access To Page"命令:

 

 

有登陆当然就有退出登陆,所以选中admin.asp里的"管理"修改为"退出",并应用服务器行为"Log Out User"

 

 

2005年08月13日

⑥管理页面(admin.asp)

管理页admin.asp其实跟留言板首页index.asp功能差不多,所以可以直接把index.asp另存为admin.asp,然后加上管理功能:删除,编辑,回复,显IP:

 

对于"删除"、"编辑"和"回复"的数据绑定很简单,主要是在链接的参数中传递当前留言的ID号,参考"QQ"的绑定方式,完成后的链接地址分别为:
"删除":delete.asp?id=<%=(rs.Fields.Item("ID").Value)%>
"编辑":edit.asp?id=<%=(rs.Fields.Item("ID").Value)%>
"回复":reply.asp?id=<%=(rs.Fields.Item("ID").Value)%>
需要注意的是,由于admin.asp页是由index.asp页另存来的,而index.asp页所建的记录集里没有选择到"ID"字段,所以在这里必须把"ID"字段选进来,方法:
1)在服务器行为面板中双击"Recordset(rs)",重新选择字段
2)也可以直接在源码中找到
rs.Source = "SELECT Content, Date, Email, Homepage, ICON, IP, Name, QQ, RDate, Reply FROM main ORDER BY Date DESC"
这行,改为
rs.Source = "SELECT ID, Content, Date, Email, Homepage, ICON, IP, Name, QQ, RDate, Reply FROM main ORDER BY Date DESC"

对于IP的相关绑定,完成后代码为:
来自:<%=ip(rs.Fields.Item("IP").Value)%>[IP:<%=(rs.Fields.Item("IP").Value)%>]

这里用到一个叫ip的Function过程来查询访客IP在数据库表address中对应的国家和城市,代码如下:

<%
Function ip(sip)
Dim iparr,iprs,country,city
‘IP为127.0.0.1时相当于192.168.0.1
If sip="127.0.0.1" then sip= "192.168.0.1"    
‘以点"."为界切割字符串sip,如果sip为“192.168.0.1”,则切割后得到的数组iparr(0)="192",iparr(1)="168",iparr(2)="0",iparr(3)="1"
iparr=split(sip,".")
‘通过计算转换,使IP地址跟数据库中的数据联系起来
sip=cint(iparr(0))*256*256*256+cint(iparr(1))*256*256+cint(iparr(2))*256+cint(iparr(3))-1

‘连接数据库,查询数据库字段ip1和ip2满足关系ip1<=sip<=ip2的记录
Set iprs = Server.CreateObject("ADODB.Recordset")
iprs.ActiveConnection = MM_conn_STRING
iprs.Source = "SELECT Top 1 city, country FROM address WHERE ip1 <=" & sip & " and " & sip & "<=ip2"
iprs.CursorType = 0
iprs.CursorLocation = 2
iprs.LockType = 1
iprs.Open()

‘判断数据库中有无记录即无相应IP地址的信息时的处理
If iprs.bof and iprs.eof then
    country="未知地区"
    city=""
Else
    country=iprs.Fields.Item("country").Value
    city=iprs.Fields.Item("city").Value
End If
ip=country&city

iprs.Close()
Set iprs = Nothing
End Function
%>

参考DW自动生成的代码,把这段代码加到HTML代码开始之前