2026年10月6日 星期二

視覺化學習(Visualize Learning)

 


AI 視覺化學習(Visualize Learning)是一種將抽象概念、複雜流程、數據關係或繁複文字,轉化為圖表、結構圖、視覺心智圖或簡圖的提問技巧。

這種方法能大幅提升學習效率,特別適合視覺型學習者或需要處理跨領域複雜主題的人。

一、 適用情境與呈現形式

抽象概念具象化: 將看不見的理論(如:區塊鏈、經濟學供需模型、AI 運算流程)轉化為視覺流程圖。

複雜架構與對比: 將繁雜的歷史演進、組織架構或產品優缺點轉化為「表格」或「文字心智圖」。

生圖工具 Prompts 生成: 讓 AI 生成可以直接貼入繪圖工具(如 Midjourney, DALL-E, Mermaid.js)的 Prompt 或程式碼。

二、 如何下指令(Prompt 範例)

1. 文字結構與流程圖(ASCII / 心智圖架構)

Prompt:

「請幫我解釋『[概念,例如:機器學習中的監督式學習 vs 非監督式學習]』。除了文字說明外,請用 ASCII 繪圖 / 文字心智圖 的格式,輸出一個簡潔的視覺架構圖,讓我一眼就能看懂兩者的核心差異與流程。」

2. Mermaid.js 流程圖程式碼(可直接貼入 Notion 或 Markdown 編輯器)

Prompt:

「我正在學習 [主題,例如:網路封包傳輸過程]。請用 Mermaid.js 語法繪製一張 Flowchart 流程圖,標示出從用戶點擊網頁到伺服器回傳資料的完整步驟,並用簡單的繁體中文註解每個節點。」

3. AI 繪圖指令生成(產出教學插圖)

Prompt:

「我想製作一張用來解釋『[概念,例如:光合作用運作機制]』的教學插圖。請幫我寫出一段詳細的 DALL-E 3 / Midjourney 繪圖 Prompt,要求風格為『簡潔的扁平化科學教學圖解(Flat scientific infographics)』,並列出圖片中應包含的視覺元素。」

三、 提問的 3 個關鍵技巧

指定視覺格式: 明確告訴 AI 你想要的視覺載體,例如:Markdown 表格、ASCII 文字架構圖、Mermaid.js 程式碼 或 簡圖說明。

限制層級與維度: 避免 AI 產出過於複雜的圖表,可限定「不超過 3 個層級」或「對比 3 個核心維度」。

圖像與比喻結合(Analogy + Visual): 要求 AI 用視覺化的比喻(例如:「請用『工廠流水線』的視覺比喻來畫出這段程式碼的執行流程」)。


Gemini



問題預測(Question Predoctor)

 


AI 問題預測(Question Predictor / Anticipatory Prompting)是一種讓 AI 提前幫你抓出盲點、預測未來疑問、考官提問或客戶反駁的提問技巧。

這項技巧的核心在於:不直接要 AI 給答案,而是讓它扮演「懷疑者」、「審查者」或「提問者」,幫你進行壓力測試(Stress Test)。

一、 適用情境

簡報/面試準備: 預測聽眾、面試官或主管會問什麼刁鑽問題。

商業提案/產品設計: 預測客戶或投資人可能提出哪些質疑與反對意見。

學習與考試復習: 讓 AI 根據教材內容,預測出題老師可能考的重點題目。

決策與風險評估: 預測某個方案執行後,可能出現哪些未知的盲點或副作用。


二、 如何下指令(Prompt 範例)

1. 商業提案與專案(預測客戶/主管的質疑)

Prompt:

「這是我即將向主管報告的行銷方案:『[貼上你的方案簡介]』。請扮演一位風格嚴格、重視ROI與風險的總監,預測你在聽完這個提案後,最有可能提出的 5 個挑戰性問題,並針對每個問題說明你為何會這樣問。」

2. 求職面試準備(預測面試官問題)

Prompt:

