顯示具有 Delphi 標籤的文章。 顯示所有文章
顯示具有 Delphi 標籤的文章。 顯示所有文章

2015年11月4日 星期三

Lazarus 系列–2. 視窗畫面的佈局

Lazarus LCL 元件組的佈局,跟 VCL 很相似。為什麼說「很相似」呢?是 Lazarus 的 LCL 元件提供比 VCL 還要多,可以更方便的做好畫面的佈局。

 

一、Align 屬性:這個屬性指定了元件在 parent 中「怎麼靠邊」有以下幾種:

  • alTop:往上靠
  • alBottom:往下靠
  • alLeft: 往左靠
  • alRight:往右靠
  • alClient:填滿中間
  • alNone:都不靠
  • alCustom:這個不明白他怎麼靠,反正不是靠北靠木就是了 (VCL 沒有這個)

  來張圖就更清楚了 (為了方便看清楚 panel 的邊界,把每一個 panel 的 BevelWidth 屬性設定為 5)
2015-11-04_075758

  善用 Align 屬性可以很方便的給畫面佈局「切版」。

 

二、Anchors 屬性:Anchor 就是船錨,這個屬性用來指定元件在 parent 中「哪幾個邊要與 parent 同方向的邊保持固定距離」(以下稱為設定錨點),有以下幾種,均可以分別開啟與關閉:

  • akTop:上方保持固定距離,預設開啟
  • akBottom:下方保持固定距離
  • akLeft:左方保持固定距離,預設開啟
  • akRight:右方保持固定距離

來兩張圖示範一下效果

Panel1 把四個 Anchors 屬性都打開了,然後把 form 拉大,Panel1 的四個邊界依然與 form 的邊界保持固定距離。

2015-11-04_082421

2015-11-04_082852

Lazarus 的 Anchors 屬性除了把錨點設定在 parent 上以外,還可以把錨點設定在不是 parent 的元件上,還可以設定錨定時如何對齊,錨定時要留多少距離

2015-11-04_203829

這是 LCL 的錨點設定視窗,可以看到每一個方向都有 4 個設定項目:

  • Enabled:是否開啟這個方向的錨點
  • Sibling:我的兄弟是誰,就是我要跟誰錨定
  • 三個按鈕:如何對齊,有「對齊邊界」「依序排列」「對齊中線」三種
  • Border space:對齊邊界或是依序排列時要空出多少寬度

打個比方,將 Edit1 做如下的錨點設定之後,移動 Label1 時,Edit1 就會跟著移動:

2015-11-04_204701

Edit1 的上邊界與 Label1 錨定,對齊中線,同時左方也與 Lable1 錨定,依序排列,中間間隔 5px,這樣設定的結果如下圖:

2015-11-04_204911

把 Label1 抓著移動時,Edit1 會跟著移動,但是 Edit1 就無法被抓著移動了:

2015-11-04_204926

 

三、ChildSizing 屬性,這是容器元件才有的屬性,用來規範自己內部的元件要如何排列

2015-11-04_205231

  • ControlsPerLine:一列要排幾個元件
  • EnlargeHorizontal:自己被拉寬時,內部元件的寬度要如何變化
  • EnlargeVertival:自己被拉高時,內部元件的高度要如何變化
  • HorizontalSpacing:內部元件的水平間距
  • Layout:要怎麼排列內部元件
  • LeftRightSpacing:排列時,左右要空多少不拿來排列內部元件,就相當於 CSS 的 padding-left 與 padding-right
  • ShrinkHorizontal:自己被拉窄時,內部元件的寬度要如何變化
  • ShrinkVertival:自己被拉矮時,內部元件的高度要如何變化
  • TopBottomSpacing:排列時,上下要空多少不拿來排列內部元件,就相當於 CSS 的 padding-top 與 padding-bottom
  • HorizontalSpacing:內部元件的垂直間距

拿兩張圖來示範一下排列前與排列後,隨意擺放幾個元件,準備來排列

2015-11-04_205845

接下來,設定 Form1 的 ChilldSizing 屬性以及這些元件的 Z-Order 如下:
(設定 Z-Order 可以在 form 上選擇一個元件,然後使用 Ctrl-PgUp 與 Ctrl-PgDn 這兩個熱鍵來調整)

2015-11-04_210238

2015-11-04_210252

然後,這些元件就排列好了:

2015-11-04_210629

將 form 改變大小試試:

2015-11-04_210733

2015-11-04_210741

很方便,對吧!
可惜有一點,一個元件固定佔用一個「格子」,沒辦法跨列、跨欄,不過已經非常方便了!

