Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ / 13 сообщений из 13, страница 1 из 1
12.10.2013, 18:09
    #38425247
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Form1 - главная форма
Кинул на нее HelpProvider1
Код:
Код: vbnet
1.
2.
3.
4.
  Private Sub Form1_Load(ByVal sender As System.Object,
                         ByVal e As System.EventArgs) Handles MyBase.Load

    HelpProvider1.HelpNamespace = Application.StartupPath & "\proga.chm"


Для Form1 поставил
Код: vbnet
1.
2.
HelpNavigator на HelpProvider1 = TopicId
HelpKeyword на HelpProvider1 = 1



Т.е. у меня по 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.
  App.HelpFile = App.Path & "\" & "proga.chm" 'для всего приложения


А потом ставишь
Код: vbnet
1.
2.
HelpContextID=1 для Form1
HelpContextID=20 для Form2

и т.д.
...
Рейтинг: 0 / 0
12.10.2013, 19:03
    #38425266
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий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.
Imports System.ComponentModel
Imports System.IO
Imports System.Windows.Forms

Public Class BaseForm
	Inherits Form

	Private ReadOnly _helpProvider As HelpProvider

	Public Sub New()
		_helpProvider = New HelpProvider()
		_helpProvider.SetHelpNavigator(Me, HelpNavigator.TopicId)
		_helpProvider.HelpNamespace = Path.Combine(Application.StartupPath, "proga.chm")
	End Sub

	<Category("Help")> _
	Public Property HelpString() As String
		Get
			Return _helpProvider.GetHelpString(Me)
		End Get
		Set(value As String)
			_helpProvider.SetHelpString(Me, value)
		End Set
	End Property

End Class

2) В Solution Explorer нажми кнопку "Show All Files"

3) Открой для каждой формы файл .Designer.vb и замени в нем Inherits System.Windows.Forms.Form на BaseForm

4) Теперь в свойствах каждой формы есть свойство HelpString унаследованное от базового класса
...
Рейтинг: 0 / 0
12.10.2013, 21:10
    #38425313
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
bazile,

Правильно ли я понял, что твой код эквивалентен добавлению
своего HelpProvider для каждой формы
+
Код: vbnet
1.
HelpProvider1.HelpNamespace = IO.Path.Combine(Application.StartupPath, "proga.chm")


+
конструктор если надо указывать ContextID для формы, отдельных ее элементов и т.д. ?

Т.е. все таки по своему HelpProvider для каждой формы? Так?
...
Рейтинг: 0 / 0
13.10.2013, 01:18
    #38425439
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Можно несколько HelpProvider -по одному на форму.

Можно без HelpProvider-ов:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
'Form1
  Private Sub Form1_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
     Help.ShowHelp(Me, IO.Path.Combine(Application.StartupPath, "proga.chm"), HelpNavigator.TopicId, "1")
  End Sub

'Form2
  Private Sub Form2_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
     Help.ShowHelp(Me, IO.Path.Combine(Application.StartupPath, "proga.chm"), HelpNavigator.TopicId, "5")
  End Sub



Но, блин, глючновато и слабовато.
Тема хэлпа в .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.
  'в первом вызове первый параметр 0 - родитель не назначается, чтобы не было OnTop поведения
  HTMLHelp 0, App.Path & "\" & "proga.chm", HH_DISPLAY_TOPIC, ByVal helpTopic
  'второй вызов - первый параметр handle родителя - чтоб определиться куда окно help будет слать сообщения
  'при этом поведение OnTop относительно Form1 уже не сработает
  hwndHelp = HTMLHelp(Form1.hwnd, App.Path & "\" & "proga.chm", _
   HH_GET_WIN_HANDLE, ByVal "ProgaHelp")


