使代码简洁的五条忠告 – DELPHI教程

写代码是一种艺术。使用Delphi,任何人都可以轻而易举地开发出某种软件、完成某些任务。而完美的代码则只有真正的高手才能写出。除了正确的缩进、大小写、命名规则之外,请时刻牢记爱因斯坦的名言–简单就是美。下面将谈及的五个代码问题,可能是初学者、甚至一些老鸟都会犯的错误。

忠告一

布尔型变量的赋值操作应该是直接的。例如,在一个if/then/else语句中,if子句将布尔型变量赋值为True,而else子句将其赋为False。下面这段代码的写法是不好的:

if If_Love_Delphi then
Result:=True
else
Result:=False;

而这样写就比较好:

Result:= If_Love_Delphi;

继续阅读

一个程序员的开发习惯 – DELPHI教程

有关开发习惯的一些想法,如鲠在喉,不吐不快。究其发贴动机,当然不排除有骗取参与分的可能,但另一方面,也希望能给同行(念Xing)者提供一些建议,或者参考(希望不是误人子弟)。同时,也希望各位能够就我的这些陋习,发表一点看法,给出批评和指正的意见。谢谢。

一.建立工程目录

首先,第一步要做的,当然是给新项目建一个单独的目录(别笑)。目录名称与项目名称同名,或者另取一个也可,只要清楚、简练。然后,在此目录中创建以下各个目录:

<Doc>:用来存放该项目相关的开发文档(需求说明,概要设计,详细设计等等等等);

<Source>:用来存放Delphi源程序中的”.Dpr”,”.Pas”,”.Dfm”等文件;

<Dcu>:该目录中存放”.Dcu”文件,将’.Pas’与’.Dcu’文件分开存放只是为了让Source目录的内容更加清楚一些;

<Bin>:存放工程的输出文件,比如”.Exe”,”.Dll”或者”.Ocx”等等;

<Log>:用来存放日志文件;通常在这个目录中我会放一个”<项目名称>程序员日志.Txt”文件。

<Images>:当然是存放工程中用到的图片的目录了。一般情况下,这个目录是少不了的。假如还用到其他资源,那么也一样建立各自的目录,比如Wav,比如Avi等等。

以前一直都没怎么注意这个问题,搞得所有的代码都在一起,不是一个乱字了得

二.设置工程选项

在Delphi中创建一个新的工程,将此工程保存到Source目录中,同时:

a. 选一个耐看的,与项目有些联系的图标作为这个工程的图标。当然,这个图标可能只是临时用用的,但是总要比Delphi默认的那个难看的要好才行,要不然,怎么对得起自己?

b. 将Project Options -> Directories/Conditionals页面中的Output Directory设置为Bin目录;

c. 将Unit output Directory设置为Dcu目录。

三.添加常量单元

添加一个新的Unit,另存为“unt<工程名> Consts.Pas”,用来保存工程中用到的常量。

四.有关窗体(Form)及单元(Unit)

按照匈牙利命名法则给Form命名,则一个用来登录的窗体可以命名为’FrmLogin’,而其单元名可以为’untLogin’。通常,两个对应的Form和Unit的名称在除去’Frm’或’unt’的缩写后应当保持一致。

在Unit的头部添加本单元的注释,注释的格式可以参照Delphi的源码,但是至少应当包含以下几项:功能描述;作者;版权;创建时间;最后修改时间;修改历史等等。

将新创建好的Form的Caption设置为该Form类的名称,而不是使用Delphi默认的。比如,将Form1更名为FrmLogin后,此时我们获得了TFrmLogin这个新的窗体类,并且Delphi自动将窗体的Caption更新为’FrmLogin’。依我看,该Caption应当为’TFrmLogin’才是,因为我们在设计的是一个窗体类TFrmLogin,而不是仅仅对FrmLogin进行操作。

向TFrmLogin这样功能明确的窗体类,许多人都有在设计期就将其Caption设置为诸如“操作员登录”这种名称的习惯。我的习惯是,象“操作员登录”这样的常量,通常存放在unt<工程名>Consts.Pas中,用ResourceString来定义,或者用Const来定义。至于窗体的Caption的命名,应当属于运行期的工作。所以,我往往在TForm.OnCreate事件触发之时才对Caption进行操作,比如:

procedure TFrmLogin.FormCreate(Sender: TObject);
begin
Caption := csLoginTitle;
....
end;

五.关于Format函数的使用