這一篇就講到這裡,我們下期再見!

2015年11月1日 星期日

Lazarus 系列–1. 環境簡介

Lazarus 是一個 Open Source、跨平台的 Free Pascal 整合開發環境,可以稱得上是 Delphi 的 open source 替代品。詳細的歷程就請大家自行前往 Wiki 與 官網 收看,這裡就不再多說了。

這一篇是介紹 Lazarus 的安裝與開發環境的巡覽

 

一、安裝

自 官網的下載頁 依據您的環境下載適當的版本,在 Windows 上安裝很簡單,就是下一步下一步而已,Linux 的使用者可能就稍微複雜一點,不同的發行版的安裝方式可能會有些不同。

安裝完成之後,首次執行會檢查必要的組件是否安裝,Windows 版本就不用煩惱,一定是全部都安裝好的,Linux 版本就要看一下了,可能要補安裝一些必要組件

 

二、開發環境巡覽

2015-11-01_214911

看到這個畫面,用過老版本 Delphi (D7及以前) 的人一定感到很親切,幾乎是一模一樣的嘛!接下來一個個視窗來說明

  1. 主功能表、工具列與元件盤
  2. 物件檢視器 Object Inspector
    顯示及修改目前選取到的物件的屬性、事件
  3. 專案檢視器 Project Inspector
    顯示專案的結構
  4. 程式碼編輯器 Source Editor
    這裡當然就是編輯程式碼的地方
  5. 訊息視窗 Messages
    顯示編譯輸出、錯誤訊息的地方
  6. 畫面設計視窗
    用拖拉方式來設計畫面的地方

看起來跟老版本 Delphi 幾乎都一樣,是吧!接下來說說跟 Delphi 不一樣的地方

  1. 可以編譯出 x86 與 x64 的應用程式,不過得安裝兩套,而且必須安裝在不同的目錄
  2. 原生支援 Unicode
  3. 程式碼編輯器採用的是 SynEdit 元件,比起 Delphi 的程式碼編輯器有蠻大的進步
  4. 程式碼的副檔名不同 dpr –> lpr、dfm –> lfm,故無法直接開 Delphi 的程式來編譯,必須經過轉換
  5. 熱鍵可以更改,也就是 Ctrl-Space 這個最常用的熱鍵可以改成別的,我個人是改成 Alt-Right (與 Visual Studio 相同)
  6. VCL 元件不是 100% 對應過來的,有些元件在 Lazarus 沒有,反之亦然
  7. 資料庫存取相關元件方面,沒有 BDE、ADO、dbExpress、FireDAC,也沒有 DataSnap,Lazarus 有一套自己的,叫做 SQLdb,支援的資料庫有 MSSQL、Sybase、MySQL、PostgreSQL、Firebird (Interbase)、Oracle、ODBC 和 SQLite,市面上常見的可以說都支援了。
  8. 對於檔案型資料庫的支援有 DBF、CSV、SDF(沒用過這個)、以及固定長度格式
  9. 安裝 package 必須重新編譯 Lazarus 開發環境
  10. 市面上的 3rd party 元件組,通常在 Lazarus 上不可用
  11. 其他還有很多,就請大家自己去發現了!

總之,要拿 Lazarus 來寫一些自己用的小程式,是完全可行的。如果要拿來寫商用軟體,則需要很大的努力,如果抱著「為什麼 Delphi 可以 Lazarus 不行」這樣的心態來對待 Lazarus,那就直接用 Delphi 就好了,不是嗎?

 

附記一:程式碼編輯器在 Linux 環境無法輸入中文的臨時解決方法

程式碼編輯器在 Linux 環境無法輸入中文,有一個勉強還可以接受的方法是按 Ctrl-Alt-T 熱鍵插入「ToDo」,輸入完之後再把
{ TODO : } 刪除掉
2015-11-01_220005

按下 OK 之後,就成了這樣
2015-11-01_220042

2012年9月13日 星期四

使用 ADO 透過 ODBC 連接至 SQLite,用 OpenSchema 取得 Table Name 會亂碼的解決方法

最近開始使用 SQLite 當作應用程式的本地資料儲存媒體,當然也想要針對 SQLite 資料庫做一些管理跟查詢工作。雖然網路上可以找到需付費或是不須付費的 SQLite 管理工具,但是還是想使用自製的 DB 工具來查詢資料。畢竟用慣了,哪裡用得不爽還可以自己改一改。

但是自製的 DB 工具使用的是 ADO 來連接資料庫,對於 SQLite 的免費連接方案只有 SQLite ODBC Driver 了

連接上是沒有問題,也可以正常的擷取資料,無亂碼
不過使用 OpenSchema 來取得資料庫中的 table,以及 table 中的欄位時,卻出現了亂碼

2012-09-13_085411

解決方法如下:
開啟 ODBC 設定,將「OEMCP Translation」打勾,就 OK 了

2012-09-13_085738

設定完成之後,就可以正確的抓到中文的 table name 跟 column name 了

2012-09-13_090117

2011年6月6日 星期一

Delphi ListBox 顯示多欄文字

  1. 設定 ListBox.TabWidth,單位是 Dialog Base Unit (DBU),以定寬字來說,英數字寬是 4 DBU,中文字寬是 8 DBU,所以每一欄 20 個英數字寬度的話,TabWidth 就要設定為 80
    不用管一個 DBU 合多少 Pt,DBU 是相對單位,會跟著字的大小而變化的
  2. Items.Add 時,要分欄的地方,插入 Tab 字元,可以用 #9 或是 ^I 例如:
    Items.Add('0001'#9'這是品名');
    或是
    Items.Add('0001'^I'這是品名');
  3. 沒辦法各欄設定不同寬度,所以 TabWidth 請設定大一點,或是最長的欄放最後
    如果一定要各欄不同寬度顯示,請改用 TListView

2011年6月2日 星期四

Delphi + PostgreSQL 處理 bytea 欄位的注意事項

設定 PostgreSQL ODBC 時,要把圖中的「bytea as LO」選項勾起來,這樣使用 bytea 欄位型態就會被判別成 TBlobField,而不是 TVarBytesField

如此一來,就可以使用 TBlobField.LoadFromFile() 跟 SaveToFile() 來存入與讀取 bytea 欄位的內容了

若讀取時只想使用 TImage 顯示,不想存檔也可以 (以 JPG 圖檔為例子)
uses jpeg;     // 支援 JPEG 圖檔
var blob: TStream;

blob := ADODataSet1.CreateBlobStream(BlobField, bmRead);
try
  blob.Seek(0, soFromBeginning);
  Image1.Picture.Graphic := TJPEGImage.Create;
  Image1.Picture.Graphic.LoadFromStream(blob);
finally
  blob.Free
end; image

2010年11月3日 星期三

Delphi 5 使 DBGrid 支援滑鼠滾輪的程式碼

Delphi 5 的 TDBGrid 無法支援滑鼠滾輪移動資掉指標,而且當有 PickList 的 Column 或是 Lookup Field 下拉時
滾動滑鼠滾輪會有很奇怪的行為。
要解決這個問題,可以繼承 TDBGrid 寫一個新的 DBGrid 類別,並覆寫兩個方法:

interface
type
  TNewDBGrid = class(TDBGrid)
  protected
    function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
    function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;    
  end;

implementation
  function TNewDBGrid.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean;
  begin
    Result := False;
    if Assigned(OnMouseWheelDown) then
      OnMouseWheelDown(Self, Shift, MousePos, Result);
    if (not Result) and (DataLink <> nil) and (DataLink.Active)
       and (DataLink.DataSet <> nil) and (DataLink.DataSet.Active) then
    begin
      DataLink.DataSet.MoveBy(1);
      Result := True;
    end;
  end;

  function TNewDBGrid.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean;
  begin
    Result := False;
    if Assigned(OnMouseWheelDown) then
      OnMouseWheelDown(Self, Shift, MousePos, Result);
    if (not Result) and (DataLink <> nil) and (DataLink.Active)
       and (DataLink.DataSet <> nil) and (DataLink.DataSet.Active) then
    begin
      DataLink.DataSet.MoveBy(-1);
      Result := True;
    end;
  end;

2009年4月17日 星期五

老問題:用滑鼠點擊 Button 與按快速鍵行為不一致的解決方法

我們常常會將 Button.Caption 設定為像「&F. 檔案」這樣的內容,以便於將 Alt-F 快速鍵與 Button 連在一起
也常常會將一些輸入 Edit 的檢查,寫在 Edit.OnExit 事件處理函式中
假如這兩個碰在一起,就會發生用滑鼠點擊 Button 與按下快速鍵行為不一致的問題
因為按下快速鍵時,並不會轉移 Focus,會直接觸發事件處理函式,使得 Edit.OnExit 事件無法被觸發

解決方法如下:
於 Button.OnClick 事件處理函式的開頭加入以下兩行:

if (Sender as TWinControl).CanFocus then
  (Sender as TWinControl).SetFocus;

這樣強迫轉移 Focus,就可以解決這個問題了