Имя: Пароль:
1C
 
Как активизировать окно 1с программно
0 Ardi
 
14.02.06
22:15
например при срабатывании ОбработкаВнешнегоСобытия()
1 PaulBC
 
15.02.06
00:45
Set WshShell = CreateObject("WScript.Shell")
Res = WshShell.AppActivate("1С:Предприятие")
2 smaharbA
 
15.02.06
06:50
(0)(1) Лучче определить ProcessID и AppActivate(ProcessID)
3 Ardi
 
15.02.06
22:15
Не получается: Другие приложения активируются, а "1С:Предприятие" и другие куски из его заголовка не берет. Код выдает -1 и 0
Процедура Сформировать()
   WshShell = CreateObject("WScript.Shell");
   Res = WshShell.AppActivate("Конфигуратор");
   Сообщить(Res);
   Для ъ=1 По 300000 Цикл
   КонецЦикла;
   WshShell = CreateObject("WScript.Shell");
   Res = WshShell.AppActivate("1C:Предприятие");
   Сообщить(Res);
КонецПроцедуры
4 smaharbA
 
15.02.06
22:54
-1 это сработало, 0  нет, а меня что непослушал ?
И уж если по заголовку то примерно так
WSHShell = СоздатьОбъект("WScript.Shell");
ПолныйЗаголовок="1С: Предприятие - "+СокрЛП(Метаданные.Идентификатор)+":  "+ЗаголовокСистемы();
wshShell.appActivate(ПолныйЗаголовок);
5 smaharbA
 
15.02.06
22:55
И посмотри чем отличаются
"1C:Предприятие... и "1С: Предприятие...
6 romix
 
модератор
15.02.06
23:14
Внешняя компонента DialMail содержит метод для активизации текущего окна 1С.

Ее работоспособность может зависеть от версии виндов: в новых виндах Microsoft стремится такие возможности ограничить и прикрыть, чтобы левые окна не мешали юзерам работать со своим основным окном (описание темы - в книге Рихтера).
7 smaharbA
 
15.02.06
23:16
(6) 8 строк и железно активизирует, но... активное еще не значит что фореграунд...
8 Ardi
 
15.02.06
23:22
(4) (5) Не помогает.
А как ProcessID определить?
9 romix
 
модератор
15.02.06
23:23
(7) Я думаю (0) хочет фореграунд, например, когда считался штрихкод. Хотя наверное проще забить на такие предъявы, чем их выполнять (имхо системное ограничение самих виндов). DialMail некими забавными трюками (я смотрел отладчиком) это ограничение обходил, но не факт что это работает во всех виндах.
10 Ardi
 
15.02.06
23:25
Как страшно жить на свете.
11 smaharbA
 
15.02.06
23:29
(8) Должно помоч, посмотри заголовок и ту строку что создается в (4) совпадают ?
+
WSHShell = СоздатьОбъект("WScript.Shell");
l = СоздатьОбъект("WBemScripting.SWbemLocator");
s = l.connectserver();
oExec = WSHShell.Exec("rundll32 kernel32,SleepEx");
ProcessID=s.get("Win32_process.Handle="+oExec.ProcessID).ParentProcessID;
oExec.Terminate();
WSHShell.appactivate(ProcessID);
12 Ardi
 
15.02.06
23:57
(11) Не хочет. Другие приложения через WSHShell.appactivate(ProcessID) активирует, а само себя не хочет.
Стоит WinXP sp2.
13 smaharbA
 
15.02.06
23:59
(12) Ну тогда только через внешнее с задержкой... напишу счас и коду немного
Да, а при выполнении в панели мигает ?
14 smaharbA
 
16.02.06
00:03
Вот счас попробовал...
//*******************************************
Процедура Сформировать()
   WSHShell = СоздатьОбъект("WScript.Shell");
   l = СоздатьОбъект("WBemScripting.SWbemLocator");
   s = l.connectserver();
   oExec = WSHShell.Exec("rundll32 kernel32,SleepEx");
   ProcessID=s.get("Win32_process.Handle="+oExec.ProcessID).ParentProcessID;
   oExec.Terminate();
   WSHShell.appactivate(ProcessID);
КонецПроцедуры

Процедура ПриОткрытии()
   Форма.ОбработкаОжидания("Сформировать",20);