有iYear,iMonth,iDay三个数据,要显示诸如“生日:1976/3/18”这样的信息,你通常怎么做?使用s := ‘生日:’+IntToStr(iYear)+’.’+IntToStr(iMonth)+’.’+IntToStr(iDay); 吗?这样实在是太累了。我的习惯是,在unt<工程名>Consts.Pas中增加一个常量csBirthDayFormat = ‘生日:%d/%d/%d’来保存显示格式,然后使用s := Format(csBirthDayFormat, [iYear, iMonth, iDay]);这样的语句完成数据的拼装。这么做的好处显而易见,那就是你只需在一个地方维护数据的显示格式。

Format函数功能强大,我对它很是推崇,你呢?

六.关于注册表或者Ini文件的存储

原先访问注册表我通常使用TRegistry,而访问Ini文件通常使用TIniFile。这两个类的使用方法各不相同,因此想要使用相同的代码既能访问注册表又能访问Ini文件几乎是不可能的。真头疼啊!

终于我发现了救星!那就是TRegistryIniFile类。查看Registry单元,我们发现,TRegistryIniFile继承自TCusomIniFile。而TIniFile也是继承于TCusomIniFile。因此,使用抽象类TCusomIniFile来实现对注册表或者Ini文件的访问便是一举两得了。比如:

var
csmIniFile: TCusomIniFile;
begin
if blUseIniFile then//如果使用Ini文件
csmIniFile:= TIniFile.Create(csRootKey)
else
csmIniFile:= TRegistryIniFile.Create(csRootKey);

//接着就可以使用csmIniFile对Ini文件进行访问,

//或者用类似访问Ini文件的方式访问注册表。

七.关于TStream流以及TFileStream,TMemoryStream等等

TFileStream和TMemoryStream都继承自抽象类TStream,这意味着我们可以使用一套代码完成对文件和内存的存取操作。因此,定义一些接口的时候,我往往倾向于将参数的类型定义为抽象类,而不是具体类。比如,要完成保存功能的一个函数,定义成

function Save(AStream: TStream): Boolean;

就比定义成

function Save(AStream: TFileStream): Boolean;

要灵活的多。

前一个定义是具有前瞻性的,因为它可以适用于以后可能出现的新型态的流。而后一个定义只适用于TFileStream这种流(当然包括TFileStream的子类),呆板多了。

我的习惯:如果存在抽象类,那么尽量将参数定义为抽象类的类型,毕竟,我们无法预见未来。

八.多使用TAction

Delphi 4以后引入了Action的概念,并且在Standard组件栏中增加TActionList组件。使用Action的好处是,控件状态同步的烦恼从此一扫而空!

[转自]一个程序员的开发习惯 – DELPHI教程

delphi7 lite 缺少clx运行库的解决办法

使用Delphi 7 lite 即精简版本,经常在安装第三方控件的时候,会发现,没有VisualCLX的运行库。

解决办法:

找到完整版的Delphi 7安装文件,其光盘的文件夹布局其实跟安装好的是类似的,只是部分文件拷贝到了system32系统目录下。

查找光盘上System32目录下包含clx的文件,拷贝到本机的delphi安装目录bin下,查找光盘上bin目录下的clx文件,拷贝到本机bin下,其实,总共的文件,都是6个,包括三个bpl,三个map文件。

继续阅读

Delphi 是否安装的判断

昨天安装了Delphi 7 Lite v2.02 集成D2007RTL,整体效果不错,运行速度也确实比较快,虽然是简化版,但是还是集成了部分常用的帮助。

不足:

1.安装过程中,选择不安装GExpert,但实际上还是安装了。

2.部分控件有独立安装程序的,安装时提示没有安装delphi,即找不到Delphi

3.由于去掉了clx,部分控件无法安装

继续阅读

