gifts2017

Иерархия окон в 1С 8.2

Опубликовал Аркадий Кучер (Abadonna) в раздел Программирование - Практика программирования

Результаты первоначального исследования окон 8.2.

Для работы с окнами 1С необходимы следующие хэндлы окон:
1. h1C – хэндл главного окна
2. hMDI – хэндл окна MDI (для 8.2 неактуально)
3. hReport - хэндл окна активной формы отчета (обработки)
4. hReportDialog - хэндл «подложки» (слой, куда можно поместить видимые компоненты)

Главное окно 8.2 имеет класс V8TopLevelFrameSDI, для вызывающей библиотеки может быть найдено как окно данного класса (с условием, что PID этого окна равен PID библиотеки, т.к. они принадлежат одному процессу)

function EnumWindows82Proc(WND: hwnd; LPARAM: lParam): bool; stdcall;
var ThrID, PID: DWORD;
var b:array[0..254] of AnsiChar;
begin
  ThrID := GetWindowThreadProcessId(wnd, PID);
  GetClassName(wnd,@b,255);

  {ищем только "своё" главное окно}
  if (b='V8TopLevelFrameSDI') and (PID=GetCurrentProcessId()) then begin
  Main82Handle:=wnd;
  end;
end;

function TMiracleClass.GetMain82: Integer;
begin
  Main82Handle:=0;
  EnumWindows(@EnumWindows82Proc, 0);
  RESULT:=Main82Handle;
end;
Примечание: для сторонней программы главное окно можно найти через
FindWindow('V8TopLevelFrameSDI',nil) – самое верхнее
или
FindWindow('V8TopLevelFrameSDI',ЗаголовокЭтогоОкна)