КонецПроцедуры    // ПриОткрытии
...
Работает...
15 Ardi
 
16.02.06
00:04
не мигает.
Сообщить(WSHShell.appactivate(220));    открывает TotalCommader

Сообщить(WSHShell.appactivate(ProcessID));  выдает 0;
16 MMF
 
16.02.06
00:07
hWnd := GetForegroundWindow;  
if hWnd = Application.Handle then Exit;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @OldTimeOut, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Pointer(000), 0);
SetForegroundWindow(Application.Handle);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Pointer(OldTimeOut), 0);
17 smaharbA
 
16.02.06
00:10
(16) Ну так и я могу,.... а "мурку" можешь...(с) ;)
18 romix
 
модератор
16.02.06
00:13
(16) что-то мне этот хакерский набор вызовов напоминает DialMail (там работало, но в более новых Windows уже не работало).

(13) Возможно, системная блокировка на автоактивацию своего собственного окна распространяется и на дочерние процессы?
19 romix
 
модератор
16.02.06
00:17
Предлагаю сделать фоново запущенную (из Автозагрузки) прогу, которая опрашивает признак (например, наличие файла) и в зависимости от него активизирует окно. :-)
20 smaharbA
 
16.02.06
00:19
(18) Не не влияет, у него выходит так внешнеесобытие еще не отработало, а управление уже попало в 1с, тут нужна задержка и все...Проверить просто перед этим вставить код ВвестиСтроку("","",0,3) к примеру...только не предупреждение, у него тайминг когда окно неактивно стоит...
21 smaharbA
 
16.02.06
00:20
(19) Да все просче и со внешним, простое создается скрипт хоть объектом текст туда передают пид и задержку секунды две и все... Но можно и без скрипта обойтись...
22 Ardi
 
16.02.06
00:21
(14) Мигает. Но видимым не становится.
У тебя какой виндовс?
ОбработкаВнешнегоСобытия() сейчас проверить не могу.
23 MMF
 
16.02.06
00:24
дети, читаем азбуку :-)
A process can set the foreground window only if one of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.

With this change, an application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user. However, on Microsoft Windows 98 and Windows Millennium Edition (Windows Me), if a nonforeground thread calls SetForegroundWindow and passes the handle of a window that was not created by the calling thread, the window is not flashed on the taskbar. To have SetForegroundWindow behave the same as it did on Windows 95 and Microsoft Windows NT 4.0, change the foreground lock timeout value when the application is installed. This can be done from the setup or installation application with the following function call:

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

This method allows SetForegroundWindow on Windows 98/Windows Me and Windows 2000/Windows XP to behave the same as Windows 95 and Windows NT 4.0, respectively, for all applications.
24 MMF
 
16.02.06
00:26
(23+) хотите гарантировано стать верхним окном и не мигать на панели - см. 16. Кроме того, возможно, следует подумать об остановке скринсейвера.
25 smaharbA
 
16.02.06
00:30
(24) Этт все ясно Михаил, но ведь хотся подручными средствами, конечно смогу, но вот как человеку помоч реально ?
Можно конечно из подручных динврап предложить, или еще какой врап, можно как я люблю вордом обойтись(но этт тяжеловато для такой простой задачи ;))
26 MMF
 
16.02.06
00:34
(25) дык пусть напишет малюсенькую внешнюю компоненту из одного метода. Еще когда-нить будет тесно в рамках 1С - добавит еще что-нить.
27 smaharbA
 
16.02.06
00:35
(26) А вобщемто верно, может эта малюсенькая ВК и другому народу пользительна станет...
28 romix
 
модератор
16.02.06
00:38
Щас напишу... С разрешения Михаила
29 MMF
 
16.02.06
00:40
(28) до кучи - остановка скринсейвера
var
 uiAction, uiParam, fWinIni: integer;
 pvParam: boolean;
begin
 uiAction:= SPI_GETSCREENSAVEACTIVE;
 fWinIni:= SPIF_UPDATEINIFILE;
 SystemParametersInfo(uiAction, uiParam, @pvParam, fWinIni);
 if pvParam then
 begin
   uiAction:= SPI_SETSCREENSAVEACTIVE;
   pvParam:= false;
   SystemParametersInfo(uiAction, uiParam, @pvParam, fWinIni);
 end;
