Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Создание WebBrowser`а средствами технологии COM средствами WinAPI


Страницы:   1 2

Klev ©   (2003-07-15 17:24:00) 

Hi All!
Нужно создать WebBrowser. Желательно без использования юнитов Sysutils, Comobj, Classes,... ,...
Сделать это можно, как выяснилось, только используя технологию COM.
Сначала я создал окно средствами WinApi, потом для создания собственно WebBrowser"a надо сделать примерно следующее:
CoInitialize(nil);
CoCreateInstance(...);
QueryInterface(...);
Далее следует создать оконный интерфейс в котором будет отображаться содержимое вебстраниц и использовать его в дальнейшем.

Но как это сделать остается загадкой 21 века.
Практических советов по этому вопросу я нигде не нашел.
Помогите пожалуйста решить данную нерешаемую проблему.


Maxim   (2003-08-22 14:12:00) [1]

Sorry, если оффтопик, я дополню, я имею ввиду стандартный компонент Delphi


Maxim   (2003-08-22 14:08:00) [2]

Господа, а не подскажете мне заодно как у энтого браузера рамку убрать? FindWindowEx, SetWindowLong не помогают совсем.


Крот   (2003-07-24 06:55:00) [3]

Удалено модератором
Примечание: Личная переписка


Klev   (2003-07-23 15:56:00) [4]

>Крот
1) Да зачем же сразу VCL использовать? Ведь есть кое-что лучше.
KOL - вот что надо использовать. Там как раз есть и поддержка ActiveX и готовый компонент WebBrowser. И размер EXE-файла не увеличится.

2) ATL тоже конечно можно приручить, но для этого надо опять же много работать. Может быть, что какой-нибудь извратный программер уже и сделал это. Просто надо поискать хорошенько.

3) Если есть пример, то отошли мне по e-mail, а лучше выкинь его в форум, что бы все могли почитать.

P.S Дело не в размерах винтов, и не в размерах экзэшника. Ведь кто-то придумал технологию COM, ActiveX, OLE. Зачем он придумал ее? Наверное для того, что бы кто-то использовал. А как можно использовать на все 100% то, что не понимаешь?


Крот   (2003-07-22 06:01:00) [5]


> Klev (15.07.03 17:24)


1. Вообще-то я предлагал TOleContainer как пример, там можно посмотреть какие надо реализовать интерфейсы, чтобы внедрить ActiveX. Если использовать VCL, то для внедрения WebBrowser TOleCOntainer вообще не нужен, т.к. WebBrowser есть в палитре компонентов.

2. Что касается примера Alex Konshin, то там внедрение происходит за счет использования специального класса окон, который есть только в ATL, так что для Delphi этот пример, по-моему мало информативен.

3. У меня где-то валялся пример внедрения ActiveX, но он MSVC.

P.S. Не совсем понятно почему нельзя использовать VCL. Чтобы размер экзэшника был меньше? Да кому это надо, сейчас винты большие, из-за копеечной выгоды в размере экзэшника столько головной боли.


Klev   (2003-07-21 20:45:00) [6]

Переписывать юниты comobj, olectrls,идр я не хотел, и под руку подвернулся практически готовый к использованию юнит ActiveKOL. Отучить его от err.pas оказалось легко, да и c KOL.pas
он расстался практически безболезненно. Делать с помощью него webbrowser я пока не пробовал, но надеюсь, что получится.


nikkie   (2003-07-19 20:15:00) [7]

>я ожидал найти в этой книге примерные алгоритмы действий при встраивании COM-объекта в приложение
COM-объект никуда встраивать не надо. CoCreateInstance + QueryInterface + вызовы методов интерфейса - вот и вся работа с COM-объектом. "Встраиваются" ActiveX-контроли.

> После чтения этой книги у меня появились некоторые мысли:
> Может быть сервер при создании запрашивает у клиента hwnd
> родительского окна. Т.о клиент должен сам реализовать некоторые
> интерфейсы и дать возможность COM-объекту ими воспользоваться.
> Через эти интерфейсы COM объект как раз и может запросить
> необходимую информацию для создания окна.

Собственно про это я тебе и говорил (nikkie © (17.07.03 16:42)). Более того, если ты посмотришь доки на интерфейсы, которые реализует TOleControl, то увидишь, что есть метод IOleWindow::GetWindow через который ActiveX контроль может получить некоторый HWND. Единственно, при создании контроль ничего у хоста спросить не может, поскольку интерфейса, через который можно спрашивать, у него пока нет. Насколько я понимаю из исходников OleCtrls.pas, этот интерфейс передается контролю через IOleObject::SetClientSite.


Klev   (2003-07-19 16:18:00) [8]

>nikkie
Действительно книжка называется "Основы...", но я ожидал найти в этой книге примерные алгоритмы действий при встраивании COM-объекта в приложение.
После чтения этой книги у меня появились некоторые мысли:
Может быть сервер при создании запрашивает у клиента hwnd родительского окна. Т.о клиент должен сам реализовать некоторые интерфейсы и дать возможность COM-объекту ими воспользоваться.
Через эти интерфейсы COM объект как раз и может запросить необходимую информацию для создания окна.


nikkie   (2003-07-19 00:46:00) [9]

>я прочел до 9-й главы. Далее идет привязывание к MSVC.
Ну это ты зря... 9-я глава действительно про C++, но там, например, объясняется про smart указатели - то, что ты здесь спрашивал. А мог бы сам прочитать :p

Глава 10 - про локальные и удаленные сервера в exe, глава 11 - про IDispatch, глава 12 - про потоковые модели COM. Все это к C++ никакого отношения не имеет, а собственно основы COM. Ну да ладно, применительно к этой задаче можно проехать пока - разве что про IDispatch хорошо бы все же почитать.

>практических обобщенных советов - мало.
Так тебе практических или обобщенных? :)
Дык книжка называется "Основы ..." и к тому же не слишком толстая :)

Несколько цитат из введения, которое ты, вероятно, пропустил ;)
COM - это основа, на которой построены такие технологие Microsoft, как ActiveX, DirectX и OLE. <...> Модель COM была разработана для решения проблемы "внедрения" электронной таблицы в текстовой редактор. Решение этой проблемы стало известным под именем OLE. <...> Теперь COM присутствует повсюду, и достаточно очевидно, что COM важнее OLE. <...> Задача этой книги - отделить COM от OLE и уделить первой то внимание, которого она заслуживает.

Тебе какие советы нужны? Про ActiveX? Или про DirectX? Может тебе надо написать как COM используется в Drag-Drop и Clipboard? Или тебя интересует OLE DB? Или несколько советов про то, как писать Shell Extensions? Или Browser Helper Objects? А может тебя интересует разработка MMC snap-in"s? Это никакой книжки не хватит, чтобы все охватить...


Klev   (2003-07-18 23:08:00) [10]

>nikkie
Книгу Дейла Роджерсона "Основы COM" я прочел до 9-й главы. Далее идет привязывание к MSVC. Вообщем книга полезная, но информацию из первых трех глав я уже встречал практически полностью в разных статьях. В книге много "воды", а практических обобщенных советов - мало.
Хорошо бы было узнать каким образом можно просто создать окно IE.
Из SHDocVw.dll можно увидеть, что у интерфейса IWebBrowser2 есть такие свойства как:
//The horizontal position (pixels) of the frame window relative to the screen/container.
property-get Left: I4; stdcall;
//The horizontal position (pixels) of the frame window relative to the screen/container.
property-put Left(: I4); stdcall;
//The vertical position (pixels) of the frame window relative to the screen/container.
property-get Top: I4; stdcall;
//The vertical position (pixels) of the frame window relative to the screen/container.
property-put Top(: I4); stdcall;
//The horizontal dimension (pixels) of the frame window/object.
property-get Width: I4; stdcall;
//The horizontal dimension (pixels) of the frame window/object.
property-put Width(: I4); stdcall;
//The vertical dimension (pixels) of the frame window/object.
property-get Height: I4; stdcall;
//The vertical dimension (pixels) of the frame window/object.
property-put Height(: I4); stdcall;

Из этого следует, что он предоставляет графическую оболочку в виде окна у которого есть ширина, высота,итд.
Значит, каким-то образом можно создать то самое окно, которое нужно, следовательно также можно установить родительское окно, сделать окно IE видимым...


Suntechnic   (2003-07-18 21:00:00) [11]

>Klev (18.07.03 19:51)
CComPtr<IWebBrowser2> spBrowser;


Это объявление т.н. smart pointer-а на COM интерфейс. "Умность" его заключается в том, что он управляет счётчиком ссылок (методы AddRef и Release) используя область видимости.


nikkie   (2003-07-18 20:31:00) [12]

>Хотя ATL в делфи - это очередная проблема.
примерно такая же как VCL в C++. но вот Борланд же решил...
тебе наверное таким же путем двигаться надо - модифицировать базовый язык, сделать компилятор
:)))


Klev   (2003-07-18 19:51:00) [13]

>Alex Konshin
Уважаемый Alex, проясните пожалуйста что значит это выражение :
CComPtr<IWebBrowser2> spBrowser;


Klev   (2003-07-18 19:24:00) [14]

>nikkie
Возможно действительно следует использовать ATL, т.к создание окна IE средствами COM действительно очень трудоемкое занятие, вынуждающее программиста становиться со временем или "богом" или мазохистом.
Кто-то и когда-то написал TOleContainer. Скорее всего этот кто-то был не один. Их было много, и называли они себя Borland inc.
И потратили они на написание много времени.
Хотя ATL в делфи - это очередная проблема.


nikkie   (2003-07-18 17:48:00) [15]

>Alex Konshin
я, конечно, извиняюсь, но
1. нить создавать не обязательно, вероятно, эта заморочка была нужна из-за связи c java - требовалось где-то разместить message loop
2. WebBrowser контроль можно создать и не через CreateWindow, в ATL много чего для этого понаписано
3. есть подозрение, что вообще получилось создать ActiveX контроль через CreateWindow только из-за того, что это ATL
4. собственно поддержка ActiveX заложена в ATL, в приведенном коде нет никакого намека на то, как это делать на api

>Крот
>делать это "вручную" - очень трудоемкое занятие
согласен. но ведь кто-то написал TOleContainer :)


Klev   (2003-07-18 17:24:00) [16]

>Крот
В том-то все и дело, что хочется сделать приложение без использования VcL и вспомогательных средств.


Klev   (2003-07-18 17:21:00) [17]

>Alex Konshin
Спасибо за кусочек кода.Более менее проблема прояснилась.


Крот   (2003-07-18 10:00:00) [18]


> Klev (15.07.03 17:24)


Нужно реализовать интерфейсы ActiveX контейнера, делать это "вручную" - очень трудоемкое занятие. Этим занимается TOleContainer.


Alex Konshin   (2003-07-18 09:16:00) [19]

Глюканул эксплорер.
Сори.


Alex Konshin   (2003-07-18 09:14:00) [20]

Я недавно писал такое, но для Java и на C++ (dll для управления IE). Занятие не для слабонервных. Мне еще нужно было редактирование поддерживать, и чтобы это еще и со swing дружило.
Реально тебе нужно просто заставить IE открыться в нужном тебе окне. Можно еще открыть окно IE и разместить его поверх какого-нибудь твоего контрола, и при изменении размеров контрола изменяй размеры окна броузера. Нужно бы еще и сообщения туда-сюда перекидать.

Это кусок из примера для java (на с++):

// Structure for Thread Parameters.
typedef struct {
char szURL[1024];
HWND hwnd;
} ThreadParam;

// Helper functions.
VOID CreateIEControl(ThreadParam *);
static void WINAPIV StartATL(LPVOID);

// native method for initializing the control.
JNIEXPORT void JNICALL Java_MyWindow_initialize
(JNIEnv *pEnv, jobject, jint hwndIn, jstring string)
{
// Fill up the params.
const char *str = pEnv->GetStringUTFChars(string, 0);
ThreadParam *pThreadParam = new ThreadParam;
pThreadParam->hwnd = (HWND) hwndIn;
strcpy(pThreadParam->szURL,str);
pEnv->ReleaseStringUTFChars(string, str);

// Launch the Thread.
_beginthread(StartATL, 0, pThreadParam);
}

// Thread for creating the control
void WINAPIV StartATL(LPVOID lpVoid)
{
ThreadParam *pThreadParam = (ThreadParam *)lpVoid;
CreateIEControl(pThreadParam);
delete pThreadParam;
MSG msg;
// Windows message loop.
while(GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

// Creates IE control
VOID CreateIEControl(ThreadParam *pThreadParam)
{
AtlAxWinInit();
printf("Create AtlAxWin Begin...[0x%x][%s]\n",pThreadParam->hwnd,pThreadParam->szURL);
// In the 2nd Param you can use ProgID or UUID of any activex control.
HWND hwndChild = ::CreateWindow("AtlAxWin",
"Shell.Explorer.1",
WS_CHILD|WS_VISIBLE,
0,0,0,0,
pThreadParam->hwnd,NULL,
::GetModuleHandle(NULL),
NULL);

IUnknown *pUnk = NULL;
AtlAxGetControl(hwndChild,&pUnk);
printf("Create AtlAxWin Done...[0x%x]\n",pUnk);

// get an interface to set the URL.
CComPtr spBrowser;
pUnk->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);
if (spBrowser)
{
CComVariant ve;
CComVariant vurl(pThreadParam->szURL);
#pragma warning(disable: 4310) // cast truncates constant value
spBrowser->put_Visible(VARIANT_TRUE);
#pragma warning(default: 4310) // cast truncates constant value
spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve);
}
}

// native method for handling resizes.
JNIEXPORT void JNICALL Java_MyWindow_resizeControl
(JNIEnv *, jobject, jint hwndIn, jint width, jint height)
{
HWND hwnd = (HWND) hwndIn;
RECT rc;
if(hwnd!=NULL)
{
::GetWindowRect(hwnd,&rc);
HWND hwndChild = GetWindow(hwnd, GW_CHILD);
printf("got resize (0x%x,%d,%d)\n",hwndChild,width,height);
( hwndChild,NULL,0,0,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOMOVE)

Я недавно писал такое, но для Java и на C++ (dll для управления IE). Занятие не для слабонервных. Мне еще нужно было редактирование поддерживать, и чтобы это еще и со swing дружило.
Реально тебе нужно просто заставить IE открыться в нужном тебе окне. Можно еще открыть окно IE и разместить его поверх какого-нибудь твоего контрола, и при изменении размеров контрола изменяй размеры окна броузера. Нужно бы еще и сообщения туда-сюда перекидать.

Это кусок из примера для java (на с++):

// Structure for Thread Parameters.
typedef struct {
char szURL[1024];
HWND hwnd;
} ThreadParam;

// Helper functions.
VOID CreateIEControl(ThreadParam *);
static void WINAPIV StartATL(LPVOID);

// native method for initializing the control.
JNIEXPORT void JNICALL Java_MyWindow_initialize
(JNIEnv *pEnv, jobject, jint hwndIn, jstring string)
{
// Fill up the params.
const char *str = pEnv->GetStringUTFChars(string, 0);
ThreadParam *pThreadParam = new ThreadParam;
pThreadParam->hwnd = (HWND) hwndIn;
strcpy(pThreadParam->szURL,str);
pEnv->ReleaseStringUTFChars(string, str);

// Launch the Thread.
_beginthread(StartATL, 0, pThreadParam);
}

// Thread for creating the control
void WINAPIV StartATL(LPVOID lpVoid)
{
ThreadParam *pThreadParam = (ThreadParam *)lpVoid;
CreateIEControl(pThreadParam);
delete pThreadParam;
MSG msg;
// Windows message loop.
while(GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

// Creates IE control
VOID CreateIEControl(ThreadParam *pThreadParam)
{
AtlAxWinInit();
printf("Create AtlAxWin Begin...[0x%x][%s]\n",pThreadParam->hwnd,pThreadParam->szURL);
// In the 2nd Param you can use ProgID or UUID of any activex control.
HWND hwndChild = ::CreateWindow("AtlAxWin",
"Shell.Explorer.1",
WS_CHILD|WS_VISIBLE,
0,0,0,0,
pThreadParam->hwnd,NULL,
::GetModuleHandle(NULL),
NULL);

IUnknown *pUnk = NULL;
AtlAxGetControl(hwndChild,&pUnk);
printf("Create AtlAxWin Done...[0x%x]\n",pUnk);

// get an interface to set the URL.
CComPtr spBrowser;
pUnk->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);
if (spBrowser)
{
CComVariant ve;
CComVariant vurl(pThreadParam->szURL);
#pragma warning(disable: 4310) // cast truncates constant value
spBrowser->put_Visible(VARIANT_TRUE);
#pragma warning(default: 4310) // cast truncates constant value
spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve);
}
}

// native method for handling resizes.
JNIEXPORT void JNICALL Java_MyWindow_resizeControl
(JNIEnv *, jobject, jint hwndIn, jint width, jint height)
{
HWND hwnd = (HWND) hwndIn;
RECT rc;
if(hwnd!=NULL)
{
::GetWindowRect(hwnd,&rc);
HWND hwndChild = GetWindow(hwnd, GW_CHILD);
printf("got resize (0x%x,%d,%d)\n",hwndChild,width,height);
::SetWindowPos(hwndChild,NULL,0,0,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOMOVE);
}
}

Из него более-менее понятно, как создать окна с броузером.
Основные моменты:
- создается нить;
- в этой нити создаем окно со специальным классом;
- в той же нити организуем цикл обработки сообщений.

Важно, чтобы все, что касается броузера отрабатывало в той самой нити, для этого можно просто определить свои сообщения и обрабатывать их в цикле той нити.

Это очень упрощенная схема.
Короче, развлечений ты себе надолго найдешь.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо