1 { Copyright (C) 2007 Salvatore Coppola
2 
3   This library is free software; you can redistribute it and/or modify it
4   under the terms of the GNU Library General Public License as published by
5   the Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but WITHOUT
9   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
11   for more details.
12 
13   You should have received a copy of the GNU Library General Public License
14   along with this library; if not, write to the Free Software Foundation,
15   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
16 
17   Abstract:
18   This unit is a message dialog composer for Lazarus/FPC.
19   It takes into account all message dialogs platform indpendently.
20 }
21 
22 unit MessageComposer;
23 
24 {$mode objfpc}{$H+}
25 
26 interface
27 
28 uses
29   Classes, SysUtils,
30   // LCL
31   LResources, LCLType, Forms, Controls, Graphics, Dialogs,
32   StdCtrls, ExtCtrls, Spin, Grids, ActnList, Buttons, EditBtn,
33   // LazUtils
34   UITypes,
35   // IdeIntf
36   IDECommands, MenuIntf, LazIDEIntf, SrcEditorIntf;
37 
38 type
39 
40   { TFormMessagesComposer }
41 
42   TFormMessagesComposer = class(TForm)
43     HCenterBevel: TBevel;
44     HCenterBevel1: TBevel;
45     HCenterBevel2: TBevel;
46     KindMessageComboBox: TComboBox;
47     KindMessageLabel: TLabel;
48     MsgMemo: TMemo;
49     ButtonsNotebook: TNotebook;
50     PageString: TPage;
51     ButtonPanel: TPanel;
52     PositionBevel1: TBevel;
53     SourceNotebook: TNotebook;
54     Page1: TPage;
55     Page2: TPage;
56     PageIf: TPage;
57     PageCase: TPage;
58     UpdateQuestioDlgResult: TAction;
59     SetIfOrCase: TAction;
60     PositionBevel: TBevel;
61     Bevel2: TBevel;
62     HelpCtxBevel: TBevel;
63     CaseResultCheckGroup: TCheckGroup;
64     BeginEndCheckBox: TCheckBox;
65     IfResultComboBox: TComboBox;
66     StringResultEdit: TEdit;
67     GetParamsFmt: TAction;
68     OkButton: TBitBtn;
69     CancelButton: TBitBtn;
70     GetMessageForSource: TAction;
71     Label1: TLabel;
72     StringResultLabel: TLabel;
73     IfThenRadioButton: TRadioButton;
74     IfThenElseRadioButton: TRadioButton;
75     CaseOfEndRadioButton: TRadioButton;
76     CaseOfEndElseRadioButton: TRadioButton;
77     SourceWrapperGroupBox: TGroupBox;
78     Test: TAction;
79     TestButton: TButton;
80     MaskInputCheckBox: TCheckBox;
81     PromptEdit: TEdit;
82     ValueEdit: TEdit;
83     PromptLabel: TLabel;
84     HelpFileNameEdit: TFileNameEdit;
85     HelpFileNameLabel: TLabel;
86     MessagesInit: TAction;
87     DefaultEdit: TEdit;
88     ValueLabel: TLabel;
89     DefaultValue: TLabel;
90     XLabel: TLabel;
91     YLabel: TLabel;
92     MessageSetup: TAction;
93     BitBtn1: TBitBtn;
94     BitBtn2: TBitBtn;
95     DelConst: TAction;
96     AddConst: TAction;
97     ActionList1: TActionList;
98     CaptionEdit: TEdit;
99     ButtonsCheckGroup: TCheckGroup;
100     DlgTypeComboBox: TComboBox;
101     DlgTypeLabel: TLabel;
102     HelpKeyWordEdit: TEdit;
103     HelpContextLabel: TLabel;
104     HelpKeyWordLabel: TLabel;
105     CaptionLabel: TLabel;
106     MsgLabel: TLabel;
107     HelpContextSpinEdit: TSpinEdit;
108     ButtonsStringGrid: TStringGrid;
109     ButtonsPanel: TPanel;
110     Panel2: TPanel;
111     XSpinEdit: TSpinEdit;
112     YSpinEdit: TSpinEdit;
113     procedure AddConstExecute(Sender: TObject);
114     procedure ButtonsCheckGroupItemClick(Sender: TObject; {%H-}Index: integer);
115     procedure ButtonsStringGridSelectEditor(Sender: TObject; aCol,
116       {%H-}aRow: Integer; var Editor: TWinControl);
117     procedure DelConstExecute(Sender: TObject);
118     procedure FormShow(Sender: TObject);
119     procedure GetMessageForSourceExecute(Sender: TObject);
120     procedure GetParamsFmtExecute(Sender: TObject);
121     procedure MessageSetupExecute(Sender: TObject);
122     procedure MessagesInitExecute(Sender: TObject);
123     procedure SetIfOrCaseExecute(Sender: TObject);
124     procedure TestExecute(Sender: TObject);
125     procedure UpdateQuestioDlgResultExecute(Sender: TObject);
126   private
127 
128   public
129 
130   end;
131 
132 procedure Register;
133 
134 var
135   srcMessage: string;
136 
137 implementation
138 
139 {$R *.lfm}
140 
141 const
142   cMessageComposer = 'Message Composer';
143   DoubleSpace = '  ';
144   idxPageIf = 0;
145   idxPageCase = 1;
146   idxPageString = 2;
147 
148 type
149   TComposedMsgKind = (
150     cmkMsgDlgSimple,             //MessageDlg[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx]
151     cmkMsgDlgCaption,            //MessageDlg[Caption, Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx]
152     cmkMsgDlgCaptionHelpKeyWord, //MessageDlg[Caption, Msg, DlgType, Buttons(TMsgDlgButtons), HelpKeyword]
153     cmkMsgDlgPosSimple,          //MessageDlgPos[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx, X, Y]
154     cmkMsgDlgPosHelpSimple,      //MessageDlgPosHelp[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx, X, Y, HelpFileName]
155     cmkQDlgHelpCtx,              //QuestionDlg[Caption, Msg, DlgType, Buttons(array of const), HelpCtx]
156     cmkQDlgHelpKeyword,          //QuestionDlg[Caption, Msg, DlgType, Buttons(array of const), HelpKeyword]
157     cmkShowMsg,                  //ShowMessage[Msg: string];
158     cmkShowMsgFmt,               //ShowMessageFmt[Msg, Params(array of const)];
159     cmkShowMsgPos,               //ShowMessagePos[Msg, X, Y];
160     cmkInpQMask,                 //InputQuery[Caption, Prompt, MaskInput(Boolean), Value(String)]
161     cmkInpQSimple,               //InputQuery[Caption, Prompt, Value(String)]
162     cmkInpBox,                   //InputBox[Caption, Prompt, Default]
163     cmkPasswBox                  //PasswordBox[Caption, Prompt]
164   );
165 
166   const ComposedMsgStrings: array[TComposedMsgKind] of string = (
167     'MessageDlg[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx]',
168     'MessageDlg[Caption, Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx]',
169     'MessageDlg[Caption, Msg, DlgType, Buttons(TMsgDlgButtons), HelpKeyword]',
170     'MessageDlgPos[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx, X, Y]',
171     'MessageDlgPosHelp[Msg, DlgType, Buttons(TMsgDlgButtons), HelpCtx, X, Y, HelpFileName]',
172     'QuestionDlg[Caption, Msg, DlgType, Buttons(array of const), HelpCtx]',
173     'QuestionDlg[Caption, Msg, DlgType, Buttons(array of const), HelpKeyword]',
174     'ShowMessage[Msg: string];',
175     'ShowMessageFmt[Msg, Params(array of const)];',
176     'ShowMessagePos[Msg, X, Y];',
177     'InputQuery[Caption, Prompt, MaskInput(Boolean), Value(String)]',
178     'InputQuery[Caption, Prompt, Value(String)]',
179     'InputBox[Caption, Prompt, Default]',
180     'PasswordBox[Caption, Prompt]'
181   );
182 
183 
184 
185 
186 resourcestring
187   SMessageComposerMenuCaption = 'Message Composer ...';
188   SMessageComposerCaption = 'Message Composer';
189   SMsgCaption = 'The message to be shown';
190   SDlgCaption = 'Dialog caption';
191   SDlgType = 'Dialog type';
192   SPromptCaption = 'Text asking the user for input';
193   SMaskInput = 'Mask input';
194   SSourceWrapper = 'Source wrapper';
195   SKindofMessage = 'Kind of message';
196   SNotImplementedYet = 'Not implemented yet';
197   rsTest = 'Test';
198   rsOk = 'OK';
199   rsCancel = 'Cancel';
200   SHelpContext = 'Help context';
201   SHelpKeyword = 'Help keyword';
202   SHelpFilename = 'Help filename';
203   SValueVar = 'Value (var)';
204   SDefault = 'Default';
205   SButtonsTMsgDlgButtons = 'Buttons (TMsgDlgButtons)';
206   SAdd = 'Add';
207   SDelete = 'Delete';
208   SButtonsArrayOfConst = 'Buttons (array of const)';
209   SModalResult = 'Modal result';
210   SIfResult = '"If" result';
211   SCaseResult = '"Case" result';
212 
213 var
214   CmdMessageComposer: TIDECommand;
215 
216 
217 
218 { This is where it all starts. Gets called from Lazarus. }
219 procedure ExecuteMessagesComposer(Sender: TObject);
220 var FormMessagesComposer: TFormMessagesComposer;
221 
222   procedure FormatSrcMessage;
223   var ListSrcMessages: TStringList;
224       indx: integer;
225       BaseStart: string;
226   begin
227     BaseStart := EmptyStr;
228     for indx := 1 to SourceEditorManagerIntf.ActiveEditor.CursorTextXY.x-
229                      Length(SourceEditorManagerIntf.ActiveEditor.Selection)-1 do
230       BaseStart := BaseStart+#32;
231 
232     ListSrcMessages := TStringList.Create;
233     ListSrcMessages.Text := srcMessage;
234     if (Pos('if ',srcMessage) = 1)or(Pos('case ',srcMessage) = 1) then
235       for indx := 1 to ListSrcMessages.Count-1 do
236         ListSrcMessages.Strings[indx] := BaseStart+ListSrcMessages.Strings[indx];
237 
238     if Pos('case ',srcMessage) = 1 then
239       for indx := 1 to ListSrcMessages.Count-2 do
240         ListSrcMessages.Strings[indx] := DoubleSpace+ListSrcMessages.Strings[indx];
241 
242     srcMessage := ListSrcMessages.Text;
243     ListSrcMessages.Free;
244   end;
245 
246 begin
247   Assert(Sender <> nil);  // removes compiler warning
248   if SourceEditorManagerIntf.ActiveEditor = nil then exit;
249   FormMessagesComposer := TFormMessagesComposer.Create(nil);
250   try
251     FormMessagesComposer.ShowModal;
252     if FormMessagesComposer.ModalResult = mrOK then  begin
253       FormMessagesComposer.GetMessageForSource.Execute;
254       FormatSrcMessage;
255       SourceEditorManagerIntf.ActiveEditor.Selection := srcMessage;
256     end;
257   finally
258     FormMessagesComposer.Free;
259   end;
260 end;
261 
262 { TFormMessagesComposer }
263 
264 procedure TFormMessagesComposer.AddConstExecute(Sender: TObject);
265 begin
266   ButtonsStringGrid.RowCount := ButtonsStringGrid.RowCount+1;
267   ButtonsStringGrid.AutoAdjustColumns;
268   UpdateQuestioDlgResult.Execute;
269 end;
270 
271 procedure TFormMessagesComposer.ButtonsCheckGroupItemClick(Sender: TObject;
272   Index: integer);
273 begin
274   MessageSetup.Execute;
275 end;
276 
277 procedure TFormMessagesComposer.ButtonsStringGridSelectEditor(Sender: TObject; aCol,
278   aRow: Integer; var Editor: TWinControl);
279 var
280   ComposedMsgKind: TComposedMsgKind;
281 begin
282   if aCol<>1 then exit;
283   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
284   case ComposedMsgKind of
285     cmkQDlgHelpCtx, cmkQDlgHelpKeyword: begin
286       Editor := TStringGrid(Sender).EditorByStyle(cbsPickList);
287       TPickListCellEditor(Editor).Style := csDropDownList;
288       TPickListCellEditor(Editor).Clear;
289       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrNone]);
290       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrOK]);
291       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrCancel]);
292       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrAbort]);
293       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrRetry]);
294       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrIgnore]);
295       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrYes]);
296       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrNo]);
297       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrAll]);
298       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrNoToAll]);
299       TPickListCellEditor(Editor).Items.Add(ModalResultStr[mrYesToAll]);
300     end;
301     cmkShowMsgFmt: begin
302       Editor := TStringGrid(Sender).EditorByStyle(cbsAuto);
303 //D Decimal format. Precision digits in it
304 //E Scientific format. Args is a Floating point value. Precision is used to specify the total number of decimals (exponent is3 digits)
305 //F Fixed point format. Args is a floating point value. Precision indicates the number of digits following the decimal point.
306 //G General number format. Args is a floating point value. The argument is converted to a decimal string using fixed point notation or scientific notation, depending on which gives the shortest result. Precision is used to determine the number of digits after the decimal point.
307 //M Currency format. Args must be a floating point value. The argument is converted to a decimal string using currency notation. This means that fixed-point notation is used, but that the currency symbol is appended. If precision is specified, then then it overrides the CurrencyDecimals global variable used in the FloatToStrF
308 //N Number format. This is the same as fixed point format, except that thousand separators are inserted in the resulting string.
309 //P Pointer format. The next argument in the Args array must be a pointer (typed or untyped). The pointer value is converted to a string of length 8, representing the hexadecimal value of the pointer.
310 //S String format. The next argument in the Args array must be a string. The argument is simply copied to the result string. If Precision is specified, then only Precision characters are copied to the result string.
311 //U Unsigned decimal format. The next argument in the Args array should be an unsigned integer. The argument is converted to a decimal string. If precision is specified, then the string will have at least Precision digits in it. If needed, the string is (left) padded with zeroes.
312 //X hexadecimal format. The next argument in the Args array must be an integer. The argument is converted to a hexadecimal string with just enough characters to contain the value of the integer. If Precision is specified then the resulting hexadecimal representation will have at least Precision characters in it (with a maximum value of 32).
313     end;
314   end;
315   ButtonsStringGrid.AutoAdjustColumns;
316 end;
317 
318 procedure TFormMessagesComposer.DelConstExecute(Sender: TObject);
319 begin
320   if ButtonsStringGrid.RowCount = 1 then exit;
321   ButtonsStringGrid.RowCount := ButtonsStringGrid.RowCount-1;
322   ButtonsStringGrid.AutoAdjustColumns;
323   UpdateQuestioDlgResult.Execute;
324 end;
325 
326 procedure TFormMessagesComposer.FormShow(Sender: TObject);
327 begin
328   OKButton.Constraints.MinWidth := CancelButton.Width;
329   TestButton.Constraints.MinWidth := CancelButton.Width;
330 end;
331 
332 procedure TFormMessagesComposer.GetMessageForSourceExecute(Sender: TObject);
333 var Msg, MsgCaption, MsgHelpKeyword, HelpFileName, Prompt, MsgDefault,
334     Value, DlgType, MsgButtons, HelpCtx, X, Y, strParam: string;
335     i: integer;
336     intParam: integer;
337     floatParam: double;
338     ComposedMsgKind: TComposedMsgKind;
339 const
340   BoolS: Array[Boolean] of String = ('False','True');
341 begin
342   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
343   Msg := QuotedStr(MsgMemo.Lines.Text);
344 
345   if Copy(Msg,Length(Msg)-Length(LineEnding),Length(LineEnding))=LineEnding then
346     Delete(Msg,Length(Msg)-Length(LineEnding),Length(LineEnding));
347   i := pos(LineEnding,Msg);
348   while i>0 do begin
349     Delete(Msg,i,Length(LineEnding));
350     system.Insert(QuotedStr('+LineEnding+'),Msg,i);
351     i := pos(LineEnding,Msg)
352   end;
353 
354   DlgType := DlgTypeComboBox.Text;
355   MsgButtons := EmptyStr;
356   if ButtonsNotebook.PageIndex = 0 then begin  //MessageDlg();
357     if ButtonsCheckGroup.Checked[0] then
358       MsgButtons := MsgButtons+' mbYes,';
359     if ButtonsCheckGroup.Checked[1] then
360       MsgButtons := MsgButtons+' mbNo,';
361     if ButtonsCheckGroup.Checked[2] then
362       MsgButtons := MsgButtons+' mbOK,';
363     if ButtonsCheckGroup.Checked[3] then
364       MsgButtons := MsgButtons+' mbCancel,';
365     if ButtonsCheckGroup.Checked[4] then
366       MsgButtons := MsgButtons+' mbAbort,';
367     if ButtonsCheckGroup.Checked[5] then
368       MsgButtons := MsgButtons+' mbRetry,';
369     if ButtonsCheckGroup.Checked[6] then
370       MsgButtons := MsgButtons+' mbIgnore,';
371     if ButtonsCheckGroup.Checked[7] then
372       MsgButtons := MsgButtons+' mbAll,';
373     if ButtonsCheckGroup.Checked[8] then
374       MsgButtons := MsgButtons+' mbNoToAll,';
375     if ButtonsCheckGroup.Checked[9] then
376       MsgButtons := MsgButtons+' mbYesToAll,';
377     if ButtonsCheckGroup.Checked[10] then
378       MsgButtons := MsgButtons+' mbHelp,';
379     if ButtonsCheckGroup.Checked[11] then
380       MsgButtons := MsgButtons+' mbClose,';
381   end else begin //maybe QuestionDlg() or ShowMessageFmt();
382     if ComposedMsgKind=cmkShowMsgFmt then begin //ShowMessageFmt();
383       for i := 1 to ButtonsStringGrid.RowCount-1 do begin
384       //'D', 'E', 'F', 'G', 'M', 'N', 'P', 'S', 'U', 'X' format
385         strParam := #32;
386         if (ButtonsStringGrid.Cells[0, i] = '%D') then begin
387           intParam := StrToIntDef(ButtonsStringGrid.Cells[1, i], 0);
388           strParam := IntToStr(intParam);
389         end;
390         if (ButtonsStringGrid.Cells[0, i] = '%E')or
391            (ButtonsStringGrid.Cells[0, i] = '%F')or
392            (ButtonsStringGrid.Cells[0, i] = '%G')or
393            (ButtonsStringGrid.Cells[0, i] = '%M')or
394            (ButtonsStringGrid.Cells[0, i] = '%N') then begin
395           floatParam := StrToFloatDef(ButtonsStringGrid.Cells[1, i], 0.0);
396           strParam := FloatToStr(floatParam);
397           if pos('.',strParam) = 0 then
398             strParam := strParam+'.0';
399         end;
400         if (ButtonsStringGrid.Cells[0, i] = '%P') then
401           strParam := ButtonsStringGrid.Cells[1, i];//user must knows pointer var in his source
402         if (ButtonsStringGrid.Cells[0, i] = '%S') then
403           strParam := QuotedStr(ButtonsStringGrid.Cells[1, i]);
404         if (ButtonsStringGrid.Cells[0, i] = '%U') then begin
405           intParam := abs(StrToIntDef(ButtonsStringGrid.Cells[1, i], 0));
406           strParam := IntToStr(intParam);
407         end;
408         if (ButtonsStringGrid.Cells[0, i] = '%X') then begin
409           intParam := StrToIntDef(ButtonsStringGrid.Cells[1, i], 0);
410           strParam := IntToStr(intParam);
411         end;
412         if strParam<>#32 then
413           MsgButtons := MsgButtons+#32+strParam+',';
414       end;
415       if strParam=#32 then
416         MsgButtons := strParam+',';
417     end else
418       for i := 1 to ButtonsStringGrid.RowCount-1 do begin
419         if (ButtonsStringGrid.Cells[1, i] = EmptyStr)or
420            (ButtonsStringGrid.Cells[0, i] = EmptyStr) then continue;
421         MsgButtons := MsgButtons+#32+ButtonsStringGrid.Cells[1, i]+', '+
422                       QuotedStr(ButtonsStringGrid.Cells[0, i])+',';
423       end;
424   end;
425   if MsgButtons<>EmptyStr then begin
426     MsgButtons[1] := '[';
427     MsgButtons[Length(MsgButtons)] := ']';
428   end else
429     MsgButtons:='[]';
430   MsgCaption := QuotedStr(CaptionEdit.Text);
431   HelpCtx := HelpContextSpinEdit.Text;
432   MsgHelpKeyword := QuotedStr(HelpKeyWordEdit.Text);
433   HelpFileName := QuotedStr(HelpFileNameEdit.Text);
434   X := XSpinEdit.Text;
435   Y := YSpinEdit.Text;
436   Prompt := QuotedStr(PromptEdit.Text);
437   MsgDefault := QuotedStr(DefaultEdit.Text);
438   Value := ValueEdit.Text;//user must knows Value var in his source
439   case ComposedMsgKind of
440     cmkMsgDlgSimple: srcMessage := 'MessageDlg('+Msg+', '+DlgType+', '+MsgButtons+','+HelpCtx+')';
441     cmkMsgDlgCaption: srcMessage := 'MessageDlg('+MsgCaption+', '+Msg+', '+DlgType+', '+
442                                    MsgButtons+', '+HelpCtx+')';
443     cmkMsgDlgCaptionHelpKeyWord: srcMessage := 'MessageDlg('+MsgCaption+', '+Msg+', '+DlgType+', '+
444                                    MsgButtons+', '+MsgHelpKeyword+')';
445     cmkMsgDlgPosSimple: srcMessage := 'MessageDlgPos('+Msg+', '+DlgType+', '+MsgButtons+', '+
446                                       HelpCtx+', '+X+', '+Y+')';
447     cmkMsgDlgPosHelpSimple: srcMessage := 'MessageDlgPosHelp('+Msg+', '+DlgType+', '+MsgButtons+', '+
448                                           HelpCtx+', '+X+', '+Y+', '+HelpFileName+')';
449     cmkQDlgHelpCtx: srcMessage := 'QuestionDlg('+MsgCaption+', '+Msg+', '+DlgType+', '+
450                                     MsgButtons+', '+HelpCtx+')';
451     cmkQDlgHelpKeyword: srcMessage := 'QuestionDlg('+MsgCaption+', '+Msg+', '+DlgType+', '+
452                                     MsgButtons+', '+MsgHelpKeyword+')';
453     cmkShowMsg: srcMessage := 'ShowMessage('+Msg+')';
454     cmkShowMsgFmt: srcMessage := 'ShowMessageFmt('+Msg+', '+MsgButtons+')';
455     cmkShowMsgPos: srcMessage := 'ShowMessagePos('+Msg+', '+X+', '+Y+')';
456     cmkInpQMask: srcMessage := 'InputQuery('+MsgCaption+', '+Prompt+', '+
457                                 BoolS[MaskInputCheckBox.Checked]+', '+Value+')';
458     cmkInpQSimple: srcMessage := 'InputQuery('+MsgCaption+', '+Prompt+', '+Value+')';
459     cmkInpBox: srcMessage := 'InputBox('+MsgCaption+', '+Prompt+', '+MsgDefault+')';
460     cmkPasswBox: srcMessage := 'PasswordBox('+MsgCaption+', '+Prompt+')'
461   end;
462 
463   if SourceWrapperGroupBox.Enabled then begin //no showmessages
464     if (IfThenRadioButton.Checked)or(IfThenElseRadioButton.Checked) then begin
465       srcMessage := 'if '+srcMessage+' = ';
466       if SourceNoteBook.PageIndex <> idxPageString then
467         srcMessage := srcMessage+IfResultComboBox.Text
468       else
469         srcMessage := srcMessage+QuotedStr(StringResultEdit.Text);
470       srcMessage := srcMessage+' then';
471       if BeginEndCheckBox.Checked then
472         srcMessage := srcMessage+' begin '+LineEnding+'end';
473     end;
474     if IfThenElseRadioButton.Checked then begin
475       srcMessage := srcMessage+LineEnding+'else';
476       if BeginEndCheckBox.Checked then
477         srcMessage := srcMessage+' begin '+LineEnding+'end';
478     end;
479     if CaseOfEndRadioButton.Checked then begin
480       srcMessage := 'case '+srcMessage+' of'+LineEnding;
481       for i := 0 to CaseResultCheckGroup.Items.Count-1 do begin
482         if not CaseResultCheckGroup.Checked[i] then continue;
483         if BeginEndCheckBox.Checked then
484           srcMessage := srcMessage+CaseResultCheckGroup.Items[i]+
485                         ': begin'+LineEnding+'end;'+LineEnding
486         else
487           srcMessage := srcMessage+CaseResultCheckGroup.Items[i]+
488                         ': ;'+LineEnding;
489       end;
490       srcMessage := srcMessage+'end;'
491     end;
492     if CaseOfEndElseRadioButton.Checked then begin
493       srcMessage := 'case '+srcMessage+' of'+LineEnding;
494       for i := 0 to CaseResultCheckGroup.Items.Count-1 do begin
495         if not CaseResultCheckGroup.Checked[i] then continue;
496         if BeginEndCheckBox.Checked then
497           srcMessage := srcMessage+CaseResultCheckGroup.Items[i]+
498                         ': begin'+LineEnding+'end;'+LineEnding
499         else
500           srcMessage := srcMessage+CaseResultCheckGroup.Items[i]+
501                         ': ;'+LineEnding;
502       end;
503       if BeginEndCheckBox.Checked then
504         srcMessage := srcMessage+'else begin'+LineEnding+'end;'+LineEnding
505       else
506         srcMessage := srcMessage+'else'+LineEnding;
507       srcMessage := srcMessage+'end;'
508     end;
509   end;
510 end;
511 
512 procedure TFormMessagesComposer.GetParamsFmtExecute(Sender: TObject);
513 const FormatParams = ['D', 'E', 'F', 'G', 'M', 'N', 'P', 'S', 'U', 'X'];
514 var strtmp: string;
515     ListParams: TStringList;
516     indx: integer;
517     chrtmp: Char;
518     ComposedMsgKind: TComposedMsgKind;
519 begin
520   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
521   if ComposedMsgKind<>cmkShowMsgFmt then exit;
522   ButtonsStringGrid.Cells[0, 0] := 'Params (array of const)';
523   ButtonsStringGrid.Cells[1, 0] := 'Values';
524   ButtonsStringGrid.FixedCols := 1;
525   Panel2.Visible := false;
526 
527   ListParams := TStringList.Create;
528   strtmp := UpperCase(MsgMemo.Lines.Text);
529 
530   indx := pos('%', strtmp);
531   while (indx>0)and(indx<Length(strtmp)) do begin
532     chrtmp := strtmp[indx+1];
533     if chrtmp in FormatParams then
534       ListParams.Add('%'+chrtmp);
535     Delete(strtmp, indx, 1);
536     indx := pos('%',strtmp);
537   end;
538 
539   if ListParams.Count>0 then begin
540     ListParams.Insert(0,'Params (array of const)');
541     ButtonsStringGrid.RowCount := ListParams.Count;
542     if ButtonsStringGrid.Cols[0].Text<>ListParams.Text then
543       ButtonsStringGrid.Cols[0] := ListParams;
544   end;
545   ListParams.Free;
546   ButtonsStringGrid.AutoAdjustColumns;
547 end;
548 
549 procedure TFormMessagesComposer.MessageSetupExecute(Sender: TObject);
550 var indx: integer;
551     ListResult: TStringList;
552     ComposedMsgKind: TComposedMsgKind;
553 begin
554   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
555   if ComposedMsgKind in [cmkMsgDlgSimple,cmkMsgDlgCaption,cmkMsgDlgCaptionHelpKeyWord,
556                          cmkMsgDlgPosSimple,cmkMsgDlgPosHelpSimple] then
557     ButtonsNotebook.PageIndex := 0 // ButtonsCheckGroup
558   else
559     ButtonsNotebook.PageIndex := 1; // ButtonsPanel
560 //Msg
561   case ComposedMsgKind of
562     cmkMsgDlgSimple,cmkMsgDlgCaption,cmkMsgDlgCaptionHelpKeyWord,
563     cmkMsgDlgPosSimple,cmkMsgDlgPosHelpSimple,
564     cmkQDlgHelpCtx,cmkQDlgHelpKeyword,cmkShowMsg,
565     cmkShowMsgFmt,cmkShowMsgPos:
566     begin
567       MsgMemo.Color := clWindow;
568       MsgMemo.Enabled := true;
569     end;
570     else begin
571       MsgMemo.Color := clBtnFace;
572       MsgMemo.Enabled := false;
573     end;
574   end;
575 //Caption
576   case ComposedMsgKind of
577     cmkMsgDlgCaption,
578     cmkMsgDlgCaptionHelpKeyWord,
579     cmkQDlgHelpCtx,
580     cmkQDlgHelpKeyword,
581     cmkInpQMask,
582     cmkInpQSimple,
583     cmkInpBox,
584     cmkPasswBox: begin
585       CaptionEdit.Color := clWindow;
586       CaptionEdit.Enabled := true;
587     end;
588     else begin
589       CaptionEdit.Color := clBtnFace;
590       CaptionEdit.Enabled := false;
591     end;
592   end;
593 //DlgType;
594   case ComposedMsgKind of
595     cmkMsgDlgSimple,
596     cmkMsgDlgCaption,
597     cmkMsgDlgCaptionHelpKeyWord,
598     cmkMsgDlgPosSimple,
599     cmkMsgDlgPosHelpSimple,
600     cmkQDlgHelpCtx,
601     cmkQDlgHelpKeyword: begin
602       DlgTypeComboBox.Color := clWindow;
603       DlgTypeComboBox.Enabled := true;
604     end;
605     else begin
606       DlgTypeComboBox.Color := clBtnFace;
607       DlgTypeComboBox.Enabled := false;
608     end;
609   end;
610 //HelpContext
611   case ComposedMsgKind of
612     cmkMsgDlgSimple,
613     cmkMsgDlgCaption,
614     cmkMsgDlgPosSimple,
615     cmkMsgDlgPosHelpSimple,
616     cmkQDlgHelpCtx: begin
617       HelpContextSpinEdit.Color := clWindow;
618       HelpContextSpinEdit.Enabled := true;
619     end;
620     else begin
621       HelpContextSpinEdit.Color := clBtnFace;
622       HelpContextSpinEdit.Enabled := false;
623     end;
624   end;
625 //HelpKeyword
626   case ComposedMsgKind of
627     cmkMsgDlgCaptionHelpKeyWord,
628     cmkQDlgHelpKeyword: begin
629       HelpKeyWordEdit.Color := clWindow;
630       HelpKeyWordEdit.Enabled := true;
631     end;
632     else begin
633       HelpKeyWordEdit.Color := clBtnFace;
634       HelpKeyWordEdit.Enabled := false;
635     end;
636   end;
637 //Position X Y
638   case ComposedMsgKind of
639     cmkMsgDlgPosSimple,
640     cmkMsgDlgPosHelpSimple,
641     cmkShowMsgPos: begin
642       XSpinEdit.Color := clWindow;
643       XSpinEdit.Enabled := true;
644       YSpinEdit.Color := clWindow;
645       YSpinEdit.Enabled := true;
646     end;
647     else begin
648       XSpinEdit.Color := clBtnFace;
649       XSpinEdit.Enabled := false;
650       YSpinEdit.Color := clBtnFace;
651       YSpinEdit.Enabled := false;
652     end;
653   end;
654 //HelpFileName
655   case ComposedMsgKind of
656     cmkMsgDlgPosHelpSimple: begin
657       HelpFileNameEdit.Color := clWindow;
658       HelpFileNameEdit.Enabled := true;
659     end;
660     else begin
661       HelpFileNameEdit.Color := clBtnFace;
662       HelpFileNameEdit.Enabled := false;
663     end;
664   end;
665 //Params (array of const)
666   case ComposedMsgKind of
667     cmkShowMsgFmt: begin
668       GetParamsFmt.Execute;
669     end;
670     else begin
671       ButtonsStringGrid.Cells[0, 0] := SButtonsArrayOfConst;
672       ButtonsStringGrid.Cells[1, 0] := SModalResult;
673       ButtonsStringGrid.FixedCols := 0;
674       Panel2.Visible := true;
675     end;
676   end;
677 //Prompt
678   case ComposedMsgKind of
679     cmkInpQMask,
680     cmkInpQSimple,
681     cmkInpBox,
682     cmkPasswBox: begin
683       PromptEdit.Color := clWindow;
684       PromptEdit.Enabled := true;
685     end;
686     else begin
687       PromptEdit.Color := clBtnFace;
688       PromptEdit.Enabled := false;
689     end;
690   end;
691 //MaskInput
692   case ComposedMsgKind of
693     cmkInpQMask: begin
694       MaskInputCheckBox.Enabled := true;
695     end;
696     else begin
697       MaskInputCheckBox.Enabled := false;
698     end;
699   end;
700 //Value
701   case ComposedMsgKind of
702     cmkInpQMask,
703     cmkInpQSimple: begin
704       ValueEdit.Color := clWindow;
705       ValueEdit.Enabled := true;
706     end;
707     else begin
708       ValueEdit.Color := clBtnFace;
709       ValueEdit.Enabled := false;
710     end;
711   end;
712 //Default
713   case ComposedMsgKind of
714     cmkInpBox: begin
715       DefaultEdit.Color := clWindow;
716       DefaultEdit.Enabled := true;
717     end;
718     else begin
719       DefaultEdit.Color := clBtnFace;
720       DefaultEdit.Enabled := false;
721     end;
722   end;
723 
724 /////  Results and Source Wrapper for message //////
725 
726 //InputBox(); PasswordBox();
727   case ComposedMsgKind of
728     cmkInpBox,
729     cmkPasswBox: begin
730       SourceNotebook.PageIndex := idxPageString;
731       if CaseOfEndRadioButton.Checked then IfThenRadioButton.Checked := True;
732       if CaseOfEndElseRadioButton.Checked then IfThenElseRadioButton.Checked := True;
733       CaseOfEndRadioButton.Enabled := False;
734       CaseOfEndElseRadioButton.Enabled := False;
735       //StringResultEdit.Enabled := true;
736       //StringResultEdit.Color := clWindow;
737       //IfResultComboBox.Enabled := false;
738       //IfResultComboBox.Color := clBtnFace;
739       //CaseResultCheckGroup.Enabled := false;
740       //CaseOfEndElseRadioButton.Enabled := false;
741       //CaseOfEndRadioButton.Enabled := false;
742     end;
743     else begin
744       CaseOfEndRadioButton.Enabled := True;
745       CaseOfEndElseRadioButton.Enabled := True;
746       if IfThenRadioButton.Checked or IfThenElseRadioButton.Checked then
747         SourceNotebook.PageIndex := idxPageIf
748       else
749         SourceNotebook.PageIndex := idxPageCase;
750       //StringResultEdit.Enabled := false;
751       //StringResultEdit.Color := clBtnFace;
752       //IfResultComboBox.Enabled := true;
753       //IfResultComboBox.Color := clWindow;
754       //CaseResultCheckGroup.Enabled := true;
755       //CaseOfEndElseRadioButton.Enabled := true;
756       //CaseOfEndRadioButton.Enabled := true;
757     end;
758   end;
759 
760 //ShowMessage(); ShowMessageFmt(); ShowMessagePos();
761   case ComposedMsgKind of
762     cmkShowMsg,
763     cmkShowMsgFmt,
764     cmkShowMsgPos: SourceWrapperGroupBox.Enabled := false;
765     else
766       SourceWrapperGroupBox.Enabled := true;
767   end;
768 
769 //MessageDlg() Result
770   case ComposedMsgKind of
771     cmkMsgDlgSimple,
772     cmkMsgDlgCaption,
773     cmkMsgDlgCaptionHelpKeyWord,
774     cmkMsgDlgPosSimple,
775     cmkMsgDlgPosHelpSimple: begin
776       ListResult := TStringList.Create;
777       for indx := 0 to ButtonsCheckGroup.Items.Count-1 do
778         if ButtonsCheckGroup.Checked[indx] then begin
779           if ButtonsCheckGroup.Items[indx] = 'mbOK' then
780             ListResult.Add(ModalResultStr[mrOK]);
781           if ButtonsCheckGroup.Items[indx] = 'mbCancel' then
782             ListResult.Add(ModalResultStr[mrCancel]);
783           if ButtonsCheckGroup.Items[indx] = 'mbYes' then
784             ListResult.Add(ModalResultStr[mrYes]);
785           if ButtonsCheckGroup.Items[indx] = 'mbNo' then
786             ListResult.Add(ModalResultStr[mrNo]);
787           if ButtonsCheckGroup.Items[indx] = 'mbAbort' then
788             ListResult.Add(ModalResultStr[mrAbort]);
789           if ButtonsCheckGroup.Items[indx] = 'mbRetry' then
790             ListResult.Add(ModalResultStr[mrRetry]);
791           if ButtonsCheckGroup.Items[indx] = 'mbIgnore' then
792             ListResult.Add(ModalResultStr[mrIgnore]);
793           if ButtonsCheckGroup.Items[indx] = 'mbAll' then
794             ListResult.Add(ModalResultStr[mrAll]);
795           if ButtonsCheckGroup.Items[indx] = 'mbNoToAll' then
796             ListResult.Add(ModalResultStr[mrNoToAll]);
797           if ButtonsCheckGroup.Items[indx] = 'mbYesToAll' then
798             ListResult.Add(ModalResultStr[mrYesToAll]);
799           if (ButtonsCheckGroup.Items[indx] = 'mbClose')and
800              (ListResult.IndexOf(ModalResultStr[mrCancel]) = -1) then
801             ListResult.Add(ModalResultStr[mrCancel]);
802         end;
803       if ListResult.Text<>IfResultComboBox.Items.Text then begin
804         IfResultComboBox.Items := ListResult;
805         CaseResultCheckGroup.Items := ListResult;
806         if ListResult.Count>0 then begin
807           IfResultComboBox.ItemIndex := 0;
808           CaseResultCheckGroup.Checked[0] := true;
809         end;
810       end;
811       ListResult.Free;
812     end;
813   end;
814 
815 //QuestionDlg() Result
816   case ComposedMsgKind of
817     cmkQDlgHelpCtx,
818     cmkQDlgHelpKeyword: begin
819       ListResult := TStringList.Create;
820       ListResult.Assign(ButtonsStringGrid.Cols[1]);
821       ListResult.Delete(0);
822       if ListResult.Text<>IfResultComboBox.Items.Text then begin
823         IfResultComboBox.Items := ListResult;
824         CaseResultCheckGroup.Items := ListResult;
825         if ListResult.Count>0 then begin
826           IfResultComboBox.ItemIndex := 0;
827           CaseResultCheckGroup.Checked[0] := true;
828         end;
829       end;
830       ListResult.Free;
831     end;
832   end;
833 
834 //InputQuery() Result
835   case ComposedMsgKind of
836     cmkInpQMask,
837     cmkInpQSimple: if (CaseResultCheckGroup.Items.Count=0) or (CaseResultCheckGroup.Items[0]<>'false') then begin
838       CaseResultCheckGroup.Items.Clear;
839       CaseResultCheckGroup.Items.Add('false');
840       CaseResultCheckGroup.Items.Add('true');
841       IfResultComboBox.Items := CaseResultCheckGroup.Items;
842       IfResultComboBox.ItemIndex := 0;
843       CaseResultCheckGroup.Checked[0] := true;
844     end;
845   end;
846   ButtonsStringGrid.AutoAdjustColumns;
847   ButtonsPanel.Visible := not (ComposedMsgKind in [cmkShowMsg,cmkShowMsgPos,
848                                  cmkInpQMask,cmkInpQSimple,cmkInpBox,cmkPasswBox]);
849 end;
850 
851 procedure TFormMessagesComposer.MessagesInitExecute(Sender: TObject);
852 begin
853   XSpinEdit.MaxValue := Screen.Width;
854   XLabel.Caption := 'X ('+IntToStr(Screen.Width)+')';
855   YSpinEdit.MaxValue := Screen.Height;
856   YLabel.Caption := 'Y ('+IntToStr(Screen.Height)+')';
857   HelpContextSpinEdit.Width := 80;
858   XSpinEdit.Width := 60;
859   YSpinEdit.Width := 60;
860 
861   KindMessageComboBox.Clear;
862   KindMessageCombobox.Items.AddStrings(ComposedMsgStrings);
863   KindMessageComboBox.ItemIndex := 0;
864   Caption := SMessageComposerCaption;
865   CaptionLabel.Caption := SDlgCaption;
866   DlgTypeLabel.Caption := SDlgType;
867   MsgLabel.Caption := SMsgCaption;
868   ButtonsCheckGroup.Caption := SButtonsTMsgDlgButtons;
869   ButtonsStringGrid.Cells[0,0] := SButtonsArrayOfConst;
870   ButtonsStringGrid.Cells[1,0] := SModalResult;
871   BitBtn1.Caption := SAdd;
872   BitBtn2.Caption := SDelete;
873   PromptLabel.Caption := SPromptCaption;
874   MaskInputCheckBox.Caption := SMaskInput;
875   ValueLabel.Caption := SValueVar;
876   DefaultValue.Caption := SDefault;
877   SourceWrapperGroupBox.Caption := SSourceWrapper;
878   KindMessageLabel.Caption := SKindofMessage;
879   Label1.Caption := SIfResult;
880   CaseResultCheckGroup.Caption := SCaseResult;
881   TestButton.Caption:=rsTest;
882   OkButton.Caption:=rsOk;
883   CancelButton.Caption:=rsCancel;
884   HelpContextLabel.Caption := SHelpContext;
885   HelpKeyWordLabel.Caption := SHelpKeyword;
886   HelpFileNameLabel.Caption := SHelpFilename;
887   MessageSetup.Execute;
888 end;
889 
890 procedure TFormMessagesComposer.SetIfOrCaseExecute(Sender: TObject);
891 var
892   ComposedMsgKind: TComposedMsgKind;
893 begin
894   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
895   if (ComposedMsgKind in [cmkInpBox, cmkPasswBox]) then exit;
896   if IfThenRadioButton.Checked or IfThenElseRadioButton.Checked then
897     SourceNotebook.PageIndex := idxPageIf
898   else
899     SourceNotebook.PageIndex := idxPageCase;
900 end;
901 
902 procedure TFormMessagesComposer.TestExecute(Sender: TObject);
903 var Msg, MsgCaption, MsgHelpKeyword, HelpFileName, Prompt,
904     MsgDefault, Value: string;
905     DlgType: TMsgDlgType;
906     MsgButtons: TMsgDlgButtons;
907     HelpCtx: Longint;
908     X, Y: integer;
909     ComposedMsgKind: TComposedMsgKind;
910 begin
911   Msg := MsgMemo.Lines.Text;
912   DlgType := TMsgDlgType(DlgTypeComboBox.ItemIndex);
913   MsgButtons := [];
914   if ButtonsCheckGroup.Checked[0] then
915     MsgButtons := MsgButtons+[mbYes];
916   if ButtonsCheckGroup.Checked[1] then
917     MsgButtons := MsgButtons+[mbNo];
918   if ButtonsCheckGroup.Checked[2] then
919     MsgButtons := MsgButtons+[mbOK];
920   if ButtonsCheckGroup.Checked[3] then
921     MsgButtons := MsgButtons+[mbCancel];
922   if ButtonsCheckGroup.Checked[4] then
923     MsgButtons := MsgButtons+[mbAbort];
924   if ButtonsCheckGroup.Checked[5] then
925     MsgButtons := MsgButtons+[mbRetry];
926   if ButtonsCheckGroup.Checked[6] then
927     MsgButtons := MsgButtons+[mbIgnore];
928   if ButtonsCheckGroup.Checked[7] then
929     MsgButtons := MsgButtons+[mbAll];
930   if ButtonsCheckGroup.Checked[8] then
931     MsgButtons := MsgButtons+[mbNoToAll];
932   if ButtonsCheckGroup.Checked[9] then
933     MsgButtons := MsgButtons+[mbYesToAll];
934   if ButtonsCheckGroup.Checked[10] then
935     MsgButtons := MsgButtons+[mbHelp];
936   if ButtonsCheckGroup.Checked[11] then
937     MsgButtons := MsgButtons+[mbClose];
938   MsgCaption := CaptionEdit.Text;
939   HelpCtx := HelpContextSpinEdit.Value;
940   HelpKeyword := HelpKeyWordEdit.Text;
941   X := XSpinEdit.Value;
942   Y := YSpinEdit.Value;
943   Prompt := PromptEdit.Text;
944   MsgDefault := DefaultEdit.Text;
945   Value := ValueEdit.Text;
946   HelpFileName:='';
947   MsgHelpKeyword:='';
948   ComposedMsgKind := TComposedMsgKind(KindMessageComboBox.ItemIndex);
949   case ComposedMsgKind of
950     cmkMsgDlgSimple: MessageDlg(Msg, DlgType, MsgButtons, HelpCtx);
951     cmkMsgDlgCaption: MessageDlg(MsgCaption, Msg, DlgType, MsgButtons, HelpCtx);
952     cmkMsgDlgCaptionHelpKeyWord: MessageDlg(MsgCaption, Msg, DlgType, MsgButtons, MsgHelpKeyword);
953     cmkMsgDlgPosSimple: MessageDlgPos(Msg, DlgType, MsgButtons, HelpCtx, X, Y);
954     cmkMsgDlgPosHelpSimple: MessageDlgPosHelp(Msg, DlgType, MsgButtons, HelpCtx, X, Y, HelpFileName);
955     cmkQDlgHelpCtx: QuestionDlg(MsgCaption, Msg+' ('+SNotImplementedYet+')', DlgType, [mrYes, 'Yes', mrNo, 'No',
956        mrCancel, 'Cancel'], HelpCtx);
957     cmkQDlgHelpKeyword: QuestionDlg(MsgCaption, Msg+' ('+SNotImplementedYet+')', DlgType, [mrYes, 'Yes', mrNo, 'No',
958        mrCancel, 'Cancel'], HelpKeyword);
959     cmkShowMsg: ShowMessage(Msg);
960     cmkShowMsgFmt: ShowMessageFmt(Msg+' ('+SNotImplementedYet+')', ['Yes','No','Cancel']);
961     cmkShowMsgPos: ShowMessagePos(Msg, X, Y);
962     cmkInpQMask: InputQuery(MsgCaption, Prompt, MaskInputCheckBox.Checked, Value);
963     cmkInpQSimple: InputQuery(MsgCaption, Prompt, Value);
964     cmkInpBox: InputBox(Caption, Prompt, MsgDefault);
965     cmkPasswBox: PasswordBox(MsgCaption, Prompt)
966   end;
967 end;
968 
969 procedure TFormMessagesComposer.UpdateQuestioDlgResultExecute(Sender: TObject);
970 var ListResult: TStringList;
971 begin
972   ListResult := TStringList.Create;
973   ListResult.Assign(ButtonsStringGrid.Cols[1]);
974   ListResult.Delete(0);
975   if ListResult.Text<>IfResultComboBox.Items.Text then begin
976     IfResultComboBox.Items := ListResult;
977     CaseResultCheckGroup.Items := ListResult;
978     if ListResult.Count>0 then begin
979       IfResultComboBox.ItemIndex := 0;
980       CaseResultCheckGroup.Checked[0] := true;
981     end;
982   end;
983   ListResult.Free;
984 end;
985 
986 { Registers a keyboard shortcut and menu item in Lazarus}
987 procedure Register;
988 var
989   Key1,Key2: TIDEShortCut;
990   Cat: TIDECommandCategory;
991 begin
992   Key1 := IDEShortCut(VK_M, [ssCtrl], VK_UNKNOWN, []);
993   Key2 := IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []);
994   Cat := IDECommandList.CreateCategory(Nil, cMessageComposer,
995                                        SMessageComposerCaption,
996                                        IDECmdScopeSrcEditOnly);
997 
998   CmdMessageComposer := RegisterIDECommand(Cat, cMessageComposer,
999                                           SMessageComposerCaption,
1000                                           Key1, Key2,nil,
1001                                           @ExecuteMessagesComposer);
1002 
1003   RegisterIDEMenuCommand(itmSourceTools, cMessageComposer,
1004                          SMessageComposerMenuCaption,
1005                          nil, nil, CmdMessageComposer);
1006 end;
1007 
1008 end.
1009 
1010