.Net -реализация (ф-ция Help.ShowHelp)
Код: vbnet
1.
Help.ShowHelp(Nothing, 


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

ГЛЮК 2.
Здесь придется чуть объяснить.
Если задана обработка события
Код: vbnet
1.
2.
'Form2
  Private Sub Form2_HelpRequested(ByVal sender As Object,


либо
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 это не реализовано.
...
Рейтинг: 0 / 0
13.10.2013, 05:02
    #38425496
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий77 ГЛЮК 1. Окно htmlhelp всегда On Top относительно первого окна (Form1, Form2) из которого оно было вызвано.
Такое поведение нежелательно.
.Net -реализация (ф-ция Help.ShowHelp)
Код: vbnet
1.
Help.ShowHelp(Nothing, 


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

ГЛЮК 2.
4) А потом случайно нажали F1 еще раз - когда окно help активно - и он перепрыгнет на contextID для Form1
Это как раз лечится:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
  Private Sub Form1_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
    Help.ShowHelp(New Control(), help_path, HelpNavigator.TopicId, "1")
  End Sub
  Private Sub ButtonHelp_Click(ByVal sender As System.Object,
                               ByVal e As System.EventArgs) Handles ButtonHelp.Click
    'если нужна своя кнопка Help
    Form1_HelpRequested(Me, New System.Windows.Forms.HelpEventArgs(Cursor.Position))
  End Sub


С учетом того что .Net-овский Help - класс ничего особо не умеет, назначать в Help.ShowHelp - метод реального родителя
parent
Тип: System.Windows.Forms.Control
A Control это указывает родительский объект для диалогового окна Справки.
абсолютно бессмысленно, разве что порождает вышеописанные глюки.

P.S. HelpProvider лечению не подлежит (пациент мертв).

Далее, .Net -овская реализация несовместима с оригинальной:
About the HTML Help API Function

Если подряд выполнить код:
Код: vbnet
1.
2.
    Help.ShowHelp(New Control(), help_path, HelpNavigator.TopicId, "1")
    HTMLHelp(IntPtr.Zero, help_path, HH_HELP_CONTEXT, 1)


обе строчки которого суть одно и то же,
то выскочат два окна хэлпа, хотя по идее должно быть одно.
(В 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.
  Public Declare Function HTMLHelp Lib "hhctrl.ocx" Alias "HtmlHelpA" _
   (ByVal hwndCaller As IntPtr, ByVal pszFile As String, _
    ByVal uCommand As Integer, ByVal dwData As Integer) As IntPtr
  Public Declare Function HTMLHelp_str Lib "hhctrl.ocx" Alias "HtmlHelpA" _
   (ByVal hwndCaller As IntPtr, ByVal pszFile As String, _
    ByVal uCommand As Integer, ByVal dwData As String) As IntPtr

  Public Const HH_HELP_CONTEXT = &HF             '  display mapped numeric

  ' Notification codes
  Public Const HHN_FIRST = (0 - 860)
  Public Const HHN_NAVCOMPLETE = (HHN_FIRST - 0)
  Public Const HHN_TRACK = (HHN_FIRST - 1)
  Public Const HHN_WINDOW_CREATE = (HHN_FIRST - 2)
'==========================
'В главной форме Form1
  Private Sub Form1_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
    HTMLHelp(IntPtr.Zero, help_path, HH_HELP_CONTEXT, 1)
    Dim hwndHelp As IntPtr = HTMLHelp_str(Me.Handle, help_path, _
     HH_GET_WIN_HANDLE, "ProgaHelp")
  End Sub

  Private Sub ButtonHelp_Click(ByVal sender As System.Object,
                               ByVal e As System.EventArgs) Handles ButtonHelp.Click
    Form1_HelpRequested(Me, New System.Windows.Forms.HelpEventArgs(Cursor.Position))
  End Sub

  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

    Select Case m.Msg

      Case WM_NOTIFY
        Dim uNMHDR As NMHDR = CType(Marshal.PtrToStructure(m.LParam, GetType(NMHDR)), NMHDR)
        Select Case uNMHDR.code
          Case HHN_TRACK
            'Debug.WriteLine("HHN_TRACK")
            Dim tHDN As NMHEADER = _
             CType(Marshal.PtrToStructure(m.LParam, GetType(NMHEADER)), NMHEADER)
            If tHDN.iButton = 5 Then 'кнопка Show
              Debug.WriteLine("Show button clicked in help")
            End If
          Case Else
        End Select
      Case Else
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)

  End Sub
'===================
В Form2 например:
Public Class Form2

  Private Sub Form2_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
    HTMLHelp(IntPtr.Zero, help_path, HH_HELP_CONTEXT, 5)
    Dim hwndHelp As IntPtr = HTMLHelp_str(Form1.Handle, help_path, _
     HH_GET_WIN_HANDLE, "ProgaHelp") '!!!Но Notifications от help вешаются на Form1 все равно
  End Sub



А без API хэлпу "современности" не придашь.
Единственное, что разумно использовать, это .NET событие _HelpRequested по F1, которое генерируется текущим контролом, и либо оно обрабатывается в обработчике Control.HelpRequested, либо при отсутствии этого обработчика отправляется в Parent.HelpRequested
(WM_HELP по F1 в .NET похоже заботливо "забито" предусмотрительными разработчиками).
...
Рейтинг: 0 / 0
13.10.2013, 09:32
    #38425514
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий77,

хочешь что-либо сделать хорошо - сделай сам :)
http://support.microsoft.com/kb/317406
...
Рейтинг: 0 / 0
13.10.2013, 15:46
    #38425699
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Изопропилхочешь что-либо сделать хорошо - сделай сам :)
Так и делаю.
У меня принцип при "учебном" перекатывании проекта 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 стилю.
...
Рейтинг: 0 / 0
14.10.2013, 16:41
    #38426911
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий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.
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.IO
Imports System.Windows.Forms