30 Ardi
 
16.02.06
00:51
(29) Я дико извиняюсь, но что с этим делать?
31 MMF
 
16.02.06
00:55
(30) ну вон (28) грозится сделать ВК. А тебе останется только написать ОбъектВК.СкринСейверСдохни() и ОбъектВК.НуКаВверх()... хотя, возможно названия методов не будут столь поэтичными
32 romix
 
модератор
16.02.06
01:08
(31) Окно пару раз подмигивает, но не активизируется. Windows 2000, SP4.

//////////////////////////////////////////////////
procedure Activate1C();
var OldTimeOut: DWORD;
var hWnd: DWORD;
begin
//Активизирует окно 1С (с) MMF
 hWnd := GetForegroundWindow;
 if hWnd = MainWindow then Exit;
 SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @OldTimeOut, 0);
 SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Pointer(000), 0);
 //SetForegroundWindow(Application.Handle);
 SetForegroundWindow(MainWindow);
 SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Pointer(OldTimeOut), 0);
end;
33 romix
 
модератор
16.02.06
01:12
function AddInObject.Init(pConnection: IDispatch): HResult; stdcall;
...

 iExtWindows:=nil;
 pConnection.QueryInterface(IID_IExtWndsSupport,iExtWindows);

 iExtWindows.GetAppMainFrame(MainWindow);
34 MMF
 
16.02.06
01:17
(33) iExtWindows.GetAppMDIFrame(MainWindow);
35 romix
 
модератор
16.02.06
01:19
(34) То же самое. Мигает 2 или 3 раза. Щас перепроверю.
36 romix
 
модератор
16.02.06
01:21
(+35) Перепроверил путем втыкания мессаджбокса (он кстати вылазит 2 раза - видимо инит проходит 2 раза.

pConnection.QueryInterface(IID_IExtWndsSupport,iExtWindows);

 //iExtWindows.GetAppMainFrame(MainWindow);
 iExtWindows.GetAppMDIFrame(MainWindow);

 MessageBox(0,'hi','',0);
37 MMF
 
16.02.06
01:23
(36) дык ясен пень, Init выполняется два раза (у тебя ж компонента экспортирует один объект).  procedure Activate1C() как вызывается?
38 romix
 
модератор
16.02.06
01:25
Видимо, разработчики виндов тоже прочитали эту азбуку, и решили прикрыть и эту лазейку. :-) Остается поюзать "There is no foreground process". Может, сначала свернуть все окна, подождать секунду, и развернуть окно 1С? :-)
39 romix
 
модератор
16.02.06
01:26
methActivate1C: begin
            //StopScreennSaver();
            Activate1C();
         end;
40 romix
 
модератор
16.02.06
01:26
из
function AddInObject.CallAsFunc(lMethodNum: Integer; var pvarRetValue: OleVariant; var paParams: PSafeArray): HResult; stdcall;
41 MMF
 
16.02.06
01:30
(40) щас я уже выключил Дельфи, но я приводил код из работающих сырцов. Завтра попробую собрать компоненту, авось получится
42 romix
 
модератор
16.02.06
01:32
Может у тебя процесс был "Being debugged", и поэтому все работало?
43 smaharbA
 
16.02.06
01:32
Да блин, что вордом сделать ?
44 romix
 
модератор
16.02.06
01:37
(43) Пока ничего - имхо это все не работает... Ибо разработчики виндов этот лаз похоже прикрыли в 2000 SP4.
45 smaharbA
 
16.02.06
03:06
Ну что вышел каменный цветок, вот тупенький но железный метод...
...
Перем ProcessID,WSHShell,Shell;
//*******************************************
Процедура Сформировать()
   Shell.UndoMinimizeAll();
   WSHShell.appactivate(ProcessID);
КонецПроцедуры

Процедура ПриОткрытии()
   Форма.ОбработкаОжидания("Сформировать",5);
КонецПроцедуры    // ПриОткрытии
Shell=СоздатьОбъект("Shell.Application");
WSHShell = СоздатьОбъект("WScript.Shell");
l = СоздатьОбъект("WBemScripting.SWbemLocator");
s = l.connectserver();
oExec = WSHShell.Exec("rundll32 kernel32,SleepEx");
ProcessID=s.get("Win32_process.Handle="+oExec.ProcessID).ParentProcessID;
oExec.Terminate();
...
46 romix
 
