2024年2月20日 星期二
2024年1月30日 星期二
System.Generics.Collections.TDictionary
System.Generics.Collections.TDictionary
uses System.Generics.Collections;
...
var dicDoctionary: TDictionary<String, String> //Key, Value
//宣告
dicDoctionary := TDictionary<String, String>.Create;
// 建立時指定 TIgnoreCaseStringComparer.Ordinal (不分大小寫)
dicDoctionary := TDictionary<String, String>.Create(TOrdinalIStringComparer.Create); //不分大小寫
//新增
dicDoctionary.Add(Key, Value);
//刪除
dicDoctionary.Remove(Key);
//新增或取代Value
dicDoctionary.AddOrSetValue(Key, Value);
//比對Key是否存在
dicDoctionary.ContainsKey(Key);
//比對Value是否存在
dicDoctionary.ContainsValue(Value);
//數量
dicDoctornary.Count;
//取值
var sValue:String;
dicDoctionary.TryGetValue(Key, sValue);
//
var sKey, sValue:String;
for sKey in dicDoctionary.Keys do
begin
dicDoctionary.TryGetValue(sKey, sValue);
...
end;
2024年1月15日 星期一
2024年1月14日 星期日
2023年12月26日 星期二
ComboBox 繪製模式
ComboBox1.Style
csOwnerDrawFixed
- 當 ComboBox.Style 設定為 csOwnerDrawFixed 時,所有項目將以相同的高度顯示,並且當需要時,控制元件會調用 OnDrawItem 事件來繪製每個項目。
- 所有項目的高度由 ItemHeight 屬性定義。這表示無論項目的內容有多長,顯示的高度都是相同的。
- 對於列表中的每個項目,OnDrawItem 事件都會觸發,並且您必須在該事件中進行繪製。
csOwnerDrawVariable
- 當 ComboBox.Style 設定為 csOwnerDrawVariable 時,可以根據每個項目的實際內容來設置不同的高度,並且在需要時會調用 OnMeasureItem 和 OnDrawItem 事件來繪製每個項目。
- OnMeasureItem 事件用於指定每個項目的高度,您可以根據項目的內容計算不同的高度。這樣,不同的項目可以具有不同的顯示高度。
- OnDrawItem 事件用於實際的繪製操作。在該事件中,您可以根據需要來繪製每個項目的外觀。
資料來源 : CharGPT
2023年12月25日 星期一
PopupMenuLib.pas 記錄
AttachFilePopupMenu
procedure TForm1.FormCreate(Sender: TObject);beginpopAttachFile := TAttachFilePopupMenu.Create;end;procedure TForm1.Button9Click(Sender: TObject);beginpopAttachFile.Popup(Button9); //參數 nil 會在游標處展開下拉選單end;
//Property// popAttachFile.AttachFiles //附加的文件清單// popAttachFile.Readonly //唯讀,不可附加、移除// popAttachFile.DisableAttachFile //不提供附加// popAttachFile.DisableRemove //不提供移除// popAttachFile.DisableOpenFile //不提供文件開啟
PrinterPopupMenu
Uses Printers;
procedure TForm1.Button9Click(Sender: TObject);var pmPrinterList: TPrinterPopupMenu;beginpmPrinterList := TPrinterPopupMenu.Create;pmPrinterList.Popup(Button9); //參數 nil 會在游標處展開下拉選單end;
// Property// pmPrinterList.PrinterIndex //印表機Index// pmPrinterList.PrinterName //印表機名稱
TColor 調整亮度
procedure pr_BrightenColor(var Color: TColor; Brightness: Integer);
var R, G, B: Byte;
begin
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
var R, G, B: Byte;
begin
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
R := Min(255, R + Brightness);
G := Min(255, G + Brightness);
B := Min(255, B + Brightness);
Color := RGB(R, G, B);
end;
2023年12月14日 星期四
Dataset 查詢介面上被異動過的資料
ADO Dataset
在ADODataset要查看修改過且尚未寫回資料庫的資料列,可以用FilterGroup來查看
Ex:
with ADataset do
begin
if LockType = ltBatchOptimistic then
begin
Filtered := True;
FilterGroup := fgPendingRecords;
end;
FilterGroup := fgUnassigned;
Filtered := False;
end;
with ADataset do
begin
if LockType = ltBatchOptimistic then
begin
Filtered := True;
FilterGroup := fgPendingRecords;
end;
FilterGroup := fgUnassigned;
Filtered := False;
end;
ClientDataset
ClientDataset Delta 記錄了維護畫面上被異動過的資料列,ApplyUpdates將取用Delta記錄的資料狀態回寫到資料庫中。
Ex:
使用CleintDataset、DataSource、DBGrid並設定關連性。procedure TForm1.Button1Click(Sender:TObject);begin...//cdsDetail異動過的資料列,反應在ClientDataset1ClientDataset1.Data := cdsDetail.Delta;...end;
2023年12月6日 星期三
PageControl ActivePage 做顏色區別,增加閱讀性。
Procedure TForm1.pr_PageControl1_DrawTab(Control: TCustomTabControl; TabIndex: Integer; const [Ref] Rect: TRect; Active: Boolean);
var iMidWidth, iMidHeight, iTextWidth, iTextHeight:Integer;
sCaption:String;
begin
sCaption := TPageControl(Control).Pages[TabIndex].Caption;
iTextWidth := TPageControl(Control).Canvas.TextWidth(sCaption);
iTextHeight := TPageControl(Control).Canvas.TextHeight(sCaption);
iMidWidth := Rect.Left + Ceil((Rect.Width-iTextWidth)/2);
iMidHeight := Rect.Top + Ceil((Rect.Height-iTextHeight)/2);
if Active then
begin
TPageControl(Control).Canvas.Brush.Color := clHighlight;
TPageControl(Control).Canvas.Font.Color := clHighlightText;
end
else
TPageControl(Control).Canvas.Brush.Color := clScrollBar;
TPageControl(Control).Canvas.FillRect(Rect);
TPageControl(Control).Canvas.TextOut(iMidWidth, iMidHeight, sCaption);
end;
2023年11月28日 星期二
在表單底下空白處,使用LoopBand填滿表格
報表情境1 (未使用GroupBand)
procedure TForm1.DetailBand1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean);
var iCurrencyY, iPaperLength, iPrintY, iCount, iLoopBandHeight, iBottomMargin,
iPageFooterBand, iQRGroupFooter:Integer;
begin
//檢查最後一筆
if ADOQuery1.RecNo=ADOQuery1.RecordCount then
begin
iPaperLength := QuickRep1.QRPrinter.PaperLength; //報表高度
iCurrencyY := QuickRep1.CurrentY; //目前輸出的高度
iLoopBandHeight := Ceil(QRLoopBand1.Size.Length); //LoopBand 的高度
iPageFooterBand := Ceil(PageFooterBand1.Size.Length); //PageFooterBand 的高度
iBottomMargin := Ceil(QuickRep1.Page.BottomMargin); //報表邊界Bottom的高度
iPrintY := iPaperLength - iCurrencyY - iPageFooterBand - iBottomMargin; //LoopBand 輸出的高度
iCount := iPrintY div iLoopBandHeight;
QRLoopBand1.PrintCount := iCount;
end;
報表情境2 (使用GroupBand)
procedure TForm1.QuickRep2StartPage(Sender: TCustomQuickRep);
begin
//在報表上放置QRExpr1,借來運算QRGroup.Expression運算後的結果
QRExpr1.Expression := QRGroup2.Expression;
QRExpr1.Enabled := False;
end;
begin
//在報表上放置QRExpr1,借來運算QRGroup.Expression運算後的結果
QRExpr1.Expression := QRGroup2.Expression;
QRExpr1.Enabled := False;
end;
procedure TForm1.DetailBand1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean);
var iCurrencyY, iPaperLength, iPrintY, iCount, iLoopBandHeight, iBottomMargin,
iPageFooterBand, iQRGroupFooter:Integer;
sCurValue, sNextValue:String;
begin
//取得目前以及下一筆資料的運算結果做比對
sCurValue := QRExpr1.Value.StringVal;
adoQuery1.Next;
sNextValue := sCurValue;
if not adoQuery1.eof then
begin
sNextValue := QRExpr1.Value.StringVal;
adoquery1.Prior;
end;
//如果是最後一筆,或是前後筆資料不吻合,就使用LoopBand填滿
iCount := 0;
if (ADOQuery1.RecNo=ADOQuery1.RecordCount) or (sCurValue<>sNextValue) then
begin
iPaperLength := QuickRep2.QRPrinter.PaperLength; //報表高度
iCurrencyY := QuickRep2.CurrentY; //目前輸出的高度
iLoopBandHeight := Ceil(QRLoopBand2.Size.Length); //LoopBand 的高度
iQRGroupFooter := Ceil(QRGroupFooter2.Size.Length); //GroupFooter 的高度
iPageFooterBand := Ceil(PageFooterBand2.Size.Length); //PageFooter 的高度
iBottomMargin := Ceil(QuickRep2.Page.BottomMargin); //報表邊界Bottom的高度
iPrintY := iPaperLength - iCurrencyY - iPageFooterBand - iQRGroupFooter - iBottomMargin;
iCount := iPrintY div iLoopBandHeight;
end;
QRLoopBand2.PrintCount := iCount;
end;
var iCurrencyY, iPaperLength, iPrintY, iCount, iLoopBandHeight, iBottomMargin,
iPageFooterBand, iQRGroupFooter:Integer;
sCurValue, sNextValue:String;
begin
//取得目前以及下一筆資料的運算結果做比對
sCurValue := QRExpr1.Value.StringVal;
adoQuery1.Next;
sNextValue := sCurValue;
if not adoQuery1.eof then
begin
sNextValue := QRExpr1.Value.StringVal;
adoquery1.Prior;
end;
//如果是最後一筆,或是前後筆資料不吻合,就使用LoopBand填滿
iCount := 0;
if (ADOQuery1.RecNo=ADOQuery1.RecordCount) or (sCurValue<>sNextValue) then
begin
iPaperLength := QuickRep2.QRPrinter.PaperLength; //報表高度
iCurrencyY := QuickRep2.CurrentY; //目前輸出的高度
iLoopBandHeight := Ceil(QRLoopBand2.Size.Length); //LoopBand 的高度
iQRGroupFooter := Ceil(QRGroupFooter2.Size.Length); //GroupFooter 的高度
iPageFooterBand := Ceil(PageFooterBand2.Size.Length); //PageFooter 的高度
iBottomMargin := Ceil(QuickRep2.Page.BottomMargin); //報表邊界Bottom的高度
iPrintY := iPaperLength - iCurrencyY - iPageFooterBand - iQRGroupFooter - iBottomMargin;
iCount := iPrintY div iLoopBandHeight;
end;
QRLoopBand2.PrintCount := iCount;
end;
2023年11月21日 星期二
連線網路磁碟/目錄
Procedure pr_AddConnection(APath, ALocalDriver, AUserName, APassword:String);
var netSource:TNetResource;
dwResult:DWORD;
sMsg:String;
begin
dwResult := WNetCancelConnection2(PWideChar(APath),
var netSource:TNetResource;
dwResult:DWORD;
sMsg:String;
begin
dwResult := WNetCancelConnection2(PWideChar(APath),
CONNECT_UPDATE_PROFILE,
True);
if APath<>'' then
begin
with netSource do
begin
dwType := RESOURCETYPE_DISK;
lpLocalName := ''; // or H:
lpRemoteName := PWideChar(APath);
lpProvider := '';
dwResult := WNetAddConnection2(netSource,
if APath<>'' then
begin
with netSource do
begin
dwType := RESOURCETYPE_DISK;
lpLocalName := ''; // or H:
lpRemoteName := PWideChar(APath);
lpProvider := '';
dwResult := WNetAddConnection2(netSource,
PWideChar(APassword),
PWideChar(AUsername),
CONNECT_UPDATE_PROFILE);
if dwResult<>NO_ERROR then
begin
sMsg := SysErrorMessage(dwResult);
raise Exception.Create(sMsg);
end;
end;
end;
end;
if dwResult<>NO_ERROR then
begin
sMsg := SysErrorMessage(dwResult);
raise Exception.Create(sMsg);
end;
end;
end;
end;
2023年9月27日 星期三
XML Documentation Comments ,自定函式功能註解。
官方範例
/// <summary> Removes the specified item from the collection /// </summary> /// <param name="Item">The item to remove /// </param> /// <param name="Collection">The group containing the item /// </param> /// <remarks> /// If parameter "Item" is null, an exception is raised. /// <see cref="EArgumentNilException"/> /// </remarks> /// <returns>True if the specified item is successfully removed; /// otherwise False is returned. /// </returns> function RemoveItem(Item: Pointer; Collection: Pointer): Boolean; begin // Non-XML DOC comment // ... end;
![]() |
| 初始效果 |
![]() |
| 自定函式註解 |
2023年7月13日 星期四
2023年6月6日 星期二
Delphi 顯示器-縮放與版面配置,影響報表輸出的表單尺寸
縮放與版面配置
當Project Options 勾選 Enable High-DPI ,專案的界面會依照縮放比例做調整,Screen.PixelsPerInch會取得與縮放比對應的數值 (Ex: 縮放比125%會取得120)
沒有勾選 Enable High-DPI,Screen.PixelsPerInch會取得 96 (縮放比100%)
Var
iHorzres, iDesktopHorzres:Integer;
iScale:Currency;
begin
iHorzres := GetDeviceCaps(GetDC(0), HORZRES); //水平像素總數
iDesktopHorzres := GetDeviceCaps(GetDC(0), DESKTOPHORZRES); // 桌面水平像素總數
iScale := iDesktopHorzres / iHorzres ;
end
影響QuickRep 報表版面配置的處理方式
with QuickRep1 do
begin
...
...
ScaleBy(Screen.PixelsPerInch * iScale , Screen.PixelsPerInch);
Prepare;
...
...
end;
2023年5月24日 星期三
2023年5月1日 星期一
Delphi 取用系統圖示(Icon)
Uses ShellAPI;
...
Button1 : TButton;
ImageList1 : TImageList;
TListView1 : TListView;
...
...
procedure TForm1.Button1Click(Sender: TObject);
var
IconIndex: word;
sFileName:String;
Buffer: array[0..2048] of char;
IconHandle: HIcon;
...
Button1 : TButton;
ImageList1 : TImageList;
TListView1 : TListView;
...
...
procedure TForm1.Button1Click(Sender: TObject);
var
IconIndex: word;
sFileName:String;
Buffer: array[0..2048] of char;
IconHandle: HIcon;
objIcon:TIcon;
i, iCount:Integer;
lvItem:TListItem;
begin
i, iCount:Integer;
lvItem:TListItem;
begin
objIcon := TIcon.Create;
sFileName := 'Shell32.dll';
StrCopy(@Buffer, PChar(sFileName));
iCount := ExtractIcon(HInstance, PChar(sFileName), $FFFFFFFF);
for i := 0 to iCount-1 do
begin
IconIndex := i;
IconHandle := ExtractAssociatedIcon(HInstance, Buffer, IconIndex);
if IconHandle <> 0 then
objIcon.Handle := IconHandle;
ImageList1.AddIcon(objIcon);
lvItem := ListView1.Items.Add;
lvItem.ImageIndex := i;
lvItem.Caption := IntToStr(i);
end;
end;
sFileName := 'Shell32.dll';
StrCopy(@Buffer, PChar(sFileName));
iCount := ExtractIcon(HInstance, PChar(sFileName), $FFFFFFFF);
for i := 0 to iCount-1 do
begin
IconIndex := i;
IconHandle := ExtractAssociatedIcon(HInstance, Buffer, IconIndex);
if IconHandle <> 0 then
objIcon.Handle := IconHandle;
ImageList1.AddIcon(objIcon);
lvItem := ListView1.Items.Add;
lvItem.ImageIndex := i;
lvItem.Caption := IntToStr(i);
end;
end;
Windows存放系統圖示的文件
shell32.dll:包含許多與 Windows Shell 有關的圖示imageres.dll: 是一個包含大量 Windows 系統圖示的檔案user32.dll:包含一些基本的系統圖示comctl32.dll:包含一些常用的圖示
參考:
CharGRT
![]() |
| Shell32.dll |
![]() |
| Imageres.dll |
![]() |
| User32.dll |
![]() |
| Comctl32.dll |
2023年3月29日 星期三
Delphi 要如何取得DLL的檔案名稱
var
DLLFileName: array [0..MAX_PATH] of Char;
begin
GetModuleFileName(HInstance, DLLFileName, Length(DLLFileName));
ShowMessage(DLLFileName);
end;
DLLFileName: array [0..MAX_PATH] of Char;
begin
GetModuleFileName(HInstance, DLLFileName, Length(DLLFileName));
ShowMessage(DLLFileName);
end;
CharGPT 的回應
2023年3月28日 星期二
2023年3月23日 星期四
Delphi ClientDataset GetGroupState
GetGroupState
ClientDataset 需先建立IndexDef,GetGroupState代入GroupingLevel,可以取得資料列在Group中所屬的狀態gbFirst、gbMiddle、gbLast
procedure TForm1.FormCreate(Sender: TObject);
var inxIndex:TIndexDef;
aggAggregate:TAggregate;
begin
//Create Index
inxIndex := ClientDataSet1.IndexDefs.AddIndexDef;
inxIndex.Name := 'Index1';
inxIndex.Fields := 'Field1;Field2';
inxIndex.GroupingLevel := 2; //群組的層級,取決於Fields的數量
ClientDataset1.IndexName := inxIndex.Name;
end;
var inxIndex:TIndexDef;
aggAggregate:TAggregate;
begin
//Create Index
inxIndex := ClientDataSet1.IndexDefs.AddIndexDef;
inxIndex.Name := 'Index1';
inxIndex.Fields := 'Field1;Field2';
inxIndex.GroupingLevel := 2; //群組的層級,取決於Fields的數量
ClientDataset1.IndexName := inxIndex.Name;
end;
procedure TForm1.ClientDataSet1Field1GetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
//TGroupPosInd = (gbFirst, gbMiddle, gbLast);
if gbFirst in ClientDataset1.GetGroupState(1) then
Text := Sender.AsString
else
Text := '';
end;
DisplayText: Boolean);
begin
//TGroupPosInd = (gbFirst, gbMiddle, gbLast);
if gbFirst in ClientDataset1.GetGroupState(1) then
Text := Sender.AsString
else
Text := '';
end;
![]() |
| 原資料 |
![]() |
| gbFirst in ClientDataset1.GetGroupState(1) |
![]() |
| gbMiddle in ClientDataset1.GetGroupState(1) |
![]() |
| gbLast in ClientDataset1.GetGroupState(1) |
ClientDataset Methods 說明
Datasnap.DBClient.TClientDataSet Methods
訂閱:
文章 (Atom)




