「這是我要應徵的職缺說明:『[貼上 JD]』,以及我的簡歷概要:『[貼上經歷]』。請預測面試官可能會針對我經歷中的弱點或這份工作的核心需求提出哪些 5 個深度問題?請附上建議的回答方向。」

3. 學習與備考(預測考試/報告題目)

Prompt:

「這是我今天學習的內容摘要:『[貼上文字內容]』。請扮演大學教授,預測如果這是一份期末考卷,可能會針對這些內容出哪 3 題申論題?請不要直接給解答,讓我先試著回答。」


三、 提問的 3 個進階關鍵技巧

設定極端角色(Persona):

不要只讓 AI「預測問題」,要給它一個具體角色,例如:「挑剔的投資人」、「嚴格的資深工程師」、「懷疑論者」。角色越具體,預測的問題越精準。

要求包含「預估背後的理由」:

請 AI 在列出問題時,同時說明「為什麼對方會這樣問?」,這能幫助你理解背後的動機與顧慮。

搭配「組合拳」:

步驟 A: 先請 AI 預測 5 個最棘手的問題(Question Predictor)。

步驟 B: 針對每一個預測出的問題,用上一階段學到的「蘇格拉底式提問」引導自己思考最佳回答。


Gemini

蘇格拉底式提問 (Socratic Questioning)

 蘇格拉底式提問 (Socratic Questioning) 


蘇格拉底式提問(Socratic Questioning)是一種透過連續提問來引導對方主動思考、發現矛盾、最終自己得出答案的教學與思考方法。

在 AI(如 ChatGPT、Gemini)上使用蘇格拉底式提問,非常適合用於學習新觀點、深入剖析複雜問題、程式除錯、寫作邏輯檢視或職涯反思。

以下是將 AI 變成蘇格拉底導師的具體玩法與實用 Prompt 範例:

一、 如何向 AI 下指令(Prompt 範例)

你可以直接要求 AI 扮演「蘇格拉底式導師」,讓它只提問、不直接給答案。

1. 概念學習與深度思考
Prompt:
「我想理解 [議題/概念,例如:為什麼企業要實施週休三日?]。請扮演蘇格拉底,不要直接給我答案或長篇大論。請透過一次問我 1~2 個引導性問題,引導我一步步思考並分析這個主題。當我回答後,你再根據我的回答繼續提問。」

2. 批判性思考與寫作邏輯檢視

Prompt:
「這是我對於 [主題] 的觀點:『[輸入你的觀點或文章段落]』。請用蘇格拉底式提問,挑戰我的前提、假設與邏輯盲點,幫助我檢查這個觀點是否有矛盾或考慮不周之處。一次只提出一個最核心的問題。」

3. 程式除錯與技術學習(Rubber Duck Debugging)

Prompt:
「我在寫 [程式語言/專案],遇到這個問題:[描述 Bug 或需求]。請不要直接給我修正後的程式碼。請用蘇格拉底式提問,引導我自己發現問題所在並寫出解決方案。」

二、 蘇格拉底式提問的 6 大核心類型(AI 常用的引導方向)

瞭解 AI 提問的背後邏輯,能幫助你更好地回應它:

澄清概念(Clarification):

例:「你剛剛提到『公平』,你對『公平』的定義是什麼?」

檢視前提/假設(Challenging Assumptions):

例:「你假設這個方案能省錢,這個假設的前提成立嗎?」

探索證據與理由(Evidence & Reasons):

例:「是什麼樣的數據或經驗讓你得出這個結論的?」

換位思考與不同視點(Alternative Perspectives):

例:「如果從競爭對手或使用者的角度來看,他們會怎麼反駁這個想法?」

推導後果與影響(Consequences & Implications):

例:「如果這個決定真的執行了,長期來看可能會產生什麼意料之外的副作用?」

質疑問題本身(Questioning the Question):

例:「為什麼我們會認為這個問題是目前最需要優先解決的?」

三、 使用 AI 蘇格拉底提問的 3 個關鍵技巧