модератор
16.02.06
11:21
(45) Прикольно, но не работает.
Раз в 5 секунд 1С в трее 3 раза подмигивает...
Имхо задача не решается... Хотя можно попробовать такой изврат:
запустить из ВК маленькую оконную прогу в debug-режиме, и ее окно станет Foreground. А из нее уже активизировать что хочется...
47 smaharbA
 
16.02.06
12:11
(46) Работает, только задержку надо воткнуть между
   Shell.UndoMinimizeAll();
   WSHShell.appactivate(ProcessID);
48 smaharbA
 
16.02.06
12:11
+ (47) У меня послабее будет машина ;)
49 romix
 
модератор
16.02.06
12:16
(47) Так что ли:
   Shell.UndoMinimizeAll();
   для й=1 по 100000 Цикл
   КонецЦикла;
   WSHShell.appactivate(ProcessID);

У меня опять мигает в таскбаре, но не активизируется.
Имхо ограничение виндовс. У меня XP SP2.
50 smaharbA
 
16.02.06
12:19
(49) Я на 2003 пробовал, можно еще так
 Shell.TogleDesktop();
Задержка();
 Shell.TogleDesktop();
  WSHShell.appactivate(ProcessID);
51 smaharbA
 
16.02.06
12:23
Можно еще извратнее, но через АПИ, сделать вообще топмост... тогда больше ниодно приложение не покажется ;) гдето у меня такое было...
52 swa
 
16.02.06
12:43
Мда, не я один такой...
Одно из решений - сначала "свернуть" окно, потом "развернуть" (RESTORE или MAXIMIZE), а потом уже SetForegroundWindow. Результат - окно "впереди" других. Но тоже в нек. ситуациях не срабатывает.
(18) так категорично :) . В каких версиях операционок не работает? Проверял на XP, 2000 prof.
53 evGenius
 
16.02.06
12:50
Вот есть рабочий кусочек на сях:

Как утверждает документация, SetForegroundWindow работает как нам нужно, только если вызывающий её процесс является активным. А активен тот процесс, чей поток обрабатывает пользовательский ввод. Оказывается, наш процесс может "прикинуться" активным, подключив свой поток к обработке пользовательского ввода. Это осуществляется при помощи функции AttachThreadInput. После вызова SetForegroundWindow можно будет отключиться от чужого потока, используя ту же функцию (но передавая в качестве третьего параметра FALSE, а не TRUE).
Реализация этой идеи выглядит так.

HWND hCurrWnd;
int iMyTID;
int iCurrTID;
hCurrWnd = ::GetForegroundWindow();
iMyTID   = GetCurrentThreadId();
iCurrTID = GetWindowThreadProcessId(hCurrWnd,0);
AttachThreadInput(iMyTID, iCurrTID, TRUE);
// hWnd - дескриптор окна.
SetForegroundWindow(hWnd);
AttachThreadInput(iMyTID, iCurrTID, FALSE);
54 smaharbA
 
16.02.06
13:05
(53) Уже прошли это...
Вот подделал и ввод активизировал, работает ведь...
...
Перем ProcessID,WSHShell,Shell;
//*******************************************
Процедура Сформировать()
   Shell.UndoMinimizeAll();
   ВвестиСтроку("","",1,0,1);
   WSHShell.appactivate(ProcessID);
КонецПроцедуры

Процедура ПриОткрытии()
   Форма.ОбработкаОжидания("Сформировать",5);
КонецПроцедуры    // ПриОткрытии
Shell=СоздатьОбъект("Shell.Application");
WSHShell = СоздатьОбъект("WScript.Shell");
l = СоздатьОбъект("WBemScripting.SWbemLocator");
s = l.connectserver();
oExec = WSHShell.Exec("rundll32 kernel32,SleepEx");
ProcessID=s.get("Win32_process.Handle="+oExec.ProcessID).ParentProcessID;
oExec.Terminate();
...
55 evGenius
 
16.02.06
13:39
(54) Где прошли?
56 swa
 
16.02.06
20:53
(53) Замечательный способ! А почему (с) не проставлены?
http://www.rsdn.ru/article/qna/ui/wndsetfg.xml