|
EControl Ltd. VCL libraries and software support forum
|
View previous topic :: View next topic |
Author |
Message |
hyperspeed
Joined: 28 Sep 2006 Posts: 16
|
Posted: Fri May 18, 2007 10:14 am Post subject: how can i replace shortcut to commandID? (v.2.32) |
|
|
Hello.
v2.32 is very speedy.(very good!)
I read history
...
New tools linking. Now all tool components (code completion
, parameter completion, templates, auto-replace, insert character)
has CommandID property instead of ShortCut property)
...
I used AutoComplete Popup with shortcut Ctrl+J.
but in 2.32 i don't know how can do that...(I guess with Keymapping, right?)
And when will update the latest EControl Syntax Editor, SDK help?
Best regards. |
|
Back to top |
|
|
econtrol Site Admin
Joined: 09 Jun 2006 Posts: 202
|
Posted: Sat May 19, 2007 8:25 pm Post subject: |
|
|
Hello,
Yes, assigning shortcut(s) for tools components should be done in the keymapping.
There is default commands in keymapping (category "Tools").
If you create component when previous version was installed, you may load default commands set (right click on TSyntKeymapping component, menu "Load Default") or you may create commands manually in keymapping editor.
TTemplatePopup.CommandID, TAutoCompletePopup.CommandID, ... should be set to command which will fire this tool. Commands may be added in keymapping editor (double click on TSyntKeymapping component)
If you have several tool components of the same type, for example, two code template components, you may create separate command for each component and define your command ID in CommandID property of these components.
Michael. |
|
Back to top |
|
|
hyperspeed
Joined: 28 Sep 2006 Posts: 16
|
Posted: Fri May 25, 2007 9:05 am Post subject: Thanks |
|
|
I know it!
Thanks |
|
Back to top |
|
|
mstaszew
Joined: 21 Jul 2006 Posts: 67 Location: North Carolina, USA
|
Posted: Fri Jun 22, 2007 7:25 pm Post subject: |
|
|
So if I have multiple auto replace components on a form then I can create new commands? Would I simply use TSyntKeyMapping.Add and pass in a CommandID that is not already defined in ecCmdConst? If so, what range should be use for our own defined commands? If we add a command we would have to be sure that the CommandID that we choose will not be defined by you in a future release so that our users can retain key mapping during upgrade scenarios. Is it safe to assume that you will never use command ids in the negative range?
Thanks |
|
Back to top |
|
|
econtrol Site Admin
Joined: 09 Jun 2006 Posts: 202
|
Posted: Fri Jun 22, 2007 9:54 pm Post subject: |
|
|
Yes. Adding new commands allows to handle multiple tools component, for example, template lists.
Also new commands may be used to execute custom functions, for example, "open file at cursor". For this purpose you should add new command, assign any command ID and process it in OnExecuteCommand or using plug-in interfaces.
I suggest to use commands ID greater 1000 or negative. Command IDs in diapason from 0 to 1000 are reserved for internal library use.
Michael. |
|
Back to top |
|
|
mstaszew
Joined: 21 Jul 2006 Posts: 67 Location: North Carolina, USA
|
Posted: Mon Jun 25, 2007 3:56 pm Post subject: Having some problems |
|
|
I'm having some problems with this. Here is what I am doing to initialize my key mapping component and assign the user's key mapping first if it exists and my default key mapping if it does not. I am adding a custom command as well if it is not already present. My command ID is -1.
Code: |
{Read from the INI file}
S := gblIniFile.ReadString(strEditorSettings, strKeyMapping, strKeyMappingDefault);
{If the key mapping key exists, but is a blank string then assign default}
if Length(S) = 0 then
S := strKeyMappingDefault;
{Assign the key mapping}
AsString := S;
{Add our custom commands here if they are not already in the key mapping}
if CommandByID(cmdDoSomething) = nil then
Add(cmdDoSomething, 'My Category', 'My Caption', 'My Description', TextToShortCut('Ctrl+Y'), 0);
|
After I initialize my key mapping component, I have another key mapping component which I use and I do the following...
Code: |
MyOtherKeyMapping.AsString := MyFirstKeyMapping.AsString;
|
MyFirstKeyMapping was initialized with the code above.
If I test MyFirstKeyMapping.CommandByID(cmdDoSomething) then it returns a valid command. If I test MyOtherKeyMapping.CommandByID(cmdDoSomething) then it returns nil. It seems as though my custom command is not being returned in the AsString, but I am not sure on that. What am I doing wrong?
Thanks. |
|
Back to top |
|
|
econtrol Site Admin
Joined: 09 Jun 2006 Posts: 202
|
Posted: Mon Jun 25, 2007 7:57 pm Post subject: |
|
|
There is a problem in AsString property.
Fix (ecKeyMap.pas)
Code: | procedure TSyntKeyMapping.SetAsString(const Value: string);
var j, k, N1, N2: integer;
cmd: TecCommandItem;
Mem: TMemoryStream;
function ReadInt: integer;
begin
Mem.ReadBuffer(Result, sizeof(integer));
end;
begin
// Items.Clear;
// InitDefaultKeyMapping(Self);
if Length(Value) < 2 then Exit;
Mem := TMemoryStream.Create;
try
Mem.Size := Length(Value) div 2;
{$IFDEF EC_DOTNET}
HexToBin( System.Text.ASCIIEncoding.ASCII.GetBytes(Value), 0, Mem.Memory, 0, Mem.Size);
{$ELSE}
HexToBin(PChar(Value), PChar(Mem.Memory), Mem.Size);
{$ENDIF}
while Mem.Position < Mem.Size do
begin
N1 := ReadInt;
cmd := CommandByID(N1);
N1 := ReadInt;
if Assigned(Cmd) then Cmd.KeyStrokes.Clear;
for j := 0 to N1 - 1 do
begin
if Assigned(Cmd) then Cmd.KeyStrokes.Add;
N2 := ReadInt;
for k := 0 to N2 - 1 do
begin
if Assigned(Cmd) then Cmd.KeyStrokes.Last.KeyDefs.Add.ShortCut := ReadInt
else ReadInt;
end;
end;
end;
finally
Mem.Free;
end;
end;
function TSyntKeyMapping.GetAsString: string;
var //Def: TSyntKeyMapping;
i, j, k: integer;
// cmd: TecCommandItem;
Mem: TMemoryStream;
{$IFDEF EC_DOTNET}
Buf: TBytes;
{$ENDIF}
procedure WriteInt(V: integer);
begin
Mem.WriteBuffer(V, sizeof(integer));
end;
begin
Mem := TMemoryStream.Create;
try
// Def := DefaultKeyMapping;
for i := 0 to Items.Count - 1 do
with Items[i] do
if Command <> 0 then
begin
// cmd := Def.CommandByID(Command);
// if Assigned(cmd) and not cmd.KeyStrokes.IsEqual(KeyStrokes) then
// begin
WriteInt(Command);
WriteInt(KeyStrokes.Count);
for j := 0 to KeyStrokes.Count - 1 do
begin
WriteInt(KeyStrokes[j].KeyDefs.Count);
for k := 0 to KeyStrokes[j].KeyDefs.Count - 1 do
WriteInt(KeyStrokes[j].KeyDefs[k].ShortCut);
end;
// end;
end;
{$IFDEF EC_DOTNET}
SetLength(Buf, Mem.Size * 2);
BinToHex( Mem.Memory, 0, Buf, 0, Mem.Size);
Result := System.Text.ASCIIEncoding.ASCII.GetChars(Buf);
{$ELSE}
SetLength(Result, Mem.Size * 2);
BinToHex(PChar(Mem.Memory), PChar(Result), Mem.Size);
{$ENDIF}
finally
Mem.Free;
end;
end; |
Removed comparing with default keymapping. But this implementation creates big string which is not handled by Ini file (when reading string is cut). So result of AsString property may be saved in separate file or in registry (for example when using TPropsManager).
It is more correct to replace:
Code: | MyOtherKeyMapping.AsString := MyFirstKeyMapping.AsString; |
with:
Code: | MyOtherKeyMapping.Assign(MyFirstKeyMapping); |
In this case MyOtherKeyMapping will be identical to MyFirstKeyMapping.
Michael. |
|
Back to top |
|
|
mstaszew
Joined: 21 Jul 2006 Posts: 67 Location: North Carolina, USA
|
Posted: Mon Jun 25, 2007 9:29 pm Post subject: |
|
|
This isn't working.
I have a KeyMapping that is newly created and I assign AsString to the contents of a file as you suggested. After assigning AsString, Items.Count is 0. It seems that since the call to InitDefaultKeyMapping has been removed, all checked to "if Assigned(Cmd)" in SetAsString fail and there is nothing in there that adds commands that are not in there already. I still want the key mapping to include ALL commands, even if they have no assigned shortcut.
Thanks. |
|
Back to top |
|
|
econtrol Site Admin
Joined: 09 Jun 2006 Posts: 202
|
Posted: Tue Jun 26, 2007 6:41 am Post subject: |
|
|
Items.Clear; InitDefaultKeyMapping are commented in fix above.
Replace these two methods. Only after that AsString will save and restore all shortcuts.
P.S. AsString does not copy commands, it allows only to save/restore shortcuts for existent commands.
Michael. |
|
Back to top |
|
|
mstaszew
Joined: 21 Jul 2006 Posts: 67 Location: North Carolina, USA
|
Posted: Tue Jun 26, 2007 2:29 pm Post subject: |
|
|
Ok, I think that I am finally starting to understand this. Here is what I think is going on and what I should be doing. Correct me if I am wrong.
First, custom commands in the negative range are not valid after all. See TCustomSyntaxMemo.KeyDown. It only proceeds to ExecCommand if the command is greater than 0. I started my application's custom command range at 5000 to give you plenty of room for adding more commands in the future.
By leaving the Items.Clear and InitDefaultKeyMapping commented out in SetAsString, I can manually initialize my key mapping component, then add custom commands, and finally load the shortcuts from file.
Code: |
Items.Clear;
InitDefaultKeyMapping(Self);
{Add custom commands}
Add(cmdDoSomething, 'My Category', 'My Caption', 'My Description', TextToShortCut('Ctrl+Y'), 0);
{Load key mapping from file}
if FileExists(KeyMappingFile) then
begin
S := Trim(FileToString(KeyMappingFile));
{If the key mapping file exists, but contains nothing then assign default}
if Length(S) = 0 then
S := strKeyMappingDefault;
end
else
S := strKeyMappingDefault;
{Assign the key mapping}
AsString := S;
|
This allows me to restore the user's key mapping for native EControl commands as well as any custom commands that I have added. Does everything look right? It seems to work just fine.
Thanks. |
|
Back to top |
|
|
econtrol Site Admin
Joined: 09 Jun 2006 Posts: 202
|
Posted: Wed Jun 27, 2007 5:42 am Post subject: |
|
|
Yes, initializing keymapping in code is better due to all changes in default command set in future will be automatically used.
Quote: | First, custom commands in the negative range are not valid after all. See TCustomSyntaxMemo.KeyDown. It only proceeds to ExecCommand if the command is greater than 0. I started my application's custom command range at 5000 to give you plenty of room for adding more commands in the future. |
Negative command ID checking is unnecessary.
Fix (ecSyntMemo.pas):
Code: | procedure TCustomSyntaxMemo.KeyDown(var Key: Word; Shift: TShiftState);
...
// Select editor command
if Assigned(FKeyMapping) then cmd := FKeyMapping.IsHandledCmd(FKeyQueue)
else cmd := DefaultKeyMapping.IsHandledCmd(FKeyQueue);
if cmd <> 0 then
begin
ExecCommand(cmd);
PeekMessage(msg, Handle, WM_CHAR, WM_CHAR, PM_REMOVE);
end;
end;
...
procedure TCustomSyntaxMemo.ExecCommand(Command: integer; Data: ecPointer);
...
if (Command < 300) and (Command > 0) then
begin
if Command > smColSelection then
...
function TCustomSyntaxMemo.IsCommandEnabled(Command: integer; Data: ecPointer): Boolean;
...
begin
if (Command < 300) and (Command > 0) then
Command := Command mod 100;
... |
This fix will allow using of negative command IDs.
Michael. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|