Формы 8.2 хоть и принадлежат процессу главного окна, но не являются его дочками, а являются окнами верхнего уровня. Окна имеют класс V8TopLevelFrameSDIsec
Для вызывающей библиотеки хэндл формы можно найти через GetActiveWindow, со стороны через 
FindWindow('V8TopLevelFrameSDIsec',nil) – активная
или
FindWindow('V8TopLevelFrameSDIsec',ЗаголовокНужнойФормы)
А вот дальше начинается весьма запутанная иерархия дочерних окон активной формы.
Методом научного тыка (кстати, удобный - рекомендую[http://infostart.ru/public/59436/index.php?fimages=yes&PAGEN_1=7#comm], пост 124) был определен хэндл «подложки», как раз тот слой, где внедренные компоненты видимы на форме
wnd:=FindWindow('V8TopLevelFrameSDIsec',nil); // найдется активная форма
wnd:=GetTopWindow(wnd);// первый V8LayouterTabsWindow
wnd:=GetTopWindow(wnd);// его первый V8FormElement
w:=FindWindowEx(wnd,0,'V8LayouterTabsWindow',nil);// его первый V8LayouterTabsWindow
wnd:=FindWindowEx(wnd,w,'V8LayouterTabsWindow',nil); //его второй V8LayouterTabsWindow
wnd:=GetTopWindow(wnd);// его первый V8FormElement
wnd:=GetTopWindow(wnd);// его первый V8LayouterTabsWindow
wnd:=GetTopWindow(wnd);// его первый V8FormElement - он самый!!!!
{внедряем компонент дельфи}
PB:=TProgressBar.CreateParented(wnd);
PB.UpdateControlState;
PB.Left:=10;
PB.Top:=40;
PB.Width:=200;
PB.Height:=20;
PB.Visible:=true;
PB.Enabled:=true;
PB.Position:=60;
(результат на картинке)

См. также

Подписаться Добавить вознаграждение

Комментарии

1. vip (vip) 26.12.09 05:57
Молодец.
Лиха беда начало.
Любопытно, зачем 1С использует свои классы окон.
Для понтов?
2. Аркадий Кучер (Abadonna) 26.12.09 06:02
(1) Начиная с 8.1 у них пошли свои... Наверное, для понтов ;)
3. Артур Аюханов (artbear) 26.12.09 07:26
Интересно.
Но ИМХО очень важное дело с окнами 8, которое пока никто не решил - это получение текста окна :(
4. Артур Аюханов (artbear) 26.12.09 07:32
Например, очень интересная задача - получение текста модуля в Конфигураторе
5. AmoreMe (AmoreMe) 26.12.09 17:49
Для того что вы говорите нужно организовать межпроцессный обмен, на мой взгляд инжект DLL самый лучший вариант. Но о вкусах как говорится... А уж потом помятуя, что все контролы - окна, работать с ними как с обычными окнами... (API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API). А текст в конфигураторе это похоже RichEdit, ну или какая его эманация! Суть дела не меняет... (Кстати в этом случае получится не просто читать текст, но и менять его из своего приложения или контролировать ввод...)
6. Аркадий Кучер (Abadonna) 26.12.09 17:54
(5)
(API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API). А текст в конфигураторе это похоже RichEdit

Че ж думаешь, никто не проверил его, например, на стандартную API
SendMessage(wnd, em_GetLineCount,0,0)? Думаешь я и мессаги там не проконтролировал? Там только только через переопредление оконной процедуры добраться можно, или через перехват родных библиотек :(
7. Аркадий Кучер (Abadonna) 26.12.09 17:57
+(6) А метод отоляринголога для получения текста модуля в конфигураторе реализован в http://infostart.ru/public/19946/
8. Игорь Исхаков (Ish_2) 26.12.09 20:39
Хоть и не понял ни слова , а любопытствую . Скажи мне , Абадонна , по-простому. Зачем это нужно , обращение к окнам 1с из внешнего приложения ? Просто любопытно расковырять оконный интерфейс 1с ?
Или это можно где-то применить ?

Только предупреждаю ,я еле-еле вспомнил школьное определение Handle : логический номер назначаемый объекту (файлу , устройству и т.п).
9. Аркадий Кучер (Abadonna) 27.12.09 04:58
(8)
Зачем это нужно , обращение к окнам 1с из внешнего приложения ?

Из внешнего приложения не особенно и надо, а вот тут (картинка 6)
http://infostart.ru/public/59436/index.php?fimages=yes#images без этого никак не обойтись, на этом все и построено. А отлаживать- куда как удобнее из внешнего
10. Игорь Исхаков (Ish_2) 27.12.09 13:17
(9) Кроме глубокомысленного : "кому что нравится" - сказать мне нечего.
11. Аркадий Кучер (Abadonna) 27.12.09 15:35
(10)
Кроме глубокомысленного : "кому что нравится" -

Глубомысленное давно уж написано на воротах: "Каждому своё" ;)
12. Игорь Исхаков (Ish_2) 27.12.09 15:47
11) Хм.. А ,пожалуй , я с тобой согласен.
На воротах храма ВК-ашников такая надпись смотрелась бы многозначительно. И всяк входящий сюда - задумался бы.
13. Аркадий Кучер (Abadonna) 27.12.09 15:50
(12)
Нет тут, как в аське,символа с двумя пивными кружками :(
А НАДО!!!! Доржи!!!!!!!!!!!!!?????????????
14. Артур Аюханов (artbear) 28.12.09 07:56
(8) Не обязательно из внешнего приложения обращаться.
Если бы была возможность работы с окнами 1С, текстами и т.д., вполне можно было, например, упростить себе работу в Конфигураторе, сделав некое грубое подобие Опенконф для 77 с его скриптами и плагинами :)
Лично меня этот проблема очень занимает, но пока не удается решить :(
15. Аркадий Кучер (Abadonna) 28.12.09 08:05
(14) Вот и я про то же. Если уж один из авторов 1с++ пока на разобрался, то
(API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API).

никак не катит
16. Игорь Исхаков (Ish_2) 28.12.09 09:34
(14) Ага. Понятно. Опенконф полгода назад поставил. Он быстрее и функциональнее чем встроенный редактор 1сv8.
17. Александр Рытов (Арчибальд) 28.12.09 10:01
Где только черти не носят Абадонну... Надысь алиментами интересовался, теперь вот окошками :o
18. Доржи Цыденов (support) 28.12.09 12:13
(13) Да, не хватает. ;)
http://infostart.ru/profile/53/blog/868/
Вот, альтернативный:
19. Аркадий Кучер (Abadonna) 28.12.09 13:54
(17)
. Надысь алиментами интересовался, теперь вот окошками

Смотрю вот сейчас на окошко... Открыть - понимаю, закрыть - понимаю, но как, блин, свернуть? :))))
20. ilya005 (ilya005) 30.12.09 03:22
Это конечно всё здорово, НО!!!
Вы не подумали, ЗАЧЕМ 1с выпустила 8.2 ?!
Что бы кто-то потом дорабатывал ее в delphi,c, .net Итд ?
я всегда думал, что это не совсем так и вот доводы:
1. 8.2 изначально делалась как МУЛЬТИ платформенное решение, в браузере ее (теоретически) можно хоть на линуксе и на телефоне запустить! (как там ваш прогресс бар будет работать ? - НИКАК!)
2. в 8.2 сделали СВОЙ стандарт внешних компонент.
21. dushelov (Душелов) 30.12.09 08:53
(20) Для начала стоит Вам самим ознакомиться со стандартном внешних компонент, который предлает 1С.
22. Роман Осадченко (cleaner_it) 12.01.10 05:37
(16) можно поинтересоваться, а где взяли опенконф под 1С 8? Никак найти не могу, вот уже года три. Может ищу не там/не так?...
23. Артур Аюханов (artbear) 12.01.10 06:55
(22) Автор (16) ИМХО подразумевал, что поставил Опенконф для 77.
Для 8 Опенконф-а не существует, есть только некие зачатки скриптов
http://www.1cpp.ru/forum/YaBB.pl?num=1227553473/0
Посмотри ветку в начале и в конце
24. Аркадий Кучер (Abadonna) 18.01.10 03:54
(20)
Вы не подумали, ЗАЧЕМ 1с выпустила 8.2 ?!