<Designer(GetType(BaseFormDesigner), GetType(IRootDesigner))> _
Public Class BaseForm
    Inherits Form

    Public WithEvents AppHelpProvider As HelpProvider

    Public Sub New()
        AppHelpProvider = New HelpProvider()
        AppHelpProvider.HelpNamespace = Path.Combine(Application.StartupPath, "proga.chm")

        SetHelpNavigator(Me)
    End Sub

    Public Sub SetHelpNavigator(ByVal ctrl As Control)
        If ctrl IsNot Nothing Then
            AppHelpProvider.SetHelpNavigator(ctrl, HelpNavigator.TopicId)
        End If
    End Sub
End Class


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.
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Windows.Forms.Design
Imports System.Security.Permissions

<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Class BaseFormDesigner
    Inherits DocumentDesigner

    Public Overrides Sub Initialize(ByVal c As IComponent)
        MyBase.Initialize(c)

        Dim cs As IComponentChangeService = TryCast(GetService(GetType(IComponentChangeService)), IComponentChangeService)
        If (cs IsNot Nothing) Then
            AddHandler cs.ComponentChanged, AddressOf OnComponentChanged
        End If
    End Sub

    Private Sub OnComponentChanged(ByVal sender As Object, ByVal e As ComponentChangedEventArgs)
        Dim frm As BaseForm = TryCast(MyBase.Control, BaseForm)
        If frm IsNot Nothing Then
            frm.SetHelpNavigator(TryCast(e.Component, Control))
        End If
    End Sub
End Class


Применение осталось таким же - меняем Inherits для нужных форм. Выигрыш в том что выбор файла спраки делается в одном месте и HelpProvider не нужно добавлять на каждую форму. Код сильно не тестировал и в нем могут быть какие-то проблемы.

Насчет проблем с которыми ты столкнулся позже ничего не могу посоветовать. Единственное что решение лучше оформить в отдельного класса или контрола чтобы можно было использовать в любом приложении. Если интересно, то взгляни на HTML Help Builder Рика Страла.
...
Рейтинг: 0 / 0
14.10.2013, 21:05
    #38427259
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
bazile,

Ну если честно то если говорить о HelpProvider, проще накидать по одному на форму (ну 3 формы, ну даже 10) чем реализовывать "хитрый класс" для компенсации кривости дизайна. Сколько б HelpProvider-ов не было, help окно всегда будет единственное (ну если не указывать разные chm во всяком случае) Опыт показывает, что такие классы для какого-нибудь частного случая да и ошибаются.
И потом с HelpProvider глюк "Help всегда OnTop" не лечится.

