2013-09-10 2 views
6

Возможно ли это? Например, Notepad ++ делает это, но просто попытка назначить его компонентам, таким как действия или элементы меню, не работает. Событие, назначенное ему просто не запускается.Используйте Ctrl +/как ярлык в программе Delphi

Итак, я взял свой вопрос в Google. Нада. Затем я попытался выполнить различные функции быстрого вызова, в этом случае TextToShortCut и ShortCutToText.

Первый из них, TextToShortCut, преобразует такие вещи, как 'Ctrl + A' (строка) к следующему значению 16bit:

(uint)A | (uint)Ctrl 

Работает хорошо, в основном. Однако я заметил следующую странность:

// Try converting back and forward... 
TextToShortCut('Ctrl+/') = 16495 

// That's incorrect. It should be: 
Ord('/') or scCtrl = 16431 

// Incorrect too 
ShortCutToText(16495) = 'Ctrl+/' 

// This is the shortcut the first line actually creates (Ctrl+o) 
Ord('o') or scCtrl = 16495 // wut? 

// Which is invalid, cause only caps are used 
ShortCutToText(16431) = '' 

Что здесь происходит? На данный момент я считаю, что ошибка заключается в финальной части TextToShortCut: после обработки части перед знаком + (в этом случае «Ctrl») она попытается найти ярлык для оставшейся части («/»). Однако в его текущей форме часть после + также должна быть допустимой ярлыкой сама по себе.

for Key := $08 to $255 do { Copy range from table in ShortCutToText } 
    if AnsiCompareText(Text, ShortCutToText(Key)) = 0 then 
    begin 
    Result := Key or Shift; 
    Exit; 
    end; 

Таким образом, потому что:

ShortCutToText('/') = 0 (failure) 
MapVirtualKey('/',MAPVK_VK_TO_VSC) = 0 (failure) 

... петля не удается обнаружить '/' в качестве действительного ярлыка.

Это какая-то ошибка VCL или я что-то упускаю?

Вот доказательство концепции (да, я беру скриншоты кода, но затирания это вместе с палитры компонентов будет быстрее, чем с помощью этого кода непосредственно):

Edit 1:

enter image description here

Edit 2:

Ручное назначение 16431 к пункту меню не работает.

+0

Работы отлично здесь. Хотя только на клавише '/', который является частью numpad. Но вот что делает npp. Его восстановление ярлыка масштабирования отображается на 'Ctrl + Num /' –

+0

Notepad ++ использует обычный (слева от Shift на US International) для перехода к началу слова в карете тоже. – Orwell

ответ

12

Если назначить обработчик OnShortCut события для родительского меню в TForm, вы увидите, что нажатие Ctrl + / результатов в TShortCut значения 16575 от Menus.ShortCutFromMessage(), которая является функцией, что VCL использует внутренне при диспетчеризации нажатия клавиш для управления ярлыками.

Оба ShortCutToText(16495) и ShortCutToText(16575) возвращение 'Ctrl+/', так что позволяет разбить его:

scCtrl = $4000 
16495 = $406F 
16575 = $40BF 

Оба ярлыки настоящее время scCtrl флаг.

ShortCutToText($6F) и ShortCutToText($BF) оба возвращаются '/'. Это связано с тем, что MapVirtualKey() возвращает тот же код сканирования (350000 долларов) для виртуальных ключей $6F (VK_DIVIDE) и $BF (VK_OEM_2 - ключ /? для американских клавиатур).

При отправке ярлыка VCL выполняет точное сравнение значений TShortCut. Поэтому, когда у вас есть 16495, назначенный как ваш ярлык, он не будет запускаться, потому что система сообщает о сокращении на 16575 вместо этого, хотя они оба сопоставляются с Ctrl+/.

Когда я задаю 16575 к ShortCut свойству TMenuItem или TAction, нажав Ctrl + / вызывает пункт, как и ожидалось.

Так хитрость заключается в том, что система отчетности ярлык, который использует виртуальную клавишу VK_OEM_2 для /, но вы ожидаете его использовать виртуальный ключ VK_DIVIDE вместо этого.

7

простое исследование Key из обработчика OnKeyDown событий показывает два различных вида слэша:

  • / на цифровой клавиатуре = 111 (в сочетании с CTRL = 16575)
  • / рядом клавиша смены = 191 (в сочетании с CTRL = 16495)

Невозможно создать единый ярлык, который отвечает на оба.

Но вместо установки ярлыка на элементе memu вы можете приложить действие, которое имеет свойство SecondaryShortCuts. Затем используйте:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Action1.ShortCut := 16575; 
    Action1.SecondaryShortCuts.Add('Ctrl+/'); 
end; 
+2

Всегда есть свойство SecondaryShortCuts –

+0

Я не пытаюсь привязываться к обоим, я просто пытаюсь привязаться к 191-му. Спасибо, что ответили. – Orwell

+0

* Я просто пытаюсь связать 191-й. * Почему в этом не говорится? Мы собираемся угадать? –

Смежные вопросы