Тема: Работа функции acedHelp

В ARX программе вызывал нужный топик из файла помощи HLP таким образом:

acedHelp(ACRX_T("MyHelp.hlp"), ACRX_T("TopicIndex"), 0);

Переделал файл помощи из MyHelp.hlp в MyHelp.chm.
Поэтому изменил и вызов помощи:

acedHelp(ACRX_T("MyHelp.chm"), ACRX_T("Topic"), 0);

Файл помощи вызывается, а нужный топик никак не хочет открываться.
Может кто сталкивался с такой проблемой?

Re: Работа функции acedHelp

Значит имя раздела справки ("Topic") указано неверно (отличается от того, какое на самом деле внутри CHM-файла).

Re: Работа функции acedHelp

Николай Полещук
Спасибо за ответ, но если бы было так просто, я бы не стал задавать вопрос на этом форуме.

Перепробовал все:
- и русские названия топиков и английские;
- и названия индексов применять тоже пробовал;
- и менял третий параметр в функции acedHelp, чтобы выйти на WinHelp.
- пробовал на трех разных компьютерах - может что-то с системой не так.
- применял разные режимы компилирования CHM файла;
- и т.д, и т.д.

Система у меня - Windows XP SP3. Компилятор справки - HTML Help Workshop версия 1.32.
Под Автокадом 2007-м пробовал и под русским, и под английским.
Сам по себе файл справки работает нормально - все вызывается, перекрестные ссылки работают.
Вопрос стал задавать только после суток мучений.

Re: Работа функции acedHelp

Создал файл справки другим компилятором - htm2chm. Не помогло. Все тоже самое.

(изменено: Александр Ривилис, 2 октября 2010г. 15:48:21)

Re: Работа функции acedHelp

Возможно (не утверждаю) это глюк ObjectARX 2007. В этой версии был переход на UNICODE и не во всем он был гладким. Попробуй стандартный вызов справки при помощи функции HtmlHelp. Еще возможен вариант, что вместо ACRX_T("Topic") нужно указать ACRX_T("Topic.htm") или ACRX_T("Topic.html").

Re: Работа функции acedHelp

Александр Ривилис

Попробовал ACRX_T("Topic.html"). То же самое. Попробую на работе под Автокадом 2010. По итогам отпишусь.

Re: Работа функции acedHelp

http://bardsoftware.chat.ru/articles/ht … t/api.html
почитай это. если не разберешься, подскажу.
пользуюсь начиная с 2004 автокада. и по сей день глюков не замечено.

Re: Работа функции acedHelp

У меня не было проблем с обращением к CHM-справке из arx версии 2007. Правда, справки сделаны в Robohelp.

Re: Работа функции acedHelp

Николай
Спасибо за подсказку. По идентификаторам я HLP файл подключал к контекстной помощи в диалоговых окнах.
Разбирусь и отпишу.

(изменено: Сергей Кузнецов, 5 октября 2010г. 12:20:00)

Re: Работа функции acedHelp

Николай
Ну, в общем все получилось через HtmlHelp. Спасибо, Ваши подсказки очень помогли.
Так как вызовов помощи у меня в программе много, а файл помощи один, в итоге сделал одну общую функцию вызова помощи. К тому же функция HtmlHelp не ищет файлы по путям Автокада, как это делают функции работы с файлами в ObjectARX. Пришлось использовать acedFindFile. В итоге получилось примерно следующее:

void GetMyHelp(DWORD_PTR dwData){
CString csPathName;
if (acedFindFile(ACRX_T("MyHelp.chm"), csPathName.GetBuffer(_MAX_PATH)) == RTNORM){   
::HtmlHelp(NULL, csPathName, HH_HELP_CONTEXT, dwData);
}
else {
//какие-нибудь сообщения об ошибке...
}
}

Естественно, был создан заголовочный файл с картой идентификаторов и сделаны соотвествующие добавления в секции [ALIAS] и [MAP] файла помощи.

(изменено: Николай, 6 октября 2010г. 12:16:02)

Re: Работа функции acedHelp

ну вот и замечательно. только не понял один момент. ЗАЧЕМ искать файл справки. ты его каждый раз устанавливаешь в разное место? :) или может он всегда лежит в папке программы (ну и возможно в какой-то подпапке) ?
получить путь к текущей arx-ине из которой вызывается эта функция можно где-то так:

static CString getCurARXPath()
{ // на возврат идет путь к текущей arx-ине без последнего слеша. например, c:\program files\programma
   ACHAR fName[_MAX_PATH+1];
   GetModuleFileName(_hdllInstance,fName,sizeof(fName)-1);
   int i = wcslen(fName) - 1;
   while ((i > 0)&&(fName[i] != _T('\\'))) i--;
   if(i) fName[i] = _T('\0'); // убираем последний слеш.
   else _tcscpy(fName, _T("C:"));
   return fName;
}

ну а добавить к нему файл справки, который лежит в папке с arx-файлами, например, так:

#include <Ht mlHelp.h>
#include <shlwapi.h>
#pragma comment(lib, "HtmlHelp.lib")
...

static void showHelpInfo( DWORD helpIndex )
{
   ACHAR res[_MAX_PATH+1];
   _tcscpy(res,getCurARXPath().GetString());
   _tcscat(res,_T("\\MyHelp.chm"));
   if (!::PathFileExists(res))
   {
      acedAlert(_T("Автоматический вывод справочной информации невозможен,\nт.к. не найден файл справки \"MyHelp.chm\" в папке программы."));
      return;
   }
   ::HtmlHelp(0, res, HH_HELP_CONTEXT, helpIndex);
}

Re: Работа функции acedHelp

Николай
Моя программа работает у большого количества пользователей, поэтому и файлы могут лежать по каким угодно путям. Функция acedHelp ищет по путям Автокада, и я просто имитирую ее работу.
Файл справки лежит там же, где и основной arx файл. Путь к файлам программы прописывается в настройках Автокада. Это я рекомендую и в файле справки. Поэтому и ищу я файл справки функцией ObjectARX. Если пользователь распихал файлы по разным местам, ничего не прописал в настройках, и загружает ARX файл через автозагрузку - то я считаю, что это уже плохо с головой.
Вы, все-таки, наверное профессиональный программист, и у Вас более общий подход (и я уверен, более правильный). Я же делаю программы исключительно под Автокад и использую приемы программирования для Автокада. С точки зрения ObjectARX мне кажется, что у меня получилось более прозрачно. Но может я и не прав.
В любом случае, самое главное, что это работает. А как реализовать - дело вкуса.

(изменено: Александр Ривилис, 6 октября 2010г. 11:38:51)

Re: Работа функции acedHelp

Сергей Кузнецов пишет:

Поэтому и ищу я файл справки функцией ObjectARX.

В данном случае это не оптимально. Каждый раз при вызове справки идет поиск по куче каталогов. Если уж не уверен что arx-файл и chm-файл в одной папке, то вызови acedFindFile только один раз и запомни (например, в глобальной переменной) полученный путь. А при следующих вызовах справки используй его.

Re: Работа функции acedHelp

Файл справки лежит там же, где и основной arx файл

и это правильно. по крайней мере к нему можно достучаться имея путь к arx-файлу из которого он вызывается.

Путь к файлам программы прописывается в настройках Автокада. Это я рекомендую и в файле справки.

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

Поэтому и ищу я файл справки функцией ObjectARX.

а как это связано с логикой? всегда нужно идти по пути наименьшего сопротивления. если есть готовый вариант поиска папки установленной программы (например, из реестра или моей функцией getCurARXPath()), ЗАЧЕМ перебирать все прописанные пути автокада?

Если пользователь распихал файлы по разным местам, ничего не прописал в настройках, и загружает ARX файл через автозагрузку - то я считаю, что это уже плохо с головой.

где-то так оно и есть, и застаховаться от этого не получится :).

Я же делаю программы исключительно под Автокад и использую приемы программирования для Автокада

открою секрет :) я тоже программирую последнее время ТОЛЬКО под автокад. но это не значит, что я ОБЯЗАН пользоваться только возможностями автокада, тем более, что пару раз накалывался на этих самых возможностях (ну так на вскидку, классом AcString не пользуюсь принципиально, т.к. это гибрид CString и std::wstring, причем весьма неудачный)

В любом случае, самое главное, что это работает.

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

Re: Работа функции acedHelp

Александр Ривилис
Спасибо за совет! Обязательно воспользуюсь. У меня есть глобальный объект для таких случаев. Введу туда еще одну переменную. Запомнить путь к справке можно при первом обращении к ней.

Re: Работа функции acedHelp

Сергей Кузнецов пишет:

Запомнить путь к справке можно при первом обращении к ней.

Я на это и намекал. Но по большому счету Николай прав. Представь себе ситуацию что в путях доступа есть не один, а два или больше файла myhelp.chm? Какой из них будет найден? А если справка и arx-файл лежат в одном каталоге, то такой проблемы не возникнет.

Re: Работа функции acedHelp

Ну вот, накинулись...
Уговорили. Осмыслю написанное Николаем и сделаю, как он рекомендует. Тем более, так не пробовал ни разу.
В любом случае - всем огромное СПАСИБО:!::!::!:  за дельные советы!!!

(изменено: Сергей Кузнецов, 6 октября 2010г. 23:52:15)

Re: Работа функции acedHelp

Николай
Может я чего не догоняю, но результат работы функции getCurARXPath() выдает следующий результат:

C:\Program Files\AutoCAD 2007 Eng

Это путь к папке Автокада. Мой ARX файл лежит в другом месте.
Поясните, пож-та, что я делаю не так.

Re: Работа функции acedHelp

Сергей Кузнецов пишет:

Николай

Может я чего не догоняю, но результат работы функции getCurARXPath() выдает следующий результат:



C:\Program Files\AutoCAD 2007 Eng



Это путь к папке Автокада. Мой ARX файл лежит в другом месте.

Поясните, пож-та, что я делаю не так.

И чему же у тебя равно _hdllInstance??? Небось 0? Тогда ты действительно получишь путь к папке AutoCAD.
Если проект создан при помощи ObjectARX Wizard, то _hdllInstance определяется так:

#define _hdllInstance acrxGetApp()->GetModuleInstance ()

И инициализируется в коде аналогичном следующему:

extern "C"
BOOL WINAPI DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
  //- Remove this if you use lpReserved
  UNREFERENCED_PARAMETER(lpReserved) ;

  if ( dwReason == DLL_PROCESS_ATTACH ) {
    _hdllInstance = hInstance ;
    XXXXXXXX.AttachInstance (hInstance) ;
  } else if ( dwReason == DLL_PROCESS_DETACH ) {
    XXXXXXXX.DetachInstance () ;
  }
  return (TRUE) ;
}

Re: Работа функции acedHelp

Спасибо, не обратил на это внимание. Я понял, что дело в hdllInstance.
Пока Вы отвечали, я получил _hdllInstance несколько другим способом:

::GetModuleHandle(ACRX_T("XXXXXX.arx"))

Но так, как Вы подсказали, будет правильно.