2012/12/19

[轉] Delphi XE Refactor 重構功能簡單說明


Delphi XE Refactor重构功能简单说明

節錄部份說明如下:

1. Rename: 包括重命名变量,函数名,组件名等等。好处是它会把整个项目里所有引用的地方都自动修改!经常碰到名字起的不好或者不一致的,想要修改又嫌麻烦,现在省事多了。

2. Declare Variable,Declare Field: 自动声明,举个例子: for i:=0 to TmpList.Count-1 do begin ...end; 如果变量i没有声明,可以用这个功能加个声明。麻烦的是会弹出对话框让自己选变量类型,并没有节省太多时间

3. Extract Method: 提取方法。这个也很实用,举个例子:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Caption := 'This is a Test';
  Button1.Enabled := false;
end;

我们经常会在form的create事件里做很多的初始化操作,有时候发现这些初始化操作需要重复执行,选中要提取的代码,选择Extract Method,指定方法名为InitScreen,如下:


procedure TForm1.FormCreate(Sender: TObject);
begin
  InitScreen;
end;

procedure TForm1.InitScreen;
begin
  Form1.Caption := 'This is a Test';
  Button1.Enabled := false;
end;

如果提取的代码中引用了本地变量,会自动给新方法加上引用声明。不过,如果提取的代码过于复杂的时候有时会出错,需要自己手工修改。

4. Extract Resource String: 把一个字符串声明称resourcestring类型的常量,目前没发现有什么用处

5. Change Params: 修改函数参数,很不实用的功能

6. Find Unit: 查找类所在的单元,这个功能本来应该很有用,比如你在网上拷贝了一段代码,结果编译提示你找不到某个类型,用这个功能,输入类名,就可以告诉你在哪个单元里,并自动加到Interface或者implementation区域。可是,在实际使用的过程中,先是打开特别慢,我ssd的硬盘都要转半天,似乎每次都重新索引。其次就是有时有些类明明有就是找不到,目前也不清楚怎么回事。可惜这么好的一个功能变鸡肋,不知道XE2中有没有改进。

2012/12/18

自由倉頡真的好用

資料來源:Windows all x86/x64 倉頡輸入法(自由倉頡(轉載)+自製第五代碼表)

第五代碼表可採用"倉頡平台"的字碼表

終於有套符合TSF又支援第五代倉頡的免費輸入法了!

萬用字元*,用於模糊查找很好用
微軟倉是「難」鍵
自由倉是「:」鍵(沒錯,就是Shift + :)

中英切換
微軟倉是「Shift」
自由倉是「Shift + Backspace」

有些地方的切換反倒是不太習慣。
參考資料:《自由倉頡輸入法》常用熱鍵

2015/08/03 更新
由於在win7上的skype上聊天一陣子後,會造成軟體崩潰,最終還是放棄使用自由倉頡。

另一套「小小輸入法」平台則是在 PowerPoint 2010 輸入時一定會使 Powerpoint崩潰,故也無法使用。

目前,我使用的是 GCIN輸入法平台,在經過調整後,已經和微軟倉頡十分接近。

只是對win 8.1 以上的版本相容性還沒跟上。

GCIN是一套值得關注的好輸入法!

2012/12/14

幾種提昇 MDAC 應用程式效能的方法

資料來源:http://www.reocities.com/huanlin_tsai/faq/n012.txt

1.在記錄的迴圈當中使用預先連結的欄位物件

  參考下面的範例:

  procedure TForm1.Button1Click(Sender: TObject);
  var
    fldID, fldName, fldAge: TField;
  begin
    fldID := ADODataSet1.FieldByName('ID');
    fldName := ADODataSet1.FieldByName('Name');
    fldAge := ADODataSet1.FieldByName('Age');
    ADODataSet1.First;
    while not ADODataSet1.Eof do
    begin
      writeln(fldID.AsString);
      writeln(fldName.AsString);
      writeln(fldAge.AsString);
      ADODataSet1.Next;
    end;
    ADODataSet1.Close;
  end;

2.除非必要,否則不要使用 cursor-based 的方式更新資料

  雖然使用 SQL 命令來更新資料在某些情況下並不適合,你還是應該盡量
  使用這種方式,經由 recordset 物件 (TADODataSet 及其後代) 來更新
  資料雖然方便,但所必須付出的代價也較大,儘管 SQL 命令比較難以使
  用,但是絕對值得。

3.使用帶輸出參數的預儲程序取代只傳回一筆記錄的 Select 敘述

  當你知道 query 傳回的結果集只有一筆記錄時,你可以使用帶輸出參數
  的預儲程序取代開啟一個 recordset。
  當你開啟一個 recordset 時,傳回的結果集包含了資料以及 metadata
  ,通常 metadata 的資料量蠻大的,所以你可能會想用一個帶輸出參數
  的預儲程序。

  Sub SingletonSp()

    Dim cmd As New Command
   
    cmd.ActiveConnection =
      "Provider=SQLOLEDB;DataSource=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
   
    cmd.CommandText = "GetAuthorName"
    cmd.CommandType = adCmdStoredProc
   
    cmd.Parameters.Append cmd.CreateParameter(
      "Id", adChar, adParamInput, 11)
    cmd.Parameters.Append cmd.CreateParameter(
      "FName", adChar, adParamOutput, 30)
    cmd.Parameters.Append cmd.CreateParameter(
      "LName", adChar, adParamOutput, 30)
   
    cmd(0) = "172-32-1176"
    cmd.Execute
    Debug.Print cmd(1), cmd(2)

  End Sub

  Sub SingletonSelect()

    Dim rs As New Recordset
   
    rs.ActiveConnection =
      "Provider=SQLOLEDB;Data Source=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
    rs.Source = "select au_fname, au_lname from authors where" & _
      " au_id = '172-32-1176'"
    rs.Open
   
    Debug.Print rs!au_fname, rs!au_lname

End Sub


4.如果你必須使用 cursor,對傳回一筆記錄的結果集使用 Collect 方法

  Recordset::get_Collect 及 Recordset::set_Collect 方法可以讓你
  不用透過欄位物件而快速的存取欄位值,這種方法最適合用在只傳回一
  筆記錄的結果集。

  Sub Collect()

    Dim rs As New Recordset
   
    rs.ActiveConnection =
      "Provider=SQLOLEDB;Data Source=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
    rs.Source = "select au_id, au_fname, au_lname from authors" & _
      " where au_lname = 'Green'"
    rs.Open
   
    Debug.Print rs.Collect(0), rs.Collect(1), rs.Collect(2)
    ' VBA shortcut
    Debug.Print rs!au_id, rs!au_fname, rs!au_lname

  End Sub

5.只取得你所要的資料

  Select * 的簡單使用容易讓人養成壞習慣,考慮只將你要的欄位 select
  進來,同時也要考慮用 where 來限制傳回的記錄數量。

6.小心選擇你的 cursor location

  如果你不需要捲動或者更新記錄,就使用 ADO 的內定值:
    CursorLocation = adUseServer
    CursorType = adOpenForwardOnly
    LockType = adLockReadOnly
  此內定值讓你最快速的存取只能向前捲動的結果集。
  把握一個原則: 根據需求做適當的設定,不要給多餘而不必要的功能。

  如果你需要前後移動記錄,就不要使用 adUseServer,ADO 將
  adUserServer 做為內定值是由於向後相容的考量。在大部分需要捲動
  的情況下,使用 client cursor 會比較適當,只有在比較特殊的情況
  下,像是資料量非常龐大的時候,就應該使用 server cursor。
  另外,如果你使用 client cursor,但是並不需要更新資料時,請將
  LockType 設定為 adLockReadOnly,如果你需要更新資料,client
  cursor 引擎必須取得額外的 metadata,而這會付出昂貴的代價。

  後端為 SQL Server 時應避免使用 Static 及 Keyset cursor,SQL
  Server 並不直接支援 Static 及 Keyset cursor,它必須複製資料到
  暫存資料表,因此降低了效能。

  註1:當 CursorLocation 為 adUseClient 時,ADO 會自動將 CursorType
      設定為 adOpenStatic,即使你設定成其他值,在開啟資料集時 ADO
      就會自動改為 adOpenStatic。
  註2:Microsoft Jet database engine 不支援 dynamic cursor,所以OLE
      DB Provider for Microsoft Jet 不支援 adLockDynamic cursor。
  註3:當 CursorType 為 adOpenForwardOnly 或 adOpenDynamic 時,
      Recordset 的 RecordCount 屬性總是等於-1。參考 http://
      support.microsoft.com/support/kb/articles/q194/9/73.asp

7.調整 Recordset 的 CacheSize 屬性 (TADODataSet.CacheSize)

  ADO 使用 Recordset 的 CacheSize 來決定要快取的記錄數量,當你在
  快取的記錄範圍內移動 cursor 時,ADO 會直接由快取中傳回資料,當
  你移出快取範圍時,ADO 會釋放快取,並且取得下一批快取記錄。
  那麼 CacheSize 要設定多少會有最佳效能呢? 答案是視情況而定。你
  應當嘗試用多個不同的 CacheSize 來找出讓你的應用程式表現最佳的
  設定值(建議值: 10)。

8.儘快釋放掉沒有使用的 ADO 物件

9.自行描述命令參數

  即 Delphi ADOExpress 的 TADOCommand.Parameters 屬性, 例如:

    with ADOCommand1.Parameters do
    begin
      Items[0].Name := 'ReturnValue';
      Items[0].DataType := ftInteger;
      Items[0].Direction := pdReturnValue;
    end;

10.使用原生 OLE DB Providers 

11.對唯讀資料集以及需要較長時間的處理可以切斷 client cursor 與
   connection 的連結以增進效能

   切斷 Recordset 連結是 client cursor 引擎的一項功能,當你在處
   理較費時的工作時可以利用這項功能,處理完之後可以再恢復連結。
   Delphi 的 TADODataSet 及其後代應該只要將 Connection 屬性設為
   nil 即可 (未驗證)。

12.不需要傳回結果集時使用 Connection 的 adExecuteNoRecords 選項

  當你使用這個選項時,ADO 不會建立 Recordset 物件,也不會設定任
  何 cursor 屬性。

  Delphi:

    TADOConnection.Execute(CommandText, eoExecuteNoRecords);

13.對於只使用一次的命令使用 Connection::Execute

  當你使用 Connection::Execute 方法執行只需一次的命令時,ADO 對
  此做了些效能最佳化。常見的使用時機是用在 IIS, ASP, 及 MTS 環境
  下,典型的步驟是: 開啟 connection,執行傳回或不傳回資料集的命
  令,處理結果集,然後關閉 connection。在這種情況下應該使用
  Connection::Execute 以取代 Recordset::Open 或 Command::Execute
  。當你使用 Connection::Execute 方法時,ADO 不會保留任何命令的
  狀態資訊,因此會獲得較好的效能。如果你需要較多功能的 cursor 或
  者你需要再執行 Execute 方法時帶參數的話,你仍然需要使用
  Recordset::Open 或 Command::Execute 方法。



參考文件

  http://www.microsoft.com/data/impperf.htm
  http://vbdata.iwarp.com/speed.htm

关于在DELPHI6中使用正则表达式的一些心得

转载地址:
http://www.delphibbs.com/keylife/iblog_show.asp?xid=25712
http://blog.csdn.net/senfore/article/details/2154944

一. 工具选择

DELPHI6本身没有处理正则表达式的库,只能找第三方库。在选择方面,我的标准是:

1. 不必向开发环境注册控件
2. 接口简单
3. 符合主流的perl式正则语法
4. 专业,至少应该有个看上去专业的专门网站
5. 免费

目前符合以上标准, 比较好的RegEx类库有TRegExpr ( http://www.regexpstudio.com/ )与PerlRegEx ( http://www.regular-expressions.info/ )。

TRegExpr 是俄国人做的RE类库,应该说是目前国内最主流的免费RegEx类库了。纯DELPHI写成,支持中文,可以选择安装为开发环境控件,也可直接作为类库单 元使用(只有一个主类,一个pas文件)。美中不足是自从2004年后就没有更新了,版本一直是0.9xxx,就是不上1。而且不支持 Lookaround语法(前瞻与回溯功能)

PerlRegEx底层是用C的类库,完全符合PCRE标准(兼容Perl的正则表达式)。 文件结构比TRegExpr复杂一点,包括一个放底层obj文件的子目录和两个接口.pas文件,实际使用时只需要向项目中添加一个单元(当然也可以注册 成为控件)。之前的版本据说对中文支持不够,最新版本我在中文环境下用倒没遇到什么问题。说明文档也声称支持Unicode。

现在我是常 备两个这两个类库,但主要还是用PerlRegEx。除了迷信最后更新日期与C的执行效率外。还看中了RegexRubby这个基于同一套C类库的 RegEx编写工具,以及PerlRegEx提供了一个study方法,声称可以对正则式做点前期编译,提高执行效率。

=========================================================================
二 使用方法:

解 压了PerlRegEx包后,如果不想注册控件,除了PerlRegEx.pas、CHelpers.pas和PCRE目录外,其他的东西可以建个隐藏目 录搁置起来(没认真阅读用户协议,不知道能不能随便删。。。)。维持这两个文件与PCRE的目录结构不要变。使用时只需要把PerlRegEx.pas添 加进项目,在单元中uses PerlRegEx就可以了。

PerlRegEx提供了TPerlRegEx类。主要用法是:

RegEx : TPerlRegEx;
....
RegEx := TPerlRegEx;
try
  RegEx.Subject := '要匹配的正文';
  RegEx.RegEx := '正则表达式';
  if RegEx.Match then ....
finally
  RegEx.free
end;

如果要多次匹配并做一些处理,可以:
Matched : boolean;
....
RegEx.Match;
while RegEx.FoundMatch do
begin
  ....
  RegEx.MatchAgain;
end;

如果要替换匹配到的内容,可以
RegEx.Subject := '要匹配的正文';
RegEx.RegEx := '正则表达式';
RegEx.Replace := '替换的字符串'
if RegEx.Match then RegEx.ReplaceAll;  //结果在RegEx.subject
或者 if RegEx.Match then Result := RegEx.Replacement;

匹配到的字符串放在RegEx.MatchedExpression中,长度在RegEx.MatchedExpressionLength中,上一次匹配的结束位置在RegEx.Stop中

匹配到的子串放在RegEx.SubExpressions[i]中,子串个数在RegEx.SubExpressionCount中。

如果正则式很复杂而且常用,可创建一个生存期相对长的TPerlRegEx实例.设置好RegEx属性后,使用.Study方法对正则表达式进行预处理.据帮助文档说,文档资料会大大提高效率.

详情可参考文档。有一点文档上没有提到(又或者我看漏了),在第一次匹配之后,如果没有重新赋值subject,下一次匹配无论用Match或者MatchAgain,都是从上次的结束位置开始。所以如果要重新开始匹配,应先把RegEx.Start := 0;

==========================================================================
三. 使用和编写正则表达式要点

使用正则表达式,通常是用作三种用途:校验字符串,提取信息,处理字符串.

当 用作校验时,通常是对正文整体校验,例如通常是判断正文是否正确的邮件地址,而不是判断正文是否含有正确的邮件地址.因此应在正则表达式的两端加上行开始 锚点^与行结束锚点$.如果待校验的文字允许两端有空格,则应该在锚点前后用' *'或'/s*'(允许空格与TAB)匹配进去.

设计正则表达式的要点在于分段.对要匹配的内容分好段,就能够容易地各个击破.通常在要匹配的文字中会有一些分段的提示,例如逻辑上的单位、重复出现的模式或者不能连续重复出现的字符(串)。

以设计校验输入数字的正则条件为例,可以先列出符合条件的情况:
1234 / 12.34 / -12.34 / 12.3e4 / 12.3e-4 / .12E-34
可以看出,逻辑上的单位有:符号,整数部分,小数点,小数部分,e(或E),指数符号,指数部分
技术上的分段标志有:

符号:在开始与E后面各可能出现一次
小数点:只能出现一次,若出现,其后必须有小数部分。
e:只能出现一次,若出现,其后必须有指数部分。

所有“若出现,其后必须有。。。”的都可以考虑分为一组。可得初步方案: [+/-]?/d*(/./d+)?([Ee][+/-]*/d+)?

但 这个设计有问题,前半段的 /d*(/./d+)? 是可以匹配空串的,而需求是如果有整数部分,则小数部分可选。如果无整数部分,则必须有小数部分,直观的做法是改为(/d+(/./d+)?|/. /d+)。再认真观察一下,可以发现这个选择式无论任何情况,都是以/d+结尾,而我们实际上并不关心这个/d+是匹配到整数部分还是小数部分,至于前面 的小数点与整数部分都是可选的。因此,这部分可以改写为 /d*/.?/d+

所以最终的校验式是:^ *[+/-]?/d*/.?/d+([Ee][+/-]*/d+)? *$

使 用正则表达式提取信息是一个难点,但也是体现正则表达式强大实力的一个方面。提取信息的正则表达式必须要考虑四个方面:不误判(应该有一定语法检验能 力),不漏判,子串能匹配到正确位置。一些结构复杂或具有循环结构的正文,可能需要多次处理或使用开发语言的循环结构来辅助提取。具体技巧我现在还觉得比 较模糊,以下仅举几个例子:

1. 查找并分析 XX1>XX2,<,=,!,空格,TAB符号的任何字符串,式子两端与元素之间允许有空格或TAB

由 于这个不等式可能在上下文中,我们需要先在正文中把合语法的不等式隔离出来,否则下面的循环部分就会匹配到下一条不等式的部分。在这个例子中还算简单,找 到 '/b[^<>=!/s]+((不等符号)[^<>=!/s]+)+/b' 就可以了(其中不等符号在下面解释)。但这样只能匹配到整个式子而不能分别提取式子中的子串信息,当出现(...)+时,对应子串内容是只是最后一个匹配 到的串。

对每个匹配到的结果,因此这里需要分开两次提取,第二次需要使用循环来辅助。

先取最开始的子串,这个很容易,直接 '^/s*([^<>=/s]+)'就可以了,注意^ *是为了去掉开头多余的空格与TAB。真正的XX1在匹配到的子串1中。

接 着开始分析 '((不等符号)[^<>=!/s]+)+' 部分。整个(...)+结构需要在外部用开发语言的循环来逐次提取。先列出合法的不等符号:>=,>,=,<=,<,<& gt;,==,!>,!<,!>=,!<=,!=。因此不等符号部分应该是(!?>=?|!?& lt;=?|!?==?|<>)。

因此,要分析篇正文,就需要:
1)A匹配 '/b[^<>=!/s]+(/s*(!?>=?|!?<=?|!?==?|<>)/s*[^<>=!/s]+)+/b' 找出不等式。
2)    对每个A匹配结果, B匹配'^/s*([^<>=!/s])',提取子串1记录为变量名称。
3)    接着B匹配'/s*(!?>=?|!?<=?|!?==?|<>)/s*([^<>=!/s]+)',提取子串1记录为符号,子串2记录为变量名称。
4)    从3)开始循环直到找不到B匹配结果
5)从1)开始循环直到找不到A匹配结果

2. 提取电话号码

这 是不久前帮朋友做的一个小程序。事情是这样的:他的公司需要撒网式找澳大利亚酿酒公司合作伙伴,他的任务就是把网上查到的酿酒公司的联系方式记录入库。记 录联系方式的数据库是把公司名称,地址,电话号码,传真号码,邮箱等信息分开不同字段储存的。于是他必须用鼠标在网页准确选下各种信息然后粘贴到数据表 中,不但工作效率低,而且据说由于鼠标精确动作太多,手腕酸得不得了。于是找我帮忙写个小程序,需求是他可以把联系方式部分整个复制下来,我的程序自动提 取出有关信息。以下是提取电话号码信息功能的设计过程:

我看了一下联系方式的可能情况,发现有时里面会包括多个电话号码,而朋友的数据库只记录一个号码。因此我决定把他选定文本中所有电话号码都提取出来,列在一个ComboBox中让他选择。在正文中标记为“Phone”或"Ph"或"P"的优先列在前面。

电话号码的写法五花八门,先考虑电话的标记,一般有以下几种:
Phone, Phone:, (Phone), P, P-, PH 等等
因 此可把匹配标记的正则表达式设计为 '(?-i)(?:/(?Phone|Ph?)[-:]?/s*/)?)'。这种写法有个缺陷是无法保证两边括号能匹配(例如能匹配到 '(Phone:')。但在这里的目的并不是校验,括号不匹配并不影响我提取电话号码,只求简单写成这样就够了,否则就要写 成:'(?:Phone|Ph?)[-:]?|/((?:Phone|Ph?)[-:]?/s*/))' ,麻烦得多。

然后考虑电话号码本身,一个完整的固定电话号码可能是这样的:
+61 2 1234 5678 , (61 2) 1234 5678 , (61-)2-12345678, 61 (0) 2 12345678
而也可能省略国家代码(+61)或洲区号(02)简写成
02 1234 5678 , 1234 5678, 2-1234-5678
也有可能不按主号码四字一断的做法,写成
02 123 456 78 等等

构建正则表达式的过程如下:

匹 配国家代号:(?:[+( ]*61[-) ]*)?  可以看出,这个式子如果用来校验是不合格的,它能匹配到'(++61-)-'这样的正文。但我在这里是为了提取公司网页上的信息,公司不会在自己的联系 方法信息里放入这样的乱码。提取信息时,根据需求,在不误判的前提下可以假定输入信息不会出现太离谱的错误。

匹配区号:(?:/(? *0?/)? *(/d) *[-)]? *)?  同上,这个式子也可能匹配到不合法的正文。这里如果把区号与主体号码合并处理会简单很多。但我在这里想把区号提取出来,作为判断省份的一个依据。

匹 配电话号码主体:(?:/d{5,}(?:[ -]/d+)*|/d{1,4}(?:[ -]/d+)+) 如果仅考虑匹配电话号码,用/d*(?: [ -]/d+)*就行了。但澳大利亚的邮政编码刚好是四位数字,而且地址中的信箱号有可能是3到4位数字。因此这里用了个麻烦的写法,如果连续数字小于5 位,则后面必须跟一个连接号或空格,然后再跟数字,才能匹配到。

因此优先选取的号码的正则表达式是:(?-i) (?:/(?Phone|Ph?)[-:]?/s*/)?)((?:[+( ]*61[-) ]*)?(?:/(? *0?/)? *(/d) ?[-)]?/s*)?(?:/d{5,}(?:[ -]/d+)*|/d{1,4}(?:[ -]/d+)+))
电话号码在子串1,区号在子串2

第 一轮扫描正文,一边找到匹配,一边把其替换成''。完成后,就可以用((?:[+( ]*61[-) ]*)?(?:/(? *0?/)? *(/d) ?[-)]?/s*)?(?:/d{5,}(?:[ -]/d+)*|/d{1,4}(?:[ -]/d+)+)) (去掉了匹配电话标志部分)对替换后的正文,找出所有没有电话标志,但符合格式的子串。  

DBGrid繪圖上的一個小Bug

在Delphi 2010之後,DBGrid多了一個Drawing Style屬性,可以讓我們DBGrid更為漂亮

但不知怎麼的,常常在使用上見到「殘影」,難道Delphi改走武術路線不成?

當然不是,這是DBGrid的一個Bug

一直到XE3(2013)為止,這個Bug一直沒有解決

於是國外有人修改了VCL Source來解決這個問題

這邊轉貼他的Fix法:

2012/12/12

Delphi/BCB檔案名稱的處理函式整理

底下的網址有詳盡的介紹

這樣就可以少嗑些code了吧!哈哈!

資料網址:File Name Utilities

除了整理之外,還有範例碼!

一個字:讚!


2012/12/10

Delphi裡面常看到的#$D#$A是什麼意思咧?

#$D#$A = CRLF = #13#10 = char(13)+char(10)

Chrome套件介紹-Webpage Screenshot 網頁快照

當你看到某個網頁很不錯想抓圖下來留念,或者希望能將網頁上的訊息抓圖保存下來,留待日後當做證據或其他備份用途,可以試試看用下面的網頁抓圖軟體來抓圖。

Webpage Screenshot是個Gooogle Chrome瀏覽器的擴充套件,可以安裝在4.x以上版本的瀏覽器,內建繁體中文語系。可以將目前看到的可視範圍內的網頁畫面抓圖下來,存成JPG圖檔,也可將整個網頁從上到下、完整的抓圖下來,整個操作相當簡單。

詳見:重灌狂人-「網頁快照」支援自動捲頁、將網頁全文抓圖存檔(Google Chrome套件)

圖片來源:重灌狂人

2012/12/05

DataSetProvider.ResolveToDataSet

DataSetProvider.ResolveToDataSet=false时
代表DataSetProvider自动产生更新数据的Sql叙述用于更新数据库。
DataSetProvider.ResolveToDataSet=true时
代表通过DataSetProvider连接的Query来更新数据。


資料來源
关于用query 作为数据集更新数据和DataSetProvider.ResolveToDataSet的关系

2012/11/27

IdHTTP post 数据的问题

IdHTTP post 数据的问题

http://topic.csdn.net/u/20070109/20/36173cf4-c5bf-4842-81b6-b9361ed39f23.html

Delphi 的 ActiveX Form 相關筆記(未整理)






Delphi7 BUG Web Deployment Options呈灰色的解决

这是d7的bug,处理方法很简单

每次打开工程后,新建一个ActiveForm页,然后再从工程中删除,再到type   library中删掉相应的内容就可以使用deploy了。 

另一个解决办法,你可以打开".DOF"文件进行手工修改下面单元:

[Deployment]
DeployDir=d:\
DeployURL=d:\
HTMLDir=d:\
CABCompress=0
CodeSign=0
IncludeVerInfo=1
AutoIncRelease=0
DeployPackages=1
DeployFiles=0
CompanyURL=
Description=
CredFile=
PrivKey=
CryptoType=0
Timestamping=0
TimestampServer=

2012/11/26

AutoUpdate unit for Delphi/Indy

使用Delphi做自動更新的一個參考方案

AutoUpdate unit for Delphi/Indy

C++ Builder的TDataSet存取Text、Image及Memo欄位的方式

对于SQL中的TEXT、IMAGE、MEMO字段的存取,可以采用下列程序:

/* BLOB字段的读取: */
TBlobSTream* TemplateStream;
char* TempPlatePtr;              

TemplateStream = new TBlobStream((TBlobField*)WebQuery->FieldByName("SearchTem"),bmReadWrite);
TemplatePtr = new char[TemplateStream->Size];
TemplateStream->Read(TemplatePtr, TemplateStream->Size);


/* BLOB字段的写入:*/
TBlobSTream* TemplateStream;
char* TempPlatePtr;              

TemplateStream = new TBlobStream((TBlobField*)WebQuery->FieldByName("SearchTem"),bmReadWrite);
TemplatePtr = new char[TemplateStream->Size];
TemplateStream->Write(TemplatePtr, TemplateStream->Size);

________________________________________________________________
补充:
获得字段的大小用函数datalength

Flex / Flash Builder 相關資源 (未整理)

http://blog.minidx.com/category/flex

在 Flash Builder 中建立第一個桌上型 Flex AIR 應用程式

Adobe AIR SQLite Example

Adobe AIR technology


國立臺南大學數位學習科技學系畢業專題實作成果報告

國內學習AIR、FLEX必備好站

Remove selected item from DataGrid
Flex DataGrid 的基本範例

DOC? / AIRDOC

PageControl

深入分析Flex [Bindable]

Flex中[Bindable]的使用心得

NativeExcel - Delphi操作Excel的好朋友


官方網站:Nika Soft
Delphi內附的Excel元件真的是爆難用的,Obj的方式在Debug上也是痛苦,NikaSoft公司的NativeExcel產品就是以OleObject為基底下,再對它進行封裝。
非常好使的一套元件!

唯一可惜的是,並沒有提供C++ Builder的支援。
但是真的很好用!值得一推!

學DBX和DataSnap不可不學的好朋友 - TClientDataSet

在 About.Com Delphi 裡面有一篇關於 TClientDataSet 的專欄:
A Guide to Using the TClientDataSet in Delphi applications

如果沒有買到Delphi in Depth: ClientDataSet的人,可千萬不要再錯過這篇專欄哦!

2012/11/13

在Blogger裡面使用Syntax Highlight V3.0

Syntax Highlight V3.0後,Delphi, C++等語法並不能在Blogger正確被載入

Google後才找到這篇:

How To Add Syntax Highlighter (V3) To Blogger?



節錄內容如下:

  1. Select the theme of your highlighter,you can see demo of theme here.
  2. Then select the brushes which you want
  3. Click on the Get Code button
  4. Copy all the code from the text area
  5. Now go to your template
  6. Find for
  7. Add copied code just above it, tag in your template

這個網站很貼心的在底下寫了指令碼生成器,按照你需要的語法自動產生,之後再按上述的步驟修改Blogger範本,就可以開心使用囉!

基礎課程 - Delphi Interceptor Classes

利用 「Class 攔截器(Interceptor Classes)」 就可以不需要寫大量的繼承指令碼了

實戰中有時也會遇到,比方說像 TMaskEdit 的 ValidateError 事件的覆寫

2012/10/29

如何改變 TPageControl 的 Tab Title Font + BG Color


文章來源:tabsheet フォン変更   by www

雖然是日文的內容,可是還蠻容易理解的
此外,Delphi7裡面的PageControl在Win7 64bit下有bug 當設定 OwnerDraw 時,Tab Title及OnDrawTab會無功能,在文末有解決方法!

以下是節錄內容:

2012/10/18

自製類 measureText 方法 - 使用 Delphi / C++ Builder

在 JavaScript 裡面有一個好用的函式:measureText
可以利用它查出 Text string 的 PX 單位寬度和高度

雖然在 Delphi 似乎不太需要用到這項功能,因為物件本身都已經有 width 和 height 屬性了

不過無聊的時候還是可以玩玩 px / width 的單位轉換

GetTextPxWidth / GetTextPxHeight 函式是參考 How to get TextWidth of string (without Canvas)?

不囉嗦了,直接來看 code 吧!

2012/10/04

FastReport 的 Variables 和 Script Variables


Variables 可在 Design 上看到變數
Script Variables 則看不到

Design script裡面使用上
是直接使用,例如:

Script Variables :
========
Delphi:
frxReport.Script.Varialbes['XXX'] := 'XYZ';

FR Design
ShowMessage(XXX);  // 雖然看不到,但可以直接使用
========

 Variables:
========
Delphi:
frxReport.Varialbes['XXX'] := '''XYZ''';

FR Design
ShowMessage(<XXX>);  // 在Design Manager可以看到,但設定和呼叫上就比較麻煩
========


參考來源:







YA! 又過一關囉!




FastReport4.x 在 XE XE2 下編譯失敗的問題

如果是買FastReport正式版的使用者,可能會遇到FastReport 4.x的Source編譯失敗的情況

其實是因為XE2它為了與FireMonkey相容的關係

所以會把uses的位置做了一些修改

2012/09/25

Indy10 IdHTTP對非英文語的處理方式(泛中文處理)

這陣子想從網路上下載一些文件,URL大致上像下面這句:

「sUrl := http://www.DelphiCpp.com/我愛Delphi.txt」

使用 IdHTTP.Get(sUrl, ms) 方法卻怎麼也抓不到,可是也沒有Exception…

李組長眉頭一皺,發現案情並不單純。

於是請了Google大神拜了一下,也發現不少災情。

请问Delphi7怎么解决Indy发送中文字符的问题
Thread: IdHTTP and æøå ??

發現共通點都是靠「TIdTextEncoding」來解決問題
所以原先的作法就修改成這樣:

新書推薦 - Delphi XE2 Foundations (Delphi XE2 基礎)

以下是原文介紹
======================
Provides a comprehensive guide to the language and core non-visual libraries of Embarcadero Delphi XE2,
from basic language syntax to multithreading.

Adopting an integrated approach, the book covers both newer and older features alongside one another;
while it won't teach you how to program, it assumes little Delphi knowledge specifically.

Includes coverage of XE2's support for Mac OS X.

