Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

// код из OnNavigateComplete

CComQIPtr<ICustomDoc, &IID_ICustomDoc> m_pBrowserCustomDoc;

CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pADocument;

CDocHostUIHandler m_DocHostImpl;

m_DocHostImpl.AddRef;

m_DocHostImpl.m_pAppDisp = m_pApp->GetIDispatch(FALSE);

m_pBrowserCustomDoc = pADocument;

m_pBrowserCustomDoc->SetUIHandler((IDocHostUIHandler*)&m_DocHostImpl);

В данном коде фигурирует класс CDocHostUIHandler, который реализует все методы интерфейса IDocHostUIHandler (и конечно же AddRef, QueryInterface и Release от IUnknown). В базовом варианте, реализация этого объекта сводится лишь к созданию процедур-заглушек для каждого метода IDocHostUIHandler, возвращающих E_NOTIMPL. А если хочется, чтобы Internet Explorer не показывал своего конекстного меню, нужно возвращать из метода ShowContextMenu S_OK.

Если наш объект CDocHostUIHandler возвращает указатель в методе get_External, то этот указатель и используется как объект расширения и тогда где-нибудь внутри самой html странички можно будет написать такие строки:

<script language="JavaScript">

function ShowSettingsDialog {

 if (window.external.ShowSettings == true) {

document.body.bgcolor = window.external.BackColor;

 }

}

</script>

<body>

<a href="#">Settings</a>

</body>

В приведенном примере, функция ShowSettings и свойство BackColor запрашиваются из недр нашего собственного приложения.

Где хранить свои HTML

В ресурсах! К счастью, Internet explorer умеет грузить из ресурсов, нужно только в качестве префикса URL написать res://<путь к модулю>/<название ресурса>. Я привожу реализацию этого метода, выдранную из исходного текста CHTMLView.

HINSTANCE hInstance = AfxGetResourceHandle;

CString strResourceURL;

BOOL bRetVal = TRUE;

LPTSTR lpszModule = new TCHAR[_MAX_PATH];

if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH)) {

 // lpszResource - строкое название ресурса

 strResourceURL.Format(_T("res://%s/%s"), lpszModule, lpszResource);

 m_pBrowserApp->Navigate(strResourceURL, NULL, NULL, NULL, NULL);

} else bRetVal = FALSE;

delete [] lpszModule;

return bRetVal;

HTML ресурсы можно вынести в отдельный подкаталог, например html. Тогда в файле описания ресурсов (например, myapp.rc) необходимо добавить строки следующего вида:

IDR_MAIN HTML DISCARDABLE "html\\main.html"

DEL.GIF HTML DISCARDABLE "html\\del.gif"

LEFTARR.GIF HTML DISCARDABLE "html\\leftarr.gif"

RIGHTARR.GIF HTML DISCARDABLE "html\\rightarr.gif"

TITLE.GIF HTML DISCARDABLE "html\\title.gif"

NEWMSG.GIF HTML DISCARDABLE "html\\newmsg.gif"

Реализация доступа к ресурсам в IE достаточно умна, чтобы автоматически найти все необходимые объекты в ресурсах, на которые ссылается страничка, поэтому достаточно знать лишь ресурс-имя основной странички.

ВОПРОС-ОТВЕТ 

Q. Насколько корректно будут работать методы контроля утечек памяти (в частности объект CMemoryState) в многопоточных приложениях?

У меня сложилось впечатление, что объект CMemoryState не делает различия в каком потоке вызывались операторы new с момента обращения к memState.Checkpoint до обращения к memState.DumpAllObjectsSince.

Видимо "моментальные снимки" распределённой памяти в данном случае не информативны, ведь несколько потоков работают в одном адресном пространстве?

Николай Турпитко 

A. Действительно, вне зависимости от потока, все распределения памяти попадают в один большой двусвязный список блоков памяти, который поддерживает отладочная версия CRT (если задан макрос _DEBUG). Что касается MFC-класса CMemoryState, он является просто тонкой обёрткой вокруг структуры _CrtMemState и функций для диагностики утечек памяти CRT. Поэтому он также не делает различий между потоками.

Хотя функции отладочной библиотеки очень полезны, они не отличаются гибкостью. Научить класс CMemoryState выдавать список блоков, выделенных текущим потоком, возможно, только используя недокументированные возможности CRT. Но кое-что в этом направлении можно сделать и легальными средствами. 

При распределении памяти в отладочной версии программы каждому блоку назначается тип. По умолчанию блок получает тип _NORMAL_BLOCK. Существуют и другие типы: _CRT_BLOCK (блок, распределяемый для внутренних нужд CRT), _CLIENT_BLOCK (блок, к которому применяется пользовательская функция построения дампа), _FREE_BLOCK (блок, который уже освобождён с помощью free; такие блоки остаются в памяти, чтобы отладочная библиотека могла отследить ошибки, связанные с записью в уже освобождённый блок памяти) и _IGNORE_BLOCK (блок, который игнорируется при построении списка распределённых объектов). В стандартную библиотеку входит версия оператора new с четырьмя параметрами, которой можно передать тип распределяемого блока.

Соответственно, мы можем сохранить идентификатор потока, который нас интересует, в глобальной переменной, а затем передавать оператору new тип _NORMAL_BLOCK, если идентификатор текущего потока совпадает с сохранённым в переменной, и _IGNORE_BLOCK в противном случае. Чтобы облегчить эту задачу, можно написать небольшой модуль, который будет всем этим заниматься. Например: 

//------------------------------

// threadmem.h

void DumpOnlyThisThread(DWORD id);

extern DWORD __DumpThread;

#ifdef _DEBUG

#define THREAD_DEBUG_NEW \

 new((__DumpThread == ::GetCurrentThreadId ? \

 _IGNORE_BLOCK : _NORMAL_BLOCK), THIS_FILE, __LINE__)

#else

#define THREAD_DEBUG_NEW new

#endif /* _DEBUG */

//------------------------------

// threadmem.cpp

void DumpOnlyThisThread(DWORD id) {

#ifdef _DEBUG

 InterlockedExchange((LONG *)&__DumpThread, id);

#endif /* _DEBUG */

}

DWORD __DumpThread;

Теперь функция потока, в котором мы хотим отслеживать утечки памяти, может выглядеть так:

#include "threadmem.h"

#define new THREAD_DEBUG_NEW

UINT ThreadFunc(LPVOID) {

 DumpOnlyThisThread(::GetCurrentThreadId);

 CMemoryState st;

 st.Checkpoint;

 // Распределяем и освобождаем память в процессе работы…

 new int[100];

 new CPoint[200];

 …

 st.DumpAllObjectsSince;

 return 0;

}

Объекты, распределённые во всех остальных потоках, не попадут в отчёт об утечках памяти.

Александр Шаргин (rudankort@mail.ru) 
  • Читать дальше
  • 1
  • ...
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: