Sign in Join
Wiki copytemporary

Extending the IDE/zh CN: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1+## Contents
2+
3+ * 1 扩展 IDE
4+ * 1.1 概述
5+ * 1.2 包和 Makefile 依赖项
6+ * 2 菜单项
7+ * 2.1 添加菜单项
8+ * 2.2 快捷键
9+ * 3 配置文件
10+ * 4 组件
11+ * 4.1 扩展现有组件
12+ * 4.2 编写组件
13+ * 4.2.1 为组件面板提供一个新组件图标
14+ * 4.2.2 隐藏组件面板中的组件
15+ * 4.3 编写组件编辑器
16+ * 4.4 编写属性编辑器
17+ * 4.4.1 在 Object Inspector 中隐藏属性
18+ * 4.4.2 找出属性使用的属性编辑器
19+ * 4.5 窗体
20+ * 5 界面设计器(Designer)
21+ * 5.1 编写一个设计器中间层
22+ * 5.2 创建一个新的唯一组件名称
23+ * 5.3 在设计器 / 对象检查器中选择一个组件
24+ * 5.4 获取单元,设计器,文件的形式
25+ * 5.5 保存单元,设计器窗口
26+ * 5.6 将设计器窗口保存为 Pascal
27+ * 6 事件处理程序
28+ * 6.1 设计器活动
29+ * 6.1.1 设计器活动的例子
30+ * 6.1.1.1 示例:当放置新组件时,将新组件移动到子组件中
31+ * 6.1.2 禁用设计器鼠标处理程序
32+ * 6.2 在修改设计器窗体时收到通知
33+ * 6.3 项目事件
34+ * 6.4 其他 IDE 事件
35+ * 7 项目
36+ * 7.1 当前的项目
37+ * 7.2 当前项目的所有单元
38+ * 7.2.1 项目检查员的所有单元
39+ * 7.2.2 所有用过的项目单元
40+ * 7.3 项目的 .lpr、.lpi 和 .lps 文件
41+ * 7.4 项目的可执行文件 / 目标文件名
42+ * 7.5 添加您自己的项目类型
43+ * 7.6 添加您自己的文件类型
44+ * 7.7 添加新文件类型
45+ * 7.7.1 添加新表单类型
46+ * 7.8 以 lpi/lps 存储自定义值
47+ * 8 包
48+ * 8.1 搜索所有包
49+ * 8.2 搜索包含名称的包
50+ * 8.3 获取已安装软件包的 lpk 文件名
51+ * 8.4 安装包
52+ * 8.5 打开包文件(lpk)
53+ * 8.6 找到一个单元的包裹
54+ * 8.7 查找项目 / 包所需的包
55+ * 9 窗口(Windows)
56+ * 9.1 添加新的可停靠 IDE 窗口
57+ * 9.1.1 如何注册可停靠的 IDE 窗口
58+ * 9.1.2 显示 IDE 窗口
59+ * 9.1.3 有关 IDEWindowCreators 和 SimpleLayoutStorage 的注释
60+ * 10 代码工具
61+ * 10.1 将资源指令添加到文件中
62+ * 10.2 获取单元和包含文件的搜索路径
63+ * 11 源代码编辑
64+ * 11.1 激活源代码编辑器
65+ * 12 SynEdit
66+ * 12.1 获取 TSynEdit 的设置
67+ * 12.2 获取 SynEdit 的高亮设置
68+ * 13 帮助
69+ * 13.1 添加源的帮助
70+ * 13.2 在消息窗口中添加行
71+ * 14 IDE 选项框架
72+ * 14.1 打开特定框架中的选项
73+ * 15 其它
74+ * 15.1 添加宏
75+ * 15.2 调试 IDE
76+ * 15.3 另请参见
77+
178# 扩展 IDE
279
380## 概述
481
5-Lazarus IDE 支持以下几种类型的插件:
82+Lazarus IDE 支持以下几种类型的插件:
683
7-组件(Components)
8-这些是“组件面板”上的项目。例如 TButton(可以在“标准”页面上找到)可用于创建按钮。
84+组件(Components)
85+ 这些是“组件面板”上的项目。例如 TButton(可以在“标准”页面上找到)可用于创建按钮。
986
10-组件编辑器(Component Editors)
11-当你在“界面设计器(Designer)”中双击一个组件时(比如“TMainMenu”组件),将调用组件编辑器(比如“菜单编辑器”)。组件编辑器还可以在“界面设计器”的右键菜单中添加一个额外的菜单项(右键单击“界面设计器”中的组件时可以访问)。
87+组件编辑器(Component Editors)
88+ 当你在“界面设计器(Designer)”中双击一个组件时(比如“TMainMenu”组件),将调用组件编辑器(比如“菜单编辑器”)。组件编辑器还可以在“界面设计器”的右键菜单中添加一个额外的菜单项(右键单击“界面设计器”中的组件时可以访问)。
1289
13-属性编辑器(Property Editors)
14-“对象查看器”的列表中的每一行都使用属性编辑器来设置或更改该属性的值。
90+属性编辑器(Property Editors)
91+ “对象查看器”的列表中的每一行都使用属性编辑器来设置或更改该属性的值。
1592
16-专家(Experts)
17-专家包含所有其他插件类型。他们可能会注册新的菜单项,注册快捷方式或扩展其他 IDE 功能。
93+专家(Experts)
94+ 专家包含所有其他插件类型。他们可能会注册新的菜单项,注册快捷方式或扩展其他 IDE 功能。
1895
19-有两种方式可以将自己的插件添加到 Lazarus IDE:
96+
97+有两种方式可以将自己的插件添加到 Lazarus IDE:
2098
21-1. 编写一个包,安装它并在包单元的“Register”过程中注册你的插件。
22-2. 扩展 Lazarus 代码,并将您的 svn diff 发送到 Lazarus 邮件列表。
99+ 1. 编写一个包,安装它并在包单元的“Register”过程中注册你的插件。
100+ 2. 扩展 Lazarus 代码,并将您的 svn diff 发送到 Lazarus 邮件列表。
23101
24102## 包和 Makefile 依赖项
25103
26-如果添加新的包依赖项,则必须执行以下步骤。
104+如果添加新的包依赖项,则必须执行以下步骤。
27105
28-- 创建 / 通过包编辑器更新包的 MakeFile/ 更多 .../ 创建 Makefile。
29-- 修复所有依赖项。请参阅 tools/updatemakefiles.lpi
106+ * 创建 / 通过包编辑器更新包的 MakeFile/ 更多 .../ 创建 Makefile。
107+ * 修复所有依赖项。请参阅 tools/updatemakefiles.lpi
30108
31109# 菜单项
32110
33-您可以添加新菜单项,隐藏或移动现有菜单项并添加子菜单、菜单区(菜单区是整个菜单中的一块区域,它可以是一个包含子菜单的菜单项,也可以是由分隔符分隔出来的一块区域。如果菜单区中没有子项,则该菜单区将不可见。比如 itmFileNew 就是一个用分隔符分隔的菜单区,它里面包含了“新建单元”、“新建窗体”、“新建 ...” 等菜单项,itmFileRecentOpen 也是一个菜单区,它只是一个菜单项,包含“最近打开的文件”子菜单)。对于您自己的窗体,您可以注册 TMainMenu/TPopupMenu,以便其它包可以进一步扩展您的窗体。**IDEIntf** 包的 MenuIntf 单元包含菜单的所有注册函数和 IDE 本身的许多标准菜单项。
111+您可以添加新菜单项,隐藏或移动现有菜单项并添加子菜单、菜单区(菜单区是整个菜单中的一块区域,它可以是一个包含子菜单的菜单项,也可以是由分隔符分隔出来的一块区域。如果菜单区中没有子项,则该菜单区将不可见。比如 itmFileNew 就是一个用分隔符分隔的菜单区,它里面包含了“新建单元”、“新建窗体”、“新建 ...” 等菜单项,itmFileRecentOpen 也是一个菜单区,它只是一个菜单项,包含“最近打开的文件”子菜单)。对于您自己的窗体,您可以注册 TMainMenu/TPopupMenu,以便其它包可以进一步扩展您的窗体。**IDEIntf** 包的 MenuIntf 单元包含菜单的所有注册函数和 IDE 本身的许多标准菜单项。
34112
35113## 添加菜单项
36114
37-像“查看 -\> 对象查看器”这样的单个菜单项称为 **TIDEMenuCommand**。您可以使用 **RegisterIDEMenuCommand** 创建一个,它有两个带有大量参数的格式:
38-
39-``` pascal
40-function RegisterIDEMenuCommand(
41- Parent: TIDEMenuSection;
42- const Name, Caption: string;
43- const OnClickMethod: TNotifyEvent = nil;
44- const OnClickProc: TNotifyProcedure = nil;
45- const Command: TIDECommand = nil;
46- const ResourceName: String = ''
47- ): TIDEMenuCommand; overload;
48-
115+像“查看 -> 对象查看器”这样的单个菜单项称为 **TIDEMenuCommand** 。您可以使用 **RegisterIDEMenuCommand** 创建一个,它有两个带有大量参数的格式:
116+```
49117function RegisterIDEMenuCommand(
50- const Path, Name, Caption: string;
51- const OnClickMethod: TNotifyEvent = nil;
52- const OnClickProc: TNotifyProcedure = nil;
53- const Command: TIDECommand = nil;
54- const ResourceName: String = ''
55- ): TIDEMenuCommand; overload;
118+ Parent: TIDEMenuSection;
119+ const Name, Caption: string;
120+ const OnClickMethod: TNotifyEvent = nil;
121+ const OnClickProc: TNotifyProcedure = nil;
122+ const Command: TIDECommand = nil;
123+ const ResourceName: String = ''
124+ ): TIDEMenuCommand; overload;
125+
126+ function RegisterIDEMenuCommand(
127+ const Path, Name, Caption: string;
128+ const OnClickMethod: TNotifyEvent = nil;
129+ const OnClickProc: TNotifyProcedure = nil;
130+ const Command: TIDECommand = nil;
131+ const ResourceName: String = ''
132+ ): TIDEMenuCommand; overload;
56133```
57134
58-这两者之间的区别仅在于指定父菜单区的方式。您可以通过 Path 参数直接或间接地给出菜单区。*MenuIntf* 单元中可以找到许多标准菜单区。例如 **mnuTools** 菜单区,它是主 IDE 栏的 *Tools* 菜单。它包含一个子菜单区 **itmSecondaryTools**,用于第三方工具的推荐菜单区。
59-
60-下面的代码注册了一个新的菜单命令,菜单名(Name)为“MyTool”,菜单标题(Caption)为“我的工具(&T)”,点击后执行 StartMyTool 过程:
135+这两者之间的区别仅在于指定父菜单区的方式。您可以通过 Path 参数直接或间接地给出菜单区。 _MenuIntf_ 单元中可以找到许多标准菜单区。例如 **mnuTools** 菜单区,它是主 IDE 栏的 _Tools_ 菜单。它包含一个子菜单区 **itmSecondaryTools** ,用于第三方工具的推荐菜单区。
61136
62-``` pascal
137+下面的代码注册了一个新的菜单命令,菜单名(Name)为“MyTool”,菜单标题(Caption)为“我的工具(&T)”,点击后执行 StartMyTool 过程:
138+```
63139procedure StartMyTool;
64-begin
65- ... 点击菜单项后要执行的代码 ...
66-end;
67-
68-procedure Register;
69-begin
70- RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具(&T)', nil, @StartMyTool);
71-end;
140+ begin
141+ ... 点击菜单项后要执行的代码 ...
142+ end;
143+
144+ procedure Register;
145+ begin
146+ RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具(&T)', nil, @StartMyTool);
147+ end;
72148```
73149
74-如果要调用方法而不是过程,请使用 **OnClickMethod** 参数。
75-
76-此菜单项没有快捷键。如果需要快捷键,则必须创建一个 **TIDECommand** 对象并将其传递给 **Command** 参数。例如:
150+如果要调用方法而不是过程,请使用 **OnClickMethod** 参数。
77151
78-``` pascal
152+此菜单项没有快捷键。如果需要快捷键,则必须创建一个 **TIDECommand** 对象并将其传递给 **Command** 参数。例如:
153+```
79154uses
80- ... Classes, LCLType, Dialogs, IDECommands, MenuIntf;
81-
82-...
83-
84-procedure StartMyTool(Sender :TObject);
85-begin
86- ShowMessage('Hello World!');
87-end;
88-
89-procedure Register;
90-var
91- Key: TIDEShortCut;
92- Cat: TIDECommandCategory;
93- CmdMyTool: TIDECommand;
94-begin
95- // 注册 IDE 快捷键(Ctrl+Alt+Shift+T)和菜单项
96- Key := IDEShortCut(VK_T,[ssCtrl,ssAlt,ssShift],VK_UNKNOWN,[]);
97- Cat := IDECommandList.FindCategoryByName(CommandCategoryToolMenuName);
98- CmdMyTool := RegisterIDECommand(Cat, 'StartMyTool', ' 启动我的工具 ', Key, nil, @StartMyTool);
99- RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具 (&T)', nil, nil, CmdMyTool);
100-end;
155+ ... Classes, LCLType, Dialogs, IDECommands, MenuIntf;
156+
157+ ...
158+
159+ procedure StartMyTool(Sender :TObject);
160+ begin
161+ ShowMessage('Hello World!');
162+ end;
163+
164+ procedure Register;
165+ var
166+ Key: TIDEShortCut;
167+ Cat: TIDECommandCategory;
168+ CmdMyTool: TIDECommand;
169+ begin
170+ // 注册 IDE 快捷键(Ctrl+Alt+Shift+T)和菜单项
171+ Key := IDEShortCut(VK_T,[ssCtrl,ssAlt,ssShift],VK_UNKNOWN,[]);
172+ Cat := IDECommandList.FindCategoryByName(CommandCategoryToolMenuName);
173+ CmdMyTool := RegisterIDECommand(Cat, 'StartMyTool', ' 启动我的工具 ', Key, nil, @StartMyTool);
174+ RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具 (&T)', nil, nil, CmdMyTool);
175+ end;
101176```
102177
103178## 快捷键
104179
105-所有快捷键都在 IDECommandList 中注册。下面是一个示例,将查找所有使用 Ctrl-D 作为快捷键的命令:
106-
107-``` pascal
180+所有快捷键都在 IDECommandList 中注册。下面是一个示例,将查找所有使用 Ctrl-D 作为快捷键的命令:
181+```
108182uses
109- Classes, SysUtils, Dialogs, LCLType, LCLProc, IDECommands, MenuIntf;
110-
111-// 列出所有使用 Ctrl-D 的 IDE 命令
112-procedure ListCtrlD;
113-var
114- i :integer;
115- Cmd :TIDECommand;
116- Commands :TFPList;
117-begin
118- Commands := IDECommandList.FindCommandsByShortCut(IDEShortCut(VK_D, [ssCtrl], VK_UNKNOWN, []));
119- try
120- for i := 0 to Commands.Count - 1 do
183+ Classes, SysUtils, Dialogs, LCLType, LCLProc, IDECommands, MenuIntf;
184+
185+ // 列出所有使用 Ctrl-D 的 IDE 命令
186+ procedure ListCtrlD;
187+ var
188+ i :integer;
189+ Cmd :TIDECommand;
190+ Commands :TFPList;
121191 begin
122- Cmd := TIDECommand(Commands[i]);
123- ShowMessage(format('Cmd: %s, A = %s - %d, %s - %d' + #13#10 + 'B = %s - %d, %s - %d',
124- [Cmd.Name,
125- dbgs(Cmd.ShortcutA.Shift1),
126- Cmd.ShortcutA.Key1,
127- dbgs(Cmd.ShortcutA.Shift2),
128- Cmd.ShortcutA.Key2,
129- dbgs(Cmd.ShortcutB.Shift1),
130- Cmd.ShortcutB.Key1,
131- dbgs(Cmd.ShortcutB.Shift2),
132- Cmd.ShortcutB.Key2]));
192+ Commands := IDECommandList.FindCommandsByShortCut(IDEShortCut(VK_D, [ssCtrl], VK_UNKNOWN, []));
193+ try
194+ for i := 0 to Commands.Count - 1 do
195+ begin
196+ Cmd := TIDECommand(Commands[i]);
197+ ShowMessage(format('Cmd: %s, A = %s - %d, %s - %d' + #13#10 + 'B = %s - %d, %s - %d',
198+ [Cmd.Name,
199+ dbgs(Cmd.ShortcutA.Shift1),
200+ Cmd.ShortcutA.Key1,
201+ dbgs(Cmd.ShortcutA.Shift2),
202+ Cmd.ShortcutA.Key2,
203+ dbgs(Cmd.ShortcutB.Shift1),
204+ Cmd.ShortcutB.Key1,
205+ dbgs(Cmd.ShortcutB.Shift2),
206+ Cmd.ShortcutB.Key2]));
207+ end;
208+ finally
209+ Commands.Free;
210+ end;
133211 end;
134- finally
135- Commands.Free;
136- end;
137-end;
138212```
139213
140214# 配置文件
141215
142-加载和保存配置
143-
144-IDE 的所有配置文件都以 xml 格式存储在一个目录中(主配置目录)。包也可以在那里添加自己的配置文件。可以使用下面的方式读取“主配置目录”:
216+加载和保存配置
145217
146-``` pascal
218+IDE 的所有配置文件都以 xml 格式存储在一个目录中(主配置目录)。包也可以在那里添加自己的配置文件。可以使用下面的方式读取“主配置目录”:
219+```
147220uses LazIDEIntf;
148-...
149- Directory := LazarusIDE.GetPrimaryConfigPath;
221+ ...
222+ Directory := LazarusIDE.GetPrimaryConfigPath;
150223```
151224
152-包可以创建自己的 xml 文件:
153-
154-``` pascal
225+包可以创建自己的 xml 文件:
226+```
155227uses
156- ..., LCLProc, BaseIDEIntf, LazConfigStorage;
157-
158-const
159- Version = 1;
160-var
161- Config: TConfigStorage;
162- SomeValue: String;
163- SomeInteger: Integer;
164- SomeBoolean: Boolean;
165- FileVersion: LongInt;
166-begin
167- SomeValue:='Default';
168- SomeInteger:=3;
169- SomeBoolean:=true;
170-
171- // 保存配置
172- try
173- Config:=GetIDEConfigStorage('mysettings.xml',false);
174- try
175- // 存储版本号,以便将来的扩展可以处理旧的配置文件
176- Config.SetDeleteValue('Path/To/The/Version',Version,0);
177- // 存储字符串变量 “someValue”
178- // 如果 someValue 的值和默认值相同,则不会存储该项
179- // 因此只有与默认值不同的项才会被存储
180- // 这样能使 XML 保持简短,并且便于在将来改变默认值。
181- Config.SetDeleteValue('Path/To/Some/Value',SomeValue,'Default');
182- Config.SetDeleteValue('Path/To/Some/Integer',SomeInteger,3);
183- Config.SetDeleteValue('Path/To/Some/Boolean',SomeBoolean,true);
184- // 还有很多 SetDeleteValue 的重载,通过 Ctrl+Space(代码提示的快捷键)查看它们。
185- finally
186- Config.Free;
187- end;
188-
189- except
190- on E: Exception do begin
191- DebugLn(['Saving mysettings.xml failed: ',E.Message]);
192- end;
193- end;
194-
195- // 加载配置
196- try
197- Config:=GetIDEConfigStorage('mysettings.xml',true);
198- try
199- // 读取配置的版本
200- FileVersion:=Config.GetValue('Path/To/The/Version',0);
201- // 读取字符串变量“SomeValue”。如果该项不存在,则使用默认值。
202- SomeValue:=Config.GetValue('Path/To/Some/Value','Default');
203- SomeInteger:=Config.GetValue('Path/To/Some/Integer',3);
204- SomeBoolean:=Config.GetValue('Path/To/Some/Boolean',true);
205- finally
206- Config.Free;
207- end;
208- except
209- on E: Exception do begin
210- DebugLn(['Loading mysettings.xml failed: ',E.Message]);
228+ ..., LCLProc, BaseIDEIntf, LazConfigStorage;
229+
230+ const
231+ Version = 1;
232+ var
233+ Config: TConfigStorage;
234+ SomeValue: String;
235+ SomeInteger: Integer;
236+ SomeBoolean: Boolean;
237+ FileVersion: LongInt;
238+ begin
239+ SomeValue:='Default';
240+ SomeInteger:=3;
241+ SomeBoolean:=true;
242+
243+ // 保存配置
244+ try
245+ Config:=GetIDEConfigStorage('mysettings.xml',false);
246+ try
247+ // 存储版本号,以便将来的扩展可以处理旧的配置文件
248+ Config.SetDeleteValue('Path/To/The/Version',Version,0);
249+ // 存储字符串变量 “someValue”
250+ // 如果 someValue 的值和默认值相同,则不会存储该项
251+ // 因此只有与默认值不同的项才会被存储
252+ // 这样能使 XML 保持简短,并且便于在将来改变默认值。
253+ Config.SetDeleteValue('Path/To/Some/Value',SomeValue,'Default');
254+ Config.SetDeleteValue('Path/To/Some/Integer',SomeInteger,3);
255+ Config.SetDeleteValue('Path/To/Some/Boolean',SomeBoolean,true);
256+ // 还有很多 SetDeleteValue 的重载,通过 Ctrl+Space(代码提示的快捷键)查看它们。
257+ finally
258+ Config.Free;
259+ end;
260+
261+ except
262+ on E: Exception do begin
263+ DebugLn(['Saving mysettings.xml failed: ',E.Message]);
264+ end;
265+ end;
266+
267+ // 加载配置
268+ try
269+ Config:=GetIDEConfigStorage('mysettings.xml',true);
270+ try
271+ // 读取配置的版本
272+ FileVersion:=Config.GetValue('Path/To/The/Version',0);
273+ // 读取字符串变量“SomeValue”。如果该项不存在,则使用默认值。
274+ SomeValue:=Config.GetValue('Path/To/Some/Value','Default');
275+ SomeInteger:=Config.GetValue('Path/To/Some/Integer',3);
276+ SomeBoolean:=Config.GetValue('Path/To/Some/Boolean',true);
277+ finally
278+ Config.Free;
279+ end;
280+ except
281+ on E: Exception do begin
282+ DebugLn(['Loading mysettings.xml failed: ',E.Message]);
283+ end;
284+ end;
211285 end;
212- end;
213-end;
214286```
215287
216-注意:
288+注意:
217289
218-- 每个 IDE 插件都应该使用自己的配置文件。特别是您不能使用标准 IDE 选项文件,如 editoroptions.xml 或 environmentoptions.xml。
219-- GetIDEConfigStorage 在加载时,会检查文件是否存在,如果不存在,它将从辅助配置目录复制模板。
220-- 从 0.9.31 开始,您可以使用此函数在主配置目录之外加载文件。
290+ * 每个 IDE 插件都应该使用自己的配置文件。特别是您不能使用标准 IDE 选项文件,如 editoroptions.xml 或 environmentoptions.xml。
291+ * GetIDEConfigStorage 在加载时,会检查文件是否存在,如果不存在,它将从辅助配置目录复制模板。
292+ * 从 0.9.31 开始,您可以使用此函数在主配置目录之外加载文件。
221293
222294# 组件
223295
224296## 扩展现有组件
225297
226-来源:[1](http://lazarus.freepascal.org/index.php/topic,17733.msg98425.html#msg98425) 定制现有的 LCL 组件很简单,例如,如果要添加属性。
227-
228-使用字段及其相应的 setter 和 getter 方法来添加所需的属性。
298+来源:[[1]](<http://lazarus.freepascal.org/index.php/topic,17733.msg98425.html#msg98425>) 定制现有的 LCL 组件很简单,例如,如果要添加属性。
229299
230-然后“手动”实例化它们,给出一个 OWner 组件(以便处理稍后的销毁操作),并设置 Parent 和可能的 Top 和 Left 以及组件在初始化时需要的任何其他默认值。
300+使用字段及其相应的 setter 和 getter 方法来添加所需的属性。
231301
232-如果您对自定义组件的调试感到满意,请添加一个 RegisterComponent() 调用以将其加入到 IDE 的组件面板中,并保存您必须“手动”编写的设置代码(查看任一个组件的源代码以了解如何执行此操作)。
302+然后“手动”实例化它们,给出一个 OWner 组件(以便处理稍后的销毁操作),并设置 Parent 和可能的 Top 和 Left 以及组件在初始化时需要的任何其他默认值。
233303
234-这是一个简单的例子:
304+如果您对自定义组件的调试感到满意,请添加一个 RegisterComponent() 调用以将其加入到 IDE 的组件面板中,并保存您必须“手动”编写的设置代码(查看任一个组件的源代码以了解如何执行此操作)。
235305
236-``` pascal
306+这是一个简单的例子:
307+```
237308unit Unit1;
238-
239-{$mode objfpc}{$H+}
240-
241-interface
242-
243-uses
244- Classes, SysUtils, Forms, StdCtrls;
245-
246-type
247- TEdX = class(TEdit)
248- private
249- FNewIntProp: integer;
250- FNewStrProp: string;
251- procedure SetNewIntProp(AValue: integer);
252- procedure SetNewStrProp(AValue: string);
253- public
254- constructor Create(theComponent: TComponent); override;
255- property NewIntProp: integer read FNewIntProp write SetNewIntProp;
256- property NewStrProp: string read FNewStrProp write SetNewStrProp;
257- end;
258-
259- TForm1 = class(TForm)
260- procedure FormCreate(Sender: TObject);
261- private
262- edX: TEdX;
263- public
264- end;
265-
266-var
267- Form1: TForm1;
268-
269-implementation
270-
271-{ TForm1 }
272-
273-procedure TForm1.FormCreate(Sender: TObject);
274-begin
275- edX:= TEdX.Create(Self);
276- edX.Parent:= Self;
277- edX.Caption:= IntToStr(edX.NewIntProp);
278- Caption:= edX.NewStrProp;
279-end;
280-
281-{$R *.lfm}
282-
283-{ TEdX }
284-
285-procedure TEdX.SetNewIntProp(AValue: integer);
286-begin
287- if FNewIntProp=AValue then Exit;
288- FNewIntProp:=AValue;
289- // 这里填写自定义代码
290-end;
291-
292-procedure TEdX.SetNewStrProp(AValue: string);
293-begin
294- if FNewStrProp=AValue then Exit;
295- FNewStrProp:=AValue;
296- // 这里填写自定义代码
297-end;
298-
299-constructor TEdX.Create(theComponent: TComponent);
300-begin
301- inherited Create(theComponent);
302- FNewStrProp:= 'new string property value';
303- FNewIntProp:= 99;
304-end;
305-
306-end.
309+
310+ {$mode objfpc}{$H+}
311+
312+ interface
313+
314+ uses
315+ Classes, SysUtils, Forms, StdCtrls;
316+
317+ type
318+ TEdX = class(TEdit)
319+ private
320+ FNewIntProp: integer;
321+ FNewStrProp: string;
322+ procedure SetNewIntProp(AValue: integer);
323+ procedure SetNewStrProp(AValue: string);
324+ public
325+ constructor Create(theComponent: TComponent); override;
326+ property NewIntProp: integer read FNewIntProp write SetNewIntProp;
327+ property NewStrProp: string read FNewStrProp write SetNewStrProp;
328+ end;
329+
330+ TForm1 = class(TForm)
331+ procedure FormCreate(Sender: TObject);
332+ private
333+ edX: TEdX;
334+ public
335+ end;
336+
337+ var
338+ Form1: TForm1;
339+
340+ implementation
341+
342+ { TForm1 }
343+
344+ procedure TForm1.FormCreate(Sender: TObject);
345+ begin
346+ edX:= TEdX.Create(Self);
347+ edX.Parent:= Self;
348+ edX.Caption:= IntToStr(edX.NewIntProp);
349+ Caption:= edX.NewStrProp;
350+ end;
351+
352+ {$R *.lfm}
353+
354+ { TEdX }
355+
356+ procedure TEdX.SetNewIntProp(AValue: integer);
357+ begin
358+ if FNewIntProp=AValue then Exit;
359+ FNewIntProp:=AValue;
360+ // 这里填写自定义代码
361+ end;
362+
363+ procedure TEdX.SetNewStrProp(AValue: string);
364+ begin
365+ if FNewStrProp=AValue then Exit;
366+ FNewStrProp:=AValue;
367+ // 这里填写自定义代码
368+ end;
369+
370+ constructor TEdX.Create(theComponent: TComponent);
371+ begin
372+ inherited Create(theComponent);
373+ FNewStrProp:= 'new string property value';
374+ FNewIntProp:= 99;
375+ end;
376+
377+ end.
307378```
308379
309380## 编写组件
310381
311382主要文章:[[How To Write Lazarus Component]]
312383
313-您可以通过包编辑器创建新组件。
384+您可以通过包编辑器创建新组件。
314385
315-创建或打开一个包,单击“添加 -\> 新组件”,填写项目: Ancestor Type = TButton, New class name = TMyButton, palette page = Misc, Unit name = mybutton.pas(将创建此文件) , 单位名称 MyButton,然后单击确定。
386+创建或打开一个包,单击“添加 -> 新组件”,填写项目: Ancestor Type = TButton, New class name = TMyButton, palette page = Misc, Unit name = mybutton.pas(将创建此文件) , 单位名称 MyButton,然后单击确定。
316387
317388### 为组件面板提供一个新组件图标
318389
319-创建格式为 .bmp、.xpm 或 .png 的图像文件,其名称与组件类相同。例如 tmybutton.png 并将其保存在包源目录中。图像可以由任何图形程序(例如 gimp)创建,并且不应大于 24x24 像素。然后使用 lazres 工具将图像转换为资源文件,该工具可以在 lazarus/tools 目录中找到:
320-
321-``` bash
390+创建格式为 .bmp、.xpm 或 .png 的图像文件,其名称与组件类相同。例如 tmybutton.png 并将其保存在包源目录中。图像可以由任何图形程序(例如 gimp)创建,并且不应大于 24x24 像素。然后使用 lazres 工具将图像转换为资源文件,该工具可以在 lazarus/tools 目录中找到:
391+```
322392~/lazarus/tools/lazres mybutton.lrs tmybutton.png
323-# note: Laz trunk/1.4+? uses .res resource files instead of .lrs files:
324-~/lazarus/tools/lazres mybutton.res tmybutton.png
393+ # note: Laz trunk/1.4+? uses .res resource files instead of .lrs files:
394+ ~/lazarus/tools/lazres mybutton.res tmybutton.png
325395```
326396
327-这将创建一个 pascal include 文件,该文件在 mybutton.pas 的初始化部分中使用:
328-
329-``` pascal
397+这将创建一个 pascal include 文件,该文件在 mybutton.pas 的初始化部分中使用:
398+```
330399initialization
331- {$I mybutton.lrs}
332- // 或在较新的 Lazarus 版本中 - to docheck 语法
333- {$R mybutton.res}
400+ {$I mybutton.lrs}
401+ // 或在较新的 Lazarus 版本中 - to docheck 语法
402+ {$R mybutton.res}
334403```
335404
336-安装包。
405+安装包。
337406
338407### 隐藏组件面板中的组件
339408
340-Package IDEIntf, unit componentreg:
341-
342-``` pascal
343- IDEComponentPalette.FindComponent('TButton').Visible:=false;
409+Package IDEIntf, unit componentreg:
344410```
411+IDEComponentPalette.FindComponent('TButton').Visible:=false;
412+```
345413
346414## 编写组件编辑器
347415
348-组件编辑器处理诸如双击设计器中的组件或右键单击组件时添加菜单项之类的操作。编写组件编辑器很简单。有关大量示例,请参阅 IDEIntf 包的 componenteditors.pas 单元。例如,双击时显示编辑器,请参阅 TCheckListBoxComponentEditor。
416+组件编辑器处理诸如双击设计器中的组件或右键单击组件时添加菜单项之类的操作。编写组件编辑器很简单。有关大量示例,请参阅 IDEIntf 包的 componenteditors.pas 单元。例如,双击时显示编辑器,请参阅 TCheckListBoxComponentEditor。
349417
350418## 编写属性编辑器
351419
352-“属性查看器”中的每种属性(整数、字符串、TFont、...)都需要属性编辑器。如果组件具有字符串类型的属性 Password,则可以为特定组件类定义属性编辑器,并使用字符串类型的名为 Password 的属性。在 IDEIntf 的 propedits.pp 单元中包含 IDE 本身使用的许多标准属性编辑器。例如 TStringPropertyEditor 是所有字符串的默认属性编辑器,而 TComponentNamePropertyEditor 更有针对性,它只处理 TComponent.Name。请参阅示例中的单元文件。
420+“属性查看器”中的每种属性(整数、字符串、TFont、...)都需要属性编辑器。如果组件具有字符串类型的属性 Password,则可以为特定组件类定义属性编辑器,并使用字符串类型的名为 Password 的属性。在 IDEIntf 的 propedits.pp 单元中包含 IDE 本身使用的许多标准属性编辑器。例如 TStringPropertyEditor 是所有字符串的默认属性编辑器,而 TComponentNamePropertyEditor 更有针对性,它只处理 TComponent.Name。请参阅示例中的单元文件。
353421
354422### 在 Object Inspector 中隐藏属性
355423
356-有一个特殊的属性编辑器用于隐藏:
357-
358-``` pascal
359- RegisterPropertyEditor(TypeInfo(TAnchorSide), TControl, 'AnchorSideLeft', THiddenPropertyEditor);
424+有一个特殊的属性编辑器用于隐藏:
360425```
426+RegisterPropertyEditor(TypeInfo(TAnchorSide), TControl, 'AnchorSideLeft', THiddenPropertyEditor);
427+```
361428
362429### 找出属性使用的属性编辑器
363-
364-``` pascal
430+```
365431uses Classes, TypInfo;
366-var
367- Instance: TPersistent; // 你的实例
368- PropInfo: PPropInfo;
369- EdClass: TPropertyEditorClass;
370-begin
371- PropInfo:=GetPropInfo(Instance.ClassType,'Name'); // 将 Name 替换为您要搜索的属性名称
372- GetEditorClass(PropInfo, Instance);
373-end;
432+ var
433+ Instance: TPersistent; // 你的实例
434+ PropInfo: PPropInfo;
435+ EdClass: TPropertyEditorClass;
436+ begin
437+ PropInfo:=GetPropInfo(Instance.ClassType,'Name'); // 将 Name 替换为您要搜索的属性名称
438+ GetEditorClass(PropInfo, Instance);
439+ end;
374440```
375441
376442## 窗体
377443
378-IDE 允许轻松创建窗体和框架的后代。这些窗体可以包含新的 published 组件和新的 published 方法。但是,当您添加新的 published 属性时,无法通过“对象查看器”访问它们。它们仅在运行时工作。IDE 中的方法是伪造的,无法执行。IDE 可以创建组件,因为它们的类已在组件面板中注册。你的新属性仅存在于源代码中,IDE 还不能伪造它们。这就是你必须注册新类的原因。这意味着:
379-
380-- 创建设计时包(或扩展现有包)
381-- 您的窗体必须在此包的单元中
382-
383-``` pascal
384-...
385-interface
386-
387-uses FormEditingIntf, Forms;
388-
389-type
390- TYourForm = class(TForm)
391- private
392- FYourProperty: integer;
393- published
394- property YourProperty: integer read FYourProperty write FYourProperty;
395- end;
396-
397-procedure Register;
444+IDE 允许轻松创建窗体和框架的后代。这些窗体可以包含新的 published 组件和新的 published 方法。但是,当您添加新的 published 属性时,无法通过“对象查看器”访问它们。它们仅在运行时工作。IDE 中的方法是伪造的,无法执行。IDE 可以创建组件,因为它们的类已在组件面板中注册。你的新属性仅存在于源代码中,IDE 还不能伪造它们。这就是你必须注册新类的原因。这意味着:
398445
399-implementation
446+ * 创建设计时包(或扩展现有包)
447+ * 您的窗体必须在此包的单元中
400448
401-procedure Register;
402-begin
403- FormEditingHook.RegisterDesignerBaseClass(TYourForm);
404-end;
449+```
405450...
451+ interface
452+
453+ uses FormEditingIntf, Forms;
454+
455+ type
456+ TYourForm = class(TForm)
457+ private
458+ FYourProperty: integer;
459+ published
460+ property YourProperty: integer read FYourProperty write FYourProperty;
461+ end;
462+
463+ procedure Register;
464+
465+ implementation
466+
467+ procedure Register;
468+ begin
469+ FormEditingHook.RegisterDesignerBaseClass(TYourForm);
470+ end;
471+ ...
406472```
407473
408-- 检查包编辑器中本单元的“Register”。
409-- 在 IDE 中安装包
474+ * 检查包编辑器中本单元的“Register”。
475+ * 在 IDE 中安装包
410476
411477# 界面设计器(Designer)
412478
413479### 编写一个设计器中间层
414480
415-标准设计器允许可视化编辑 LCL 控件,而所有其它控件都显示为图标(如 TOpenDialog 或 TDataSource)。要可视地编辑非 LCL 控件,您需要创建一个 **设计器中间层**。这可用于设计网页,UML 图或其它小部件集,如 [[fpGUI]]。在 examples/designnonlcl/ 中有一个完整的例子。
481+标准设计器允许可视化编辑 LCL 控件,而所有其它控件都显示为图标(如 TOpenDialog 或 TDataSource)。要可视地编辑非 LCL 控件,您需要创建一个 **设计器中间层** 。这可用于设计网页,UML 图或其它小部件集,如 [[fpGUI]]。在 examples/designnonlcl/ 中有一个完整的例子。
416482
417-- 安装示例包 examples/designnonlcl/notlcldesigner.lpk 并重新启动 IDE。这将为 TMyWidget 组件注册设计器中间层,并将新组件 TMyButton,TMyGroupBox 添加到组件面板中。
418-- 打开示例项目 examples/designnonlcl/project/NonLCL1.lpi。
419-- 打开 unit1.pas 并切换到设计器界面(F12)。您应该看到组件为红色矩形,可以像 LCL 控件一样选择,移动和调整大小。
483+ * 安装示例包 examples/designnonlcl/notlcldesigner.lpk 并重新启动 IDE。这将为 TMyWidget 组件注册设计器中间层,并将新组件 TMyButton,TMyGroupBox 添加到组件面板中。
484+ * 打开示例项目 examples/designnonlcl/project/NonLCL1.lpi。
485+ * 打开 unit1.pas 并切换到设计器界面(F12)。您应该看到组件为红色矩形,可以像 LCL 控件一样选择,移动和调整大小。
420486
421487## 创建一个新的唯一组件名称
422-
423-``` pascal
488+```
424489uses FormEditingIntf;
425-
426-...
427-
428-NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
429-
430-// 或者如果您需要在创建组件之前创建名称:
431-
432-NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
433-// ComponentClassName 将用作前缀,没有前导 T.
434-// OwnerComponent 是新组件的新所有者。
490+
491+ ...
492+
493+ NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
494+
495+ // 或者如果您需要在创建组件之前创建名称:
496+
497+ NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
498+ // ComponentClassName 将用作前缀,没有前导 T.
499+ // OwnerComponent 是新组件的新所有者。
435500```
436501
437502## 在设计器 / 对象检查器中选择一个组件
438-
439-``` pascal
503+```
440504uses propedits;
441-..
442-GlobalDesignHook.SelectOnlyThis(AComponent);
505+ ..
506+ GlobalDesignHook.SelectOnlyThis(AComponent);
443507```
444508
445509## 获取单元,设计器,文件的形式
446-
447-``` pascal
510+```
448511uses ProjectIntf, LazIDEIntf, ComponentEditors;
449-...
450-// 打开文件
451-if LazarusIDE.DoOpenEditorFile(Filename,-1,-1,[ofAddToRecent])<>mrOk then exit;
452-// 获取文件界面
453-aFile:=LazarusIDE.ActiveProject.FindFile(Filename,[]);
454-// 获取设计器
455-aDesigner:=TComponentEditorDesigner(LazarusIDE.GetDesignerWithProjectFile(AFile,true));
456-if aDesigner=nil then
457- exit; // 这个单元没有资源(形式,框架,数据模块等)
458-// 获取表单
459-aForm:=aDesigner.Form;
512+ ...
513+ // 打开文件
514+ if LazarusIDE.DoOpenEditorFile(Filename,-1,-1,[ofAddToRecent])<>mrOk then exit;
515+ // 获取文件界面
516+ aFile:=LazarusIDE.ActiveProject.FindFile(Filename,[]);
517+ // 获取设计器
518+ aDesigner:=TComponentEditorDesigner(LazarusIDE.GetDesignerWithProjectFile(AFile,true));
519+ if aDesigner=nil then
520+ exit; // 这个单元没有资源(形式,框架,数据模块等)
521+ // 获取表单
522+ aForm:=aDesigner.Form;
460523```
461524
462525## 保存单元,设计器窗口
463-
464-``` pascal
526+```
465527uses LazIDEIntf;
466-...
467-if LazarusIDE.DoSaveEditorFile(Filename,[])<>mrOk then exit;
528+ ...
529+ if LazarusIDE.DoSaveEditorFile(Filename,[])<>mrOk then exit;
468530```
469531
470532## 将设计器窗口保存为 Pascal
471533
472-- 使用 *FormEditingfIntf* 单元的 **FormEditingHook.SaveComponentAsPascal** 函数。请参阅 *examples/pascalstream/CopyAsPasPkg/copyaspasdemounit1.pas*。
534+ * 使用 _FormEditingfIntf_ 单元的 **FormEditingHook.SaveComponentAsPascal** 函数。请参阅 _examples/pascalstream/CopyAsPasPkg/copyaspasdemounit1.pas_ 。
473535
474536# 事件处理程序
475537
476-IDE 中有几个事件,插件可以为其添加自己的处理程序。
538+IDE 中有几个事件,插件可以为其添加自己的处理程序。
477539
478540## 设计器活动
479541
480-在 propedits.pp 中有一个“GlobalDesignHook”对象,它维护了几个用于设计的事件。每个事件都会调用一个处理程序列表。IDE 添加了默认处理程序。您可以使用 AddHandlerXXX 和 RemoveHandlerXXX 方法添加自己的处理程序。它们将在默认处理程序之前调用。
542+在 propedits.pp 中有一个“GlobalDesignHook”对象,它维护了几个用于设计的事件。每个事件都会调用一个处理程序列表。IDE 添加了默认处理程序。您可以使用 AddHandlerXXX 和 RemoveHandlerXXX 方法添加自己的处理程序。它们将在默认处理程序之前调用。
481543
482-例子:
544+例子:
483545
484-- 添加处理程序(通常在对象的构造函数中完成):
546+ * 添加处理程序(通常在对象的构造函数中完成):
485547
486-` GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);`
548+```
549+GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);
550+```
487551
488-- 删除处理程序:
552+ * 删除处理程序:
489553
490-` GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);`
554+```
555+GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);
556+```
491557
492-- 您可以一次删除所有处理程序。例如,在对象的析构函数中添加此行是个好主意:
558+ * 您可以一次删除所有处理程序。例如,在对象的析构函数中添加此行是个好主意:
493559
494-` GlobalDesignHook.RemoveAllHandlersForObject(Self);`
560+```
561+GlobalDesignHook.RemoveAllHandlersForObject(Self);
562+```
495563
496-GlobalDesignHook 的处理程序:
564+GlobalDesignHook 的处理程序:
497565
498-- 查找根目录
499- - ChangeLookupRoot - 当“LookupRoot”发生变化时调用。“LookupRoot”是当前所选组件的所有者对象。通常这是一个 TForm。
566+ * 查找根目录
567+ * ChangeLookupRoot - 当“LookupRoot”发生变化时调用。“LookupRoot”是当前所选组件的所有者对象。通常这是一个 TForm。
500568
501-- 方法
502- - CreateMethod
503- - GetMethodName
504- - 的 getMethods
505- - MethodExists
506- - RenameMethod
507- - ShowMethod
508- - MethodFromAncestor
509- - ChainCall
569+ * 方法
570+ * CreateMethod
571+ * GetMethodName
572+ * 的 getMethods
573+ * MethodExists
574+ * RenameMethod
575+ * ShowMethod
576+ * MethodFromAncestor
577+ * ChainCall
510578
511-- 组件
512- - GetComponent
513- - GetComponentName
514- - GetComponentNames
515- - GetRootClassName
516- - AddClicked - 在用户选择组件类并单击设计器以添加新组件时调用。您可以更改组件类和父组件。
517- - ComponentRenamed - 在重命名组件时调用
579+ * 组件
580+ * GetComponent
581+ * GetComponentName
582+ * GetComponentNames
583+ * GetRootClassName
584+ * AddClicked - 在用户选择组件类并单击设计器以添加新组件时调用。您可以更改组件类和父组件。
585+ * ComponentRenamed - 在重命名组件时调用
518586
519-- TPersistent 对象
520- - PersistentAdded - 在将新的 TPersistent 添加到 LookupRoot 时调用
521- - PersistentDeleting - 在释放 TPersistent 之前调用。
522- - DeletePersistent - 由 IDE 调用以删除 TPersistent。
523- - GetSelectedPersistents - 获取当前 TPersistent 选择时调用。
524- - SetSelectedPersistents - 在设置 TPersistent 的当前选择时调用。
525- - GetObject
526- - GetObjectName
527- - GetObjectNames
587+ * TPersistent 对象
588+ * PersistentAdded - 在将新的 TPersistent 添加到 LookupRoot 时调用
589+ * PersistentDeleting - 在释放 TPersistent 之前调用。
590+ * DeletePersistent - 由 IDE 调用以删除 TPersistent。
591+ * GetSelectedPersistents - 获取当前 TPersistent 选择时调用。
592+ * SetSelectedPersistents - 在设置 TPersistent 的当前选择时调用。
593+ * GetObject
594+ * GetObjectName
595+ * GetObjectNames
528596
529-- 修改
530- - Modified
531- - Revert
532- - RefreshPropertyValues
597+ * 修改
598+ * Modified
599+ * Revert
600+ * RefreshPropertyValues
533601
534-- 选区
535- - SetSelection
536- - GetSelection
602+ * 选区
603+ * SetSelection
604+ * GetSelection
537605
538606### 设计器活动的例子
539607
540608#### 示例:当放置新组件时,将新组件移动到子组件中
541-
542-``` pascal
543-...
544-type
545- TYourDesignerExtension = class
546- private
547- function AddClicked(ADesigner: TIDesigner;
548- MouseDownComponent: TComponent; Button: TMouseButton;
549- Shift: TShiftState; X, Y: Integer;
550- var AComponentClass: TComponentClass;
551- var NewParent: TComponent): boolean of object;
552- public
553- constructor Create;
554- destructor Destroy; override;
555- end;
556-
609+```
557610...
558-constructor TYourDesignerExtension.Create;
559-begin
560- // 注册你的处理程序
561- GlobalDesignHook.AddHandlerAddClicked(@AddClicked);
562-end;
563-
564-destructor TYourDesignerExtension.Destroy;
565-begin
566- // 删除你的处理程序
567- GlobalDesignHook.RemoveHandlerAddClicked(@AddClicked);
568-end;
569-
570-function TYourDesignerExtension.AddClicked(ADesigner: TIDesigner;
571- MouseDownComponent: TComponent; Button: TMouseButton;
572- Shift: TShiftState; X, Y: Integer;
573- var AComponentClass: TComponentClass;
574- var NewParent: TComponent): boolean of object;
575-begin
576- // 在此示例中,TYourControl 是一个带有 ChildControl 的自定义控件。
577- // 每当用户删除 TYourControl 上的控件而不是将新控件添加到 TYourControl 时,新控件将被添加为 ChildControl 的子控件。
578- // 已创建
579- if MouseDownComponent is TYourControl then
580- NewParent:=TYourControl(MouseDownComponent).ChildControl;
581- Result:=true;
582-end;
611+ type
612+ TYourDesignerExtension = class
613+ private
614+ function AddClicked(ADesigner: TIDesigner;
615+ MouseDownComponent: TComponent; Button: TMouseButton;
616+ Shift: TShiftState; X, Y: Integer;
617+ var AComponentClass: TComponentClass;
618+ var NewParent: TComponent): boolean of object;
619+ public
620+ constructor Create;
621+ destructor Destroy; override;
622+ end;
623+
624+ ...
625+ constructor TYourDesignerExtension.Create;
626+ begin
627+ // 注册你的处理程序
628+ GlobalDesignHook.AddHandlerAddClicked(@AddClicked);
629+ end;
630+
631+ destructor TYourDesignerExtension.Destroy;
632+ begin
633+ // 删除你的处理程序
634+ GlobalDesignHook.RemoveHandlerAddClicked(@AddClicked);
635+ end;
636+
637+ function TYourDesignerExtension.AddClicked(ADesigner: TIDesigner;
638+ MouseDownComponent: TComponent; Button: TMouseButton;
639+ Shift: TShiftState; X, Y: Integer;
640+ var AComponentClass: TComponentClass;
641+ var NewParent: TComponent): boolean of object;
642+ begin
643+ // 在此示例中,TYourControl 是一个带有 ChildControl 的自定义控件。
644+ // 每当用户删除 TYourControl 上的控件而不是将新控件添加到 TYourControl 时,新控件将被添加为 ChildControl 的子控件。
645+ // 已创建
646+ if MouseDownComponent is TYourControl then
647+ NewParent:=TYourControl(MouseDownComponent).ChildControl;
648+ Result:=true;
649+ end;
583650```
584651
585652### 禁用设计器鼠标处理程序
586653
587-通常,设计人员会捕获组件的所有鼠标事件。如果您的自定义控件应该处理鼠标事件句柄,您可以设置 **csDesignInteractive** **控件样式**,也可以通过控件中的消息 CM_DESIGNHITTEST 对其进行精确控制:
588-
589-``` pascal
654+通常,设计人员会捕获组件的所有鼠标事件。如果您的自定义控件应该处理鼠标事件句柄,您可以设置 **csDesignInteractive** **控件样式** ,也可以通过控件中的消息 CM_DESIGNHITTEST 对其进行精确控制:
655+```
590656type
591- TYourControl = class(TCustomControl)
592- protected
593- procedure CMDesignHitTest(var Message: TLMessage); message CM_DESIGNHITTEST;
594- end;
595-...
596-procedure TYourControl.CMDesignHitTest(var Message: TLMessage);
597-var
598- p: TSmallPoint;
599- aShiftState: TShiftState;
600-begin
601- aShiftState:=KeysToShiftState(PtrUInt(Message.WParam));
602- p:=TSmallPoint(longint(Message.LParam));
603- debugln(['TForm1.CMDesignHitTest ShiftState=',dbgs(aShiftState),' x=',p.x,' y=',p.y]);
604- if SkipDesignerMouseHandler then
605- Message.Result:=1; // 现在设计器调用了正常的 MouseUp、MouseMove 和 MouseDown 方法。
606-end;
657+ TYourControl = class(TCustomControl)
658+ protected
659+ procedure CMDesignHitTest(var Message: TLMessage); message CM_DESIGNHITTEST;
660+ end;
661+ ...
662+ procedure TYourControl.CMDesignHitTest(var Message: TLMessage);
663+ var
664+ p: TSmallPoint;
665+ aShiftState: TShiftState;
666+ begin
667+ aShiftState:=KeysToShiftState(PtrUInt(Message.WParam));
668+ p:=TSmallPoint(longint(Message.LParam));
669+ debugln(['TForm1.CMDesignHitTest ShiftState=',dbgs(aShiftState),' x=',p.x,' y=',p.y]);
670+ if SkipDesignerMouseHandler then
671+ Message.Result:=1; // 现在设计器调用了正常的 MouseUp、MouseMove 和 MouseDown 方法。
672+ end;
607673```
608674
609675## 在修改设计器窗体时收到通知
610676
611-每个设计的 LCL 表格都有一个 TIDesigner 类型的设计器。IDE 将创建在 IDEIntf 单元组件中定义的 TComponentEditorDesigner 类型的设计器。例如:
612-
613-``` pascal
677+每个设计的 LCL 表格都有一个 TIDesigner 类型的设计器。IDE 将创建在 IDEIntf 单元组件中定义的 TComponentEditorDesigner 类型的设计器。例如:
678+```
614679procedure TYourAddOn.OnDesignerModified(Sender: TObject);
615-var
616- IDEDesigner: TComponentEditorDesigner;
617-begin
618- IDEDesigner:=TComponentEditorDesigner(Sender);
619- ...
620-end;
621-
622-procedure TYourAddOn.ConnectDesignerForm(Form1: TCustomForm);
623-var
624- IDEDesigner: TComponentEditorDesigner;
625-begin
626- IDEDesigner:=TComponentEditorDesigner(Form1.Designer);
627- IDEDesigner.AddHandlerModified(@OnDesignerModified);
628-end;
680+ var
681+ IDEDesigner: TComponentEditorDesigner;
682+ begin
683+ IDEDesigner:=TComponentEditorDesigner(Sender);
684+ ...
685+ end;
686+
687+ procedure TYourAddOn.ConnectDesignerForm(Form1: TCustomForm);
688+ var
689+ IDEDesigner: TComponentEditorDesigner;
690+ begin
691+ IDEDesigner:=TComponentEditorDesigner(Form1.Designer);
692+ IDEDesigner.AddHandlerModified(@OnDesignerModified);
693+ end;
629694```
630695
631696## 项目事件
632697
633-这些事件在单元 LazIDEIntf 中定义。
698+这些事件在单元 LazIDEIntf 中定义。
634699
635-- LazarusIDE.AddHandlerOnProjectClose:在项目关闭之前调用
636-- LazarusIDE.AddHandlerOnProjectOpened:在项目完全打开后调用(例如,加载了所有必需的包,在源代码编辑器中打开了单元)
637-- LazarusIDE.AddHandlerOnSavingAll:在 IDE 保存所有内容之前调用
638-- LazarusIDE.AddHandlerOnSavedAll:在 IDE 保存所有内容后调用
639-- LazarusIDE.AddHandlerOnProjectBuilding:在 IDE 构建项目之前调用
640-- LazarusIDE.AddHandlerOnProjectDependenciesCompiling:在 IDE 编译项目的包依赖项之前调用
641-- LazarusIDE.AddHandlerOnProjectDependenciesCompiled:在 IDE 编译包项目依赖项后调用
642-- LazarusIDE.AddHandlerOnProjectBuildingFinished:在 IDE 构建项目后调用(成功与否)(自 1.5 起)
700+ * LazarusIDE.AddHandlerOnProjectClose:在项目关闭之前调用
701+ * LazarusIDE.AddHandlerOnProjectOpened:在项目完全打开后调用(例如,加载了所有必需的包,在源代码编辑器中打开了单元)
702+ * LazarusIDE.AddHandlerOnSavingAll:在 IDE 保存所有内容之前调用
703+ * LazarusIDE.AddHandlerOnSavedAll:在 IDE 保存所有内容后调用
704+ * LazarusIDE.AddHandlerOnProjectBuilding:在 IDE 构建项目之前调用
705+ * LazarusIDE.AddHandlerOnProjectDependenciesCompiling:在 IDE 编译项目的包依赖项之前调用
706+ * LazarusIDE.AddHandlerOnProjectDependenciesCompiled:在 IDE 编译包项目依赖项后调用
707+ * LazarusIDE.AddHandlerOnProjectBuildingFinished:在 IDE 构建项目后调用(成功与否)(自 1.5 起)
643708
644709## 其他 IDE 事件
645710
646-uses LazIDEIntf;
711+uses LazIDEIntf;
647712
648-在包的注册过程中调用这些:
713+在包的注册过程中调用这些:
649714
650-- LazarusIDE.AddHandlerOnIDERestoreWindows:在 IDE 恢复其窗口时调用(在打开第一个项目之前)
651-- LazarusIDE.AddHandlerOnIDEClose:在 IDE 关闭时调用(在 closequery 之后调用,因此不再进行交互)
652-- LazarusIDE.AddHandlerOnQuickSyntaxCheck:执行菜单项或快速语法检查的快捷方式时调用
653-- LazarusIDE.AddHandlerOnLazarusBuilding:// 在 IDE 构建 Lazarus IDE 之前调用(从 1.5 开始)
654-- LazarusIDE.AddHandlerOnLazarusBuildingFinished:// 在 IDE 构建 Lazarus IDE 后调用(自 1.5 起)
655-- LazarusIDE.AddHandlerGetFPCFrontEndParams:// 当 IDE 获取 'fpc' 前端工具的参数时调用(自 1.5 起)
656-- LazarusIDE.AddHandlerGetFPCFrontEndPath:// 当 IDE 获取 'fpc' 前端工具的路径时调用(从 1.5 开始)
657-- LazarusIDE.AddHandlerOnUpdateIDEComponentPalette:?
658-- LazarusIDE.AddHandlerOnUpdateComponentPageControl :?
659-- LazarusIDE.AddHandlerOnShowDesignerFormOfSource:// 在显示代码编辑器的设计器表单后调用(AEditor 可以是 nil!)(自 1.5 起)
660-- LazarusIDE.AddHandlerOnShowSourceOfActiveDesignerForm:// 显示设计器表单代码后调用(自 1.5 起)
661-- LazarusIDE.AddHandlerOnChangeToolStatus:// 在 IDEToolStatus 发生变化时调用(例如 itNone-\> itBuilder 等)(自 1.5 起)
715+ * LazarusIDE.AddHandlerOnIDERestoreWindows:在 IDE 恢复其窗口时调用(在打开第一个项目之前)
716+ * LazarusIDE.AddHandlerOnIDEClose:在 IDE 关闭时调用(在 closequery 之后调用,因此不再进行交互)
717+ * LazarusIDE.AddHandlerOnQuickSyntaxCheck:执行菜单项或快速语法检查的快捷方式时调用
718+ * LazarusIDE.AddHandlerOnLazarusBuilding:// 在 IDE 构建 Lazarus IDE 之前调用(从 1.5 开始)
719+ * LazarusIDE.AddHandlerOnLazarusBuildingFinished:// 在 IDE 构建 Lazarus IDE 后调用(自 1.5 起)
720+ * LazarusIDE.AddHandlerGetFPCFrontEndParams:// 当 IDE 获取 'fpc' 前端工具的参数时调用(自 1.5 起)
721+ * LazarusIDE.AddHandlerGetFPCFrontEndPath:// 当 IDE 获取 'fpc' 前端工具的路径时调用(从 1.5 开始)
722+ * LazarusIDE.AddHandlerOnUpdateIDEComponentPalette:?
723+ * LazarusIDE.AddHandlerOnUpdateComponentPageControl :?
724+ * LazarusIDE.AddHandlerOnShowDesignerFormOfSource:// 在显示代码编辑器的设计器表单后调用(AEditor 可以是 nil!)(自 1.5 起)
725+ * LazarusIDE.AddHandlerOnShowSourceOfActiveDesignerForm:// 显示设计器表单代码后调用(自 1.5 起)
726+ * LazarusIDE.AddHandlerOnChangeToolStatus:// 在 IDEToolStatus 发生变化时调用(例如 itNone-> itBuilder 等)(自 1.5 起)
662727
663-在您的某个单元的初始化部分中调用它们:
728+在您的某个单元的初始化部分中调用它们:
664729
665-- AddBootHandler
666-- AddBootHandler(libhTransferMacrosCreated, @YourProc):创建 IDEMacros 后调用(自 1.3 起)
667-- AddBootHandler(libhEnvironmentOptionsLoaded, @YourProc):加载环境选项后调用(自 1.3 起)
730+ * AddBootHandler
731+ * AddBootHandler(libhTransferMacrosCreated, @YourProc):创建 IDEMacros 后调用(自 1.3 起)
732+ * AddBootHandler(libhEnvironmentOptionsLoaded, @YourProc):加载环境选项后调用(自 1.3 起)
668733
669734# 项目
670735
671736## 当前的项目
672737
673-目前的主要项目可以通过 LazarusIDE.ActiveProject 获得。(单元 LazIDEIntf)
738+目前的主要项目可以通过 LazarusIDE.ActiveProject 获得。(单元 LazIDEIntf)
674739
675740## 当前项目的所有单元
676741
677-请注意,术语“项目单元”是不明确的。
742+请注意,术语“项目单元”是不明确的。
678743
679-- 项目检查器显示 .lpi 文件的列表。该项目可能不会在所有平台上使用所有这些单元,也许开发人员忘记添加所有使用过的单元。
680-- 使用过的包中的单元不是项目单元。
744+ * 项目检查器显示 .lpi 文件的列表。该项目可能不会在所有平台上使用所有这些单元,也许开发人员忘记添加所有使用过的单元。
745+ * 使用过的包中的单元不是项目单元。
681746
682747### 项目检查员的所有单元
683748
684-要遍历项目检查器中列出的所有 pascal 单元,您可以使用例如:
685-
686-``` pascal
749+要遍历项目检查器中列出的所有 pascal 单元,您可以使用例如:
750+```
687751uses
688- LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
689-
690-procedure ListProjectUnits;
691-var
692- LazProject: TLazProject;
693- i: Integer;
694- LazFile: TLazProjectFile;
695-begin
696- LazProject:=LazarusIDE.ActiveProject;
697- if LazProject<>nil then
698- for i:=0 to LazProject.FileCount-1 do
752+ LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
753+
754+ procedure ListProjectUnits;
755+ var
756+ LazProject: TLazProject;
757+ i: Integer;
758+ LazFile: TLazProjectFile;
699759 begin
700- LazFile:=LazProject.Files[i];
701- if LazFile.IsPartOfProject
702- and FilenameIsPascalUnit(LazFile.Filename)
703- then
704- debugln(LazFile.Filename);
760+ LazProject:=LazarusIDE.ActiveProject;
761+ if LazProject<>nil then
762+ for i:=0 to LazProject.FileCount-1 do
763+ begin
764+ LazFile:=LazProject.Files[i];
765+ if LazFile.IsPartOfProject
766+ and FilenameIsPascalUnit(LazFile.Filename)
767+ then
768+ debugln(LazFile.Filename);
769+ end;
705770 end;
706-end;
707771```
708772
709773### 所有用过的项目单元
710774
711-要查找项目 / 包的所有当前使用单元,您可以使用以下内容。请注意,IDE 需要解析所有单元,因此可能需要一些时间。
712-
713-``` pascal
775+要查找项目 / 包的所有当前使用单元,您可以使用以下内容。请注意,IDE 需要解析所有单元,因此可能需要一些时间。
776+```
714777uses
715- LazLoggerBase, LazIDEIntf, ProjectIntf;
716-
717-procedure ListProjectUnits;
718-var
719- LazProject: TLazProject;
720- i: Integer;
721-begin
722- LazProject:=LazarusIDE.ActiveProject;
723- if LazProject<>nil then
724- begin
725- Units:=LazarusIDE.FindUnitsOfOwner(LazProject,[fuooListed,fuooUsed]); // 添加 fuooPackages 以包含包中的单位
726- try
727- for i:=0 to Units.Count-1 do
728- debugln('Filename=',Units[i]);
729- finally
730- Units.Free;
778+ LazLoggerBase, LazIDEIntf, ProjectIntf;
779+
780+ procedure ListProjectUnits;
781+ var
782+ LazProject: TLazProject;
783+ i: Integer;
784+ begin
785+ LazProject:=LazarusIDE.ActiveProject;
786+ if LazProject<>nil then
787+ begin
788+ Units:=LazarusIDE.FindUnitsOfOwner(LazProject,[fuooListed,fuooUsed]); // 添加 fuooPackages 以包含包中的单位
789+ try
790+ for i:=0 to Units.Count-1 do
791+ debugln('Filename=',Units[i]);
792+ finally
793+ Units.Free;
794+ end;
795+ end;
731796 end;
732- end;
733-end;
734797```
735798
736799## 项目的 .lpr、.lpi 和 .lps 文件
737-
738-``` pascal
800+```
739801uses
740- LCLProc, FileUtil, ProjectIntf, LazIDEIntf;
741-var
742- LazProject: TLazProject;
743-begin
744- LazProject:=LazarusIDE.ActiveProject;
745- // 每个项目都有一个 .lpi 文件:
746- DebugLn(['Project'' lpi file: ',LazProject.ProjectInfoFile]);
747-
748- // 如果项目会话信息存储在单独的 .lps 文件中:
749- if LazProject.SessionStorage<>pssNone then
750- DebugLn(['Project'' lps file: ',LazProject.ProjectSessionFile]);
751-
752- // 如果项目有 .lpr 文件,那么它是主要的源文件:
753- if (LazProject.MainFile<>nil)
754- and (CompareFileExt(LazProject.MainFile.Filename,'lpr')=0) then
755- DebugLn(['Project has lpr file: ',LazProject.MainFile.Filename]);
756-end;
802+ LCLProc, FileUtil, ProjectIntf, LazIDEIntf;
803+ var
804+ LazProject: TLazProject;
805+ begin
806+ LazProject:=LazarusIDE.ActiveProject;
807+ // 每个项目都有一个 .lpi 文件:
808+ DebugLn(['Project'' lpi file: ',LazProject.ProjectInfoFile]);
809+
810+ // 如果项目会话信息存储在单独的 .lps 文件中:
811+ if LazProject.SessionStorage<>pssNone then
812+ DebugLn(['Project'' lps file: ',LazProject.ProjectSessionFile]);
813+
814+ // 如果项目有 .lpr 文件,那么它是主要的源文件:
815+ if (LazProject.MainFile<>nil)
816+ and (CompareFileExt(LazProject.MainFile.Filename,'lpr')=0) then
817+ DebugLn(['Project has lpr file: ',LazProject.MainFile.Filename]);
818+ end;
757819```
758820
759821## 项目的可执行文件 / 目标文件名
760822
761-有一个宏 \$(TargetFile),可用于路径和外部工具。您可以在代码中查询宏:
762-
763-``` pascal
823+有一个宏 $(TargetFile),可用于路径和外部工具。您可以在代码中查询宏:
824+```
764825uses MacroIntf;
765-
766-function MyGetProjectTargetFile: string;
767-begin
768- Result:='$(TargetFile)';
769- if not IDEMacros.SubstituteMacros(Result) then
770- raise Exception.Create('unable to retrieve target file of project');
771-end;
826+
827+ function MyGetProjectTargetFile: string;
828+ begin
829+ Result:='$(TargetFile)';
830+ if not IDEMacros.SubstituteMacros(Result) then
831+ raise Exception.Create('unable to retrieve target file of project');
832+ end;
772833```
773834
774-有关更多宏的信息,请参阅此处:[[IDE Macros in paths and filenames]]。
835+有关更多宏的信息,请参阅此处:[[IDE Macros in paths and filenames]]。
775836
776837## 添加您自己的项目类型
777838
778-您可以在“新建 ...”对话框中添加项目:
839+您可以在“新建 ...”对话框中添加项目:
779840
780-- 请参阅 IDEIntf 包的单元 ProjectIntf。
781-- 请参阅项目模板
841+ * 请参阅 IDEIntf 包的单元 ProjectIntf。
842+ * 请参阅项目模板
782843
783844## 添加您自己的文件类型
784845
785-您可以在“新建 ...”对话框中添加项目:
846+您可以在“新建 ...”对话框中添加项目:
786847
787-- 请参阅 IDEIntf 包的单元 ProjectIntf。
788-- 为普通单元选择基类 TFileDescPascalUnit,为新表单 / 数据模块选择 TFileDescPascalUnitWithResource。
848+ * 请参阅 IDEIntf 包的单元 ProjectIntf。
849+ * 为普通单元选择基类 TFileDescPascalUnit,为新表单 / 数据模块选择 TFileDescPascalUnitWithResource。
789850
790851## 添加新文件类型
791-
792-``` pascal
852+```
793853uses ProjectIntf;
794-...
795- { TFileDescText }
796-
797- TFileDescMyText = class(TProjectFileDescriptor)
798- public
799- constructor Create; override;
800- function GetLocalizedName: string; override;
801- function GetLocalizedDescription: string; override;
802- end;
803-...
804-
805-procedure Register;
806-
807-implementation
808-
809-procedure Register;
810-begin
811- RegisterProjectFileDescriptor(TFileDescMyText.Create,FileDescGroupName);
812-end;
813-
814-{ TFileDescMyText }
815-
816-constructor TFileDescMyText.Create;
817-begin
818- inherited Create;
819- Name:='MyText'; // 不要翻译这个
820- DefaultFilename:='text.txt';
821- AddToProject:=false;
822-end;
823-
824-function TFileDescText.GetLocalizedName: string;
825-begin
826- Result:='My Text'; // 用 resourcestring 替换它
827-end;
828-
829-function TFileDescText.GetLocalizedDescription: string;
830-begin
831- Result:='An empty text file';
832-end;
854+ ...
855+ { TFileDescText }
856+
857+ TFileDescMyText = class(TProjectFileDescriptor)
858+ public
859+ constructor Create; override;
860+ function GetLocalizedName: string; override;
861+ function GetLocalizedDescription: string; override;
862+ end;
863+ ...
864+
865+ procedure Register;
866+
867+ implementation
868+
869+ procedure Register;
870+ begin
871+ RegisterProjectFileDescriptor(TFileDescMyText.Create,FileDescGroupName);
872+ end;
873+
874+ { TFileDescMyText }
875+
876+ constructor TFileDescMyText.Create;
877+ begin
878+ inherited Create;
879+ Name:='MyText'; // 不要翻译这个
880+ DefaultFilename:='text.txt';
881+ AddToProject:=false;
882+ end;
883+
884+ function TFileDescText.GetLocalizedName: string;
885+ begin
886+ Result:='My Text'; // 用 resourcestring 替换它
887+ end;
888+
889+ function TFileDescText.GetLocalizedDescription: string;
890+ begin
891+ Result:='An empty text file';
892+ end;
833893```
834894
835895### 添加新表单类型
836-
837-``` pascal
896+```
838897uses ProjectIntf;
839-
840-...
841- TFileDescPascalUnitWithMyForm = class(TFileDescPascalUnitWithResource)
842- public
843- constructor Create; override;
844- function GetInterfaceUsesSection: string; override;
845- function GetLocalizedName: string; override;
846- function GetLocalizedDescription: string; override;
847- end;
848-...
849-
850-procedure Register;
851-
852-implementation
853-
854-procedure Register;
855-begin
856- RegisterProjectFileDescriptor(TFileDescPascalUnitWithMyForm.Create,FileDescGroupName);
857-end;
858-
859-{ TFileDescPascalUnitWithMyForm }
860-
861-constructor TFileDescPascalUnitWithMyForm.Create;
862-begin
863- inherited Create;
864- Name:='MyForm'; // 不要翻译这个
865- ResourceClass:=TMyForm;
866- UseCreateFormStatements:=true;
867-end;
868-
869-function TFileDescPascalUnitWithMyForm.GetInterfaceUsesSection: string;
870-begin
871- Result:='Classes, SysUtils, MyWidgetSet';
872-end;
873-
874-function TFileDescPascalUnitWithForm.GetLocalizedName: string;
875-begin
876- Result:='MyForm'; // 用 resourcestring 替换它
877-end;
878-
879-function TFileDescPascalUnitWithForm.GetLocalizedDescription: string;
880-begin
881- Result:='Create a new MyForm from example package NotLCLDesigner';
882-end;
898+
899+ ...
900+ TFileDescPascalUnitWithMyForm = class(TFileDescPascalUnitWithResource)
901+ public
902+ constructor Create; override;
903+ function GetInterfaceUsesSection: string; override;
904+ function GetLocalizedName: string; override;
905+ function GetLocalizedDescription: string; override;
906+ end;
907+ ...
908+
909+ procedure Register;
910+
911+ implementation
912+
913+ procedure Register;
914+ begin
915+ RegisterProjectFileDescriptor(TFileDescPascalUnitWithMyForm.Create,FileDescGroupName);
916+ end;
917+
918+ { TFileDescPascalUnitWithMyForm }
919+
920+ constructor TFileDescPascalUnitWithMyForm.Create;
921+ begin
922+ inherited Create;
923+ Name:='MyForm'; // 不要翻译这个
924+ ResourceClass:=TMyForm;
925+ UseCreateFormStatements:=true;
926+ end;
927+
928+ function TFileDescPascalUnitWithMyForm.GetInterfaceUsesSection: string;
929+ begin
930+ Result:='Classes, SysUtils, MyWidgetSet';
931+ end;
932+
933+ function TFileDescPascalUnitWithForm.GetLocalizedName: string;
934+ begin
935+ Result:='MyForm'; // 用 resourcestring 替换它
936+ end;
937+
938+ function TFileDescPascalUnitWithForm.GetLocalizedDescription: string;
939+ begin
940+ Result:='Create a new MyForm from example package NotLCLDesigner';
941+ end;
883942```
884943
885944## 以 lpi/lps 存储自定义值
886945
887-您可以通过 CustomData 和 CustomSessionData 中的键值对存储您自己的数据。
888-
889-` LazarusIDE.ActiveProject.CustomData['Name'] := Value ; // 存储在 lpi-x-platform 中,共享数据`\
890-` LazarusIDE.ActiveProject.CustomSessionData['Name'] := Value ; // 存储在 lps 中 - 只有本机`
946+您可以通过 CustomData 和 CustomSessionData 中的键值对存储您自己的数据。
947+```
948+LazarusIDE.ActiveProject.CustomData['Name'] := Value ; // 存储在 lpi-x-platform 中,共享数据
949+ LazarusIDE.ActiveProject.CustomSessionData['Name'] := Value ; // 存储在 lps 中 - 只有本机
950+```
891951
892952# 包
893953
894-您可以使用 Packages 执行各种操作:
954+您可以使用 Packages 执行各种操作:
895955
896956## 搜索所有包
897957
898-迭代 IDE 中加载的所有包(自 0.9.29 起)。
899-
900-``` pascal
958+迭代 IDE 中加载的所有包(自 0.9.29 起)。
959+```
901960uses PackageIntf;
902-...
903-for i:=0 to PackageEditingInterface.GetPackageCount-1 do
904- writeln(PackageEditingInterface.GetPackages(i).Name);
961+ ...
962+ for i:=0 to PackageEditingInterface.GetPackageCount-1 do
963+ writeln(PackageEditingInterface.GetPackages(i).Name);
905964```
906965
907966## 搜索包含名称的包
908-
909-``` pascal
967+```
910968uses PackageIntf;
911-...
912-var
913- Pkg: TIDEPackage;
914-begin
915- Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
916- if Pkg<>nil then
917969 ...
918-end;
970+ var
971+ Pkg: TIDEPackage;
972+ begin
973+ Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
974+ if Pkg<>nil then
975+ ...
976+ end;
919977```
920978
921-注意:FindPackageWithName 不会打开包编辑器。为此使用 DoOpenPackageWithName。
979+注意:FindPackageWithName 不会打开包编辑器。为此使用 DoOpenPackageWithName。
922980
923981## 获取已安装软件包的 lpk 文件名
924-
925-``` pascal
982+```
926983uses PackageIntf;
927-...
928-var
929- Pkg: TIDEPackage;
930-begin
931- Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
932- if Pkg<>nil then
933- LPKFilename:=Pkg.Filename;
934-end;
984+ ...
985+ var
986+ Pkg: TIDEPackage;
987+ begin
988+ Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
989+ if Pkg<>nil then
990+ LPKFilename:=Pkg.Filename;
991+ end;
935992```
936993
937994## 安装包
938995
939-注意:仅安装带有 IDE 插件的软件包。安装其他软件包可能会使 IDE 不稳定。
940-
941-``` pascal
996+注意:仅安装带有 IDE 插件的软件包。安装其他软件包可能会使 IDE 不稳定。
997+```
942998uses PackageIntf, contnrs;
943-...
944- PkgList:=TObjectList.create(true);
945- try
946- Pkg:=TLazPackageID.Create;
947- Pkg.Name:='Cody';
948- PkgList.Add(Pkg);
949- // 检查 IDE 是否可以找到 cody.lpk 和所有依赖项
950- // 如果看起来很奇怪,IDE 会提示一些警告 / 确认。
951- if not PackageEditingInterface.CheckInstallPackageList(PkgList,[]) then
952- exit;
953- // 在这个例子中我们已经检查过,所以跳过警告并重建 IDE
954- if PackageEditingInterface.InstallPackages(PkgList,[piiifSkipChecks,piiifRebuildIDE])<>mrOK then
955- exit;
956- finally
957- PkgList.Free;
958- end;
999+ ...
1000+ PkgList:=TObjectList.create(true);
1001+ try
1002+ Pkg:=TLazPackageID.Create;
1003+ Pkg.Name:='Cody';
1004+ PkgList.Add(Pkg);
1005+ // 检查 IDE 是否可以找到 cody.lpk 和所有依赖项
1006+ // 如果看起来很奇怪,IDE 会提示一些警告 / 确认。
1007+ if not PackageEditingInterface.CheckInstallPackageList(PkgList,[]) then
1008+ exit;
1009+ // 在这个例子中我们已经检查过,所以跳过警告并重建 IDE
1010+ if PackageEditingInterface.InstallPackages(PkgList,[piiifSkipChecks,piiifRebuildIDE])<>mrOK then
1011+ exit;
1012+ finally
1013+ PkgList.Free;
1014+ end;
9591015```
9601016
9611017## 打开包文件(lpk)
962-
963-``` pascal
1018+```
9641019uses PackageIntf, FileUtil;
965-...
966-var
967- pkg: TIDEPackage;
968-begin
969- if PackageEditingInterface.DoOpenPackageFile(LPKFilename,[pofAddToRecent],false)<>mrOk then
970- exit;
971- Pkg:=PackageEditingInterface.FindPackageWithName(ExtractFilenameOnly(LPKFilename));
972- ...
973-end;
1020+ ...
1021+ var
1022+ pkg: TIDEPackage;
1023+ begin
1024+ if PackageEditingInterface.DoOpenPackageFile(LPKFilename,[pofAddToRecent],false)<>mrOk then
1025+ exit;
1026+ Pkg:=PackageEditingInterface.FindPackageWithName(ExtractFilenameOnly(LPKFilename));
1027+ ...
1028+ end;
9741029```
9751030
976-> **Warning:** IDE 会在空闲时自动关闭未使用的软件包。永远不要引用 TIDEPackage。
1031+[![Warning-icon.png](/wiki-images/b/b2/Warning-icon.png)](</File:Warning-icon.png>)
9771032
978-## 找到一个单元的包裹
1033+**Warning:** IDE 会在空闲时自动关闭未使用的软件包。永远不要引用 TIDEPackage。
9791034
980-你有一个单元的文件名,例如 '/home/user/unit.pas',你想知道它属于哪个包和项目使用这个:
1035+## 找到一个单元的包裹
9811036
982-``` pascal
1037+你有一个单元的文件名,例如 '/home/user/unit.pas',你想知道它属于哪个包和项目使用这个:
1038+```
9831039uses Classes, PackageIntf, ProjectIntf;
984-...
985-var
986- Owners: TFPList;
987- i: Integer;
988- o: TObject;
989-begin
990- Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',[]);
991- if Owners=nil then begin
992- // 单元与项目 / 包没有直接关联
993- // 也许单元出于某种原因没有添加,但可以访问
994- // 搜索所有项目 / 包的所有单元路径
995- // 注意:这会导致错误命中
996- Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',
997- [piosfExcludeOwned,piosfIncludeSourceDirectories]);
998- end;
999- if Owners=nil then exit;
1000- try
1001- for i:=0 to Owners.Count-1 do begin
1002- o:=TObject(Owners[i]);
1003- if o is TIDEPackage then begin
1004- writeln('Owner is package ',TIDEPackage(o).Name);
1005- end else if o is TLazProject then begin
1006- writeln('Owner is project ',TLazProject(o).ProjectInfoFile);
1040+ ...
1041+ var
1042+ Owners: TFPList;
1043+ i: Integer;
1044+ o: TObject;
1045+ begin
1046+ Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',[]);
1047+ if Owners=nil then begin
1048+ // 单元与项目 / 包没有直接关联
1049+ // 也许单元出于某种原因没有添加,但可以访问
1050+ // 搜索所有项目 / 包的所有单元路径
1051+ // 注意:这会导致错误命中
1052+ Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',
1053+ [piosfExcludeOwned,piosfIncludeSourceDirectories]);
10071054 end;
1008- end;
1009- finally
1010- Owners.Free;
1011- end;
1055+ if Owners=nil then exit;
1056+ try
1057+ for i:=0 to Owners.Count-1 do begin
1058+ o:=TObject(Owners[i]);
1059+ if o is TIDEPackage then begin
1060+ writeln('Owner is package ',TIDEPackage(o).Name);
1061+ end else if o is TLazProject then begin
1062+ writeln('Owner is project ',TLazProject(o).ProjectInfoFile);
1063+ end;
1064+ end;
1065+ finally
1066+ Owners.Free;
1067+ end;
10121068```
10131069
10141070## 查找项目 / 包所需的包
10151071
1016-您有一个项目或包,并且您想知道需要哪个包,使用:
1017-
1018-``` pascal
1072+您有一个项目或包,并且您想知道需要哪个包,使用:
1073+```
10191074uses Classes, PackageIntf, ProjectIntf;
1020-...
1021-var
1022- lPkgList: TFPList;
1023- i: Integer;
1024-begin
1025- PackageEditingInterface.GetRequiredPackages(LazarusIDE.ActiveProject, lPkgList, [pirNotRecursive]);
1026- try
1027- for i := 0 to lPkgList.Count - 1 do begin
1028- writeln('required package is ' + TIDEPackage(lPkgList[i]).Filename);
1029- end;
1030- finally
1031- lPkgList.Free;
1032- end;
1033-...
1075+ ...
1076+ var
1077+ lPkgList: TFPList;
1078+ i: Integer;
1079+ begin
1080+ PackageEditingInterface.GetRequiredPackages(LazarusIDE.ActiveProject, lPkgList, [pirNotRecursive]);
1081+ try
1082+ for i := 0 to lPkgList.Count - 1 do begin
1083+ writeln('required package is ' + TIDEPackage(lPkgList[i]).Filename);
1084+ end;
1085+ finally
1086+ lPkgList.Free;
1087+ end;
1088+ ...
10341089```
10351090
10361091# 窗口(Windows)
10371092
1038-基本上有四种类型的 IDE 窗口。
1093+基本上有四种类型的 IDE 窗口。
10391094
1040-- 主 IDE 栏是 Application.MainForm。它始终存在。
1041-- 浮动 / 可停靠窗口,如源代码编辑器,对象检查器和消息。
1042-- 模态表单,如查找对话框,选项对话框和问题。
1043-- 提示和完成表格
1095+ * 主 IDE 栏是 Application.MainForm。它始终存在。
1096+ * 浮动 / 可停靠窗口,如源代码编辑器,对象检查器和消息。
1097+ * 模态表单,如查找对话框,选项对话框和问题。
1098+ * 提示和完成表格
10441099
10451100## 添加新的可停靠 IDE 窗口
10461101
1047-什么是可停靠的 IDE 窗口:像源代码编辑器或对象检查器这样的 Windows 是浮动窗口,如果安装了扩展包,则可以停靠它,并在下次 IDE 启动时存储和恢复其状态,位置和大小。为了恢复窗口,IDE 需要在 IDEIntf 包的单元 IDEWindowIntf 中定义的创建者。每个可停靠窗口必须具有唯一名称。不要使用像 'FileBrowser' 这样的通用名称,因为这很容易与其他包冲突。并且不要使用像“XYZ”这样的短名称,因为创建者负责以此名称开头的所有表单。
1102+什么是可停靠的 IDE 窗口:像源代码编辑器或对象检查器这样的 Windows 是浮动窗口,如果安装了扩展包,则可以停靠它,并在下次 IDE 启动时存储和恢复其状态,位置和大小。为了恢复窗口,IDE 需要在 IDEIntf 包的单元 IDEWindowIntf 中定义的创建者。每个可停靠窗口必须具有唯一名称。不要使用像 'FileBrowser' 这样的通用名称,因为这很容易与其他包冲突。并且不要使用像“XYZ”这样的短名称,因为创建者负责以此名称开头的所有表单。
10481103
10491104### 如何注册可停靠的 IDE 窗口
10501105
1051-请记住选择一个有效的 pascal 标识符的长唯一名称。您的窗口可以包含您想要的任何标题。
1052-
1053-``` pascal
1106+请记住选择一个有效的 pascal 标识符的长唯一名称。您的窗口可以包含您想要的任何标题。
1107+```
10541108uses SysUtils, IDEWindowIntf;
1055-...
1056-var MyIDEWindow: TMyIDEWindow = nil;
1057-
1058-procedure CreateMyIDEWindow(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean);
1059-begin
1060- // 检查名称
1061- if CompareText(aFormName,MyIDEWindowName)<>0 then exit;
1062- // 如果尚未创建表单并禁用自动调整大小
1063- IDEWindowCreators.CreateForm(MyIDEWindow,TMyIDEWindowm,DoDisableAutosizing,Application);
1064- ... init the window ...
1065- AForm:=MyIDEWindow;
1066-end;
1067-
1068-procedure Register;
1069-begin
1070- IDEWindowCreators.Add('MyIDEWindow',@CreateMyIDEWindow,nil,'100','50%','+300','+20%');
1071- // 表单的默认边界是:
1072- // Left=100, Top=Screen.Height div 2, Width=300, Height=Screen.Height div 5
1073- // 当 IDE 需要此窗口的实例时,它会调用 CreateMyIDEWindow 过程。
1074-end;
1109+ ...
1110+ var MyIDEWindow: TMyIDEWindow = nil;
1111+
1112+ procedure CreateMyIDEWindow(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean);
1113+ begin
1114+ // 检查名称
1115+ if CompareText(aFormName,MyIDEWindowName)<>0 then exit;
1116+ // 如果尚未创建表单并禁用自动调整大小
1117+ IDEWindowCreators.CreateForm(MyIDEWindow,TMyIDEWindowm,DoDisableAutosizing,Application);
1118+ ... init the window ...
1119+ AForm:=MyIDEWindow;
1120+ end;
1121+
1122+ procedure Register;
1123+ begin
1124+ IDEWindowCreators.Add('MyIDEWindow',@CreateMyIDEWindow,nil,'100','50%','+300','+20%');
1125+ // 表单的默认边界是:
1126+ // Left=100, Top=Screen.Height div 2, Width=300, Height=Screen.Height div 5
1127+ // 当 IDE 需要此窗口的实例时,它会调用 CreateMyIDEWindow 过程。
1128+ end;
10751129```
10761130
10771131### 显示 IDE 窗口
10781132
1079-不要使用 Show。使用:
1080-
1081-``` pascal
1133+不要使用 Show。使用:
1134+```
10821135IDEWindowCreators.ShowForm(MyIDEWindow,false);
10831136```
10841137
1085-这将适用于对接。对接系统可以将表格包裹到对接站点中。BringToFront 参数告诉对接系统使表单及其所有父站点可见,并将顶层站点放在前面。
1138+这将适用于对接。对接系统可以将表格包裹到对接站点中。BringToFront 参数告诉对接系统使表单及其所有父站点可见,并将顶层站点放在前面。
10861139
10871140### 有关 IDEWindowCreators 和 SimpleLayoutStorage 的注释
10881141
1089-IDEWindowCreators.SimpleLayoutStorage 只存储曾经打开过的所有表单的 BoundsRect 和 WindowState。如果没有安装 dockmaster,它将用作后备。即使安装了 DockMaster,它也会存储状态,因此在卸载 dockmaster 时,将恢复表单边界。
1142+IDEWindowCreators.SimpleLayoutStorage 只存储曾经打开过的所有表单的 BoundsRect 和 WindowState。如果没有安装 dockmaster,它将用作后备。即使安装了 DockMaster,它也会存储状态,因此在卸载 dockmaster 时,将恢复表单边界。
10901143
1091-所有可停靠表单都使用 IDEWindowCreators 来注册自己并显示表单。在显示表单时,Creator 会检查是否安装了 IDEDockMaster,并将显示委托给它。如果没有安装 IDEDockMaster,它只显示表单。IDEDockMaster 可以使用 IDEWindowCreators 中的信息按名称创建表单,并在第一次显示表单时了解放置表单的位置。有关更多详细信息,请参阅包 AnchorDockingDsgn 和 EasyDockMgDsgn。
1144+所有可停靠表单都使用 IDEWindowCreators 来注册自己并显示表单。在显示表单时,Creator 会检查是否安装了 IDEDockMaster,并将显示委托给它。如果没有安装 IDEDockMaster,它只显示表单。IDEDockMaster 可以使用 IDEWindowCreators 中的信息按名称创建表单,并在第一次显示表单时了解放置表单的位置。有关更多详细信息,请参阅包 AnchorDockingDsgn 和 EasyDockMgDsgn。
10921145
10931146# 代码工具
10941147
1095-CodeTools 是一个包,提供了大量的功能来解析、搜索和更改 pascal 源代码以及其他语言的一些基本功能。您也可以在没有 IDE 的情况下使用它们。在 IDE 中使用它们之前,建议您首先阅读 [[Codetools]]。
1096-
1097-在调用 IDE 中的任何 CodeTools 函数之前,您应该将源代码编辑器的当前更改提交到 CodeTools 缓冲区:
1148+CodeTools 是一个包,提供了大量的功能来解析、搜索和更改 pascal 源代码以及其他语言的一些基本功能。您也可以在没有 IDE 的情况下使用它们。在 IDE 中使用它们之前,建议您首先阅读 [[Codetools]]。
10981149
1099-``` pascal
1150+在调用 IDE 中的任何 CodeTools 函数之前,您应该将源代码编辑器的当前更改提交到 CodeTools 缓冲区:
1151+```
11001152uses LazIDEIntf;
1101-...
1102- // 将源代码编辑器中的更改保存到 codetools
1103- LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1:提交所有源代码编辑器
1153+ ...
1154+ // 将源代码编辑器中的更改保存到 codetools
1155+ LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1:提交所有源代码编辑器
11041156```
11051157
11061158## 将资源指令添加到文件中
11071159
1108-这为 pascal 单元添加 {\$R example.res}:
1109-
1110-``` pascal
1160+这为 pascal 单元添加 {$R example.res}:
1161+```
11111162procedure AddResourceDirectiveToPascalSource(const Filename: string);
1112-var
1113- ExpandedFilename: String;
1114- CodeBuf: TCodeBuffer;
1115-begin
1116- // 确保修剪文件名并包含完整路径
1117- ExpandedFilename:=CleanAndExpandFilename(Filename);
1118-
1119- // 将源代码编辑器中的更改保存到 codetools
1120- LazarusIDE.SaveSourceEditorChangesToCodeCache(-1);
1121-
1122- // 加载文件
1123- CodeBuf:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
1124-
1125- // 添加资源指令
1126- if not CodeToolBoss.AddResourceDirective(CodeBuf,'example.res') then
1127- LazarusIDE.DoJumpToCodeToolBossError;
1128-end;
1163+ var
1164+ ExpandedFilename: String;
1165+ CodeBuf: TCodeBuffer;
1166+ begin
1167+ // 确保修剪文件名并包含完整路径
1168+ ExpandedFilename:=CleanAndExpandFilename(Filename);
1169+
1170+ // 将源代码编辑器中的更改保存到 codetools
1171+ LazarusIDE.SaveSourceEditorChangesToCodeCache(-1);
1172+
1173+ // 加载文件
1174+ CodeBuf:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
1175+
1176+ // 添加资源指令
1177+ if not CodeToolBoss.AddResourceDirective(CodeBuf,'example.res') then
1178+ LazarusIDE.DoJumpToCodeToolBossError;
1179+ end;
11291180```
11301181
1131-codetools 还提供 FindResourceDirective 和 RemoveDirective 等函数。
1182+codetools 还提供 FindResourceDirective 和 RemoveDirective 等函数。
11321183
11331184## 获取单元和包含文件的搜索路径
11341185
1135-IDE 中有许多不同的搜索路径来自项目,包,fpc 和 lazarus 目录,并且有许多类型的路径:在解析宏之前或之后,有或没有继承的搜索路径,作为相对路径或绝对路径。目录中的所有文件共享同一组搜索路径。您可以通过询问 codetools 来完全解析每个目录的搜索路径:
1136-
1137-``` pascal
1186+IDE 中有许多不同的搜索路径来自项目,包,fpc 和 lazarus 目录,并且有许多类型的路径:在解析宏之前或之后,有或没有继承的搜索路径,作为相对路径或绝对路径。目录中的所有文件共享同一组搜索路径。您可以通过询问 codetools 来完全解析每个目录的搜索路径:
1187+```
11381188uses CodeToolManager;
1139-...
1140-
1141-Dir:=''; // 空目录用于新文件,并且具有与项目目录相同的设置
1142-
1143-// 获取包含文件的搜索路径:
1144-Path:=CodeToolBoss.GetIncludePathForDirectory(Dir);
1145-
1146-// 获取单元的搜索路径:
1147-// 此搜索路径将传递给编译器。
1148-// 它包含包输出目录,但不包含包源目录。
1149-Path:=CodeToolBoss.GetUnitPathForDirectory(Dir);
1150-
1151-// 只能为 IDE 提供额外的单元搜索路径(不传递给编译器)
1152-Path:=CodeToolBoss.GetSrcPathForDirectory(Dir);
1153-
1154-// 完整的搜索路径还包含单元的所有包源路径:
1155-Path:=CodeToolBoss.GetCompleteSrcPathForDirectory(Dir);
1189+ ...
1190+
1191+ Dir:=''; // 空目录用于新文件,并且具有与项目目录相同的设置
1192+
1193+ // 获取包含文件的搜索路径:
1194+ Path:=CodeToolBoss.GetIncludePathForDirectory(Dir);
1195+
1196+ // 获取单元的搜索路径:
1197+ // 此搜索路径将传递给编译器。
1198+ // 它包含包输出目录,但不包含包源目录。
1199+ Path:=CodeToolBoss.GetUnitPathForDirectory(Dir);
1200+
1201+ // 只能为 IDE 提供额外的单元搜索路径(不传递给编译器)
1202+ Path:=CodeToolBoss.GetSrcPathForDirectory(Dir);
1203+
1204+ // 完整的搜索路径还包含单元的所有包源路径:
1205+ Path:=CodeToolBoss.GetCompleteSrcPathForDirectory(Dir);
11561206```
11571207
11581208# 源代码编辑
11591209
11601210## 激活源代码编辑器
1161-
1162-``` pascal
1211+```
11631212uses SrcEditorIntf;
1164-...
1165-Editor:=SourceEditorManagerIntf.ActiveEditor;
1166-if Editor=nil then exit;
1167-Filename:=Editor.FileName;
1168-ScreenPos:=Editor.CursorScreenXY;
1169-TextPos:=Editor.CursorTextXY;
1213+ ...
1214+ Editor:=SourceEditorManagerIntf.ActiveEditor;
1215+ if Editor=nil then exit;
1216+ Filename:=Editor.FileName;
1217+ ScreenPos:=Editor.CursorScreenXY;
1218+ TextPos:=Editor.CursorTextXY;
11701219```
11711220
11721221# SynEdit
11731222
11741223## 获取 TSynEdit 的设置
11751224
1176-当您使用 TSynEdit 进行对话时,如果要使用与源代码编辑器相同的字体和设置,请使用:
1177-
1178-``` pascal
1225+当您使用 TSynEdit 进行对话时,如果要使用与源代码编辑器相同的字体和设置,请使用:
1226+```
11791227uses SrcEditorIntf;
1180-...
1181-SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
1228+ ...
1229+ SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
11821230```
11831231
11841232## 获取 SynEdit 的高亮设置
11851233
1186-如果您有一个带有高亮的 TSynEdit 的对话框,并且您希望使用与源代码编辑器高亮相同的颜色来使用此语言:
1187-
1188-使
1234+如果您有一个带有高亮的 TSynEdit 的对话框,并且您希望使用与源代码编辑器高亮相同的颜色来使用此语言:
11891235
1190-``` pascal
1236+使
1237+```
11911238uses SrcEditorIntf;
1192-...
1193-SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
1239+ ...
1240+ SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
11941241```
11951242
1196-请参阅示例:[SQLStringsPropertyEditorDlg](http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas) 单元中的 TSQLStringsPropertyEditorDlg.Create。
1243+请参阅示例:[SQLStringsPropertyEditorDlg](<http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas>) 单元中的 TSQLStringsPropertyEditorDlg.Create。
11971244
11981245# 帮助
11991246
12001247## 添加源的帮助
12011248
1202-首先创建一个 THelpDatabase:
1203-
1204-``` pascal
1249+首先创建一个 THelpDatabase:
1250+```
12051251HelpDB := TFPDocHTMLHelpDatabase(
1206- HelpDatabases.CreateHelpDatabase('ANameOfYourChoiceForTheDatabase',
1207- TFPDocHTMLHelpDatabase,true));
1208-HelpDB.DefaultBaseURL := 'http://your.help.org/';
1209-
1210-FPDocNode := THelpNode.CreateURL(HelpDB,
1211- 'Package1 - A new package',
1212- 'file://index.html');
1213-HelpDB.TOCNode := THelpNode.Create(HelpDB,FPDocNode);// 一次作为 TOC
1214-DirectoryItem := THelpDBISourceDirectory.Create(FPDocNode,'$(PkgDir)/lcl',
1215- '*.pp;*.pas',false);// 一次作为正常页面
1216-HelpDB.RegisterItem(DirectoryItem);
1252+ HelpDatabases.CreateHelpDatabase('ANameOfYourChoiceForTheDatabase',
1253+ TFPDocHTMLHelpDatabase,true));
1254+ HelpDB.DefaultBaseURL := 'http://your.help.org/';
1255+
1256+ FPDocNode := THelpNode.CreateURL(HelpDB,
1257+ 'Package1 - A new package',
1258+ 'file://index.html');
1259+ HelpDB.TOCNode := THelpNode.Create(HelpDB,FPDocNode);// 一次作为 TOC
1260+ DirectoryItem := THelpDBISourceDirectory.Create(FPDocNode,'$(PkgDir)/lcl',
1261+ '*.pp;*.pas',false);// 一次作为正常页面
1262+ HelpDB.RegisterItem(DirectoryItem);
12171263```
12181264
12191265## 在消息窗口中添加行
1220-
1221-``` pascal
1266+```
12221267unit IDEMsgIntf;
1223-...
1224-var Dir: String;
1225-begin
1226- Dir:=GetCurrentDir;
1227- IDEMessagesWindow.BeginBlock;
1228- IDEMessagesWindow.AddMsg('unit1.pas(30,4) Error: Identifier not found "a"',Dir,0);
1229- IDEMessagesWindow.EndBlock;
1230-end;
1268+ ...
1269+ var Dir: String;
1270+ begin
1271+ Dir:=GetCurrentDir;
1272+ IDEMessagesWindow.BeginBlock;
1273+ IDEMessagesWindow.AddMsg('unit1.pas(30,4) Error: Identifier not found "a"',Dir,0);
1274+ IDEMessagesWindow.EndBlock;
1275+ end;
12311276```
12321277
12331278# IDE 选项框架
12341279
12351280## 打开特定框架中的选项
1236-
1237-``` pascal
1281+```
12381282uses LazIDEIntf;
1239-...
1240-LazarusIDE.DoOpenIDEOptions(TYourIDEOptionsFrame);
1283+ ...
1284+ LazarusIDE.DoOpenIDEOptions(TYourIDEOptionsFrame);
12411285```
12421286
12431287# 其它
12441288
12451289## 添加宏
12461290
1247-您可以添加自己的 IDE 宏:
1248-
1249-``` pascal
1291+您可以添加自己的 IDE 宏:
1292+```
12501293uses MacroIntf, MacroDefIntf;
1251-
1252-procedure Register;
1253-begin
1254- // 注册具有固定值的宏:
1255- IDEMacros.Add(TTransferMacro.Create('MyMacro1','Value','Description',nil,[]));
1256-end;
1257-
1258-// 使用动态值注册宏需要一个对象的方法
1259-procedure TForm1.Init;
1260-begin
1261- IDEMacros.Add(TTransferMacro.Create('MyMacro','Value','Description',@OnResolveMyMacro,[]));
1262-end;
1263-
1264-function TForm1.OnResolveMyMacro(const s: string; const Data: PtrInt;
1265- var Abort: boolean): string;
1266-// s 是参数。例如 $MyMacro(parameter)
1267-// 数据是查询实例。可以是零。
1268-// 如果有错误设置 Abort 为 true。
1269-// 结果字符串可以包含宏。例如 Result:='$(FPCVer)/$(TargetOS)';
1270-begin
1271- Result:='MyValue';
1272-end;
1294+
1295+ procedure Register;
1296+ begin
1297+ // 注册具有固定值的宏:
1298+ IDEMacros.Add(TTransferMacro.Create('MyMacro1','Value','Description',nil,[]));
1299+ end;
1300+
1301+ // 使用动态值注册宏需要一个对象的方法
1302+ procedure TForm1.Init;
1303+ begin
1304+ IDEMacros.Add(TTransferMacro.Create('MyMacro','Value','Description',@OnResolveMyMacro,[]));
1305+ end;
1306+
1307+ function TForm1.OnResolveMyMacro(const s: string; const Data: PtrInt;
1308+ var Abort: boolean): string;
1309+ // s 是参数。例如 $MyMacro(parameter)
1310+ // 数据是查询实例。可以是零。
1311+ // 如果有错误设置 Abort 为 true。
1312+ // 结果字符串可以包含宏。例如 Result:='$(FPCVer)/$(TargetOS)';
1313+ begin
1314+ Result:='MyValue';
1315+ end;
12731316```
12741317
12751318## 调试 IDE
12761319
1277-- 像往常一样编译 IDE,例如通过 Tools/Build Lazarus。确保设置调试标志,如 -g 或 -gw2。最好是使用配置文件“Debug IDE”,其中包含许多用于调试的标志。
1278-- 打开 ide \\ lazarus.lpi 项目。您无法直接编译此项目。
1279-- 根据需要设置断点等运行项目。
1320+ * 像往常一样编译 IDE,例如通过 Tools/Build Lazarus。确保设置调试标志,如 -g 或 -gw2。最好是使用配置文件“Debug IDE”,其中包含许多用于调试的标志。
1321+ * 打开 ide \ lazarus.lpi 项目。您无法直接编译此项目。
1322+ * 根据需要设置断点等运行项目。
12801323
12811324## 另请参见
12821325
1283-- [[Creating IDE Help]]
1284-- [[Help protocol]]
1285-- [[How To Write Lazarus Component]]
1326+ * [[Creating IDE Help]]
1327+ * [[Help protocol]]
1328+ * [[How To Write Lazarus Component]]
12861329
12871330---
1288-*From the Free Pascal wiki, page "Extending the IDE/zh CN", as it stood on 2020-02-14 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
1331+*From the Free Pascal wiki, page "Extending the IDE/zh CN", as the Internet Archive kept it on 2024-07-25. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history