明確規定「一次只問一個問題」:
AI 預設喜歡講很多話。如果不限定,它可能會一次列出 5~10 個問題,這會讓你失去思考與對話的節奏。

誠實回答「我不知道」:
當 AI 問到你沒想過的問題時,可以直接回答「我沒想過這一點,你覺得有什麼可能性?」讓 AI 稍微給予提示後再繼續提問。

設定情境角色:
可以讓 AI 結合特定身份,例如:「請扮演一位嚴格的商業投資人,用蘇格拉底式提問來挑戰我的商業計劃。」


Gemini



Merge

 


Gemini



2026年9月17日 星期四

ListView


//取CheckBox寬度
function GetListViewCheckboxWidth: Integer;
begin
  // SM_CXMENUCHECK 傳回選單與清單控制項中 Checkbox 的寬度(像素)
  Result := GetSystemMetrics(SM_CXMENUCHECK);
end;

//取單列的高度
function GetItemHeightSimple(AListView: TListView): Integer;
var
  R: TRect;
begin
  Result := 0;
  if AListView.Items.Count > 0 then
  begin
    // drBounds 相當於 LVIR_BOUNDS
    R := AListView.Items[0].DisplayRect(drBounds);
    Result := R.Bottom - R.Top;
  end;
end;

//取垂直ScrollBar的寬度
ScrollBarWidth := GetSystemMetrics(SM_CXVSCROLL);




2026年7月28日 星期二

No FTP list parsers have been registered

 

FTPListItems := idFTP.DirectoryListing,出現錯誤訊息


No FTP list parsers have been registered


只需要在程式的 uses 區段中加入 IdAllFTPListParsers 即可


2026年6月30日 星期二

Delphi 函式庫發佈方式(提供 Interface PAS + DCU)

 

如果想將程式工具提供他人使用,且不想提供程式原始碼,可以參考以下做法

Delphi 函式庫發佈方式(提供 Interface PAS + DCU)

一、目的

當 Delphi 開發完成一個 Unit,希望提供給其他開發者使用,但又不希望公開原始程式碼時,可以採用:

  • 公開 Interface PAS
  • 提供編譯完成的 DCU

使用者可以正常 uses 該 Unit,也能使用 IDE 的型別提示及程式碼完成(Code Insight),但無法看到真正的程式實作。


二、發佈內容

假設原始 Unit 名稱為:

MyLib.pas

發佈內容如下:

Release
│
├── MyLib.pas ← 只有 Interface 宣告
└── MyLib.dcu ← 編譯完成的程式

不提供完整原始碼。


三、原始 Unit

例如:

unit MyLib;

interface

uses
System.SysUtils;

type
TMyClass = class
public
constructor Create;
destructor Destroy; override;

function Add(A, B: Integer): Integer;
function Sub(A, B: Integer): Integer;
end;

function GetVersion: string;

implementation

constructor TMyClass.Create;
begin
inherited;
end;

destructor TMyClass.Destroy;
begin
inherited;
end;

function TMyClass.Add(A, B: Integer): Integer;
begin
Result := A + B;
end;

function TMyClass.Sub(A, B: Integer): Integer;
begin
Result := A - B;
end;

function GetVersion: string;
begin
Result := '1.0';
end;

end.

四、編譯產生 DCU

使用 Delphi 編譯後,會產生:

MyLib.dcu

真正執行的程式都在 DCU 內。


五、建立公開 PAS

建立另一份供發布使用的 MyLib.pas。

注意:不要修改原始碼,而是另外建立一份。

例如:

Project
│
├── Source
│ MyLib.pas ← 原始完整程式
│
└── Release
MyLib.pas ← 公開介面
MyLib.dcu

公開 PAS 保留 Interface:

unit MyLib;

interface

uses
System.SysUtils;

type
TMyClass = class
public
constructor Create;
destructor Destroy; override;

function Add(A, B: Integer): Integer;
function Sub(A, B: Integer): Integer;
end;

function GetVersion: string;

implementation

end.