Думаю, чтобы бабла еще срубить, а зачем еще? ;)
25. Аркадий Кучер (Abadonna) 19.01.10 19:42
(4)
Например, очень интересная задача - получение текста модуля в Конфигураторе

Вот такая безрадостная фигня пока ;(
1. Окошко ввода совсем не желает вести себя как нормальный контрол оpгана упpавления pедактиpованием. В частности не реагирует на стандартную API SendMessage(handle,em_GetLineCount,0,0), которая должна вернуть количество строк в органе управления.
2. Нажатие любой клавиши выдает неопознанную виндой мессагу 0x0118, при этом для любой клавиши wParam=0000FFFF, а lParam=BF84AC9A (всегда, блин!)
см. рис.
Прикрепленные файлы:
26. dushelov (Душелов) 19.01.10 20:53
(25) Формат бы этих сообщений получить...
27. Vladimir K (KroVladS) 26.08.13 17:05
(0)
класс V8TopLevelFrameSDI в 8.2 актуален только для Управляемых форм или для обычных тоже?

Обычные формы:

ищу
FindWindow(L"V8TopLevelFrameSDIsec",NULL);
ничего не находит.
FindWindow(NULL,L"1С:Предприятие - Конфигурация");
находит.

не могу найти окно обработки. не подскажите как?

можно ли встроить фрейм в окно обработки средствами WIN API?
28. Аркадий Кучер (Abadonna) 26.08.13 17:51
(27) KroVladS,
1. Рекомендую использовать мелкософтовский SpyXX - удобная штука.
SPYXX
2. Для обычного приложения иерархия совсем другая, похожая на иерархию окон 7.7
Хендл MDI-окна
hMDI:=FindWindowEx(MainHandle,0,'V8MDIClient',''); где MainHandle - хендл главного окна
Хендл активной обработки
hActiveForm:=GetTopWindow(hMDI);
Прикрепленные файлы:
29. Vladimir K (KroVladS) 26.08.13 18:59
(28) Abadonna,

Спасибо всё нашёл.
30. Vladimir K (KroVladS) 28.08.13 14:23
(28) Abadonna,
Ещё один глупый вопрос.

Есть dll библиотека которая отправляет видеопоток в окно по его Хендлу.
По COM подключить её нельзя т.к. отсутствуют точки входа.
Обернул её в внешнюю компоненту NativeAPI, отправляю в окно обработки 1с, всё хорошо пока фокус захвачен dll (вместо паузы использую MessageBoxA(hMDI,"","",MB_OK)), как только 1с возвращают фокус она видит что над её формой нагло надругались и падает.

в какую сторону капать ?
31. Аркадий Кучер (Abadonna) 02.09.13 06:50
(30) KroVladS, в своей Native используй компонент TMediaPlayer - и всех проблем. Там можно и в MDI отправить, и в активную форму, и вообще в отдельное окно.
32. Аркадий Кучер (Abadonna) 02.09.13 06:57
/+31/
Прикрепленные файлы:
33. Аркадий Кучер (Abadonna) 02.09.13 07:06
(30) KroVladS, Блинский клин! Классно свайт обновили: "Изменить" отправляет хз куда, только не в редактирование, файлы прикрепить не дает...
К /31/ посмотри картинку в http://infostart.ru/public/18629/
Как раз TMediaPlayer на активной форме 1С
34. Vladimir K (KroVladS) 03.09.13 15:33
(33) Abadonna,
Спасибо за ответ. но задача несколько иная и компонент TMediaPlayer не подойдет.
т.к. необходимо использовать именно эту библиотеку.

Если копнуть чуть глубже, падает сама dll из-за ошибки доступа к памяти.
Есть сишный проект построенный на этой dll вроде работает, делаю те-же вызовы из NativeAPI всё падает.

В общем это офтопный офтоп.
35. Vladimir K (KroVladS) 04.09.13 16:40
(33) Abadonna,

офтоп
Обернул dll библиотеку в ActiveX и 1с перестала падать.
з.ы. да я извращенец, но работает же :)
36. Аркадий Кучер (Abadonna) 04.09.13 16:50
(35) KroVladS, там еще нюанс мог быть...
Ты поток на хендл активной формы выводил? А, скорее всего надо было на то, что я называю hReportDialog
37. Vladimir K (KroVladS) 04.09.13 16:52
(36) Abadonna,
И на хендл активной формы.
И на стандартный элемент картинка.
И вставлял на форму стандартный ActivX элемент MS Forms 2.0 Frame

