关于藏历新年

今年有人对我说藏历新年快乐。虽知道藏历跟我们的农历不同,但没想到这么早就过年。上网查了一下,今年正好藏历木羊年正月初一和汉族农历正月初一是同一天。那就不对了,怎么会是今天新年呢。

继续查阅资料,才知道在藏区的不同地方,新年的时间是不同的。藏历新年藏语称“洛萨”,最早迎来“洛萨”的就是西藏南部的林芝地区,即藏历十月初一,而阿里地区普兰县的新年则在藏历十一月初一,日喀则地区新年是藏历十二月初一,最后才是影响最大的藏历初一拉萨新年。

2015-1-21 11:27:20 评论(3) 生活随笔
全文完 阅读全文

Delphi利用Indy构建SMTP服务器

近日搭邮件服务器,按照网上的教程总出现这样那样的错误。浪费了好几天,不如自己写个算了。

幸好Indy将SMTP协议封装好了,使用起来十分方便。

简述一下邮件投递的过程。连接上SMTP服务器并身份验证后,SMTP服务器检查目标邮箱系统域名的MX记录,再将邮件投递至MX记录所指向的地址。

MX(Mail Exchanger)记录是邮件交换记录,它指向一个邮件服务器,用于电子邮件系统发邮件时根据收信人的地址后缀来定位邮件服务器。

主要用了三个控件,IdSMTPServer负责SMTP服务器的接收投递,IdDNSResolver负责域名解析,IdSMTP负责发送邮件。

取MX记录:

function GetMx(const Domain: string): string;
var
  I: Integer;
  DnsRes: TResultRecord;
  LMx: TMxRecord;
  iPref: Word;
  ServerList: TStrings;
begin
  Result := '';
  IdDNSResolver1.Host := '180.76.76.76'; //设定域名解析服务器
  IdDNSResolver1.QueryType := [qxMX];    //设定需要解析MX记录
  IdDNSResolver1.Resolve(Domain);        //解析域名
  iPref := High(Word);
  ServerList := TStringList.Create;
  for I := 0 to IdDNS.QueryResult.Count - 1 do
  begin
    DnsRes := IdDNS.QueryResult[I];
    if (DnsRes is TMXRecord) then
    begin
      LMx := TMXRecord(DnsRes);
      Result := LMx.ExchangeServer;
      if LMx.Preference < iPref then
      begin
        iPref := LMx.Preference;
        ServerList.Insert(0, LMx.ExchangeServer);
        //可能一个域名有多条MX记录,按照优先级最终取出第一条
      end else begin
        ServerList.Add(LMx.ExchangeServer);
      end;
    end;
  end;
  if ServerList.Count > 0 then
    Result := ServerList[0];
  ServerList.Free;
end;

验证投递邮箱合法性:直接设为rAddressOk跳过

procedure TForm1.IdSMTPServer1RcptTo(ASender: TIdSMTPServerContext;
  const AAddress: string; AParams: TStrings; var VAction: TIdRCPToReply;
  var VForward: string);
begin
  VAction := TIdRCPToReply.rAddressOk;
end;

验证用户:直接将VAuthenticated设为True跳过

procedure TForm1.IdSMTPServer1UserLogin(ASender: TIdSMTPServerContext;
  const AUsername, APassword: string; var VAuthenticated: Boolean);
begin
  VAuthenticated := True;
end;

SMTPServer收到邮件时的处理:

procedure TForm1.IdSMTPServerMsgReceive(ASender: TIdSMTPServerContext;
  AMsg: TStream; var VAction: TIdDataReply);
var
  MailMsg: TIdMessage;
  P: Integer;
  EMail: string;
  Domain: string;
  ThoughAddress: string;
begin
  MailMsg := TIdMessage.Create;
  try
    MailMsg.LoadFromStream(AMsg);
    EMail := MailMsg.Recipients.EMailAddresses; //取目标邮件地址
    P := EMail.IndexOf('@');
    Domain := EMail.Substring(P + 1, EMail.Length); //取邮件域名
    ThoughAddress := GetMx(Domain); //取投递的MX记录

    with IdSMTP1 do //通过IdSMTP发送邮件
    begin
      Host := ThoughAddress;
      Port := 25;
      Connect;
      try
        Send(MailMsg); //转发刚才收到的邮件
      finally
        Disconnect;
      end;
    end;
  finally
    FreeAndNil(MailMsg);
  end;

  VAction := TIdDataReply.dOk;
end;

程序在Delphi XE7 update1 调试通过。

2014-12-20 20:20:03 评论(1) 程序设计
全文完 阅读全文

SQLite字符串连接

SQLite的字符串连接不是用 + 而是用 || 。

+是将前后两字符串转成数字再进行加法运算。

||是将前后两字符串连接。

2014-12-7 14:18:56 评论(1) 程序设计
全文完 阅读全文

Delphi的类变量、类构造方法

type
  TTest = class
  private
    class var A: Integer;  //类变量
    B: Integer; //普通成员变量
  public
    class constructor Create;  //类构造方法
    class destructor Destroy;  //类析构方法
    constructor Create; //实例构造方法
    destructor Destroy; //实例析构方法
  end;

类构造方法顾名思义就是在类初始化的时候执行。以前只能在initialization段中才能初始化,现在可以在类构造方法中初始化类变量,使得程序结构更加有条理。

2014-10-31 10:57:23 评论(0) 程序设计
全文完 阅读全文

