☰
Delphi7 里 Image 与 SpeedButton 组件配 TaoToken:从零搭一个可复用的 AI 工具调用面板
2026/9/27 20:10:33 网站建设 项目流程

1. Delphi7 桌面端做 AI 工具调用面板,为什么绕不开 Image 和 SpeedButton

如果你手上还有一套 Delphi7 的老项目,想给它加一个「AI 工具调用面板」,最省事的做法不是换框架,而是直接用 VCL 自带的 Image 和 SpeedButton 拼一个可视化面板。Image 负责状态图标(空闲、请求中、成功、失败),SpeedButton 负责触发按钮(发请求、清空、复制结果),两者配合就能做出一个能看、能点、能跑通真实调用的桌面小工具。

这篇面向的是还在用 Delphi7 的桌面开发者,尤其是那种「不想动主工程结构,只想加一个独立面板」的场景。核心检索词就三个:Delphi7、Image 组件、SpeedButton 组件。我会把 Image 的 Align 和 Stretch、SpeedButton 的 Flat、Cursor、Layout、Transparent、Margin、Spacing 这些属性讲清楚,然后接上 TaoToken 的统一 Key/API 通道,给出一份可复制的 settings.json 和 config.toml 骨架,最后让 SpeedButton 点下去真的能拿到模型返回。

老 IDE 不代表不能接新能力。Delphi7 的 VCL 控件虽然年代久,但事件模型清晰、属性直观,用来做「按钮触发 + 图标反馈」这种交互反而比很多新框架更直接。下面从面板布局开始,一步步搭到真实请求返回。

2. 前置准备:TaoToken 统一 Key 与 API 通道

在写 Delphi 代码之前,先把通道准备好。TaoToken 的作用是把多家模型的调用收敛成一个统一的 Key 和统一的 API 入口,这样你在 Delphi 里只需要维护一套请求逻辑,不用为每个模型写不同的鉴权。

你需要做三件事:

第一,拿到 API Key。登录后进入控制台,在 API Keys 页面创建一个 Key,复制保存。这个 Key 就是 Delphi 里要填的凭证。

第二,确认 API 基地址。统一入口是https://taotoken.net/api,注意这里不带任何查询参数,代码里拼接路径时用这个前缀。

第三,选一个你要调用的模型名。模型对话页面可以看到当前可用的模型列表,先记下一个,后面写进配置。

相关入口我列一下,方便你对照操作:

  • 控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite
  • API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
  • 模型对话:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite

注意:Key 只放在本地配置文件里,不要硬编码进 .pas 源码,更不要提交到版本库。Delphi7 项目经常用 ini 或 json 存配置,这里我们用 json + toml 双份,方便你按习惯选。

如果你后面要做长期编码或 Agent 类任务,可以了解 Coding Plan,入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。本篇先聚焦单次调用面板。

3. 可复制配置:settings.json 与 config.toml 骨架

Delphi7 本身没有内置 JSON 解析,但你可以用 SuperObject 或者简单的字符串拼接。为了让你先跑通,我把配置拆成两份:一份 JSON 给程序读,一份 TOML 给你自己看和改。

先看settings.json,放在 exe 同目录:

{ "taotoken": { "api_base": "https://taotoken.net/api", "api_key": "sk-你的Key填这里", "model": "你选定的模型名", "timeout_ms": 30000 }, "ui": { "status_idle_icon": "idle.ico", "status_busy_icon": "busy.ico", "status_ok_icon": "ok.ico", "status_fail_icon": "fail.ico" } }

再看config.toml,这份是给你手动维护用的,字段和 JSON 对齐:

[taotoken] api_base = "https://taotoken.net/api" api_key = "sk-你的Key填这里" model = "你选定的模型名" timeout_ms = 30000 [ui] status_idle_icon = "idle.ico" status_busy_icon = "busy.ico" status_ok_icon = "ok.ico" status_fail_icon = "fail.ico"

两份配置的字段含义一致:api_base是统一入口,api_key是凭证,model是模型名,timeout_ms是超时。UI 部分对应四个状态图标文件名,放在 exe 同目录即可。

