Имя: Пароль:
IT
 
Как программно послать символ "*" с правой доп. клавиатуры в буфер обмена?
0 247tsm
 
18.04.12
20:07
Добрый день,
У меня такой вопрос. Как программно послать символ "*" с правой дополнительной клавиатуры в буфер обмена? С помощью WHS или по-другому. Вообще была поставлена задача: в 1с7.7 при открытии справочника Номенклатура должно полностью раскрываться дерево групп. Вручную это делается так: становимся мышкой на самый верхний элемент дерева групп и нажимаем на "*" (но только с дополнительной правой клавиатуры). Я так понимаю, что в этом случае в буфер обмена попадает не символ "*" с кодом 42, а что-то другое. В разделе для 1с7.7, к сожалению, мне не смогли помочь. Вот попытаю счастье здесь.
Спасибо.
1 Один С
 
18.04.12
20:12
РежимСправочника.Иерархический или както так, разве нет в семерке?
2 andrewks
 
18.04.12
20:13
SendKey()
3 247tsm
 
18.04.12
20:16
(1) есть, но нет почти никаких команд. А я не могу именно программно иммитировать нажатие "*" с правой дополнительной клавиатуры.
4 palpetrovich
 
18.04.12
20:16
мда уж, горе от ума  :)
5 palpetrovich
 
18.04.12
20:17
(3) забудь о иммитировать нажатие "*" , сконцентрируйся на (1)
6 Скользящий
 
18.04.12
20:20
блин, зачем тебе имитировать "*"?? В СП посмотри ИерархическийСписок()
7 247tsm
 
18.04.12
20:21
(2) использовал SendKey(). Но что посылать?
Вот программный код:
       addon=CreateObject("addon1c.commands");    
       addon.SendKeys("+{TAB}");
       addon.SendKeys("*");
Командой addon.SendKeys("+{TAB}") я иммитирую активацию (переход на дерево групп).
А командой addon.SendKeys("*") пытаюсь раскрыть это дерево.
Но не срабатывает, потому что символ "*" с левой клавиатуры и с правой дополнительной клавиатуры, очевидно, разные, но когда программно вывожу коды этих символов - они одинаковые 42. Значит еще какой-то код присутствует.
8 247tsm
 
18.04.12
20:22
(5) и (6), Вы поймите, что я знаю про команду ИерархическийСписок(1,1), ну и что? Она не решает мою задачу
9 kotletka
 
18.04.12
20:24
тогда опиши чем именно тебя не устраивает (1) и в чем плюс твоего метода, из (0) плюсов не видно
10 247tsm
 
18.04.12
20:25
Я предполагаю, что на низком уровне 1С различает символ "*" с левой и правой клавиатуры. Но чем они отличаются в деталях я не знаю, поэтому и решил спросить у знатоков.
11 andrewks
 
18.04.12
20:26
(7) 0x6A
12 Один С
 
18.04.12
20:28
(10) конечно она их различает, потомучто у них разные коды символа..
13 247tsm
 
18.04.12
20:28
(9) в том то и дело, что в 1С нет возможности программно открыть все уровни дерева групп. Только интерактивно "руками". А я хочу программно. Поэтому и спрашиваю, как?
14 andrewks
 
18.04.12
20:29
(12) коды символа одинаковые. а вот коды клавиш разные
(10) и различает их не 1С, а ось
15 PR
 
18.04.12
20:29
(7) NUM, а не TAB
16 247tsm
 
18.04.12
20:37
(11) а как 0х6А записать с помощью SendKeys()?
17 247tsm
 
18.04.12
20:39
(15) "+{TAB}" = SHIFT-TAB   это для установки курсора на дерево групп.
18 vis_tmp
 
18.04.12
20:40
(16)6*16+10 ?
19 247tsm
 
18.04.12
20:56
(14) А как с помощью SendKeys() послать код клавиши "*" с правой клавиатуры? Или по-другому. Как отловить и увидеть, что делается после нажатия "*" на правой клавиатуре? И как то же самое послать в буфер с помощью SendKeys() или как-нибудь по-другому?
20 247tsm
 