Delphi利用FireDac连接SQLite数据库时文字丢失

最近用FireDac连接SQLite,老是会有部分不知道哪国语言的文本丢失,存储后全变成了问号,第一反应一定是字符集的问题。修改了连接设置,

FDConnection1.Params.Add('StringFormat=Unicode');

结果还是文字丢失。研究了一下发现Param参数中有个AsWideString,一试,果然可以了。

ParamByName('text').AsWideString := 'hello world.';

测试环境:Delphi XE7

2014-9-29 18:28:14 评论(0) 程序设计
全文完 阅读全文

游戏管理器 2.0

忙忙碌碌了许多天,推出了全新的《游戏管理器 2.0》。说到制作游戏管理器的初衷,只是电脑上的游戏太多,寻找起来不便便想做一个快捷的管理工具,对游戏进行分类整理,说白了就是一个快捷方式集合。

两年前做过管理器的1.0版本,虽然使用起来是挺方便的,但是界面实在是太难看了。这回重制,重点就从界面着手,尽量让每一个细节都显得美观。FireMonkey真是帮大忙了,其界面设计能力实在强悍,虽然其bug无数,但已经可以凑合着用了,只是在稳定性上同VCL相比确实还有不小的差距。

说到这个版本的程序,可以说是我写出来最烂的代码了,丝毫没有条理性可言,东一点西一点的拼凑在一起。之后回顾这些代码时一定连自己都不认识了。将来一定不能再这么乱来,图什么省事!

2014-3-26 11:35:40 评论(4) 生活随笔
全文完 阅读全文

流浪~勇气

晚上一个人躺在床上睡不着,拿平板翻看以前的日志还有照片,想起在江西认识的两位徒步少年。一个背包,就能上路,背上帐篷,随处就是家。这种感觉,也许就叫作流浪。

也曾幻想着能够背上行囊,仗剑走天涯,一个人在外飘泊,见识世界之大之奇妙发。但是总是因为种种的原因,没有勇气踏出那第一步。也许有太多世俗的牵绊,也许这才叫作生活,终究自己只是个普通人。

时间一天一天流逝,自己也一天一天老去,曾经的那些梦想,如今还剩下什么?想到当年还在迷恋小虎队的那个年纪听的一首歌,苏有朋的《勇气》。总是想知道世界还有什么,流浪的感觉也许才是人生。当年听这歌时,也许只是觉得好听;而如今再次听来,却句句说到心上。想想自己到了福州已经第十个年头,毕业也已经许多年,这些年来,我到底是过得充实还是虚度光阴呢?也许连自己都已经解释不清。没人能为我唤回青春,没人能替我走完人生。自己的路还是得自己走,珍惜当下时光,开心面对每一天的生活,我想已经足矣。做个有故事的人,到老去之时才不会后悔。时光蹉跎,保持一颗年轻的心,也许真像某人说的,“只有老的心,没有老的人。”

2014-3-23 01:57:17 评论(1) 生活随笔
全文完 阅读全文

FireMonkey中TabControl的滑动效果

近日在FireMonkey中使用了TabControl控件,将选项卡隐藏了(TabPosition:=TTabPosition.tpNone),另设了几个按钮进行选项卡切换。想要做成像手机那个的滑动效果,看了Demo,创建一个ActionList,添加ChangeTabAction,设定Action的Tab为指定TabItem页,设定Action的Transition为ttSlide,将Action绑定到按钮。当按下按钮时,就会产生滑动效果。

如果在程序中调用,要执行Action.ExecuteTarget(nil);

查看了TabControl的源码,其实不需要Action就能够实现滑动切换。Action.ExecuteTarget的实现调用了TabControl.SetActiveTabWithTransition这个方法。

procedure TTabControl.SetActiveTabWithTransition(const ATab: TTabItem; ATransition: TTabTransition; const ADirection: TTabTransitionDirection);

ATab为目标要切换的TabItem名;

ATransition为是否滑动效果,取值为ttNone和ttSlide;

ADirection为滑动方向,取值为tdNormal和tdReversed,默认为tdNormal。

另外,在TabItem的页中,千万不能将任何一个控件的Enabled设为False,否则将卡死你。

再另外一下,在TabItem的页面中,如果有ListView控件就一定要注意了。XE5的TabControl和ListView有冲突,如果是使用SetActiveTabWithTransition并且ttSlide滑动切换的话,切换几次就会产生内存地址无法访问的错误,一定要在TabControl的Change事件中判断ActiveTab,如果不是ListView所在的页的话,要将ListView设为隐藏。此问题困扰了我三天。
 

2014-3-19 02:32:44 评论(0) 程序设计
全文完 阅读全文

博客重新开放

同样由于服务器更换,博客系统关闭也一年有余。将十字之门网站重写之后,也抽空用PHP重写了博客代码。前台界面没有变,还是沿用之前的模板;后台收设计得比较清爽简单,反正也只是对数据库的增删改查嘛。

发觉自己对PHP是越来越喜欢了。这些天来配置服务器,研究Linux,找回了许久没有的电脑的乐趣。

2014-3-4 23:43:11 评论(2) 生活随笔
全文完 阅读全文

昆明·祈福

昨晚在昆明火车站发生的恐怖袭击事件令人震惊,春城进入了冬季。为昆明祈福。希望都好好的。
 

2014-3-2 10:49:43 评论(0) 生活随笔
全文完 阅读全文
2/29, 281 « 1234567 »