Если делать чисто на .Net (ограничиваясь стандартными возможностями), то видимо просто AddHandle события .HelpRequested на единственную ф-цию для всех форм/контролов, для кот. нужен собственный ContextId, и уж в ней рассматривать case-ы для параметра Help.ShowHelp.

Но, опять же, с реально устаревшим окном HtmlHelp (имеется ввиду внешний вид кнопок, дерева и т.д.) без API ничего не сделаешь, единственную пользу кот. я для себя усмотрел, это событие .HelpRequested по F1 (с пониманием какой контрол затребовал хэлпа), в которое втыкается собственный (апишный) код вызова.
...
Рейтинг: 0 / 0
14.10.2013, 22:41
    #38427355
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий77единственную пользу кот. я для себя усмотрел, это событие .HelpRequested по F1 (с пониманием какой контрол затребовал хэлпа), в которое втыкается собственный (апишный) код вызова.
нормально

Дмитрий77и уж в ней рассматривать case-ы для параметра Help.ShowHelp.
а вот это можно и поинтереснее сделать, всё таки форма сама должна знать "что" показывать, а "единственная" функция должна знать "как" показывать
...
Рейтинг: 0 / 0
15.10.2013, 01:00
    #38427450
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Дмитрий77Ну если честно то если говорить о HelpProvider, проще накидать по одному на форму (ну 3 формы, ну даже 10) чем реализовывать "хитрый класс" для компенсации кривости дизайна. Сколько б HelpProvider-ов не было, help окно всегда будет единственное (ну если не указывать разные chm во всяком случае) Опыт показывает, что такие классы для какого-нибудь частного случая да и ошибаются.
Накидать элементы управления на форму это не проблема конечно. Дело в другом. Базовый класс с дизайнером держит код ициализации в одном месте и для каждого нового контрола на форме назначает TopicId как источник (экономия времени).

Дмитрий77И потом с HelpProvider глюк "Help всегда OnTop" не лечится.
Вроде лечится путем подсовывания невидимой формы. Видел пример где-то.
...
Рейтинг: 0 / 0
15.10.2013, 11:09
    #38427771
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
Изопропилможно и поинтереснее сделать...
Ну, интересно когда результат интересный (картинка прилагается).
Для начала понял что .Net позволяет сабклассить окно Help без глюков . В VB6 сабклассинг help-а вылетал.
Здесь удалось допилить идею.
1) Привязать ширину ребара к ширине help-формы (отслеживаю WM_SIZE help формы)
2) Привязать высоту ребара к высоте тулбара (опять же по WM_SIZE help формы)
Код: vbnet
1.
rbBand.cyMinChild = crcToolbar.Bottom + 2 'по фактической высоте Toolbar


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.
  Private Sub s_Help_CallBackWndProc(ByRef m As System.Windows.Forms.Message, ByRef Cancel As Boolean) _
   Handles s_Help.CallBackWndProc
      Case WM_NOTIFY
        Dim uNMHDR As NMHDR = CType(Marshal.PtrToStructure(m.LParam, GetType(NMHDR)), NMHDR)
        Select Case uNMHDR.code
          Case TBN_DROPDOWN
            Dim nmTB As NMTOOLBAR = _
             CType(Marshal.PtrToStructure(m.LParam, GetType(NMTOOLBAR)), NMTOOLBAR)
            If nmTB.iItem = 1001 Then 'кнопка Interface
              'только виста+темы, в остальных случаях нет кнопки
              Dim pt As POINTAPI
              pt.x = nmTB.rcButton.Left
              pt.y = nmTB.rcButton.Bottom
              ClientToScreen(nmTB.hdr.hwndFrom, pt)
              'Form1.Visible = True 'для проверки чего происходит
              TrackPopupMenu(Form1.menu_HelpStyle.Handle, 0,
               pt.x, pt.y, 0, Form1.Handle)
              Cancel = True
            End If