浅谈Delphi如何控制Excel操作

    1 创建Excel文件
  要在Delphi中控制Excel,就必须用到OLE自动化。现在一般采用OLE2来创建OLE对象,当激活一个OLE对象时,服务器程序仅在容器程序内部激活,这就是所谓的“就地激活”(in-place activation)。

  创建Excel文件时,先创建一个OLE对象,然后在对象中建立工作表worksheet,如函数createExcel所示:

  function createExcel:variant;

  var

  v:variant;

  sheet:variant;

  begin

  v:=createoleobject(‘Excel.Application’);//创建OLE对象

  v.visible:=true;

  v.workbooks.add(-4167); //添加工作表

  v.workbooks[1].sheets[1].name:=’test’;

  sheet:=v.workbooks[1].sheets[‘test’];

  return v;

  end;

  2 数据表格控制

  Excel表格的控制,主要包括数据的导入、修改;单元格的合并、边框的控制;表格的复制、粘贴等。当报表格式一定的情况下,表格的复制、粘贴显得尤为重要,这样,可以先制作一个文件模板,然后按照实际需要输出多页报表即可。

  (1)数据的导入(importData)

  procedure importData;

  var

  I,j:integer;

  v:variant;

  begin

  v:=createExcel; //创建Excel文件test

  for I:=0 to maxcolumn do

  begin

  for j:=0 to maxrow do

  v.workbooks[1].sheets[1].cells[I,j]:=I*j; //导入数据

  end;

  end;

  (2)单元格的合并、边框的控制(lineStylecontrol)

  单元格的合并,是在选定合并范围的情况下进行的。边框控制可以操作边框线条的是否显示。其他方式的控制,可以仿照下面过程进行。

  procedure lineStylecontrol;

  var

  v,sheet,range:variant;

  begin

  v:=createExecl;

  sheet:= v.workbooks[1].sheets[1];

  range:=sheet.range[sheet.cells[1,1],sheet.cells[39,30]];//选定表格

  range.select;

  range.merge; //合并单元格

  range.borders.linestyle:=xlcontinuous; //置边框线可见

  range.font.size:=9; //改变表格内文本字体大小

  end;

KOL and MCK Web page

KOLKey Objects Library is a set of objects to develop power (but small) 32 bit Windows GUI applications using Delphi but without VCL (or Free Pascal). It is distributed free of charge, with source code.

————————————-

呵呵,挺有意思的一个项目,感觉好像开始很久了,有很多的附加工具和代码,有空去研究一下~

做个记录

KOL and MCK Web page

How to call JavaScript functions in a TWebBrowser from Delphi

Introduction

On some occasions when using a TWebBrowser I’ve needed to use Delphi to call JavaScript functions contained in the current document.

This is quite easy to do. We’ll first examine the techniques then we’ll look at a case study that changes the font in an HTML document.

Overview of solution

The window object associated with an HTML document exposes a method – execScript – that enables JavaScript to be called. The first parameter of this method takes a string containing the required function call (complete with actual parameters). The method’s second parameter specifies the script language being used – in our case 'JavaScript'.

So, how do we get hold of the window object that exposes the required method? We simply use the parentWindow property of the web browser control’s document object. We need to ensure that a document object is available by first loading the required document into the web browser and then wait for it to finish loading.

Implementing the solution

Let us assume we have a TWebBrowser control on a form into which an HTML document has been loaded. Assume also that the HTML document defines a JavaScript function named Foo() that takes a string and an integer parameter. Assuming the document is fully loaded, we can call Foo() with a method similar to this:

uses
  MSHTML;
  
procedure TForm1.CallFoo(S: string; I: Integer);
  { Calls JavaScript Foo() function }
var
  Doc: IHTMLDocument2;      // current HTML document
  HTMLWindow: IHTMLWindow2; // parent window of current HTML document
  JSFn: string;             // stores JavaScipt function call
begin
  // Get reference to current document
  Doc := WebBrowser1.Document as IHTMLDocument2;
  if not Assigned(Doc) then
    Exit;
  // Get parent window of current document
  HTMLWindow := Doc.parentWindow;
  if not Assigned(HTMLWindow) then
    Exit;
  // Run JavaScript
  try
    JSFn := Format('Foo("%s",%d)', [S, I]);  // build function call
    HTMLWindow.execScript(JSFn, 'JavaScript'); // execute function
  except
    // handle exception in case JavaScript fails to run
  end;
end;

Listing 1

Let’s look at what’s going on here. We first check that a document is available and store a reference to in Doc. We then attempt to get a reference to the document’s parent window object and store it in HTMLWindow. Once we have a valid window object we call its execScript method, passing the call to Foo(). The parameters to Foo() must be literal values – we can’t pass variables. String literals must be enclosed by double or single quotes.

Escaping quotes in string literal parameters

When passing string literal parameters to JavaScript functions you need to be careful to escape any quote characters contained in the string, otherwise the quote will terminate the string prematurely. Since JavaScript can use either single or double quotes to delimit literal strings you may need to escape either of these types of quote by preceeding it with a backslash.

As an example, suppose we need to pass the string He didn't say "hello" to a JavaScript function. If we delimit the string with double quotes we pass the it as "He didn't say "hello"".

