Кучу всего перелопатил - горы инфы, а того, что надо - не могу собрать. Помогите, пожалуйста.
Задача в следующем. Пишу справку в мою программу. Пишу в вёрде, сохраняю в *.mht Загружаю в CppWebBrowser:
В событии нажатия на кнопку загрузки файла:
C++ (Qt)Выделить код |
1
2
3
4
| string s;
s = GetCurrentDir().c_str();
s += "\\1.mht";
CppWebBrowser1 -> Navigate(WideString(s.c_str())); |
|
Далее. В тексте документа справки описывается моя программа и описывается назначение параметров, которые вводит пользователь. Текст с картинками (может, и таблицы будут). При клике мышкой на Label с названием параметра - на панели, на которой находится CppWebBrowser1 программа должна автоматически перемещаться в соответствующее место в документе. За двое суток танцев с бубном нарыл в инете и слепил до кучи следующую функцию:
C++ (Qt)Выделить код |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| void ScrollToInHelp(TCppWebBrowser *WB, int Pos)
{LPDISPATCH pDispatch = WB -> Document;
if (pDispatch)
{IHTMLDocument2* pHTMLDocument2 = NULL;
HRESULT hr = pDispatch -> QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDocument2);
if (SUCCEEDED(hr))
{IHTMLWindow2* pHTMLWindow2 = NULL;
hr = pHTMLDocument2 -> get_parentWindow(&pHTMLWindow2);
if (SUCCEEDED(hr))
{pHTMLWindow2 -> scrollTo(0, Pos);
pHTMLWindow2 -> Release();
}
pHTMLDocument2->Release();
}
}
} |
|
Перехожу к нужному месту в документе так:
C++ (Qt)Выделить код |
1
| ScrollToInHelp(CppWebBrowser1, HelpPos); |
|
Проблема в том, что значение переменной Pos - это расстояние от начала документа до нужного места.... в пикселях. Можно, конечно, подолбаться и повбивать фиксированные значения пикселей для каждого параметра. Тем более, что размер панели со справкой фиксирован и формат текста от размеров окна не зависит. Но! Параметров у меня невдолбенно много и если мне захочется дописать что-либо в текст справки или исправить его, то придётся всё перевбивать... В общем, было бы намного проще, если б в вёрде подобавлять закладок в ключевые места и навигироваться не по пикселям, а по ним. По идее, это должно выглядеть как-то так:
C++ (Qt)Выделить код |
1
2
| CppWebBrowser1->OleObject.OlePropertyGet("Document").OlePropertyGet("All").OleFunction("Item", i).OlePropertyGet("InnerText");
//именно эта запись возвращает текст i-го блока данных в документе (просто для примера) |
|
Только надо в кавычках писать что-то типа "закладка" и как-то переходить к ним, каким-то образом видоизменив ту функцию ScrollToInHelp(...).
В общем, как перейти к закладке в mht документе, загруженном в CppWebBrowser? Заранее спасибо!
Добавлено через 23 часа 10 минут
В общем, не без помощи, но разобрался. Выкладываю ответ, может, кому пригодится.
Т.к. в mht-документе закладок много, то чтоб не анализировать весь документ при каждом новом поиске следующей закладки - использую вектор структур, в который записываю имена закладок и отступ в пикселях от начала документа до закладки.
В Unit1.h пишу:
C++ (Qt)Выделить код |
1
2
3
4
| struct AllHelpAnchors
{BSTR* Anch; // Здесь будут имена закладок
long Pos; // здесь отступ в пикселях от начала документа
}; |
|
В Unit1.cpp:
C++ (Qt)Выделить код |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| #include <mshtml.h>
#include <vector.h>
HRESULT hr;
bool HelpLoaded, VectorCreated;
BSTR* Anch;
vector<struct AllHelpAnchors > HelpAnchors;
string CurDir;
//---------------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{string filename;
CurDir = GetCurrentDir().c_str();
filename = CurDir + "\\Doc\\1.mht";
Anch = new BSTR;
HelpAnchors.resize(0);
HelpLoaded = false;
VectorCreated = false;
if (FileExists(filename.c_str()))
{CppWebBrowser1 -> Navigate(WideString(filename.c_str()));
HelpLoaded = true;
}
} |
|
Теперь функция заполнения вектора структур:
C++ (Qt)Выделить код |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| void CreateHelpVector(TCppWebBrowser *WB)
{if (VectorCreated == false)
{struct AllHelpAnchors ha; // вспомогательная структура, которую я хотел заталкивать в HelpAnchors с помощью .push_back(), но не получилось, видимо, из-за указателей. Переделывать не стал.
ha.Anch = new BSTR;
long QuantityOfAnchors;
int i;
long l;
IDispatch* retVal;
IHTMLElement* pElem;
IHTMLAnchorElement* pAnchElem;
LONG pos;
VARIANT varIndex;
varIndex.vt = VT_UINT;
VARIANT var2;
IHTMLDocument2* pHTMLDocument2 = NULL;
LPDISPATCH pDispatch = WB -> Document;
hr = pDispatch -> QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDocument2);
if (SUCCEEDED(hr))
{IHTMLElementCollection* pIHTMLElementCollection = NULL;
hr = pHTMLDocument2 -> get_anchors(&pIHTMLElementCollection);
if (SUCCEEDED(hr))
{pIHTMLElementCollection -> get_length(&QuantityOfAnchors); // количество закладок в документе
for (i = 0; i < QuantityOfAnchors; i++)
{varIndex.lVal = i;
VariantInit(&var2);
l = pIHTMLElementCollection -> item(varIndex, var2, &retVal);
if (l == S_OK)
{hr = retVal -> QueryInterface(IID_IHTMLAnchorElement, (void**)&pAnchElem);
if (SUCCEEDED(hr))
{l = pAnchElem -> get_name(ha.Anch);
if (l == S_OK)
{hr = retVal -> QueryInterface(IID_IHTMLElement, (void **)&pElem);
if (SUCCEEDED(hr))
{hr = pElem -> get_offsetTop(&ha.Pos);
if (SUCCEEDED(hr))
{HelpAnchors.resize(HelpAnchors.size() + 1);
HelpAnchors[HelpAnchors.size() - 1].Anch = new BSTR;
*HelpAnchors[HelpAnchors.size() - 1].Anch = *ha.Anch;
HelpAnchors[HelpAnchors.size() - 1].Pos = ha.Pos;
}
}
}
}
}
}
}
}
VectorCreated = true;
}
} |
|
Вектор заполнен, теперь функция перехода к закладке (модифицированная приведенная в первом сообщении
C++ (Qt)Выделить код |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| void ScrollToInHelp(TCppWebBrowser *WB, BSTR* Anch)
{LPDISPATCH pDispatch = WB -> Document;
if (pDispatch)
{IHTMLDocument2* pHTMLDocument2 = NULL;
HRESULT hr = pDispatch -> QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDocument2);
if (SUCCEEDED(hr))
{IHTMLWindow2* pHTMLWindow2 = NULL;
hr = pHTMLDocument2 -> get_parentWindow(&pHTMLWindow2);
if (SUCCEEDED(hr))
{int i;
for (i = 0; i < HelpAnchors.size(); i++)
if (wcscmp(*HelpAnchors[i].Anch, *Anch) == 0) // сравнивает, совпадает ли закладка с требуемой
{pHTMLWindow2 -> scrollTo(0, HelpAnchors[i].Pos - 7); // вычитаю 7 пикселей, чтоб красивый отступ сверху оставить
pHTMLWindow2 -> Release();
break;
}
}
pHTMLDocument2->Release();
}
}
} |
|
Вот и всё. При первом вызове окна справки вызываю функцию:
C++ (Qt)Выделить код |
1
2
3
| //...
CreateHelpVector(CppWebBrowser1);
//... |
|
При клике на элементе, для которого в справке есть закладка делаю так:
C++ (Qt)Выделить код |
1
2
3
4
| //...
*Anch = L"z019"; // "z019" - это имя девятнадцатой закладки в *.mht
ScrollToInHelp(CppWebBrowser1, Anch);
//... |
|
Всем спасибо за активное участие и посильную помощь!