18.04.12
20:58
(19)+ т.е., как запустить тот же механизм 1С, что и при нажатии на "*" на правой клавиатуре?
21 247tsm
 
18.04.12
21:00
(18) пробую, но пока никак.
22 PR
 
18.04.12
21:32
23 247tsm
 
19.04.12
00:06
(22) посмотрел, но не понял, как можно использовать.
24 247tsm
 
19.04.12
01:29
А вообще, дерево групп имеет какое-нибудь системное имя, как элемент формы, чтобы к нему программно обратиться и сделать его активным, т.е., как будто установили на него курсор мышки?
25 andrewks
 
19.04.12
08:03
(24) нет
26 andrewks
 
19.04.12
08:17
(24) а у тебя вообще курсор на дерево перемещается после твоих манипуляций?
27 PR
 
19.04.12
11:01
(23) Там собсно и написано, что никак.
В http://sargaev.ru/?p=608 написано, что {MULTIPLY}, но что-то не пашет.
28 PR
 
19.04.12
11:02
(26) Не в этом дело. Я в восьмерке пробовал, тоже не пашет.
29 palpetrovich
 
19.04.12
11:02
(13) хз, почему у тебя "1С нет возможности программно открыть все уровни дерева групп"
спецом попробовал, все работает  
Процедура ПриОткрытии() // в форме списка
   ИерархическийСписок(0);
КонецПроцедуры
30 andrewks
 
19.04.12
11:03
(28) а ты как пробовал? через DynamicWrapper, или VBS?
31 PR
 
19.04.12
11:04
(30) Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys("{MULTIPLY}");
32 andrewks
 
19.04.12
11:06
(31) я так понял, основной косяк с получателем события.

вчера баловался через DynamicWrapper - нажатия клавиш проходят, но 1С-ка их не получает. например, NumLock зажигается, т.е. какой-то глобальный контекст их обрабатывает, а в 1с-ку не приходит
33 andrewks
 
19.04.12
12:36
(31) что думаешь по этому поводу?
34 andrewks
 
19.04.12
12:38
причём пробовал и через PostMessage, и keybd_event, и с EnableWindow/SetFocus, и без, однохерственно
нажатия проходят, глобальный контекст изменяется, а в 1с ничего не происходит
35 PR
 
19.04.12
12:58
(33) Думаю, что непонятно, почему не пашет {MULTIPLY}. Странно это.
36 247tsm
 
19.04.12
13:14
(24) Сначала перемещался, а теперь не хочет, но почему - не могу понять
37 247tsm
 
19.04.12
13:28
(29) я попробовал - не работает, т.е. при открытии справочника номенклатура дерево не раскрывается автоматически.
38 andrewks
 
19.04.12
13:29
(35) да дело-то не в том, что {MULTIPLY} не работает, а в том, что вообще посланные по WinAPI нажатия клавиш не приходят в 1с вообще (либо, как вариант, не обрабатываются ей)
39 PR
 
19.04.12
13:31
(38) Почему?
Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys("*");
прекрасно работает например.
40 andrewks
 
19.04.12
13:33
(39) я про вызовы WinAPI в (34)
41 247tsm
 
19.04.12
13:45
(31) Небольшое замечание. Нужно не просто послать {MULTIPLY}, а сначала спозиционироваться на дереве, а затем послать {MULTIPLY}. Но у меня так:

Процедура ПриОткрытии()
  Shell = CreateObject("WScript.Shell");
  Shell.SendKeys("{MULTIPLY}");    
КонецПроцедуры

и на второй строке останавливается:
Shell.SendKeys("{MULTIPLY}");    
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(171)}: :

т.е. не принимает название клавиши.
Но сначала все же нужно спозиционироваться на дереве.
42 247tsm
 
19.04.12
13:55
(26) Сначала перемещался, а теперь не хочет, но почему - не могу понять. Я делал так.

   Ws = CreateObject("WScript.Shell");
   Ws.SendKeys ("+{TAB}");
   Ws.SendKeys ("+{TAB}");
и так
   addon=CreateObject("addon1c.commands");    
   addon.SendKeys("+{TAB}");
   addon.SendKeys("+{TAB}");

То, что перемещался - это 100%. Затем начал экспериментировать и в какой-то момент перестал перемещаться. Я попробовал перерегистрировать addon1c.dll, но не помогло.
43 247tsm
 
19.04.12
13:58
(42)+ я два раза посылаю SendKeys("+{TAB}"), потому что на форме списка есть еще элементы. Количество SendKeys("+{TAB}") я определил экспериментально - проделал сначала вручную эти операции, а затем попробовал программно - т.е. как макрос в Excel.
44 247tsm
 
19.04.12
14:09
Прошу прощения, просчитался. Следующий код работает 100% - позиционирует на дереве:

   Shell = CreateObject("WScript.Shell");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");
Нужно аккуратно посчитать, сколько раз послать SendKeys("+{TAB}").
Теперь осталось решить с {MULTIPLY}.
45 andrewks
 
19.04.12
14:20
(44) в том-то и дело, что с "WScript.Shell" ты с MULTIPLY не решишь, ибо его там просто нет. я попытался сделать через WinAPI, но там вообще всё глухо, как в танке
46 247tsm
 
19.04.12
14:27
В принципе, одно решение, кажется, нашел:

   Shell = CreateObject("WScript.Shell");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");
   Shell.SendKeys ("+{TAB}");

   Для нн = 1 по 10 Цикл
       Shell.SendKeys("{RIGHT}");
       Shell.SendKeys("{DOWN}");
   КонецЦикла;

Но для цикла нужно указать число не больше, чем папок+элементов в дереве, а иначе почему-то дерево не раскрывается, а курсор улетает на табличную часть. Хотя, когда я проделываю то же вручную - могу хоть 100 раз нажать {RIGHT} {DOWN} и курсор не выходит за рамки дерева. Не понятно, почему?
47 andrewks
 
19.04.12
14:29
(46) во изврат...
48 247tsm
 
19.04.12
14:29
Срабатывает и так:
. . .
   Для нн = 1 по 10 Цикл
       Shell.SendKeys("{RIGHT}{DOWN}");
   КонецЦикла;
49 247tsm
 
19.04.12
14:31
Вот только не удается указать коэффициент:
для одной клавиши понятно {RIGHT 10}, а как указать для группы клавишей?
50 247tsm
 
19.04.12
14:37
(47) да, немного поизвращался - но что делать, если в 1С такое дерево.
Есть другой вариант - воспользоваться FormEx - там есть "дерево+таблица", но уверяю, что кода там будет в 3 раза больше, а мне всего-то нужно раскрыть дерево и все.
51 247tsm
 
19.04.12
14:40
Работает и такой вариант:
   addon=CreateObject("addon1c.commands");    
   addon.SendKeys("+{TAB}");
   addon.SendKeys("+{TAB}");
   addon.SendKeys("+{TAB}");
   addon.SendKeys("+{TAB}");

   Для нн = 1 по 10 Цикл
       addon.SendKeys("{RIGHT}{DOWN}");
   КонецЦикла;
52 247tsm
 
19.04.12
14:40
Но все же хотелось бы сделать красиво с {MULTIPLY}
53 247tsm
 
19.04.12
14:41
... и вместо цикла с коэффициентом.
54 247tsm
 
19.04.12
14:42
(53) ... или вместо цикла с коэффициентом
55 andrewks
 
19.04.12
14:43
56 247tsm
 
19.04.12
14:44
Пока самый короткий вариант:
   addon=CreateObject("addon1c.commands");    
   addon.SendKeys("+{TAB 4}");
   Для нн = 1 по 10 Цикл
      addon.SendKeys("{RIGHT}{DOWN}");
   КонецЦикла;
57 247tsm
 
19.04.12
14:56
Интересно, какой вариант лучше: WScript.Shell или addon1c.commands? (без тормозов ... или может есть подводные камни)
58 catena
 
19.04.12
19:20
"addon.SendKeys("+{TAB}"); "

Кто-нибудь изменит порядок обхода на форме и полетит весь твой код за синей птицей...
59 Torquader
 
19.04.12
19:54
Ну, там же стандартное дерево - пишем dll, которая по идентификатору окна находит это "дерево" и шлёт ему команду развернуть.
Сообщение TVM_EXPAND - но его нужно слать для каждого элемента.
Если DLL в адресном просотранстве 1С (ActiveX from DLL), то спокойно можно получать элементы и делать с ними всё, что душа пожелает.
Только желательно помнить, что "умные" элементы управления шлют нотификацию своему окну, которую 1С будет обрабатывать - то есть нужно будет слать сообщения из отдельного потока, чтобы не мешать 1С их обрабатывать.
60 PR
 
19.04.12
20:09
Скажите мне кто-нить pls, почему все-таки не пашет {MULTIPLY}?
Это же вроде как вполне себе официальный параметр SendKeys?
61 Torquader
 
19.04.12
20:14
(60) Я когда смотрел SendKeys выяснил, что оно неправильно использует символы клавиатуры, то есть * транслируется именно в клавишу * вне зависимости, от того, что ты хочешь.
kbd_event спасёт, наверное.

http://www.nncron.ru/help/RU/add_info/keys_mnemonics.htm
62 andrewks
 
19.04.12
21:17
(60) в описании SendKeys есть закрытый перечень виртуальных кодов, и MULTIPLY среди них нет. зато есть в .NET'овском варианте
(61) kbd_event не взлетает, см (34)
63 Torquader
 
19.04.12
21:34
(62) kbd_event - это запись события в буфер клавиатуры ещё до распределения сообщения - если оно не взлетает, то не взлетит вообще ничего, так как сообщение не доходит до получателя.
P.S. а слать нужно через SendMessage, так как PostMessage обрабатывается при исполнении кода как ожидание Esc для его прерывания (в момент перехода с одной строки на другую), кстати, ваши SendKeys тож идут к тому же самому коту под хвост.
Посылать сообщения нужно не из потока 1С, а от кого-то другого.
64 andrewks
 
19.04.12
21:37
(63) "Посылать сообщения нужно не из потока 1С, а от кого-то другого." т.е. PostMessage тоже не взлетит?
65 andrewks
 
19.04.12
21:38
а "WScript.Shell" взлетает только потому, что клавиши идут от скриптовой длл-ки?
66 Torquader
 
19.04.12
21:43
(65) Насколько я помню, WScript вставляет коды клавиш в буфер клавиатуры, но не ожидает их обработки, то есть код продолжает исполняться.
Кроме того, любой объект из 1С исполняется не в её коде (то есть при вызове любого объекта исполнение кода 1С прерывается до окончания вызова).

А почему не прошло SendMessage WM_KEYDOWN самому элементу с деревом - у меня всегда проходило - я даже автосоздавалку объектов в конфиругаторе писал через него - 20тыс. справочников она за ночь сделала.
67 andrewks
 
19.04.12
21:45
SendMessage - аналогично, не взлетает
68 andrewks
 
19.04.12
21:48
делаю так:
в форме списка справочника в ПриОткрытии()


   HWND=WinAPI.GetActiveWindow();
   WinAPI.EnableWindow(HWND,-1);
   WinAPI.SetFocus(HWND);
   WinAPI.SendMessage(HWND,WM_KEYDOWN,VK_TAB,1);
   WinAPI.SendMessage(HWND,WM_KEYUP,VK_TAB,1);


и так:

   ScanCode=WinAPI.MapVirtualKey(VK_TAB,0); // MAPVK_VK_TO_VSC
   WinAPI.keybd_event(VK_TAB,ScanCode,0,0);
   WinAPI.keybd_event(VK_TAB,ScanCode,2,0);


1с-ка ничего не обрабатывает.