Я то привык что Form1 это Form1 и обращаться к ней прямолинейно из любого места кода (напр. из сабклассинга),
меню выводит, но что-то в Form1 глючит.
Хорошо догадался Form1.Visible=true сделать,
понял что он гад мне второй экземпляр Form1 накатал.
Т.е. получается что если в другом потоке и вне класса Form1, он делает новый экземпляр Form1.

Ладно, бог с ним. Запихнул сабклассинг хэлпа внутрь Class Form1.
Получилось
Код: vbnet
1.
2.
              TrackPopupMenu(Me.menu_HelpStyle.Handle, 0,
               pt.x, pt.y, 0, Me.Handle)


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.
   SetPopup(pt.x, pt.y)
...
  ' This delegate enables asynchronous calls for setting
   Delegate Sub SetPopupCallback(ByVal [x] As Integer, ByVal [y] As Integer)

    Private Sub SetPopup(ByVal [x] As Integer, ByVal [y] As Integer)

        ' InvokeRequired required compares the thread ID of the
        ' calling thread to the thread ID of the creating thread.
        ' If these threads are different, it returns true.
        If Me.textBox1.InvokeRequired Then
            Dim d As New SetPopupCallback(AddressOf SetPopup)
            Me.Invoke(d, New Object() {[x], [y]})
        Else
            TrackPopupMenu(Me.menu_HelpStyle.Handle, 0,
               [x], [y], 0, Me.Handle)
        End If
    End Sub


Получилось, но следующая проблема:
3-я возникшая проблема:
Ну, если кто с TrayNotify работал, то меня поймет.
TrackPopupMenu function
Внизу пример:
Код: plaintext
1.
2.
3.
4.
   SetForegroundWindow(hDlg);

   // Display the menu
   TrackPopupMenu(   hSubMenu,


Но 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.
          Case TBN_DROPDOWN
...
              'FormHelper.Visible = True 'для проверки чего происходит
              FormHelper.Tag = CType(m.HWnd, IntPtr) 'hwnd хэлпа
              TrackPopupMenu(FormHelper.menu_HelpStyle.Handle, 0,
               pt.x, pt.y, 0, FormHelper.Handle)
              Cancel = True

...в форме FormHelper
  Public Sub New()
    InitializeComponent()
    For Each menu_item As MenuItem In menu_HelpStyle.MenuItems
      AddHandler menu_item.Click, AddressOf MenuItem_Click
    Next
...
  Private Sub MenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    For Each menu_item As MenuItem In menu_HelpStyle.MenuItems
      menu_item.Checked = False
    Next
    CType(sender, MenuItem).Checked = True
    Select Case CType(sender, MenuItem).Text
      Case "&Communications"
        params.m_HelpStyle = "Communications"
      Case "&Media"
...


Хотел ее честно грохать после каждого вызова меню (после закрытия Context меню), но не получилось.
MenuItem_Click к сожалению срабатывает после Menu_Complete, т.е.
если грохать по Menu_Complete, то
до MenuItem_Click дело не дойдет.

Как -то так...
...
Рейтинг: 0 / 0
15.10.2013, 11:27
    #38427808
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ
bazileДмитрий77И потом с HelpProvider глюк "Help всегда OnTop" не лечится.
Вроде лечится путем подсовывания невидимой формы. Видел пример где-то.

Я тоже этот пример видел, но он кажется относится к Help.ShowHelp:
New Control() -этого достаточно для реализации "невидимой формы"
Дмитрий77Это как раз лечится:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
  Private Sub Form1_HelpRequested(ByVal sender As Object,
   ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles Me.HelpRequested
    Help.ShowHelp(New Control(), help_path, HelpNavigator.TopicId, "1")
  End Sub
  Private Sub ButtonHelp_Click(ByVal sender As System.Object,
                               ByVal e As System.EventArgs) Handles ButtonHelp.Click
    'если нужна своя кнопка Help
    Form1_HelpRequested(Me, New System.Windows.Forms.HelpEventArgs(Cursor.Position))
  End Sub


Ну не в конструкторе же ее рисовать?
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / HelpProvider + F1 + HelpNavigator(TopicID) + НЕСКОЛЬКО ФОРМ / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]