在 Delphi7 里读取时,你可以先用最简单的 TStringList 逐行解析,或者引入 SuperObject。下面给一个不依赖第三方库的读取片段,假设你只读 JSON 里的三个关键字段:

function ReadConfigValue(const AFile, AKey: string): string; var sl: TStringList; i: Integer; line, pattern: string; begin Result := ''; sl := TStringList.Create; try sl.LoadFromFile(AFile); pattern := '"' + AKey + '"'; for i := 0 to sl.Count - 1 do begin line := Trim(sl[i]); if Pos(pattern, line) = 1 then begin // 形如 "api_key": "sk-xxx", Result := Trim(Copy(line, Pos(':', line) + 1, Length(line))); Result := StringReplace(Result, '"', '', [rfReplaceAll]); Result := StringReplace(Result, ',', '', [rfReplaceAll]); Break; end; end; finally sl.Free; end; end;

这段代码只做演示,生产环境建议换成正规 JSON 库。重点是:配置和代码分离,换 Key 不用重新编译。

4. 面板搭建:Image 状态图标 + SpeedButton 触发按钮

现在进入 UI 部分。新建一个 Form,放一个 Image 和三个 SpeedButton,布局如下:

Image 放在左上角,Align 设为alNone,手动调成 32x32,用来显示状态图标。SpeedButton1 做「发送」,SpeedButton2 做「清空」,SpeedButton3 做「复制结果」。右侧放一个 Memo 显示返回内容。

4.1 Image 组件:Align 与 Stretch 怎么设

Image 有两个关键属性。Align常见设成alClient,这样 Image 会充满整个窗体;但我们的场景里 Image 只做状态图标,所以保持alNone,手动设 Width 和 Height 为 32。

Stretch设为True时,图片会自动缩放到 Image 选框大小。状态图标建议统一做成 32x32,Stretch 设 True,这样换图标不会因为尺寸不一致而变形。

procedure TForm1.FormCreate(Sender: TObject); begin Image1.Width := 32; Image1.Height := 32; Image1.Stretch := True; Image1.Picture.LoadFromFile('idle.ico'); end;

切换状态时,只需要换 Picture:

procedure TForm1.SetStatus(const AIconFile: string); begin if FileExists(AIconFile) then Image1.Picture.LoadFromFile(AIconFile); end;

4.2 SpeedButton 组件:Flat、Cursor、Layout、Transparent、Margin、Spacing

SpeedButton 的属性比较多,逐个说清楚:

Flat设为 True 时按钮是平铺外观,False 是立体效果。面板风格建议 True,看起来更干净。

Cursor改成crHandPoint,鼠标移上去变手型,交互感更好。

Layout控制位图在按钮上的位置,比如blGlyphLeft。原文提到「虽然可以让位图居左,但是还是不够左」,这是因为还有Margin在起作用。

Transparent设为 True 时按钮背景透明,适合放在有底色的面板上。

Margin设置边界像素,想让图标更靠左,就把 Margin 调小,比如 2。

Spacing指定图标和文字之间的距离,默认是 4,想让文字离图标远一点就调大。

procedure TForm1.FormCreate(Sender: TObject); begin SpeedButton1.Flat := True; SpeedButton1.Cursor := crHandPoint; SpeedButton1.Layout := blGlyphLeft; SpeedButton1.Transparent := True; SpeedButton1.Margin := 2; SpeedButton1.Spacing := 6; SpeedButton1.Caption := '发送'; end;

关于NumGlyphs,它用于指定按钮位图包含几个状态图(比如正常、按下、禁用)。如果你只用一张图,保持默认 1 即可;要用多状态,就把位图做成横向排列的多帧,NumGlyphs 设为帧数。新手常见问题是位图只做了一帧却把 NumGlyphs 设成 3,结果按钮显示错位,改回 1 就正常了。

5. 按钮点击后:发请求并验证返回

UI 搭好后,核心是 SpeedButton1 的 OnClick 里发 HTTP 请求。Delphi7 可以用 Indy 的 TIdHTTP,或者用 WinINet。这里用 Indy,因为大多数 Delphi7 环境都自带。

uses IdHTTP, IdSSLOpenSSL, IdGlobal; function TForm1.CallTaoToken(const APrompt: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocket; reqBody: TStringStream; respBody: TStringStream; json: string; begin http := TIdHTTP.Create(nil); ssl := TIdSSLIOHandlerSocket.Create(nil); reqBody := TStringStream.Create(''); respBody := TStringStream.Create(''); try ssl.SSLOptions.Method := sslvTLSv1_2; http.IOHandler := ssl; http.Request.ContentType := 'application/json'; http.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + ReadConfigValue('settings.json', 'api_key'); http.ReadTimeout := 30000; json := '{"model":"' + ReadConfigValue('settings.json', 'model') + '",' + '"messages":[{"role":"user","content":"' + APrompt + '"}]}'; reqBody.WriteString(UTF8Encode(json)); http.Post('https://taotoken.net/api/v1/chat/completions', reqBody, respBody); Result := UTF8Decode(respBody.DataString); finally reqBody.Free; respBody.Free; ssl.Free; http.Free; end; end;

按钮点击事件:

procedure TForm1.SpeedButton1Click(Sender: TObject); begin SetStatus('busy.ico'); SpeedButton1.Enabled := False; try Memo1.Lines.Text := CallTaoToken(Memo1.Lines.Text); SetStatus('ok.ico'); except on E: Exception do begin Memo1.Lines.Text := '请求失败: ' + E.Message; SetStatus('fail.ico'); end; end; SpeedButton1.Enabled := True; end;

验证成功的标志:Memo 里出现模型返回的文本,Image 从 busy 切到 ok。如果失败,Image 切到 fail,Memo 显示错误信息。这一步跑通,说明 Key、API 地址、模型名、网络都对了。

6. 本篇常见错排查

错误一:请求返回 401。多半是 Key 没读到,或者 Authorization 头拼错。检查ReadConfigValue是否真的读到了值,可以在调试时把 Key 前几位打印出来。注意 Bearer 后面有一个空格。

错误二:返回 404。检查 URL 路径。基地址是https://taotoken.net/api,聊天补全路径是/v1/chat/completions,拼起来是https://taotoken.net/api/v1/chat/completions。不要多加斜杠。

错误三:中文乱码。Delphi7 的字符串是 ANSI,请求体要 UTF8Encode,返回要 UTF8Decode。Memo 显示前确认解码正确。

错误四:SSL 握手失败。Delphi7 自带的 Indy 版本较老,需要确认IdSSLOpenSSL已安装,并且 OpenSSL 的 dll 在 exe 同目录。TLS 版本设成 1.2。

错误五:SpeedButton 图标不显示。检查Glyph是否加载,NumGlyphs是否和位图帧数一致,Margin是否把图标挤出去了。

错误六:Image 图标切换无效。确认图标文件路径正确,Stretch为 True 时图片会缩放,如果原图比例不对会变形,建议统一 32x32。

排障时优先看 API Keys 和接入文档两个入口,对照请求头和路径:

  • API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite

7. 继续往下走:从单次调用到可复用面板

面板跑通一次真实调用后,你可以把它做成可复用的:把 CallTaoToken 抽成独立单元,配置读取抽成 Config 类,Image 和 SpeedButton 封装成一个 TAIStatusPanel 组件。这样在别的 Form 上直接放一个面板就能用。

如果后面要做更长的编码任务或 Agent 流程,单次请求面板就不够了,可以看 Coding Plan,入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。模型对话入口是 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,可以先用它验证模型名和返回格式,再写进 Delphi 配置。

我试过在 Delphi7 里把 SpeedButton 的 Margin 调到 0、Spacing 调到 8,图标和文字的组合最舒服。另外一个小技巧:把四个状态图标做成同一套配色,Image 切换时视觉上不会跳。面板虽小,但状态反馈清楚,用起来比纯文本框踏实得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询