хотя, если делаю так:


   ScanCode=WinAPI.MapVirtualKey(VK_NUMLOCK,0); // MAPVK_VK_TO_VSC
   WinAPI.keybd_event(VK_NUMLOCK,ScanCode,0,0);
   WinAPI.keybd_event(VK_NUMLOCK,ScanCode,2,0);


то NumLock загорается/тухнет
69 Torquader
 
19.04.12
21:50
(67) Ну, тогда нужно взять и сделать Trace сообщений и посмотреть, что происходит.
Может быть, на некоторые сообщения просто акселераторы стоят, которые в потоке основого окна по Hook-процедуре ловятся - CommonControls, например, всплывающие подсказки именно так и ловит - тут уже нужно Hook найти и "скормить" ему то, что он хочет.
70 Torquader
 
19.04.12
21:51
(68) Какого "ПриОткрытии" - в лес!
При открытии - у тебя ещё формы нет - она будет только тогда, когда откроется.
Иди читай про ложное закрытие и не мучайся.
71 andrewks
 
19.04.12
21:52
(70) "При открытии - у тебя ещё формы нет"  ну как же нет? есть, и это можно увидеть, если поставить задержку, а потом закрыть форму. на экране увидишь родимую форму
72 andrewks
 
19.04.12
21:53
кстати, из других мест тоже пробовал, аналогично, так что дело не в этом
73 Torquader
 
19.04.12
21:56
Тогда пробуй просто получить список окон через GetWindow - и послать сообщение твоему несчастному окну через PostMessage или SendMessage, например.
74 andrewks
 
19.04.12
21:58
(73) т.е., возможно, сообщение уходит главному окну, вместо окна списка справочника?  была такая мысль, надо попробовать
75 Torquader
 
19.04.12
22:00
(74) Сообщение клавиатуры посылается тому, у кого выполнен SetFocus, но на время выполнения кода активность формы выключается, чтобы пользователь не нажал чего лишнего.
P.S. через обработку ожидания можно послать - она, если в глобальнике, то в другом потоке выполняется.
76 247tsm
 
20.04.12
00:00
Извините, что прерываю, но снова непонятка.
Если я вставляю какой-то программный код перед этими действиями по разворачиванию дерева, то дерево не раскрывается.
Этот код не работает:

       // Определяем кол-во папок
   Спр=СоздатьОбъект("Справочник.Номенклатура");
   Спр.ВыбратьЭлементы();
   КолПапок = 0;
   Пока спр.ПолучитьЭлемент()=1 Цикл
       Если спр.ЭтоГруппа()=1 Тогда
           КолПапок = КолПапок + 1;
       КонецЕсли;
   КонецЦикла;
   // КОНЕЦ Определяем количество папок
   
   //    Раскрываем дерево
   addon=CreateObject("addon1c.commands");    
   addon.SendKeys("^{HOME}");
   addon.SendKeys("+{TAB 4}");
   
   //КолПапок = 10;
   Для нн = 1 по КолПапок Цикл
       addon.SendKeys("{RIGHT}{DOWN}");
   КонецЦикла;

А следующий работает:

   //    Раскрываем дерево
   addon=CreateObject("addon1c.commands");    
   addon.SendKeys("^{HOME}");
   addon.SendKeys("+{TAB 4}");
   
   КолПапок = 10;
   Для нн = 1 по КолПапок Цикл
       addon.SendKeys("{RIGHT}{DOWN}");
   КонецЦикла;

В чем секрет?
77 247tsm
 
20.04.12
00:09
Вопрос решил - вывел из процедуры в тело модуля формы списка подсчет количества папок и снова заработало.
78 SUA
 
20.04.12
19:02
sendkeys(Символ(106)) не поможет?
79 smaharbA
 
20.04.12
19:05
сканкоды не предлагали еще ?
80 andrewks
 
20.04.12
19:16
(79) если сможешь их заслать в 1сину без использования внешней dll - то предлагай
81 smaharbA
 
20.04.12
19:49
(80) debug.exe
Основная теорема систематики: Новые системы плодят новые проблемы.