Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Meverik, Вы писали:
M>>В C# пытаюсь работать с неуправляемым кодом DLL а конкретно с DLL написанной на Delphi содержащей форму.
M>>Все создается, формой управляю, но вот когда из Delphi еще одна форма создается,
M>>вот тут начинаются проблемы по созданию компонентов (расположенных на данной форме) основанных на стандартных оконных классах (TButton, TEdit и т.п.). Точнее объект Delphi класса создается, но
M>>когда происходит создание Windows окна компонента (непосредственно метод TWinControl.CreateWnd), то с помощью GetClassInfoA вычисляется адрес стандартного оконного класса, а этот адрес уже не тот, что при создании компонентов на первой форме и соответственно при передачи его в CreateWindowEx функция в итоге не возвращает Handle окна, что приводит к ошибке RaiseLastOSError (A call to an OS function failed). После длительного разбора "полетов" пришел вот к такой особенности C#.... И как это обойти пока не ясно....
PD>Могу предложить попробовать трюк. А именно, создать никому не нужную форму из C# до всей этой деятельности (сделать ее невидимой, конечно). Возможно, при этом вся деятельность по сабклассингу пройдет, так что создание как первой , так и второй Delphi форм будет происходить уже в условиях свершившегося сабклассинга. Поможет или нет — бог знает.
Так дело в том что первая форма создается нормально, а вот если из нее еще одну создавать.... вообщем уже не суть....
В итоге проблема решена. Для истории опишу что было:
В C# есть метод класса Application: EnableVisualStyles(); -- Этот метод включает визуальные стили приложения, что в итоге приводит к тому, что для прорисовки управляющих элементов (которые соответственно основаны на стандартных оконных классах типа BUTTON, EDIT и т.п.) необходимо использовать библиотеку comctl32.dll 6-ой версии, а по умолчанию используется comctl32.dll 5-ой версии, для отрисовки все тех же элементов управления. Так вот в Windows XP уже была добавлена возможность работать одновременно с двумя одинаковыми библиотеками разных версий, что успешно делает C#. Вот почему до создания формы в C# GetClassInfoExA возвращал один адрес оконной процедуры (которая прописана для данного оконного класса в comctl32.dll 5-ой версии), а при созданной форме уже использовал для элементов управления библиотеку comctl32.dll 6-ой версии, вот GetClassInfoExA и возвращая другой адрес, т.к. фактически классы EDIT, BUTTON и т.п. созданы в другой библиотеки. Ну а Delphi по умолчанию просто использует comctl32.dll 5-ой версии и в нем таких проблем не было.
Решение следующее (возможно можно как-то по другому, если есть идея, буду рад ознакомиться с ней): Комментим Application.EnableVisualStyles() для того, чтобы C# использовал только comctl32.dll 5-ой версии и все.... все будет работать, только визуальные компоненты отображаются уже не "красивыми" как изначально с данной опцией.... !!! НО !!! Есть, начиная с Windows XP такие файлы: Manifest называются )) Вот с помощью их описываем, что приложение должно использовать comctl32.dll 6-ой версии и C# тогда начинает во всем приложении использовать только 6-ую версию библиотеки... включая модули (DLL формы) написанные на Delphi и все управляющие элементы становятся снова "красивыми" ))
Манифест можно положить рядом с EXE файлом программы (с названием: [имя файла программы].exe.Manifest) или добавить его в C# проект и в настройка проекта выбрать данный файл манифеста, чтобы он присутствовал в самом EXE файле программы, что я и сделал.
Манифест у меня такой:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
<assemblyIdentity
name="Название моей программы"
processorArchitecture="*"
version="1.0.0.0"
type="win32"/>
<description>Описание моей программы</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>