EControl Ltd. Forum Index EControl Ltd.
VCL libraries and software support forum
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

how can i replace shortcut to commandID? (v.2.32)

 
Post new topic   Reply to topic    EControl Ltd. Forum Index -> EControl Syntax Editor
View previous topic :: View next topic  
Author Message
hyperspeed



Joined: 28 Sep 2006
Posts: 16

PostPosted: Fri May 18, 2007 10:14 am    Post subject: how can i replace shortcut to commandID? (v.2.32) Reply with quote

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
View user's profile Send private message
econtrol
Site Admin


Joined: 09 Jun 2006
Posts: 202

PostPosted: Sat May 19, 2007 8:25 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
hyperspeed



Joined: 28 Sep 2006
Posts: 16

PostPosted: Fri May 25, 2007 9:05 am    Post subject: Thanks Reply with quote

I know it!

Thanks
Back to top
View user's profile Send private message
mstaszew



Joined: 21 Jul 2006
Posts: 67
Location: North Carolina, USA

PostPosted: Fri Jun 22, 2007 7:25 pm    Post subject: Reply with quote

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
View user's profile Send private message
econtrol
Site Admin


Joined: 09 Jun 2006
Posts: 202

PostPosted: Fri Jun 22, 2007 9:54 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
mstaszew



Joined: 21 Jul 2006
Posts: 67
Location: North Carolina, USA

PostPosted: Mon Jun 25, 2007 3:56 pm    Post subject: Having some problems Reply with quote

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
View user's profile Send private message
econtrol
Site Admin


Joined: 09 Jun 2006
Posts: 202

PostPosted: Mon Jun 25, 2007 7:57 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
mstaszew



Joined: 21 Jul 2006
Posts: 67
Location: North Carolina, USA

PostPosted: Mon Jun 25, 2007 9:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
econtrol
Site Admin


Joined: 09 Jun 2006
Posts: 202

PostPosted: Tue Jun 26, 2007 6:41 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
mstaszew



Joined: 21 Jul 2006
Posts: 67
Location: North Carolina, USA

PostPosted: Tue Jun 26, 2007 2:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
econtrol
Site Admin


Joined: 09 Jun 2006
Posts: 202

PostPosted: Wed Jun 27, 2007 5:42 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    EControl Ltd. Forum Index -> EControl Syntax Editor All times are GMT
Page 1 of 1

 
Jump to:  
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