Alternatively we may delimit the string with single quotes and pass it as 'He didn't say "hello"'.

If the JavaScript function contains errors or doesn’t exist an exception will be raised. We may wish to handle such exceptions before returning.

Note that execScript always returns a varEmpty value so we can’t use it to return a value from a JavaScript function. This means we can only use execScript to call JavaScript functions that return no value or where we don’t need the return value.

Case study

In this case study we will develop a small application that displays an HTML document in a browser window. The document will contain a Javascript function – SetFont() – that can change document’s default font. The application will display a combo box containing a list of all installed screen fonts. When the user selects a font from the combo box the font used in the web browser will be changed accordingly. We do this by calling SetFont() from Delphi.

Firstly, create an HTML document with any content you choose and include the following JavaScript function in the document’s <head> section:

<script type="text/javascript">
<!--
  function SetFont(fontname) {
    document.body.style.fontFamily = fontname;
  }
// -->
</script>

Listing 2

This is the code that changes the font.

Now create a new delphi application and drop a TComboBox and a TWebBrowser on the main form. We will load the HTML document when the form is first shown. We will also load the screen fonts into the combo box at the same time. To do this create an OnShow event handler for the form with the following code:

procedure TForm1.FormShow(Sender: TObject);
  { Setup combo box and load document }
begin
  // Store screen fonts in combo box and disabled it
  ComboBox1.Items.Assign(Screen.Fonts);
  ComboBox1.Enabled := False;
  // Load the HTML page
  WebBrowser1.Navigate(ExtractFilePath(ParamStr(0)) + 'Test.html');
end;

Listing 3

Note that we disabled the combo box to prevent a font from being selected. We do this because to set a font we need to access the browser’s Document object – and this object is only available when the HTML document is fully loaded. TWebBrowser triggers an OnDocumentComplete event when the document has finished loading. Therefore we handle that event and enable the combo box:

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
  { Document loaded: enable combo box }
begin
  ComboBox1.Enabled := True;
end;

Listing 4

We now come to the code that actually calls the JavaScript function. When the user selects a new font the combo box triggers its OnChange event. We handle this event by calling the JavaScript SetFont() function with the name of the selected font, as follows:

procedure TForm1.ComboBox1Change(Sender: TObject);
  { Make browser use selected font }
var
  Doc: IHTMLDocument2;      // current HTML document
  HTMLWindow: IHTMLWindow2; // parent window of current HTML document
  JSFn: string;             // stores JavaScipt function call
begin 
  // Get reference to current document
  Doc := WebBrowser1.Document as IHTMLDocument2;
  if not Assigned(Doc) then
    Exit;
  // Get parent window of current document
  HTMLWindow := Doc.parentWindow;
  if not Assigned(HTMLWindow) then
    Exit;
  // Run JavaScript
  try
    JSFn := 'SetFont(''' + ComboBox1.Text + ''')';
    HTMLWindow.execScript(JSFn, 'JavaScript');
  except
    // handle exception in case JavaScript fails to run
    ShowMessage('Error running JavaScript');
  end;
end;

Listing 5

This method is very similar to that described in the previous section. SetFont() is called with the name of the font selected in the combo box. If an exception is raised when the JavaScript is called we display a message.

We have now developed all the code. All that remains is to add the following uses clause to the implementation section of the unit to enable the program to compile:

uses
  SysUtils, MSHTML, Dialogs;

Listing 6

Demo code

The source code on the code study is available for download. The code was developed using Delphi 7 Professional.

This article is copyright © Peter D Johnson 2002-2007

Licensed under a Creative Commons LicenseOffsite icon.

 

How to call JavaScript functions in a TWebBrowser from Delphi

datasource 的onStateChange事件小议

发现一怪事:

一Form,上一dbgrid,一dataSource,一adoquery,FormShow时adoquery.open

1.发现事件触发顺序是这样的:

dataSource的OnStateChange——Form的Create——Form的Show等

很奇怪,应该是FromCreate最先发生的才对

2.另有一些窗体是正常顺序:

FormCreate——FormShow——StateChange

 

经过对比,发现

是因为1中的窗体设计时,adoquery是open的

应该是窗体在create的时候,会把dataset close,所以引发了datasource的StateChange

而这时,还没有调用FormCreate,导致了StateChange事件比FormCreate还早触发

 

设计时关闭数据库连接,重新编译,就是2的状态了。

 

做个记录,嘻嘻