(Edition note: the printed version combines the three parts of the eBook version, which is available separately.)

如果手上有Kindle的人也可以考慮買Kindle Edition

不知道怎麼買的人也可以到這裡購買

天瓏

Amazon Delphi XE2 Foundations part1 for Kindle Edition

2012/08/20

IE Table 專用的 "bordercolordark" 和 "bordercolorlight"

 參考了以下的網頁:
http://w3help.org/zh-cn/causes/BT3003
http://help.dottoro.com/lhcrketd.php

知道這兩個屬性是IE專用的屬性,微軟也說不要再用它了,但卻也沒提到如何解決。

所以參考了 Dorroto 網頁的寫法:
// top right bottom left
    // blue cyan cyan blue
<table style="border:4px solid; border-color:#0000FF #00ffff #00ffff #0000FF;">
    <tr>
        <td onclick="ChangeBorder ();">Click this text!</td>
    </tr>
</table>


border-color 的配置順序是:上 左 下 右
所以要達成配色的話會是:色1 色2 色2 色1

但TD標籤並不會影響,那怎麼辦呢?

所以還需要再加上

<td style="border-color:#00FFFF #0000FF #0000FF #00FFFF;">Click this text!</td>
也就是反過來:色2 色1 色1 色2

2012/08/01

[轉]SQL SERVER 2000 事件探查器无法暂停及停止的解决办法

http://servicehome.ufida.com.cn/space/viewspacepost.aspx?postid=387
http://www.zu14.cn/2010/06/29/sql-server-profiler-can-not-stop-or-pause/

SQL SERVER事件探查器虽好用,可有的服务器上会出现针对本地数据库(local)启动事件探查器后无法暂停及停止的问题(一旦暂停或停止就长时间没响 应),出现这个问题主要原因是由于事件探查器默认使用安装SQL SERVER时记录下来的本地计算机名来访问本地数据库,一旦安装SQL SERVER后修改了计算机名,就会出现事件探查器能启动不能停止的问题。

   治标的解决办法:使用计算机名或IP来使用事件探查器连接数据库,而非用(local),则能正常暂停及停止了。

   治本的解决办法:更新SQL SERVER中记录的计算机名。打开master数据库的sysservers表,修改srvname字段及datasource字段为当前计算机名(由 于是系统表,默认不允许修改,所以修改前需要先进行设置:在企业管理器中的(local)节点点鼠标右键,“属性”-“服务器设置”,勾选“服务器行为”中的“允许对系统目录直接进行修改”)。

2012/07/30

ProcessInfo 1.5 is released with Win64 support

想取得程序的Handle等其它資訊還蠻好用的

ProcessInfo 1.5 is released with Win64 support

Posted on September 12th, 2011 Ali Keshavarz 5 comments
ProcessInfo 1.5 is released. The changes in this release are:
  • Added support for Win64 and Delphi XE2.
  • Added TProcessItem.CloseProcess method to close a process normally (not forcefully).
  • Added TProcessItem.CurrentProcess property. This property always refers to the current process in the list of running processes.
  • Added PrivateWorkingSetSize property to TProcessItem.MemoryInfo.
  • Added global  ProcessInformation function. This function returns a global instance of TProcessInfo. The instance will be freed when the application is terminating.
  • Fixed a few minor bugs.
To download ProcessInfo 1.5, please go to ProcessInfo page.


2012/07/25

SQL Server月份相減跨年度的計算方法

SET @YY='2012'
SET @MM='03'
SET @MM=@MM - 5

  IF @MM <= 0
  BEGIN
      SET @YY=@YY - 1
      SET @MM=@MM + 12
  END

雖然好像有更好的作法,但找到之前還是將就點吧

2012/07/23

Open dbExpress 安裝

http://sourceforge.net/projects/open-dbexpress/files/dbxoodbc%202012%20-%20dbx%20ODBC%20driver/dbxoodbc_3_2012_0716dev.7z/download

一、首先是先安裝bpl到RAD Studio裡面
dbxoodbc\lib\{%DelphiVersion%}\dbxoodbc*.bpl
以XE2來看的話,就會是在「dbxoodbc\lib\delphi-2012(16)XE2\win32」(32bit)目錄裡面

二、接下來再把dbxoodbc\lib\dbxoodbc_driver\(%Platform%)\release目錄裡的相關檔案複製到系統路徑
以Win32系統為例,就是把「dbxoodbc\lib\dbxoodbc_driver\win32\release」複製到Delphi安裝目錄裡的bin資料夾下,也就是「{%DELPHI}\Bin」

