|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Form1 - главная форма Кинул на нее HelpProvider1 Код: Код: vbnet 1. 2. 3. 4.
Для Form1 поставил Код: vbnet 1. 2.
Т.е. у меня по F1 открывается страница с HelpContextID=1 Все как хотелось. Но у меня есть еще Form2, Form3 и т.д. Т.е. например для Form2 я хочу сделать HelpKeyword на HelpProvider... = 20 Чтоб по F1 открывалась страница с HelpContextID=20 (другая страница того же help) Но у меня HelpProvider1 на Form1, соответственно HelpNavigator и HelpKeyword недоступны на Form2. Help то по F1 открывается и на Form2 (видимо по принципу Child-Parent), но свойство, чтоб установить HelpKeyword то отсутствует. Т.е. как это осуществить? Кидать по HelpProvider на каждую Form? Я думаю, что это неправильно, help то один и тот же (для всего приложения). Понятно что я могу издеваться над всякими ShowHelp, но хотелось бы сделать этот скелет на "конструкторном уровне". ==== Для сравнения: В VB6 такого вопроса не возникало. Код: vbnet 1.
А потом ставишь Код: vbnet 1. 2.
и т.д. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2013, 18:09 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Дмитрий77, каждой форме соответствует свой класс. Раз тебе в каждой форме нужна обшая функциональность, то создай базовый класс и унаследуй все формы в приложении от него. 1) Добавь в проект новый класс: BaseForm.vb Код: vbnet 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.
3) Открой для каждой формы файл .Designer.vb и замени в нем Inherits System.Windows.Forms.Form на BaseForm 4) Теперь в свойствах каждой формы есть свойство HelpString унаследованное от базового класса ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2013, 19:03 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
bazile, Правильно ли я понял, что твой код эквивалентен добавлению своего HelpProvider для каждой формы + Код: vbnet 1.
+ конструктор если надо указывать ContextID для формы, отдельных ее элементов и т.д. ? Т.е. все таки по своему HelpProvider для каждой формы? Так? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.10.2013, 21:10 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Можно несколько HelpProvider -по одному на форму. Можно без HelpProvider-ов: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Но, блин, глючновато и слабовато. Тема хэлпа в .Net не раскрыта. Сразу вижу 2 глюка (причем они одинаково проявляются как при использовании HelpProvider, так и при использовании _HelpRequested) (ни одного из этих глюков нет в в VB6 реализации) ГЛЮК 1. Окно htmlhelp всегда On Top относительно первого окна (Form1, Form2) из которого оно было вызвано. Такое поведение нежелательно. Окно htmlhelp по идее должно слать сообщения родительскому (если сообщения нужны, то родитель должен быть задан). С другой стороны HTMLHelp API устроена так, что если при первом вызове задается родитель, то окно help всегда находится OnTop родителя. Через API решается двойным вызовом HTMLHelp, например: Код: vbnet 1. 2. 3. 4. 5. 6.
.Net -реализация (ф-ция Help.ShowHelp) Код: vbnet 1.
все равно назначает родителем текущее Me, а фишка в том что первый вызов хэлпа не должен назначать родительскую форму. ГЛЮК 2. Здесь придется чуть объяснить. Если задана обработка события Код: vbnet 1. 2.
либо HelpProvider для Form2 + свойство ShowHelp на HelpProvider(Form2) =True то WM_HELP (_HelpRequested) будет вызываться в Form2 при нажатии F1 в Form2 Если для Form2 ничего такого не задано, то WM_HELP (_HelpRequested) будет генерироваться в обработчике родителя (Form1) Глюк состоит в том, что если в самом HtmlHelp окне нажать F1 , то событие WM_HELP (_HelpRequested) вызовется в обработчике Form1, т.е. страница хэлпа перепрыгнет на индекс, соответствующий Form1. Т.е. 1) Вызвали F1 из Form1 -отобразился contextID для Form1 2) потом вызвали Form2 3) потом Вызвали F1 из Form2 -отобразился contextID для Form2 4) А потом случайно нажали F1 еще раз - когда окно help активно - и он перепрыгнет на contextID для Form1 (т.к. само окно help было ошибочно назначено child от Form1=onTop относительно Form1 на шаге 1) Как это все увязывать и лечить, пока не понял. Ну и потом, мне понадобится hwndHelp (handle окна хэлпа) и события HTMLHelp Notification Messages ни в HelpProvider. ни в .Help это не реализовано. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2013, 01:18 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Дмитрий77 ГЛЮК 1. Окно htmlhelp всегда On Top относительно первого окна (Form1, Form2) из которого оно было вызвано. Такое поведение нежелательно. .Net -реализация (ф-ция Help.ShowHelp) Код: vbnet 1.
все равно назначает родителем текущее Me, а фишка в том что первый вызов хэлпа не должен назначать родительскую форму. ГЛЮК 2. 4) А потом случайно нажали F1 еще раз - когда окно help активно - и он перепрыгнет на contextID для Form1 Это как раз лечится: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9.
С учетом того что .Net-овский Help - класс ничего особо не умеет, назначать в Help.ShowHelp - метод реального родителя parent Тип: System.Windows.Forms.Control A Control это указывает родительский объект для диалогового окна Справки. абсолютно бессмысленно, разве что порождает вышеописанные глюки. P.S. HelpProvider лечению не подлежит (пациент мертв). Далее, .Net -овская реализация несовместима с оригинальной: About the HTML Help API Function Если подряд выполнить код: Код: vbnet 1. 2.
обе строчки которого суть одно и то же, то выскочат два окна хэлпа, хотя по идее должно быть одно. (В VB6 реализация F1 + HelpContextID удачнее и полностью совместима с оригинальной HTMLHelp -будет единственное окно в аналогичной ситуации). Дмитрий77Ну и потом, мне понадобится hwndHelp (handle окна хэлпа) и события HTMLHelp Notification Messages ни в HelpProvider. ни в .Help это не реализовано. Бесполезняк, только API: Код: vbnet 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. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61.
А без API хэлпу "современности" не придашь. Единственное, что разумно использовать, это .NET событие _HelpRequested по F1, которое генерируется текущим контролом, и либо оно обрабатывается в обработчике Control.HelpRequested, либо при отсутствии этого обработчика отправляется в Parent.HelpRequested (WM_HELP по F1 в .NET похоже заботливо "забито" предусмотрительными разработчиками). ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2013, 05:02 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2013, 09:32 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Изопропилхочешь что-либо сделать хорошо - сделай сам :) Так и делаю. У меня принцип при "учебном" перекатывании проекта VB6->.Net такой (для когда-то "хорошо сделанных" API реализаций): 1) Пытаюсь найти в .Net простую реализацию (которую естественно использовать ЛУЧШЕ) 2) Если нахожу, то использую 3) Если не нахожу, либо понимаю что "все криво - все плохо" (на основании имеющегося опыта работы с данном объектом), то перерабатываю с минимально необходимыми исправлениями имеющийся API-вариант (при этом по возможности заменяю отдельные места .Net реализациями). Изопропил http://support.microsoft.com/kb/317406 Ну, по сути тоже самое что я делаю. Отличие (по подходу): 1)Я предпочитаю использовать "модули" а не "классы" (видимо привычка). Здесь и в VB6 можно поспорить, но я так привык 2)Приведенный код перегружен словом Marshal. Не знаю насколько это важно по .Net -науке, но я для себя решил этим "словом" не злоупотреблять. Т.е. SendMessage_STRUCT(........ByRef struct as STRUCT) вместо SendMessage(........ByVal ptr as IntPtr) + набор махинаций с Marshal или чем-то еще А с другой стороны Marshal.PtrToStruct гораздо удобнее чем CopyMemory. Ну т.е. стараюсь не умничать и пишу подобные коды приближенно к VB6 стилю. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.10.2013, 15:46 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Дмитрий77Правильно ли я понял, что твой код эквивалентен добавлению своего HelpProvider для каждой формы Я пытался этого добиться, но оказалось что в таком виде HelpProvider виден только для формы, но не для элементов управления на ней. Пришлось переделать немного код: BaseForm.vb Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
BaseFormDesigner.vb Код: vbnet 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.
Применение осталось таким же - меняем Inherits для нужных форм. Выигрыш в том что выбор файла спраки делается в одном месте и HelpProvider не нужно добавлять на каждую форму. Код сильно не тестировал и в нем могут быть какие-то проблемы. Насчет проблем с которыми ты столкнулся позже ничего не могу посоветовать. Единственное что решение лучше оформить в отдельного класса или контрола чтобы можно было использовать в любом приложении. Если интересно, то взгляни на HTML Help Builder Рика Страла. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.10.2013, 16:41 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
bazile, Ну если честно то если говорить о HelpProvider, проще накидать по одному на форму (ну 3 формы, ну даже 10) чем реализовывать "хитрый класс" для компенсации кривости дизайна. Сколько б HelpProvider-ов не было, help окно всегда будет единственное (ну если не указывать разные chm во всяком случае) Опыт показывает, что такие классы для какого-нибудь частного случая да и ошибаются. И потом с HelpProvider глюк "Help всегда OnTop" не лечится. Если делать чисто на .Net (ограничиваясь стандартными возможностями), то видимо просто AddHandle события .HelpRequested на единственную ф-цию для всех форм/контролов, для кот. нужен собственный ContextId, и уж в ней рассматривать case-ы для параметра Help.ShowHelp. Но, опять же, с реально устаревшим окном HtmlHelp (имеется ввиду внешний вид кнопок, дерева и т.д.) без API ничего не сделаешь, единственную пользу кот. я для себя усмотрел, это событие .HelpRequested по F1 (с пониманием какой контрол затребовал хэлпа), в которое втыкается собственный (апишный) код вызова. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.10.2013, 21:05 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Дмитрий77единственную пользу кот. я для себя усмотрел, это событие .HelpRequested по F1 (с пониманием какой контрол затребовал хэлпа), в которое втыкается собственный (апишный) код вызова. нормально Дмитрий77и уж в ней рассматривать case-ы для параметра Help.ShowHelp. а вот это можно и поинтереснее сделать, всё таки форма сама должна знать "что" показывать, а "единственная" функция должна знать "как" показывать ... |
|||
:
Нравится:
Не нравится:
|
|||
14.10.2013, 22:41 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Дмитрий77Ну если честно то если говорить о HelpProvider, проще накидать по одному на форму (ну 3 формы, ну даже 10) чем реализовывать "хитрый класс" для компенсации кривости дизайна. Сколько б HelpProvider-ов не было, help окно всегда будет единственное (ну если не указывать разные chm во всяком случае) Опыт показывает, что такие классы для какого-нибудь частного случая да и ошибаются. Накидать элементы управления на форму это не проблема конечно. Дело в другом. Базовый класс с дизайнером держит код ициализации в одном месте и для каждого нового контрола на форме назначает TopicId как источник (экономия времени). Дмитрий77И потом с HelpProvider глюк "Help всегда OnTop" не лечится. Вроде лечится путем подсовывания невидимой формы. Видел пример где-то. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.10.2013, 01:00 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
Изопропилможно и поинтереснее сделать... Ну, интересно когда результат интересный (картинка прилагается). Для начала понял что .Net позволяет сабклассить окно Help без глюков . В VB6 сабклассинг help-а вылетал. Здесь удалось допилить идею. 1) Привязать ширину ребара к ширине help-формы (отслеживаю WM_SIZE help формы) 2) Привязать высоту ребара к высоте тулбара (опять же по WM_SIZE help формы) Код: vbnet 1.
3) Ну и наконец добавить свою кнопку "Themes" с меню (работающую) для настройки тематики хэлпа Вот с последним конечно жестоко, стоко нового узнал. В качестве меню кнопки решил использовать .Net ContextMenu (ну не стрип естественно) А вот ленюсь я их через API рисовать. 1-я возникшая проблема: Код сначала был в публичном модуле, где s_Help (класс сабклассинга) был объявлен как Public Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Я то привык что Form1 это Form1 и обращаться к ней прямолинейно из любого места кода (напр. из сабклассинга), меню выводит, но что-то в Form1 глючит. Хорошо догадался Form1.Visible=true сделать, понял что он гад мне второй экземпляр Form1 накатал. Т.е. получается что если в другом потоке и вне класса Form1, он делает новый экземпляр Form1. Ладно, бог с ним. Запихнул сабклассинг хэлпа внутрь Class Form1. Получилось Код: vbnet 1. 2.
2-я возникшая проблема: Он начал ругаться на то что я пытаюсь добраться до Me (Form1) из другого потока. Почитал How to: Make Thread-Safe Calls to Windows Forms Controls Сделал код по типу (взят из примера по ссылке) Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Получилось, но следующая проблема: 3-я возникшая проблема: Ну, если кто с TrayNotify работал, то меня поймет. TrackPopupMenu function Внизу пример: Код: plaintext 1. 2. 3. 4.
Но SetForegroundWindow выносит окно- хозяина ContextMenu (а у меня сначала была Form1) поверх окна help, что мне не надо. А иначе нажал на меню и все "подвисло" - пока мышку в сторону не отодвинул. Не вариант. Уже пожалел, что позарился на Net.Сontext Menu Но правда добил. Сунул ContextMenu в отдельную форму. Правда пришлось попотеть, 1) чтоб не больше одного экземпляра -слово New использовать в коде вызова не стал 2) зато пришлось добавить New() в код этой формы и оттуда инициализировать меню- при таком "вызове" Form_Load не срабатывает. 3) Ну, т.е. единственная форма FormHelper запускается вместе с первым вызовом меню, а убивается вместе с потоком - а поток связан с окном Help-а: Код: vbnet 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.
Хотел ее честно грохать после каждого вызова меню (после закрытия Context меню), но не получилось. MenuItem_Click к сожалению срабатывает после Menu_Complete, т.е. если грохать по Menu_Complete, то до MenuItem_Click дело не дойдет. Как -то так... ... |
|||
:
Нравится:
Не нравится:
|
|||
15.10.2013, 11:09 |
|
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
|
|||
---|---|---|---|
#18+
bazileДмитрий77И потом с HelpProvider глюк "Help всегда OnTop" не лечится. Вроде лечится путем подсовывания невидимой формы. Видел пример где-то. Я тоже этот пример видел, но он кажется относится к Help.ShowHelp: New Control() -этого достаточно для реализации "невидимой формы" Дмитрий77Это как раз лечится: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9.
Ну не в конструкторе же ее рисовать? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.10.2013, 11:27 |
|
|
start [/forum/topic.php?fid=20&msg=38425439&tid=1403870]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
71ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 181ms |
0 / 0 |