Sign in Join
Wiki copytemporary

Extending the IDE/zh CN: what changed

Revision 2 to 3. 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-
781# 扩展 IDE
792
803## 概述
814
82-Lazarus IDE 支持以下几种类型的插件:
5+Lazarus IDE 支持以下几种类型的插件:
836
84-组件(Components)
85- 这些是“组件面板”上的项目。例如 TButton(可以在“标准”页面上找到)可用于创建按钮。
7+组件(Components)
8+这些是“组件面板”上的项目。例如 TButton(可以在“标准”页面上找到)可用于创建按钮。
869
87-组件编辑器(Component Editors)
88- 当你在“界面设计器(Designer)”中双击一个组件时(比如“TMainMenu”组件),将调用组件编辑器(比如“菜单编辑器”)。组件编辑器还可以在“界面设计器”的右键菜单中添加一个额外的菜单项(右键单击“界面设计器”中的组件时可以访问)。
10+组件编辑器(Component Editors)
11+当你在“界面设计器(Designer)”中双击一个组件时(比如“TMainMenu”组件),将调用组件编辑器(比如“菜单编辑器”)。组件编辑器还可以在“界面设计器”的右键菜单中添加一个额外的菜单项(右键单击“界面设计器”中的组件时可以访问)。
8912
90-属性编辑器(Property Editors)
91- “对象查看器”的列表中的每一行都使用属性编辑器来设置或更改该属性的值。
13+属性编辑器(Property Editors)
14+“对象查看器”的列表中的每一行都使用属性编辑器来设置或更改该属性的值。
9215
93-专家(Experts)
94- 专家包含所有其他插件类型。他们可能会注册新的菜单项,注册快捷方式或扩展其他 IDE 功能。
16+专家(Experts)
17+专家包含所有其他插件类型。他们可能会注册新的菜单项,注册快捷方式或扩展其他 IDE 功能。
9518
96-
97-有两种方式可以将自己的插件添加到 Lazarus IDE:
19+有两种方式可以将自己的插件添加到 Lazarus IDE:
9820
99- 1. 编写一个包,安装它并在包单元的“Register”过程中注册你的插件。
100- 2. 扩展 Lazarus 代码,并将您的 svn diff 发送到 Lazarus 邮件列表。
21+1. 编写一个包,安装它并在包单元的“Register”过程中注册你的插件。
22+2. 扩展 Lazarus 代码,并将您的 svn diff 发送到 Lazarus 邮件列表。
10123
10224## 包和 Makefile 依赖项
10325
104-如果添加新的包依赖项,则必须执行以下步骤。
26+如果添加新的包依赖项,则必须执行以下步骤。
10527
106- * 创建 / 通过包编辑器更新包的 MakeFile/ 更多 .../ 创建 Makefile。
107- * 修复所有依赖项。请参阅 tools/updatemakefiles.lpi
28+- 创建 / 通过包编辑器更新包的 MakeFile/ 更多 .../ 创建 Makefile。
29+- 修复所有依赖项。请参阅 tools/updatemakefiles.lpi
10830
10931# 菜单项
11032
111-您可以添加新菜单项,隐藏或移动现有菜单项并添加子菜单、菜单区(菜单区是整个菜单中的一块区域,它可以是一个包含子菜单的菜单项,也可以是由分隔符分隔出来的一块区域。如果菜单区中没有子项,则该菜单区将不可见。比如 itmFileNew 就是一个用分隔符分隔的菜单区,它里面包含了“新建单元”、“新建窗体”、“新建 ...” 等菜单项,itmFileRecentOpen 也是一个菜单区,它只是一个菜单项,包含“最近打开的文件”子菜单)。对于您自己的窗体,您可以注册 TMainMenu/TPopupMenu,以便其它包可以进一步扩展您的窗体。**IDEIntf** 包的 MenuIntf 单元包含菜单的所有注册函数和 IDE 本身的许多标准菜单项。
33+您可以添加新菜单项,隐藏或移动现有菜单项并添加子菜单、菜单区(菜单区是整个菜单中的一块区域,它可以是一个包含子菜单的菜单项,也可以是由分隔符分隔出来的一块区域。如果菜单区中没有子项,则该菜单区将不可见。比如 itmFileNew 就是一个用分隔符分隔的菜单区,它里面包含了“新建单元”、“新建窗体”、“新建 ...” 等菜单项,itmFileRecentOpen 也是一个菜单区,它只是一个菜单项,包含“最近打开的文件”子菜单)。对于您自己的窗体,您可以注册 TMainMenu/TPopupMenu,以便其它包可以进一步扩展您的窗体。**IDEIntf** 包的 MenuIntf 单元包含菜单的所有注册函数和 IDE 本身的许多标准菜单项。
11234
11335## 添加菜单项
11436
115-像“查看 -> 对象查看器”这样的单个菜单项称为 **TIDEMenuCommand** 。您可以使用 **RegisterIDEMenuCommand** 创建一个,它有两个带有大量参数的格式:
116-```
37+像“查看 -\> 对象查看器”这样的单个菜单项称为 **TIDEMenuCommand**。您可以使用 **RegisterIDEMenuCommand** 创建一个,它有两个带有大量参数的格式:
38+
39+``` pascal
11740function RegisterIDEMenuCommand(
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;
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+
49+function 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;
13356```
13457
135-这两者之间的区别仅在于指定父菜单区的方式。您可以通过 Path 参数直接或间接地给出菜单区。 _MenuIntf_ 单元中可以找到许多标准菜单区。例如 **mnuTools** 菜单区,它是主 IDE 栏的 _Tools_ 菜单。它包含一个子菜单区 **itmSecondaryTools** ,用于第三方工具的推荐菜单区。
58+这两者之间的区别仅在于指定父菜单区的方式。您可以通过 Path 参数直接或间接地给出菜单区。*MenuIntf* 单元中可以找到许多标准菜单区。例如 **mnuTools** 菜单区,它是主 IDE 栏的 *Tools* 菜单。它包含一个子菜单区 **itmSecondaryTools**,用于第三方工具的推荐菜单区。
13659
137-下面的代码注册了一个新的菜单命令,菜单名(Name)为“MyTool”,菜单标题(Caption)为“我的工具(&T)”,点击后执行 StartMyTool 过程:
138-```
60+下面的代码注册了一个新的菜单命令,菜单名(Name)为“MyTool”,菜单标题(Caption)为“我的工具(&T)”,点击后执行 StartMyTool 过程:
61+
62+``` pascal
13963procedure StartMyTool;
140- begin
141- ... 点击菜单项后要执行的代码 ...
142- end;
143-
144- procedure Register;
145- begin
146- RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具(&T)', nil, @StartMyTool);
147- end;
64+begin
65+ ... 点击菜单项后要执行的代码 ...
66+end;
67+
68+procedure Register;
69+begin
70+ RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', ' 我的工具(&T)', nil, @StartMyTool);
71+end;
14872```
14973
150-如果要调用方法而不是过程,请使用 **OnClickMethod** 参数。
74+如果要调用方法而不是过程,请使用 **OnClickMethod** 参数。
15175
152-此菜单项没有快捷键。如果需要快捷键,则必须创建一个 **TIDECommand** 对象并将其传递给 **Command** 参数。例如:
153-```
76+此菜单项没有快捷键。如果需要快捷键,则必须创建一个 **TIDECommand** 对象并将其传递给 **Command** 参数。例如:
77+
78+``` pascal
15479uses
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;
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;
176101```
177102
178103## 快捷键
179104
180-所有快捷键都在 IDECommandList 中注册。下面是一个示例,将查找所有使用 Ctrl-D 作为快捷键的命令:
181-```
105+所有快捷键都在 IDECommandList 中注册。下面是一个示例,将查找所有使用 Ctrl-D 作为快捷键的命令:
106+
107+``` pascal
182108uses
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;
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
191121 begin
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;
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]));
211133 end;
134+ finally
135+ Commands.Free;
136+ end;
137+end;
212138```
213139
214140# 配置文件
215141
216-加载和保存配置
142+加载和保存配置
217143
218-IDE 的所有配置文件都以 xml 格式存储在一个目录中(主配置目录)。包也可以在那里添加自己的配置文件。可以使用下面的方式读取“主配置目录”:
219-```
144+IDE 的所有配置文件都以 xml 格式存储在一个目录中(主配置目录)。包也可以在那里添加自己的配置文件。可以使用下面的方式读取“主配置目录”:
145+
146+``` pascal
220147uses LazIDEIntf;
221- ...
222- Directory := LazarusIDE.GetPrimaryConfigPath;
148+...
149+ Directory := LazarusIDE.GetPrimaryConfigPath;
223150```
224151
225-包可以创建自己的 xml 文件:
226-```
152+包可以创建自己的 xml 文件:
153+
154+``` pascal
227155uses
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;
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;
285187 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]);
211+ end;
212+ end;
213+end;
286214```
287215
288-注意:
216+注意:
289217
290- * 每个 IDE 插件都应该使用自己的配置文件。特别是您不能使用标准 IDE 选项文件,如 editoroptions.xml 或 environmentoptions.xml。
291- * GetIDEConfigStorage 在加载时,会检查文件是否存在,如果不存在,它将从辅助配置目录复制模板。
292- * 从 0.9.31 开始,您可以使用此函数在主配置目录之外加载文件。
218+- 每个 IDE 插件都应该使用自己的配置文件。特别是您不能使用标准 IDE 选项文件,如 editoroptions.xml 或 environmentoptions.xml。
219+- GetIDEConfigStorage 在加载时,会检查文件是否存在,如果不存在,它将从辅助配置目录复制模板。
220+- 从 0.9.31 开始,您可以使用此函数在主配置目录之外加载文件。
293221
294222# 组件
295223
296224## 扩展现有组件
297225
298-来源:[[1]](<http://lazarus.freepascal.org/index.php/topic,17733.msg98425.html#msg98425>) 定制现有的 LCL 组件很简单,例如,如果要添加属性。
226+来源:[1](http://lazarus.freepascal.org/index.php/topic,17733.msg98425.html#msg98425) 定制现有的 LCL 组件很简单,例如,如果要添加属性。
299227
300-使用字段及其相应的 setter 和 getter 方法来添加所需的属性。
228+使用字段及其相应的 setter 和 getter 方法来添加所需的属性。
301229
302-然后“手动”实例化它们,给出一个 OWner 组件(以便处理稍后的销毁操作),并设置 Parent 和可能的 Top 和 Left 以及组件在初始化时需要的任何其他默认值。
230+然后“手动”实例化它们,给出一个 OWner 组件(以便处理稍后的销毁操作),并设置 Parent 和可能的 Top 和 Left 以及组件在初始化时需要的任何其他默认值。
303231
304-如果您对自定义组件的调试感到满意,请添加一个 RegisterComponent() 调用以将其加入到 IDE 的组件面板中,并保存您必须“手动”编写的设置代码(查看任一个组件的源代码以了解如何执行此操作)。
232+如果您对自定义组件的调试感到满意,请添加一个 RegisterComponent() 调用以将其加入到 IDE 的组件面板中,并保存您必须“手动”编写的设置代码(查看任一个组件的源代码以了解如何执行此操作)。
305233
306-这是一个简单的例子:
307-```
234+这是一个简单的例子:
235+
236+``` pascal
308237unit Unit1;
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.
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.
378307```
379308
380309## 编写组件
381310
382311主要文章:[[How To Write Lazarus Component]]
383312
384-您可以通过包编辑器创建新组件。
313+您可以通过包编辑器创建新组件。
385314
386-创建或打开一个包,单击“添加 -> 新组件”,填写项目: Ancestor Type = TButton, New class name = TMyButton, palette page = Misc, Unit name = mybutton.pas(将创建此文件) , 单位名称 MyButton,然后单击确定。
315+创建或打开一个包,单击“添加 -\> 新组件”,填写项目: Ancestor Type = TButton, New class name = TMyButton, palette page = Misc, Unit name = mybutton.pas(将创建此文件) , 单位名称 MyButton,然后单击确定。
387316
388317### 为组件面板提供一个新组件图标
389318
390-创建格式为 .bmp、.xpm 或 .png 的图像文件,其名称与组件类相同。例如 tmybutton.png 并将其保存在包源目录中。图像可以由任何图形程序(例如 gimp)创建,并且不应大于 24x24 像素。然后使用 lazres 工具将图像转换为资源文件,该工具可以在 lazarus/tools 目录中找到:
391-```
319+创建格式为 .bmp、.xpm 或 .png 的图像文件,其名称与组件类相同。例如 tmybutton.png 并将其保存在包源目录中。图像可以由任何图形程序(例如 gimp)创建,并且不应大于 24x24 像素。然后使用 lazres 工具将图像转换为资源文件,该工具可以在 lazarus/tools 目录中找到:
320+
321+``` bash
392322~/lazarus/tools/lazres mybutton.lrs tmybutton.png
393- # note: Laz trunk/1.4+? uses .res resource files instead of .lrs files:
394- ~/lazarus/tools/lazres mybutton.res tmybutton.png
323+# note: Laz trunk/1.4+? uses .res resource files instead of .lrs files:
324+~/lazarus/tools/lazres mybutton.res tmybutton.png
395325```
396326
397-这将创建一个 pascal include 文件,该文件在 mybutton.pas 的初始化部分中使用:
398-```
327+这将创建一个 pascal include 文件,该文件在 mybutton.pas 的初始化部分中使用:
328+
329+``` pascal
399330initialization
400- {$I mybutton.lrs}
401- // 或在较新的 Lazarus 版本中 - to docheck 语法
402- {$R mybutton.res}
331+ {$I mybutton.lrs}
332+ // 或在较新的 Lazarus 版本中 - to docheck 语法
333+ {$R mybutton.res}
403334```
404335
405-安装包。
336+安装包。
406337
407338### 隐藏组件面板中的组件
408339
409-Package IDEIntf, unit componentreg:
410-```
411-IDEComponentPalette.FindComponent('TButton').Visible:=false;
340+Package IDEIntf, unit componentreg:
341+
342+``` pascal
343+ IDEComponentPalette.FindComponent('TButton').Visible:=false;
412344```
413345
414346## 编写组件编辑器
415347
416-组件编辑器处理诸如双击设计器中的组件或右键单击组件时添加菜单项之类的操作。编写组件编辑器很简单。有关大量示例,请参阅 IDEIntf 包的 componenteditors.pas 单元。例如,双击时显示编辑器,请参阅 TCheckListBoxComponentEditor。
348+组件编辑器处理诸如双击设计器中的组件或右键单击组件时添加菜单项之类的操作。编写组件编辑器很简单。有关大量示例,请参阅 IDEIntf 包的 componenteditors.pas 单元。例如,双击时显示编辑器,请参阅 TCheckListBoxComponentEditor。
417349
418350## 编写属性编辑器
419351
420-“属性查看器”中的每种属性(整数、字符串、TFont、...)都需要属性编辑器。如果组件具有字符串类型的属性 Password,则可以为特定组件类定义属性编辑器,并使用字符串类型的名为 Password 的属性。在 IDEIntf 的 propedits.pp 单元中包含 IDE 本身使用的许多标准属性编辑器。例如 TStringPropertyEditor 是所有字符串的默认属性编辑器,而 TComponentNamePropertyEditor 更有针对性,它只处理 TComponent.Name。请参阅示例中的单元文件。
352+“属性查看器”中的每种属性(整数、字符串、TFont、...)都需要属性编辑器。如果组件具有字符串类型的属性 Password,则可以为特定组件类定义属性编辑器,并使用字符串类型的名为 Password 的属性。在 IDEIntf 的 propedits.pp 单元中包含 IDE 本身使用的许多标准属性编辑器。例如 TStringPropertyEditor 是所有字符串的默认属性编辑器,而 TComponentNamePropertyEditor 更有针对性,它只处理 TComponent.Name。请参阅示例中的单元文件。
421353
422354### 在 Object Inspector 中隐藏属性
423355
424-有一个特殊的属性编辑器用于隐藏:
425-```
426-RegisterPropertyEditor(TypeInfo(TAnchorSide), TControl, 'AnchorSideLeft', THiddenPropertyEditor);
356+有一个特殊的属性编辑器用于隐藏:
357+
358+``` pascal
359+ RegisterPropertyEditor(TypeInfo(TAnchorSide), TControl, 'AnchorSideLeft', THiddenPropertyEditor);
427360```
428361
429362### 找出属性使用的属性编辑器
430-```
363+
364+``` pascal
431365uses Classes, TypInfo;
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;
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;
440374```
441375
442376## 窗体
443377
444-IDE 允许轻松创建窗体和框架的后代。这些窗体可以包含新的 published 组件和新的 published 方法。但是,当您添加新的 published 属性时,无法通过“对象查看器”访问它们。它们仅在运行时工作。IDE 中的方法是伪造的,无法执行。IDE 可以创建组件,因为它们的类已在组件面板中注册。你的新属性仅存在于源代码中,IDE 还不能伪造它们。这就是你必须注册新类的原因。这意味着:
378+IDE 允许轻松创建窗体和框架的后代。这些窗体可以包含新的 published 组件和新的 published 方法。但是,当您添加新的 published 属性时,无法通过“对象查看器”访问它们。它们仅在运行时工作。IDE 中的方法是伪造的,无法执行。IDE 可以创建组件,因为它们的类已在组件面板中注册。你的新属性仅存在于源代码中,IDE 还不能伪造它们。这就是你必须注册新类的原因。这意味着:
445379
446- * 创建设计时包(或扩展现有包)
447- * 您的窗体必须在此包的单元中
380+- 创建设计时包(或扩展现有包)
381+- 您的窗体必须在此包的单元中
448382
449-```
383+``` pascal
450384...
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- ...
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;
398+
399+implementation
400+
401+procedure Register;
402+begin
403+ FormEditingHook.RegisterDesignerBaseClass(TYourForm);
404+end;
405+...
472406```
473407
474- * 检查包编辑器中本单元的“Register”。
475- * 在 IDE 中安装包
408+- 检查包编辑器中本单元的“Register”。
409+- 在 IDE 中安装包
476410
477411# 界面设计器(Designer)
478412
479413### 编写一个设计器中间层
480414
481-标准设计器允许可视化编辑 LCL 控件,而所有其它控件都显示为图标(如 TOpenDialog 或 TDataSource)。要可视地编辑非 LCL 控件,您需要创建一个 **设计器中间层** 。这可用于设计网页,UML 图或其它小部件集,如 [[fpGUI]]。在 examples/designnonlcl/ 中有一个完整的例子。
415+标准设计器允许可视化编辑 LCL 控件,而所有其它控件都显示为图标(如 TOpenDialog 或 TDataSource)。要可视地编辑非 LCL 控件,您需要创建一个 **设计器中间层**。这可用于设计网页,UML 图或其它小部件集,如 [[fpGUI]]。在 examples/designnonlcl/ 中有一个完整的例子。
482416
483- * 安装示例包 examples/designnonlcl/notlcldesigner.lpk 并重新启动 IDE。这将为 TMyWidget 组件注册设计器中间层,并将新组件 TMyButton,TMyGroupBox 添加到组件面板中。
484- * 打开示例项目 examples/designnonlcl/project/NonLCL1.lpi。
485- * 打开 unit1.pas 并切换到设计器界面(F12)。您应该看到组件为红色矩形,可以像 LCL 控件一样选择,移动和调整大小。
417+- 安装示例包 examples/designnonlcl/notlcldesigner.lpk 并重新启动 IDE。这将为 TMyWidget 组件注册设计器中间层,并将新组件 TMyButton,TMyGroupBox 添加到组件面板中。
418+- 打开示例项目 examples/designnonlcl/project/NonLCL1.lpi。
419+- 打开 unit1.pas 并切换到设计器界面(F12)。您应该看到组件为红色矩形,可以像 LCL 控件一样选择,移动和调整大小。
486420
487421## 创建一个新的唯一组件名称
488-```
422+
423+``` pascal
489424uses FormEditingIntf;
490-
491- ...
492-
493- NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
494-
495- // 或者如果您需要在创建组件之前创建名称:
496-
497- NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
498- // ComponentClassName 将用作前缀,没有前导 T.
499- // OwnerComponent 是新组件的新所有者。
425+
426+...
427+
428+NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
429+
430+// 或者如果您需要在创建组件之前创建名称:
431+
432+NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
433+// ComponentClassName 将用作前缀,没有前导 T.
434+// OwnerComponent 是新组件的新所有者。
500435```
501436
502437## 在设计器 / 对象检查器中选择一个组件
503-```
438+
439+``` pascal
504440uses propedits;
505- ..
506- GlobalDesignHook.SelectOnlyThis(AComponent);
441+..
442+GlobalDesignHook.SelectOnlyThis(AComponent);
507443```
508444
509445## 获取单元,设计器,文件的形式
510-```
446+
447+``` pascal
511448uses ProjectIntf, LazIDEIntf, ComponentEditors;
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;
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;
523460```
524461
525462## 保存单元,设计器窗口
526-```
463+
464+``` pascal
527465uses LazIDEIntf;
528- ...
529- if LazarusIDE.DoSaveEditorFile(Filename,[])<>mrOk then exit;
466+...
467+if LazarusIDE.DoSaveEditorFile(Filename,[])<>mrOk then exit;
530468```
531469
532470## 将设计器窗口保存为 Pascal
533471
534- * 使用 _FormEditingfIntf_ 单元的 **FormEditingHook.SaveComponentAsPascal** 函数。请参阅 _examples/pascalstream/CopyAsPasPkg/copyaspasdemounit1.pas_ 。
472+- 使用 *FormEditingfIntf* 单元的 **FormEditingHook.SaveComponentAsPascal** 函数。请参阅 *examples/pascalstream/CopyAsPasPkg/copyaspasdemounit1.pas*。
535473
536474# 事件处理程序
537475
538-IDE 中有几个事件,插件可以为其添加自己的处理程序。
476+IDE 中有几个事件,插件可以为其添加自己的处理程序。
539477
540478## 设计器活动
541479
542-在 propedits.pp 中有一个“GlobalDesignHook”对象,它维护了几个用于设计的事件。每个事件都会调用一个处理程序列表。IDE 添加了默认处理程序。您可以使用 AddHandlerXXX 和 RemoveHandlerXXX 方法添加自己的处理程序。它们将在默认处理程序之前调用。
480+在 propedits.pp 中有一个“GlobalDesignHook”对象,它维护了几个用于设计的事件。每个事件都会调用一个处理程序列表。IDE 添加了默认处理程序。您可以使用 AddHandlerXXX 和 RemoveHandlerXXX 方法添加自己的处理程序。它们将在默认处理程序之前调用。
543481
544-例子:
482+例子:
545483
546- * 添加处理程序(通常在对象的构造函数中完成):
484+- 添加处理程序(通常在对象的构造函数中完成):
547485
548-```
549-GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);
550-```
486+` GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);`
551487
552- * 删除处理程序:
488+- 删除处理程序:
553489
554-```
555-GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);
556-```
490+` GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);`
557491
558- * 您可以一次删除所有处理程序。例如,在对象的析构函数中添加此行是个好主意:
492+- 您可以一次删除所有处理程序。例如,在对象的析构函数中添加此行是个好主意:
559493
560-```
561-GlobalDesignHook.RemoveAllHandlersForObject(Self);
562-```
494+` GlobalDesignHook.RemoveAllHandlersForObject(Self);`
563495
564-GlobalDesignHook 的处理程序:
496+GlobalDesignHook 的处理程序:
565497
566- * 查找根目录
567- * ChangeLookupRoot - 当“LookupRoot”发生变化时调用。“LookupRoot”是当前所选组件的所有者对象。通常这是一个 TForm。
498+- 查找根目录
499+ - ChangeLookupRoot - 当“LookupRoot”发生变化时调用。“LookupRoot”是当前所选组件的所有者对象。通常这是一个 TForm。
568500
569- * 方法
570- * CreateMethod
571- * GetMethodName
572- * 的 getMethods
573- * MethodExists
574- * RenameMethod
575- * ShowMethod
576- * MethodFromAncestor
577- * ChainCall
501+- 方法
502+ - CreateMethod
503+ - GetMethodName
504+ - 的 getMethods
505+ - MethodExists
506+ - RenameMethod
507+ - ShowMethod
508+ - MethodFromAncestor
509+ - ChainCall
578510
579- * 组件
580- * GetComponent
581- * GetComponentName
582- * GetComponentNames
583- * GetRootClassName
584- * AddClicked - 在用户选择组件类并单击设计器以添加新组件时调用。您可以更改组件类和父组件。
585- * ComponentRenamed - 在重命名组件时调用
511+- 组件
512+ - GetComponent
513+ - GetComponentName
514+ - GetComponentNames
515+ - GetRootClassName
516+ - AddClicked - 在用户选择组件类并单击设计器以添加新组件时调用。您可以更改组件类和父组件。
517+ - ComponentRenamed - 在重命名组件时调用
586518
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
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
596528
597- * 修改
598- * Modified
599- * Revert
600- * RefreshPropertyValues
529+- 修改
530+ - Modified
531+ - Revert
532+ - RefreshPropertyValues
601533
602- * 选区
603- * SetSelection
604- * GetSelection
534+- 选区
535+ - SetSelection
536+ - GetSelection
605537
606538### 设计器活动的例子
607539
608540#### 示例:当放置新组件时,将新组件移动到子组件中
609-```
541+
542+``` pascal
610543...
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;
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+
557+...
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;
650583```
651584
652585### 禁用设计器鼠标处理程序
653586
654-通常,设计人员会捕获组件的所有鼠标事件。如果您的自定义控件应该处理鼠标事件句柄,您可以设置 **csDesignInteractive** **控件样式** ,也可以通过控件中的消息 CM_DESIGNHITTEST 对其进行精确控制:
655-```
587+通常,设计人员会捕获组件的所有鼠标事件。如果您的自定义控件应该处理鼠标事件句柄,您可以设置 **csDesignInteractive** **控件样式**,也可以通过控件中的消息 CM_DESIGNHITTEST 对其进行精确控制:
588+
589+``` pascal
656590type
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;
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;
673607```
674608
675609## 在修改设计器窗体时收到通知
676610
677-每个设计的 LCL 表格都有一个 TIDesigner 类型的设计器。IDE 将创建在 IDEIntf 单元组件中定义的 TComponentEditorDesigner 类型的设计器。例如:
678-```
611+每个设计的 LCL 表格都有一个 TIDesigner 类型的设计器。IDE 将创建在 IDEIntf 单元组件中定义的 TComponentEditorDesigner 类型的设计器。例如:
612+
613+``` pascal
679614procedure TYourAddOn.OnDesignerModified(Sender: TObject);
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;
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;
694629```
695630
696631## 项目事件
697632
698-这些事件在单元 LazIDEIntf 中定义。
633+这些事件在单元 LazIDEIntf 中定义。
699634
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 起)
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 起)
708643
709644## 其他 IDE 事件
710645
711-uses LazIDEIntf;
646+uses LazIDEIntf;
712647
713-在包的注册过程中调用这些:
648+在包的注册过程中调用这些:
714649
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 起)
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 起)
727662
728-在您的某个单元的初始化部分中调用它们:
663+在您的某个单元的初始化部分中调用它们:
729664
730- * AddBootHandler
731- * AddBootHandler(libhTransferMacrosCreated, @YourProc):创建 IDEMacros 后调用(自 1.3 起)
732- * AddBootHandler(libhEnvironmentOptionsLoaded, @YourProc):加载环境选项后调用(自 1.3 起)
665+- AddBootHandler
666+- AddBootHandler(libhTransferMacrosCreated, @YourProc):创建 IDEMacros 后调用(自 1.3 起)
667+- AddBootHandler(libhEnvironmentOptionsLoaded, @YourProc):加载环境选项后调用(自 1.3 起)
733668
734669# 项目
735670
736671## 当前的项目
737672
738-目前的主要项目可以通过 LazarusIDE.ActiveProject 获得。(单元 LazIDEIntf)
673+目前的主要项目可以通过 LazarusIDE.ActiveProject 获得。(单元 LazIDEIntf)
739674
740675## 当前项目的所有单元
741676
742-请注意,术语“项目单元”是不明确的。
677+请注意,术语“项目单元”是不明确的。
743678
744- * 项目检查器显示 .lpi 文件的列表。该项目可能不会在所有平台上使用所有这些单元,也许开发人员忘记添加所有使用过的单元。
745- * 使用过的包中的单元不是项目单元。
679+- 项目检查器显示 .lpi 文件的列表。该项目可能不会在所有平台上使用所有这些单元,也许开发人员忘记添加所有使用过的单元。
680+- 使用过的包中的单元不是项目单元。
746681
747682### 项目检查员的所有单元
748683
749-要遍历项目检查器中列出的所有 pascal 单元,您可以使用例如:
750-```
684+要遍历项目检查器中列出的所有 pascal 单元,您可以使用例如:
685+
686+``` pascal
751687uses
752- LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
753-
754- procedure ListProjectUnits;
755- var
756- LazProject: TLazProject;
757- i: Integer;
758- LazFile: TLazProjectFile;
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
759699 begin
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;
700+ LazFile:=LazProject.Files[i];
701+ if LazFile.IsPartOfProject
702+ and FilenameIsPascalUnit(LazFile.Filename)
703+ then
704+ debugln(LazFile.Filename);
770705 end;
706+end;
771707```
772708
773709### 所有用过的项目单元
774710
775-要查找项目 / 包的所有当前使用单元,您可以使用以下内容。请注意,IDE 需要解析所有单元,因此可能需要一些时间。
776-```
711+要查找项目 / 包的所有当前使用单元,您可以使用以下内容。请注意,IDE 需要解析所有单元,因此可能需要一些时间。
712+
713+``` pascal
777714uses
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;
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;
796731 end;
732+ end;
733+end;
797734```
798735
799736## 项目的 .lpr、.lpi 和 .lps 文件
800-```
737+
738+``` pascal
801739uses
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;
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;
819757```
820758
821759## 项目的可执行文件 / 目标文件名
822760
823-有一个宏 $(TargetFile),可用于路径和外部工具。您可以在代码中查询宏:
824-```
761+有一个宏 \$(TargetFile),可用于路径和外部工具。您可以在代码中查询宏:
762+
763+``` pascal
825764uses MacroIntf;
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;
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;
833772```
834773
835-有关更多宏的信息,请参阅此处:[[IDE Macros in paths and filenames]]。
774+有关更多宏的信息,请参阅此处:[[IDE Macros in paths and filenames]]。
836775
837776## 添加您自己的项目类型
838777
839-您可以在“新建 ...”对话框中添加项目:
778+您可以在“新建 ...”对话框中添加项目:
840779
841- * 请参阅 IDEIntf 包的单元 ProjectIntf。
842- * 请参阅项目模板
780+- 请参阅 IDEIntf 包的单元 ProjectIntf。
781+- 请参阅项目模板
843782
844783## 添加您自己的文件类型
845784
846-您可以在“新建 ...”对话框中添加项目:
785+您可以在“新建 ...”对话框中添加项目:
847786
848- * 请参阅 IDEIntf 包的单元 ProjectIntf。
849- * 为普通单元选择基类 TFileDescPascalUnit,为新表单 / 数据模块选择 TFileDescPascalUnitWithResource。
787+- 请参阅 IDEIntf 包的单元 ProjectIntf。
788+- 为普通单元选择基类 TFileDescPascalUnit,为新表单 / 数据模块选择 TFileDescPascalUnitWithResource。
850789
851790## 添加新文件类型
852-```
791+
792+``` pascal
853793uses ProjectIntf;
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;
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;
893833```
894834
895835### 添加新表单类型
896-```
836+
837+``` pascal
897838uses ProjectIntf;
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;
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;
942883```
943884
944885## 以 lpi/lps 存储自定义值
945886
946-您可以通过 CustomData 和 CustomSessionData 中的键值对存储您自己的数据。
947-```
948-LazarusIDE.ActiveProject.CustomData['Name'] := Value ; // 存储在 lpi-x-platform 中,共享数据
949- LazarusIDE.ActiveProject.CustomSessionData['Name'] := Value ; // 存储在 lps 中 - 只有本机
950-```
887+您可以通过 CustomData 和 CustomSessionData 中的键值对存储您自己的数据。
951888
889+` LazarusIDE.ActiveProject.CustomData['Name'] := Value ; // 存储在 lpi-x-platform 中,共享数据`\
890+` LazarusIDE.ActiveProject.CustomSessionData['Name'] := Value ; // 存储在 lps 中 - 只有本机`
891+
952892# 包
953893
954-您可以使用 Packages 执行各种操作:
894+您可以使用 Packages 执行各种操作:
955895
956896## 搜索所有包
957897
958-迭代 IDE 中加载的所有包(自 0.9.29 起)。
959-```
898+迭代 IDE 中加载的所有包(自 0.9.29 起)。
899+
900+``` pascal
960901uses PackageIntf;
961- ...
962- for i:=0 to PackageEditingInterface.GetPackageCount-1 do
963- writeln(PackageEditingInterface.GetPackages(i).Name);
902+...
903+for i:=0 to PackageEditingInterface.GetPackageCount-1 do
904+ writeln(PackageEditingInterface.GetPackages(i).Name);
964905```
965906
966907## 搜索包含名称的包
967-```
908+
909+``` pascal
968910uses PackageIntf;
911+...
912+var
913+ Pkg: TIDEPackage;
914+begin
915+ Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
916+ if Pkg<>nil then
969917 ...
970- var
971- Pkg: TIDEPackage;
972- begin
973- Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
974- if Pkg<>nil then
975- ...
976- end;
918+end;
977919```
978920
979-注意:FindPackageWithName 不会打开包编辑器。为此使用 DoOpenPackageWithName。
921+注意:FindPackageWithName 不会打开包编辑器。为此使用 DoOpenPackageWithName。
980922
981923## 获取已安装软件包的 lpk 文件名
982-```
924+
925+``` pascal
983926uses PackageIntf;
984- ...
985- var
986- Pkg: TIDEPackage;
987- begin
988- Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
989- if Pkg<>nil then
990- LPKFilename:=Pkg.Filename;
991- end;
927+...
928+var
929+ Pkg: TIDEPackage;
930+begin
931+ Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
932+ if Pkg<>nil then
933+ LPKFilename:=Pkg.Filename;
934+end;
992935```
993936
994937## 安装包
995938
996-注意:仅安装带有 IDE 插件的软件包。安装其他软件包可能会使 IDE 不稳定。
997-```
939+注意:仅安装带有 IDE 插件的软件包。安装其他软件包可能会使 IDE 不稳定。
940+
941+``` pascal
998942uses PackageIntf, contnrs;
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;
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;
1015959```
1016960
1017961## 打开包文件(lpk)
1018-```
962+
963+``` pascal
1019964uses PackageIntf, FileUtil;
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;
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;
1029974```
1030975
1031-[![Warning-icon.png](/wiki-images/b/b2/Warning-icon.png)](</File:Warning-icon.png>)
1032-
1033-**Warning:** IDE 会在空闲时自动关闭未使用的软件包。永远不要引用 TIDEPackage。
976+> **Warning:** IDE 会在空闲时自动关闭未使用的软件包。永远不要引用 TIDEPackage。
1034977
1035978## 找到一个单元的包裹
1036979
1037-你有一个单元的文件名,例如 '/home/user/unit.pas',你想知道它属于哪个包和项目使用这个:
1038-```
980+你有一个单元的文件名,例如 '/home/user/unit.pas',你想知道它属于哪个包和项目使用这个:
981+
982+``` pascal
1039983uses Classes, PackageIntf, ProjectIntf;
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]);
1054- 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;
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);
10671007 end;
1008+ end;
1009+ finally
1010+ Owners.Free;
1011+ end;
10681012```
10691013
10701014## 查找项目 / 包所需的包
10711015
1072-您有一个项目或包,并且您想知道需要哪个包,使用:
1073-```
1016+您有一个项目或包,并且您想知道需要哪个包,使用:
1017+
1018+``` pascal
10741019uses Classes, PackageIntf, ProjectIntf;
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- ...
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+...
10891034```
10901035
10911036# 窗口(Windows)
10921037
1093-基本上有四种类型的 IDE 窗口。
1038+基本上有四种类型的 IDE 窗口。
10941039
1095- * 主 IDE 栏是 Application.MainForm。它始终存在。
1096- * 浮动 / 可停靠窗口,如源代码编辑器,对象检查器和消息。
1097- * 模态表单,如查找对话框,选项对话框和问题。
1098- * 提示和完成表格
1040+- 主 IDE 栏是 Application.MainForm。它始终存在。
1041+- 浮动 / 可停靠窗口,如源代码编辑器,对象检查器和消息。
1042+- 模态表单,如查找对话框,选项对话框和问题。
1043+- 提示和完成表格
10991044
11001045## 添加新的可停靠 IDE 窗口
11011046
1102-什么是可停靠的 IDE 窗口:像源代码编辑器或对象检查器这样的 Windows 是浮动窗口,如果安装了扩展包,则可以停靠它,并在下次 IDE 启动时存储和恢复其状态,位置和大小。为了恢复窗口,IDE 需要在 IDEIntf 包的单元 IDEWindowIntf 中定义的创建者。每个可停靠窗口必须具有唯一名称。不要使用像 'FileBrowser' 这样的通用名称,因为这很容易与其他包冲突。并且不要使用像“XYZ”这样的短名称,因为创建者负责以此名称开头的所有表单。
1047+什么是可停靠的 IDE 窗口:像源代码编辑器或对象检查器这样的 Windows 是浮动窗口,如果安装了扩展包,则可以停靠它,并在下次 IDE 启动时存储和恢复其状态,位置和大小。为了恢复窗口,IDE 需要在 IDEIntf 包的单元 IDEWindowIntf 中定义的创建者。每个可停靠窗口必须具有唯一名称。不要使用像 'FileBrowser' 这样的通用名称,因为这很容易与其他包冲突。并且不要使用像“XYZ”这样的短名称,因为创建者负责以此名称开头的所有表单。
11031048
11041049### 如何注册可停靠的 IDE 窗口
11051050
1106-请记住选择一个有效的 pascal 标识符的长唯一名称。您的窗口可以包含您想要的任何标题。
1107-```
1051+请记住选择一个有效的 pascal 标识符的长唯一名称。您的窗口可以包含您想要的任何标题。
1052+
1053+``` pascal
11081054uses SysUtils, IDEWindowIntf;
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;
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;
11291075```
11301076
11311077### 显示 IDE 窗口
11321078
1133-不要使用 Show。使用:
1134-```
1079+不要使用 Show。使用:
1080+
1081+``` pascal
11351082IDEWindowCreators.ShowForm(MyIDEWindow,false);
11361083```
11371084
1138-这将适用于对接。对接系统可以将表格包裹到对接站点中。BringToFront 参数告诉对接系统使表单及其所有父站点可见,并将顶层站点放在前面。
1085+这将适用于对接。对接系统可以将表格包裹到对接站点中。BringToFront 参数告诉对接系统使表单及其所有父站点可见,并将顶层站点放在前面。
11391086
11401087### 有关 IDEWindowCreators 和 SimpleLayoutStorage 的注释
11411088
1142-IDEWindowCreators.SimpleLayoutStorage 只存储曾经打开过的所有表单的 BoundsRect 和 WindowState。如果没有安装 dockmaster,它将用作后备。即使安装了 DockMaster,它也会存储状态,因此在卸载 dockmaster 时,将恢复表单边界。
1089+IDEWindowCreators.SimpleLayoutStorage 只存储曾经打开过的所有表单的 BoundsRect 和 WindowState。如果没有安装 dockmaster,它将用作后备。即使安装了 DockMaster,它也会存储状态,因此在卸载 dockmaster 时,将恢复表单边界。
11431090
1144-所有可停靠表单都使用 IDEWindowCreators 来注册自己并显示表单。在显示表单时,Creator 会检查是否安装了 IDEDockMaster,并将显示委托给它。如果没有安装 IDEDockMaster,它只显示表单。IDEDockMaster 可以使用 IDEWindowCreators 中的信息按名称创建表单,并在第一次显示表单时了解放置表单的位置。有关更多详细信息,请参阅包 AnchorDockingDsgn 和 EasyDockMgDsgn。
1091+所有可停靠表单都使用 IDEWindowCreators 来注册自己并显示表单。在显示表单时,Creator 会检查是否安装了 IDEDockMaster,并将显示委托给它。如果没有安装 IDEDockMaster,它只显示表单。IDEDockMaster 可以使用 IDEWindowCreators 中的信息按名称创建表单,并在第一次显示表单时了解放置表单的位置。有关更多详细信息,请参阅包 AnchorDockingDsgn 和 EasyDockMgDsgn。
11451092
11461093# 代码工具
11471094
1148-CodeTools 是一个包,提供了大量的功能来解析、搜索和更改 pascal 源代码以及其他语言的一些基本功能。您也可以在没有 IDE 的情况下使用它们。在 IDE 中使用它们之前,建议您首先阅读 [[Codetools]]。
1095+CodeTools 是一个包,提供了大量的功能来解析、搜索和更改 pascal 源代码以及其他语言的一些基本功能。您也可以在没有 IDE 的情况下使用它们。在 IDE 中使用它们之前,建议您首先阅读 [[Codetools]]。
11491096
1150-在调用 IDE 中的任何 CodeTools 函数之前,您应该将源代码编辑器的当前更改提交到 CodeTools 缓冲区:
1151-```
1097+在调用 IDE 中的任何 CodeTools 函数之前,您应该将源代码编辑器的当前更改提交到 CodeTools 缓冲区:
1098+
1099+``` pascal
11521100uses LazIDEIntf;
1153- ...
1154- // 将源代码编辑器中的更改保存到 codetools
1155- LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1:提交所有源代码编辑器
1101+...
1102+ // 将源代码编辑器中的更改保存到 codetools
1103+ LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1:提交所有源代码编辑器
11561104```
11571105
11581106## 将资源指令添加到文件中
11591107
1160-这为 pascal 单元添加 {$R example.res}:
1161-```
1108+这为 pascal 单元添加 {\$R example.res}:
1109+
1110+``` pascal
11621111procedure AddResourceDirectiveToPascalSource(const Filename: string);
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;
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;
11801129```
11811130
1182-codetools 还提供 FindResourceDirective 和 RemoveDirective 等函数。
1131+codetools 还提供 FindResourceDirective 和 RemoveDirective 等函数。
11831132
11841133## 获取单元和包含文件的搜索路径
11851134
1186-IDE 中有许多不同的搜索路径来自项目,包,fpc 和 lazarus 目录,并且有许多类型的路径:在解析宏之前或之后,有或没有继承的搜索路径,作为相对路径或绝对路径。目录中的所有文件共享同一组搜索路径。您可以通过询问 codetools 来完全解析每个目录的搜索路径:
1187-```
1135+IDE 中有许多不同的搜索路径来自项目,包,fpc 和 lazarus 目录,并且有许多类型的路径:在解析宏之前或之后,有或没有继承的搜索路径,作为相对路径或绝对路径。目录中的所有文件共享同一组搜索路径。您可以通过询问 codetools 来完全解析每个目录的搜索路径:
1136+
1137+``` pascal
11881138uses CodeToolManager;
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);
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);
12061156```
12071157
12081158# 源代码编辑
12091159
12101160## 激活源代码编辑器
1211-```
1161+
1162+``` pascal
12121163uses SrcEditorIntf;
1213- ...
1214- Editor:=SourceEditorManagerIntf.ActiveEditor;
1215- if Editor=nil then exit;
1216- Filename:=Editor.FileName;
1217- ScreenPos:=Editor.CursorScreenXY;
1218- TextPos:=Editor.CursorTextXY;
1164+...
1165+Editor:=SourceEditorManagerIntf.ActiveEditor;
1166+if Editor=nil then exit;
1167+Filename:=Editor.FileName;
1168+ScreenPos:=Editor.CursorScreenXY;
1169+TextPos:=Editor.CursorTextXY;
12191170```
12201171
12211172# SynEdit
12221173
12231174## 获取 TSynEdit 的设置
12241175
1225-当您使用 TSynEdit 进行对话时,如果要使用与源代码编辑器相同的字体和设置,请使用:
1226-```
1176+当您使用 TSynEdit 进行对话时,如果要使用与源代码编辑器相同的字体和设置,请使用:
1177+
1178+``` pascal
12271179uses SrcEditorIntf;
1228- ...
1229- SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
1180+...
1181+SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
12301182```
12311183
12321184## 获取 SynEdit 的高亮设置
12331185
1234-如果您有一个带有高亮的 TSynEdit 的对话框,并且您希望使用与源代码编辑器高亮相同的颜色来使用此语言:
1186+如果您有一个带有高亮的 TSynEdit 的对话框,并且您希望使用与源代码编辑器高亮相同的颜色来使用此语言:
12351187
1236-使
1237-```
1188+使
1189+
1190+``` pascal
12381191uses SrcEditorIntf;
1239- ...
1240- SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
1192+...
1193+SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
12411194```
12421195
1243-请参阅示例:[SQLStringsPropertyEditorDlg](<http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas>) 单元中的 TSQLStringsPropertyEditorDlg.Create。
1196+请参阅示例:[SQLStringsPropertyEditorDlg](http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas) 单元中的 TSQLStringsPropertyEditorDlg.Create。
12441197
12451198# 帮助
12461199
12471200## 添加源的帮助
12481201
1249-首先创建一个 THelpDatabase:
1250-```
1202+首先创建一个 THelpDatabase:
1203+
1204+``` pascal
12511205HelpDB := TFPDocHTMLHelpDatabase(
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);
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);
12631217```
12641218
12651219## 在消息窗口中添加行
1266-```
1220+
1221+``` pascal
12671222unit IDEMsgIntf;
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;
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;
12761231```
12771232
12781233# IDE 选项框架
12791234
12801235## 打开特定框架中的选项
1281-```
1236+
1237+``` pascal
12821238uses LazIDEIntf;
1283- ...
1284- LazarusIDE.DoOpenIDEOptions(TYourIDEOptionsFrame);
1239+...
1240+LazarusIDE.DoOpenIDEOptions(TYourIDEOptionsFrame);
12851241```
12861242
12871243# 其它
12881244
12891245## 添加宏
12901246
1291-您可以添加自己的 IDE 宏:
1292-```
1247+您可以添加自己的 IDE 宏:
1248+
1249+``` pascal
12931250uses MacroIntf, MacroDefIntf;
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;
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;
13161273```
13171274
13181275## 调试 IDE
13191276
1320- * 像往常一样编译 IDE,例如通过 Tools/Build Lazarus。确保设置调试标志,如 -g 或 -gw2。最好是使用配置文件“Debug IDE”,其中包含许多用于调试的标志。
1321- * 打开 ide \ lazarus.lpi 项目。您无法直接编译此项目。
1322- * 根据需要设置断点等运行项目。
1277+- 像往常一样编译 IDE,例如通过 Tools/Build Lazarus。确保设置调试标志,如 -g 或 -gw2。最好是使用配置文件“Debug IDE”,其中包含许多用于调试的标志。
1278+- 打开 ide \\ lazarus.lpi 项目。您无法直接编译此项目。
1279+- 根据需要设置断点等运行项目。
13231280
13241281## 另请参见
13251282
1326- * [[Creating IDE Help]]
1327- * [[Help protocol]]
1328- * [[How To Write Lazarus Component]]
1283+- [[Creating IDE Help]]
1284+- [[Help protocol]]
1285+- [[How To Write Lazarus Component]]
13291286
13301287---
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).*
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).*

Back to history