三、接下來是要註冊 dbxconnections.ini 及 dbxdrivers.ini
說真的,這兩個檔案不是放在特定資料夾中,常常會找不到它們
以我的XE2為例,它們是放置在「c:\users\public\documents\RAD Studio\dbExpress\9.0」目錄中,如果你的電腦沒有的話,可以在底下的機碼中尋找「[HKEY_CURRENT_USER\Software\Embarcadero\BDS\9.0\DBExpress」

台灣大多數的人都是用SQL Server,所以我們就以它的設定為範本:
===dbxconnections.ini===
;--------------------------------------------------------------------------------------------------
[dbxoodbc_SS_DirectMode]
DriverName=DbxSQLServer
GetDriverFunc=getSQLDriverODBCW
VendorLib=sqlsrv32.dll;sqlncli10.dll;sqlncli.dll;odbc32.dll
Trusted_Connection=No
User_Name=name
Password=secret
BlobSize=-1
RowsetSize=20
OpenOdbc TransIsolation=ReadCommited
Trim Char=True
Database=?
ConnectionString=coCatPrefix=DATABASE;SERVER=?
MetaDataPackageLoader=TDBXOpenODBCMetaDataCommandFactoryMSSQL
DriverPackageLoader=TDBXDynalinkDriverLoaderOpenOdbc
;--------------------------------------------------------------------------------------------------
===dbxdrivers.ini===
[Installed Drivers]
DbxSQLServer=1
;--------------------------------------------------------------------------------------------------
[DbxSQLServer]
LibraryName=dbxoodbc.dll
ProductName=DbxOpenODBC
DriverUnit=Dbx34Drv
MetaDataPackageLoader=TDBXOpenODBCMetaDataCommandFactoryMSSQL
DriverPackageLoader=TDBXDynalinkDriverLoaderOpenOdbc
DbxSQLServer TransIsolation=ReadCommited
GetDriverFunc=getSQLDriverODBCW
VendorLib=sqlsrv32.dll;sqlncli10.dll;sqlncli.dll;odbc32.dll
DATABASE=(Database Name)
Trusted_Connection=YES
User_Name=
Password=
ConnectionString=coCatPrefix=DATABASE;Server=(Server Name)

[DbxSQLServer TransIsolation]
DirtyRead=0
ReadCommited=1
RepeatableRead=2
;--------------------------------------------------------------------------------------------------
四、接下來我們要在bpr裡面,增加一個uses模組項目:
uses DbxXXDrv, ...

五、開啟XE2並建立一個新專案,再drop一個TSQLConnection到裡面,設定
ConnectionName = dbxoodbc_SS_DirectMode
LoginPrompt = False
接下來要注意的是
Params裡面的項目
============
DriverName=DbxSQLServer
GetDriverFunc=getSQLDriverODBCW
VendorLib=sqlsrv32.dll;sqlncli10.dll;sqlncli.dll;odbc32.dll
Trusted_Connection=No
User_Name=name
Password=secret
BlobSize=-1
RowsetSize=20
OpenOdbc TransIsolation=ReadCommited
Trim Char=True
Database=?
ConnectionString=coCatPrefix=DATABASE;SERVER=?
MetaDataPackageLoader=TDBXOpenODBCMetaDataCommandFactoryMSSQL
DriverPackageLoader=TDBXDynalinkDriverLoaderOpenOdbc
=============

2012/06/13

[轉]Delphi实现Js中的Eval函数

原文網址:Delphi实现Js中的Eval函数



procedure Eval(Formula: string; {   要計算的表達式   }
  var Value: Real; {   返回數值   }
  var ErrPos: Integer); {   錯誤信息   }
const
  Digit: set of Char = ['0'..'9'];
var
  Posn: Integer; {   算式當前位置   }
  CurrChar: Char; {   算式當前字符   }

  procedure ParseNext;
  begin
    repeat
      Posn := Posn + 1;
      if Posn <= Length(Formula) then
        CurrChar := Formula[Posn]
      else
        CurrChar := ^M;
    until CurrChar <> '   ';
  end {   ParseNext   };

  function add_subt: Real;
  var
    E: Real;
    Opr: Char;

    function mult_DIV: Real;
    var
      S: Real;
      Opr: Char;

      function Power: Real;
      var
        T: Real;

        function SignedOp: Real;

          function UnsignedOp: Real;
          type
            StdFunc = (fabs, fsqrt, fsqr, fsin, fcos,
              farctan, fln, flog, fexp, ffact);
            StdFuncList = array[StdFunc] of string[6];

          const
            StdFuncName: StdFuncList =
            ('ABS', 'SQRT', 'SQR', 'SIN', 'COS',
              'ARCTAN', 'LN', 'LOG', 'EXP', 'FACT');
          var
            E, L, Start: Integer;
            Funnet: Boolean;
            F: Real;
            Sf: StdFunc;

            function Fact(I: Integer): Real;
            begin
              if I > 0 then
              begin
                Fact := I * Fact(I - 1);
              end
              else
                Fact := 1;
            end {   Fact   };

          begin
            if CurrChar in Digit then
            begin
              Start := Posn;
              repeat ParseNext until not (CurrChar in Digit);
              if CurrChar = '.' then
                repeat ParseNext until not (CurrChar in Digit);
              if CurrChar = 'E' then
              begin
                ParseNext;
                repeat ParseNext until not (CurrChar in Digit);
              end;
              Val(Copy(Formula, Start, Posn - Start), F, ErrPos);
            end
            else if CurrChar = '(' then
            begin
              ParseNext;
              F := add_subt;
              if CurrChar = ')' then
                ParseNext
              else
                ErrPos := Posn;
            end
            else
            begin
              Funnet := False;
              for sf := fabs to ffact do
                if not Funnet then
                begin
                  l := Length(StdFuncName[sf]);
                  if Copy(Formula, Posn, l) = StdFuncName[sf] then
                  begin
                    Posn := Posn + l - 1;
                    ParseNext;
                    f := UnsignedOp;
                    case sf of
                      fabs: f := abs(f);
                      fsqrt: f := SqrT(f);
                      fsqr: f := Sqr(f);
                      fsin: f := Sin(f);
                      fcos: f := Cos(f);
                      farctan: f := ArcTan(f);
                      fln: f := LN(f);
                      flog: f := LN(f) / LN(10);
                      fexp: f := EXP(f);
                      ffact: f := fact(Trunc(f));
                    end;
                    Funnet := True;
                  end;
                end;
              if not Funnet then
              begin
                ErrPos := Posn;
                f := 0;
              end;
            end;
            UnsignedOp := F;
          end {   UnsignedOp};

        begin {   SignedOp   }
          if CurrChar = '-' then
          begin
            ParseNext;
            SignedOp := -UnsignedOp;
          end
          else
            SignedOp := UnsignedOp;
        end {   SignedOp   };

      begin {   Power   }
        T := SignedOp;
        while CurrChar = '^' do
        begin
          ParseNext;
          if t <> 0 then
            t := EXP(LN(abs(t)) * SignedOp)
          else
            t := 0;
        end;
        Power := t;
      end {   Power   };

    begin
      s := Power;
      while CurrChar in ['*', '/'] do
      begin
        Opr := CurrChar;
        ParseNext;
        case Opr of
          '*': s := s * Power;
          '/': s := s / Power;
        end;
      end;
      mult_DIV := s;
    end;

  begin
    E := mult_DIV;
    while CurrChar in ['+', '-'] do
    begin
      Opr := CurrChar;
      ParseNext;
      case Opr of
        '+': e := e + mult_DIV;
        '-': e := e - mult_DIV;
      end;
    end;
    add_subt := E;
  end;

begin
  if Formula[1] = '.' then
    Formula := '0' + Formula;
  if Formula[1] = '+' then
    Delete(Formula, 1, 1);
  for Posn := 1 to Length(Formula) do
    Formula[Posn] := Upcase(Formula[Posn]);
  Posn := 0;
  ParseNext;
  Value := add_subt;
  if CurrChar = ^M then
    ErrPos := 0
  else
    ErrPos := Posn;
end;

2012/05/29

2012/05/25

使用 OLE 開啟 Excel 的小陷井

從MSDN上看到Workbook.Open函式是這樣寫的:
Workbook Open(
 [In] string Filename, 
 [In, Optional] object UpdateLinks, 
 [In, Optional] object ReadOnly, 
 [In, Optional] object Format, 
 [In, Optional] object Password, 
 [In, Optional] object WriteResPassword, 
 [In, Optional] object IgnoreReadOnlyRecommended, 
 [In, Optional] object Origin, 
 [In, Optional] object Delimiter, 
 [In, Optional] object Editable, 
 [In, Optional] object Notify, 
 [In, Optional] object Converter, 
 [In, Optional] object AddToMru, 
 [In, Optional] object Local, 
 [In, Optional] object CorruptLoad
);


一票網站在抄來抄去,除了第一個參數是Filename不變外,其它不是都沒給值,就是直接給EmptyParam

2012/04/24

Create DBDEMOS from BDE into PostgreSQL

BDE have a demo database: DBDEMOS.

But, dbExpress is not easy a demo database, so I just to create a sample program.

I used:
1. Devart dbExpress for PostgreSQL
2. Delphi XE
3. BDE + Paradox database

Below my example picture:
First, I select our db data (C:\Program Files (x86)\Common Files\CodeGear Shared\Data; C:\Program Files (x86)\Common Files\Borland Shared\Data), when we get all xml's db file(same Paradox format) on the folder.

Then we can to click "Create SQL". Create SQL Statement when after copy to pgAdmin run it.
Or to use "Create Table" direct to create table.

Setting PostgreSQL's login param.

Final, click "Import Postgres", The data pump will all data append from xml into PostgreSQL.

Now, we can try dbexpress framework for PostgreSQL!

2012/04/13

[轉]Fixing TCriticalSection


TCriticalSection (along with TMonitor*) suffers from a severe design flaw in which entering/leaving different TCriticalSection instances can end up serializing your threads, and the whole can even end up performing worse than if your threads had been serialized.
This is because it’s a small, dynamically allocated object, so several TCriticalSection instances can end up in the same CPU cache line, and when that happens, you’ll have cache conflicts aplenty between the cores running the threads.
How severe can that be? Well, it depends on how many cores you have, but the more cores you have, the more severe it can get. On a quad core, a bad case of contention can easily result in a 200% slowdown on top of the serialization. And it won’t always be reproducible, since it’s related to dynamic memory allocation.
There is thankfully a simple fix for that, use TFixedCriticalSection:
type
   TFixedCriticalSection = class(TCriticalSection)
      private
         FDummy : array [0..95] of Byte;
   end;
That’s it folks. This makes sure the instance size larger than 96 bytes, which means that it’ll be larger than the cache line in all current CPUs, so no serialization anymore across distinct critical section instances.
As a bonus, it also ends up using one of the larger, more aligned, FastMM bucket, which seems to improve critical section code performance by about 7%. The downside is you use more RAM… but how many critical sections do you really have?
* (11-12-01): as noted by Allen Bauer in the comments, the issue is fixed for TMonitor in XE2.

2012/04/10

High Five - SQL Complete 介紹

還記得之前介紹過的「SQL Pretty Printer:好用的 SQL Formatter 工具」嗎?

這次來介紹 DBA 的好朋友 - Devart 公司所出品的「SQL Complete」

What is SQL Comlete?
Devart的Demo圖片已經完整呈現這款工具的概念了!
圖片擷自 Devart 官方網站
簡單的說,就是自動完成的工具

當然還有更多額外的工具

我們先來看與SQL Pretty Printer比較吧:
參賽者
SQL Complete
(Express Version)
SQL Pretty Printer
智慧感知功能
Smart Intellisense
V
X
提供表格物件名稱
Name suggestions for major objects
V
X
提供函式名稱
Name suggestions for advanced objects
部份提供
Partial Support
X
智慧篩選清單
Smart filtering in the suggestion list
V
X
輸入關鍵字後的內容建議
Context-sensitive suggestion of keywords
部份提供
Partial Support
X
資料庫名稱建議功能
Database context detection
V
X
依照SELECT, DML, DROP, EXEC, SET USE 語法的上下文提供建議清單
Context-sensitive object suggestions for SELECT, DML, DROP, EXEC, SET, and USE statements
V
X
提供函式所需參數種類及數量
Parameter information for functions
V
X
快捷物件資訊(如表格所含的欄位及格式內容)
Quick object information
部份提供
Partial Support
X
SQL 格式化處理
SQL formatting
部份提供
Partial Support
V
執行當前語法
Execute current statement
V
依賴SSMS
內建功能
Dependent SSMS
Built-in features
半透明的訊息箱
Semi-transparent view of the suggestion box
V
X
提供的SQL文字組譯成各種語法
(SQL to c#, Dephi, C++ string etc)
X
V
提供各語法轉成標準SQL語言
(Any language to SQL)
X
V
Single License Price ($$$)
Free
$50

與 SQL Complete Express 版本比較時,雖然 SQL Pretty Printer 有提供較為完整的 SQL Formatter (SQL 格式化處理) ,但 SQL Complete 提供了更多有利於DBA工作的工具,整體來說:

SQL Pretty Printer 適合給 Programmer 使用

SQL Complete 適合給專業 DBA 來使用。

注意!我只是拿 Express 版本來作比較,Standard版當然是更加強大的!(詳情請參閱:Editions of dbForge SQL Complete)

你對SSMS內建的半吊子功能感到綁手綁腳的嗎?
那 SQL Complete 一定能讓你的工作更加得心應手!

2012/4/16 補充:
很高興 Devart 公司能看到這篇文章,他們也提供了很多訊息給我,關於 SQL Complete 的核心價值是在於它的

「智慧感知」(Smart Intellisense) 功能

所謂的智慧感知(Smart Intellisense),就是使用者在輸入SQL語法時,SQL Complete會自動判斷上下文、分析使用者輸入的指令, 然後智慧地填入下一個指令, 讓使用者不用熟背 SQL 指令 也能如同使用新注音一樣的熟練、方便。

SSMS 雖然有內建 Microsoft IntelliSense (Stupid IntelliSense),但是它的功能遠比不上 SQL Complete (Best Smart)

SQL Complete 先進的智慧感知功能對於初學入門的使用者來說,這套工具仍然能保證讓你的功力在短時間內獲得提升,而對於已有基礎的進階使用者,SQL Complete更可以縮短你的工作時間

SQL Complete 絕對是一個值得入手的產品!

很高興你可以看到這一行,還等什麼?趕快去嚐試一下吧!

2012/04/17 再補充:
剛剛看到 Devart 關於 SQL Complete 的教學影片,來分享一下!

How to use URLEncode in Delphi

URL編碼,也稱【百分號編碼(Percent-encoding)】 由於 URL 不能直接接受 UTF8 文字,所以要先轉成百分號編碼後,如此網址才能順利送給 HTTP Server 從 Indy 加入 Delphi 後,就可以用 IdURI.TIdURI 單元進行編碼 ...