可以看到:

  • Class
  • Function
  • Procedure
  • Property
  • Event
  • Record
  • Enum

都需要保留。

但是:

所有 Implementation 內的程式碼全部刪除。


六、使用者如何使用

使用者只要:

uses
MyLib;

即可正常呼叫:

var
M: TMyClass;
begin
M := TMyClass.Create;
try
ShowMessage(IntToStr(M.Add(3,5)));
finally
M.Free;
end;
end;

不需要任何特殊設定。


七、IDE 功能

由於 Interface 仍存在,因此 Delphi IDE 可以提供:

  • Code Insight
  • Auto Complete
  • Parameter Hint
  • 型別檢查
  • 編譯檢查

使用體驗與一般 Unit 幾乎相同。


八、可以隱藏哪些內容

可以隱藏:

  • 所有演算法
  • 所有商業邏輯
  • SQL
  • 加解密流程
  • API 呼叫方式
  • 所有 Function 實作
  • 所有 Method 實作

仍然會看到:

  • Class 名稱
  • Function 名稱
  • Procedure 名稱
  • Property 名稱
  • Record 定義
  • Enum 定義
  • Event 定義

如果 Interface 中宣告了 Private 欄位:

private
FData: Integer;

使用者仍然可以看到:

FData

只是無法知道如何使用。

因此,如果希望降低資訊曝光,建議不要在 Interface 中放置過多內部欄位或實作細節。


九、優點

  1. 不公開原始碼。
  2. 使用方式與一般 Unit 完全相同。
  3. IDE 可正常提供 Code Insight。
  4. 不需要 DLL。
  5. 執行速度與一般 Delphi 程式相同。
  6. 發布方便。

十、缺點

1. 無法跨 Delphi 版本

DCU 為 Delphi 編譯器產生的中間檔。

不同 Delphi 版本的 DCU 格式可能不同,因此:

  • 無法保證相容
  • 通常不可共用

例如:

編譯版本使用版本是否可用
XE10XE10✔
XE10XE8✘
XE10Delphi 10.4✘
XE10Delphi 11✘
XE10Delphi 12✘

因此,每個 Delphi 版本都需要重新編譯對應的 DCU。


2. 每個版本都需要重新發布

若要支援:

  • XE10
  • 10.4 Sydney
  • 11 Alexandria
  • 12 Athens

通常需要:

Release
│
├── XE10
│ MyLib.pas
│ MyLib.dcu
│
├── 10.4
│ MyLib.pas
│ MyLib.dcu
│
├── 11
│ MyLib.pas
│ MyLib.dcu
│
└── 12
MyLib.pas
MyLib.dcu

3. 若公開介面有修改

例如新增:

function Test: Integer;

就需要重新:

  1. 編譯 DCU。
  2. 更新公開 PAS。
  3. 一起發布。

兩者必須保持一致。


十一、適用情況

適合:

  • 公司內部函式庫。
  • 不希望公開原始碼。
  • Delphi 開發團隊使用相同版本。
  • 商業 Delphi 函式庫。
  • 元件開發。

十二、不適合情況

若需要:

  • 支援 Delphi 多個版本
  • 支援 C++
  • 支援 C#
  • 支援 VB
  • 支援其他語言

則建議使用:

  • DLL
  • COM
  • Web API
  • REST API

而不是 DCU。


十三、建議

若所有使用者皆使用相同 Delphi 版本,採用 Interface PAS + DCU 是一種簡單且成熟的封裝方式,能兼顧開發便利性與原始碼保護。

若需支援不同 Delphi 版本,則必須針對每個版本重新編譯並發布對應的 .dcu;單一 DCU 無法跨 Delphi 版本使用。如果目標是跨 Delphi 版本,建議直接提供相容的原始碼,或改以 DLL、COM、REST API 等方式封裝功能,以降低版本相依性。

2026年5月21日 星期四

Delphi Enum 轉字串

 

uses
  System.TypInfo;

type
  TDataState = (stInquiry, stNew, stEdit, stDelete, stRecall);

function DataStateToString(AState: TDataState): string;
begin
  Result := GetEnumName(TypeInfo(TDataState), Ord(AState));
end;



2026年3月23日 星期一

Delphi FireDAC

 FDManager

var sParams:TStringList;

sParams.Add('Server=xx.xx.xx.xx');
sParams.Add('User_Name=xxxxx');
sParams.Add('Password=xxxxx');
sParams.Add('Database=xxxxx');
sParams.Add('DriverID=MSSQL');
sParams.Add('Pooled=True');
          sParams.Add('ExtendedMetadata=True');  //可以用來取得欄位屬性歸屬
FDManager1.AddConnectionDef('MSSQL_Pool', 'MSSQL', sParams);

FDConnection (與FDManager搭配使用,可以理解是DB Session)

FDConnection1.ConnectionDefName := 'MSSQL_Pool';
FDConnection1.Connected := True;

FDQuery / FDUpdateSQL

with FDQuery1 do
begin
  Connection := FDConnection1;
  CachedUpdates := True;
  UpdateOptions.UpdateTableName := 'Table1';
  UpdateOptions.KeyFields := 'Field1,Field2';
  UpdateOptions.UpdateMode := upWhereKeyOnly;
 
            UpdateObject := Self.FDUpdateSQL1;

  Close;
  SQL.Text :=
    ' select a.*, b.Fiedl5 '+
    ' from Table1 a '+
    ' left join Table2 b on b.field1=a.field1 '+
    ' where ... ';
  Open;
end;

ApplyUpdates

FDQuery1.CheckBrowseMode;
FDQuery1.FetchNext;  //抓資料到本地快取, 確保快取內容有提供回寫的資料
FDQuery1.ApplyUpdates(-1);


取得別名欄位的表格屬性及原欄名稱,需設定連線參數 ExtendedMetadata=True
var column:TFDDatSColumn;
column := FDQuery1.GetFieldColumn(Field);
column.ActualOriginTabName // Field歸屬的Table
column.ActualOriginColName // Field實體表格中的Column Name


FDConnection -> FDQuery,當FDQuery資料是分批讀取還沒完全將資料載入時,FDConnection沒辦法被其他FDQuery操作使用,會出現以下的錯誤訊息。


FDQuery.SourceEOF; //可以知道資料是否已完全載入

提供的建議做法是放二個FDConnection,一個做 Select...,另一個做Update/Insert/Delete/Exec ...
如果沒有閒置的 FDConnection, 就要Create一個FDConnection提供給FDQuery使用。





2026年3月19日 星期四

美元 為何又稱美金

 「美元」之所以在華語世界常被稱為「美金」,主要與歷史上的貨幣制度以及黃金的關聯性有關。這可以追溯到 19 世紀到 20 世紀中葉的全球金融背景:

1. 金本位制度(Gold Standard)

在 19 世紀後半葉至 20 世紀初,世界主要經濟體實行「金本位制」。當時的美元與黃金是直接掛鉤的,面額可以隨時向銀行兌換成等值的實體黃金。

實質等同: 由於美元在當時代表著特定重量的黃金,民眾習慣將這種具有黃金價值的貨幣稱為「美金」。

2. 布列頓森林體系(Bretton Woods System)

二戰結束後(1944 年),全球建立了布列頓森林體系。該體系確立了美元與黃金掛鉤(每 35 美元兌換 1 盎司黃金),而其他國家的貨幣再與美元掛鉤。

國際儲備: 美元成為全球最主要的儲備貨幣,地位如同黃金般穩固。這進一步加深了「美元即黃金」的社會認知,「美金」這個稱呼也因此在兩岸三地及海外華人圈廣為流傳。

3. 文化與習慣

雖然 1971 年尼克森衝擊(Nixon Shock)宣告美元正式脫離金本位,美元不再能兌換黃金,但「美金」這個詞彙已經深植於語言習慣中:

辨識度: 在華語口語中,「美金」聽起來比「美元」更具備財富的象徵意義。

區分需求: 在早期外匯管制較嚴格的時期,民間習慣用「美金」來區分本地貨幣與這種強勢的國際貨幣。

補充小知識:

儘管現在美元本質上是「法定貨幣」(Fiat Money)而非金幣,但這種稱呼已成為一種文化印記。在正式的金融公文或新聞報導中,通常會使用「美元」;而在日常生活中,「美金」依然是極為普遍的用法。


Gemini

 

2026年2月25日 星期三

修正 Quick Report 預覽/列印的顯示比例

 當調整了電腦螢幕的縮放比例後,操作程式裡的報表QuickReport,發現報表預覽的資料內容沒有隨著顯示縮放比跟著做調整,但不影響實際列印輸出的結果。



參考網上的作法,修正 QuickReport 需 QRPrntr.pas 排除縮放比的問題。

我採用網友提供的方法1來處理。

File Name : QRPrntr.pas

Procedure Name : CreateMetafileCanvas


QRPrntr.pas 修正後,重新編譯QR506RunDXE10.bpl,

預覽結果就會以符合系統縮放比做調整了。


【參考連結】

老森常譚 IT Help 《Delphi》修正 Quick Report 預覽列印的比例問題


2025年12月25日 星期四

QuickReport - 載入 Qrp 報表文件時,會預先使用預設印表機的紙張格式套用在文件上,與設計的報表格式不符...

 var 
  repReport:TQuickRep;
  iPageHeightPixel, iPageWidthPixel:Integer;
  Meta: TMetafile;
begin
  inherited;
  repReport := TQuickRep.Create(nil);
  repReport.PrevInitialZoom := qrZoomToWidth;   //頁寬
  repReport.PrevShowThumbs := False;            //不顯示簡視欄
  repReport.PrevShowSearch := False;            //不顯示搜尋欄
  repReport.PreviewInitialState := wsMaximized; //最大化
  repReport.ShowProgress := True;
  repReport.PreviewDefaultSaveType := stQRP;

  repReport.Prepare;
  repReport.QRPrinter.Load('Report.qrp');    //載入檔案

  Meta := repReport.QRPrinter.GetPage(1);
  iPageWidthPixel := Meta.Width;    //取得文件記錄中的尺寸 Pixel
  iPageHeightPixel := Meta.Height;  //取得文件記錄中的尺寸 Pixel

  repReport.Page.Orientation := repReport.QRPrinter.Orientation; //報表直/橫向
  repReport.Page.PaperSize := TQRPaperSize.Custom; //報表紙張格式
  repReport.Units := TQRUnit.Pixels;
  repReport.Page.Length := iPageHeightPixel; //設定報表長度
  repReport.Page.Width := iPageWidthPixel;   //設定報表寬度

  repReport.PrinterSettings.PaperSize := TQRPaperSize.Custom;  //報表紙張格式
  repReport.PrinterSettings.PrinterIndex := 1;      //指定印表機
  repReport.PrinterSettings.ApplySettings(repReport.QRPrinter);

  repReport.QRPrinter.PrinterIndex := 1;            //指定印表機
  repReport.QRPrinter.aPrinterSettings.ApplySettings;
  repReport.QRPrinter.PreviewModal;      //預覽文件
end;

2025年12月18日 星期四

QuickReport Prepare / Preview / Print Event觸發的差異




 

面對風險、機遇和挑戰,你為什麽總是賺小虧大?


 

高智商問題:100名囚犯如何用數學拯救自己?

 


透過詢問專業建議,更能具體掌握需要改進細節

 


#CharGPT

在參與考試或競賽後,建立回饋機制對個人成長至關重要。不論最終的成績表現如何,主動向評分委員請益都是提升自我的關鍵步驟。透過詢問專業建議,參賽者能具體掌握需要改進的空間或加強的細節。這種積極的學習態度有助於發現盲點,進而在未來的挑戰中展現更優異的實力。總結而言,將賽後的檢討視為持續進步的契機,是追求卓越不可或缺的過程。