Всё одно падал.
38. Аркадий Кучер (Abadonna) 04.09.13 16:57
(37) KroVladS, сюда не пробовал?:
........................
wnd:=FindWindowEx(wnd,w,'V8LayouterTabsWindow',nil); //его второй V8LayouterTabsWindow
wnd:=GetTopWindow(wnd);// его первый V8FormElement
wnd:=GetTopWindow(wnd);// его первый V8LayouterTabsWindow
wnd:=GetTopWindow(wnd);// его первый V8FormElement - он самый!!!!
____________
Последний как раз hReportDialog
_________________
Тебе на обычные формы надо? Тогда напишу как там его найти
39. Vladimir K (KroVladS) 04.09.13 17:11
(38) Abadonna,
Именно туда и выводил.
Для неуправляемых форм.

HWND hWnd1с = FindWindow(L"V8TopLevelFrame",NULL);
HWND hMDI = FindWindowEx(hWnd1с,NULL,L"V8MDIClient",NULL);
hMDI =GetTopWindow(hMDI);
hMDI =GetTopWindow(hMDI);
hMDI =GetTopWindow(hMDI);
hMDI =GetTopWindow(hMDI);// <-- Элемент картинка на форме
//лишний уровень
// hMDI =GetTopWindow(hMDI);

код правда сишный
40. Аркадий Кучер (Abadonna) 04.09.13 17:16
(39) KroVladS, стоп-стоп-стоп! Еще раз вопрос повторяю: форма обычная или управляемая?
41. Vladimir K (KroVladS) 04.09.13 17:19
42. Vladimir K (KroVladS) 04.09.13 17:19
43. Аркадий Кучер (Abadonna) 04.09.13 17:23
(41) KroVladS,
hReport:=GetTopWindow(hMDI);

hReportDialog:=GetTopWindow(GetTopWindow(hReport));

три раза TOP от MDI - вот тут железно любые компоненты рисуются
44. Vladimir K (KroVladS) 04.09.13 17:31
(43) Abadonna,
В одном из первых сообщений я дезинформировал Вас
как только 1с возвращают фокус она видит что над её формой нагло надругались и падает.


На самом деле
Если копнуть чуть глубже, падает сама dll из-за ошибки доступа к памяти.
45. Сергей Паринов (rootuk) 12.03.14 22:25
Подскажите, пожалуйста, могу я с помощью данного подхода изменить шрифт кнопки в командной панели? (это 1С сделать не дает), или задать размер колонки меньше ширина слова, которое в нем(как будто пользователь сам уменьшил размер колонки)?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа