powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / 3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
19 сообщений из 19, страница 1 из 1
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38215777
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача наверно на 2 копейки, но чего-то не получается.

Есть основная Form1.
Из нее вызываем Form2:
Код: vbnet
1.
2.
3.
4.
Private Sub Command1_Click()
  Load Form2
  Form2.Visible = True
End Sub


(обе формы доступны одновременно, т.е. с Form1 можно работать не закрывая Form2)

Теперь из Form2 вызываем Form3 (какая-нибудь мелкая настройка).
Надо сделать так, чтоб Form3 вызывалась модально относит. только Form2,
но при этом Form1 оставалась бы доступна для работы с ней.

Делаю (в Form2):

Код: vbnet
1.
2.
3.
  Form3.Show 1
'или
  Form3.Show 1, Form2


и недоступны сразу Form1 и Form2
Как выкрутиться?

Ну, тест накатал (во вложении) -неработающий.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38215785
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я ловлю Activate на Form2 и переключаю на Form3
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38215789
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Proя ловлю Activate на Form2 и переключаю на Form3
не понял что имеешь в виду

Исходя из того что я начал искать-читать, дело дрянь.
Модальная, по определению блокирует "ВСЕ".
Создавать какие-то "потоки" -извините, уже наигрались, оно того не стоит да и не надо.

Разделять exe-шники в данном случае не хочу, заколебешься обмен между формами делать.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38215796
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,

Ну т.е. уже понял, но это глюкота какая-то получается.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38215873
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну это как бы псевдомодальная форма.

На самом деле у меня все посложнее, а именно - формами и обменом данными между ними управляет движок форм, он в том числе и отслеживает подобные цепочки и поддерживает таскбар внутри приложения (MDI). То есть для твоего случая - если пользователь переключается через такскбар или напрямую на Form1, то ничего не происходит, если на Form2 - автоматически на экран вылазит Form2, за ней Form3 и т.п. (то есть цепочка может быть и длиннее).

Можно еще сделать Form2.Enabled=False, то тогда есть недостаток - пользователь не может переключиться на форму с помощью клика по ней.

ЗЫ: есть и другой вариант - следить за Form3.Deactivate. Если фокус ушел на родительскую форму - возвращать его себе обратно. То есть эдакая псевдомодальность.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216292
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProМожно еще сделать Form2.Enabled=False, то тогда есть недостаток - пользователь не может переключиться на форму с помощью клика по ней.
Почему не может? После закрытия Form3 сможет.
Все формы вызывать не модально, а в Form3 прописать:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Private Sub Form_Load()
  Form2.Enabled = False
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  Form2.Enabled = True
End Sub
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216319
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVIПочему не может? После закрытия Form3 сможет.а ДО закрытия не может. Клик в пустоту уходит. То есть логично было бы, чтобы по клику на Form2 активировалась бы Form2, а поверх нее Form3. А так клик проходит "сквозь" Form2 и активируется то, что находится "позади" Form2
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216345
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А об чем спор?

Form1 (типа основная):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Private Sub Command1_Click()
  Form2.Show
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Unload Form2 'и по индукции все дочернее что за Form2
End Sub



Form2 (типа параллельная):
Код: vbnet
1.
2.
3.
Private Sub Command1_Click()
  Form3.Show , Me
End Sub



Form3 (псевдомодальная относительно Form2):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
Private Sub Form_Load()
  Form2.Enabled = False
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Form2.Enabled = True
  Form2.SetFocus
End Sub



И вроде как все путем, и придраться нельзя.
Или я чего-то не заметил?
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216346
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а, прекрасно, вроде то, что надо
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216348
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не, придрался.
Если щелкнуть не по самой Form2, а по "Form2" в панели задач, то она получает-таки фокус, хотя и поверх не вылазит.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216352
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ах ты, блин
не заметил косяк
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216375
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно спрятать Form2 из таскбара, пока отображается Form3.
Когда-то мы уже обсуждали, как это сделать.

Например,
код Form2:
Код: 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.
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Const GWL_EXSTYLE = -20&
Private Const WS_EX_APPWINDOW = &H40000

Private Sub Command1_Click()
  Me.Enabled = False
  InTaskbar False
  Form3.Show , Me
End Sub

Private Sub Form_GotFocus()
  'Me.Enabled = True
  InTaskbar True
End Sub

Private Sub InTaskbar(b As Boolean)
  ' Freeze the window
  LockWindowUpdate hWnd
  ' Hide Form
  Me.Hide
  If b Then
    ' Show this form on the taskbar
    SetWindowLong hWnd, GWL_EXSTYLE, (GetWindowLong(hWnd, GWL_EXSTYLE) Or WS_EX_APPWINDOW)
  Else
    ' Hide Form from the taskbar
    SetWindowLong hWnd, GWL_EXSTYLE, (GetWindowLong(hWnd, GWL_EXSTYLE) And Not WS_EX_APPWINDOW)
  End If
  ' Show Form
  Me.Show
  ' Release the lock
  LockWindowUpdate 0&
End Sub



код Form3:
Код: vbnet
1.
2.
3.
4.
Private Sub Form_Unload(Cancel As Integer)
  Form2.Enabled = True
  Form2.SetFocus
End Sub

...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216381
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недожал немного :)
Вот так правильнее:

Например,
код Form2:
Код: vbnet
1.
2.
3.
Private Sub Command1_Click()
  Form3.Show , Me
End Sub



код Form3:
Код: 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.
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Const GWL_EXSTYLE = -20&
Private Const WS_EX_APPWINDOW = &H40000

Private Sub InTaskbar(Frm As Form, b As Boolean)
  ' Freeze the window
  LockWindowUpdate hWnd
  ' Hide Form
  Frm.Hide
  If b Then
    ' Show this form on the taskbar
    SetWindowLong Frm.hWnd, GWL_EXSTYLE, (GetWindowLong(Frm.hWnd, GWL_EXSTYLE) Or WS_EX_APPWINDOW)
  Else
    ' Hide Form from the taskbar
    SetWindowLong Frm.hWnd, GWL_EXSTYLE, (GetWindowLong(Frm.hWnd, GWL_EXSTYLE) And Not WS_EX_APPWINDOW)
  End If
  ' Show Form
  Frm.Show
  ' Release the lock
  LockWindowUpdate 0&
End Sub

Private Sub Form_Load()
  Form2.Enabled = True
  InTaskbar Form2, False
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Form2.Enabled = True
  InTaskbar Form2, True
  Form2.SetFocus
End Sub

...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216383
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

Модальное окно одно для всего приложения и действует на всё приложение. То, чего ты хочешь, не бывает в природе.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216384
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извиняюсь за спам, исправил опечатку в Form3

код Form2 (без изменений):
Код: vbnet
1.
2.
3.
Private Sub Command1_Click()
  Form3.Show , Me
End Sub



код Form3 (исправлено Form_Load):
Код: 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.
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Const GWL_EXSTYLE = -20&
Private Const WS_EX_APPWINDOW = &H40000

Private Sub InTaskbar(Frm As Form, b As Boolean)
  ' Freeze the window
  LockWindowUpdate hWnd
  ' Hide Form
  Frm.Hide
  If b Then
    ' Show this form on the taskbar
    SetWindowLong Frm.hWnd, GWL_EXSTYLE, (GetWindowLong(Frm.hWnd, GWL_EXSTYLE) Or WS_EX_APPWINDOW)
  Else
    ' Hide Form from the taskbar
    SetWindowLong Frm.hWnd, GWL_EXSTYLE, (GetWindowLong(Frm.hWnd, GWL_EXSTYLE) And Not WS_EX_APPWINDOW)
  End If
  ' Show Form
  Frm.Show
  ' Release the lock
  LockWindowUpdate 0&
End Sub

Private Sub Form_Load()
  Form2.Enabled = False
  InTaskbar Form2, False
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Form2.Enabled = True
  InTaskbar Form2, True
  Form2.SetFocus
End Sub

...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216396
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVI,
прятать Form2 из TaskBar я не хочу. За тот код с шапкой спасибо.

MasterZiv,
>Модальное окно одно для всего приложения и действует на всё приложение
то что я это понял практически сразу, следует из моего 3-го поста:
>Модальная, по определению блокирует "ВСЕ".

Поэтому сейчас речь идет о ПСЕВДОмодальности.

Дело осталось возможно за малым:

Когда щелкаешь на кнопке "Form2" TaskBar и Form3 модальная, то
1) Кнопка нажимается
2) Кнопка "отскакивает" и "фокус" возвращается в Form3 (Form3-заголовок активируется)

В случае "почти рабочего" примера с ПСЕВДО,
при нажатии на кнопке "Form2" TaskBar
1) Кнопка нажимается (как и в случае выше)
НО
2) Кнопка НЕ "отскакивает" и при отжатии мышки активируется заголовок Form2 (а не Form3)

Думаю:
надо сабклассить Form2
1) понять событие "нажатия кнопки TaskBar"
2) понять что послать и какому окну (Form2 ? Form3) в ответ на п.(1), чтоб сразу "отжать "кнопку "Form2" на TaskBar

сдается мне что WM_ACTIVATEAPP
что-то вокруг вот этого
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
   Case WM_ACTIVATEAPP
     If wParam = 1 Then
       Debug.Print "WM_ACTIVATEAPP(is being activated)"
     Else
       Debug.Print "WM_ACTIVATEAPP(is being deactivated)"
        If FormLoadedByName("Form3") Then SetActiveWindow Form3.hWnd
     End If


Но конкретно с этим не взлетело (кнопка на Taskbar остается нажатой).

Вот если здесь довести до ума, то будет "как надо".

MasterZiv, м.б. дашь идею, VB тут как бы ни причем.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38216731
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

Я драм идею, не маяться дурью, а переделать как-то интерфейс по-другому.

Если тебе такое нужно, значит тебе нужно, чтобы первое окно было доступно, второе тоже, одновременно, а третье, "МОДАЛЬНОЕ", доступно вместе с первым, но вместо второго. Так так и сделай, два немодальных окна, второе состоит из двух, которые меняют друг друга, например, на двух вкладках.
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38217529
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv,
>Так так и сделай, два немодальных окна, второе состоит из двух, которые меняют друг друга, например, на двух вкладках
Нет, так не пойдет.

Form1 - основное окно приложения
Form2 -окно мониторинга определенного функционала (можно сделать как отдельный exe, но по ряду причин это крайне неудобно)
Form3 -окно настроек этого функционала (работа этого функционала отображается в Form2), там и так Tabstrip, его логично вызывать из Form2.
Да, изначально была идея лепить все в Form2, но это громоздко и некрасиво.

Т.е. надо сделать именно как хочу. И в принципе почти сделал, и никакой дури в этом не вижу.

Давайте локализуем задачу. Я убрал Form1.

Form3 вызывается немодально и пока она в работе, Form2.enabled=false.
Кнопка "Form2" на Taskbar нужна, она подымает наверх Form2+Form3, если прикрыто "другими" окнами.
И делает это правильно.
Единственная проблемка: "фокус" (заголовок активирован) переходит на Form2, а не на Form3 и кнопка "Form2" на Taskbar остается нажатой.
Так вот как с этим побороться?

Во вложении тест с Form2+Form3(без Form1)
+сабклассинг Form2 -пока не знаю что там делать.

В принципе на эту мелочь можно забить...
...
Рейтинг: 0 / 0
3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
    #38217964
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче сделал.

На время отображения Form3, надо сабклассить Form2:

Код в Form3:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Private Sub Form_Load()
  Form2.Enabled = False
  OldForm2WindowProc = SetWindowLong( _
   Form2.hWnd, GWL_WNDPROC, _
   AddressOf NewForm2WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
  SetWindowLong Form2.hWnd, GWL_WNDPROC, OldForm2WindowProc
  Form2.Enabled = True
  Form2.SetFocus
End Sub



Далее ловится некое волшебное (не упомянутое нигде в MSDN и т.п., я не нашел) сообщение:
Код: vbnet
1.
Private Const WM_XZ = &H105A '4186


и применяется любой из вариантов:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Private Declare Function SetActiveWindow Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function SetForegroundWindow Lib "user32" _
 (ByVal hWnd As Long) As Long
Private Declare Function PutFocus Lib "user32" Alias "SetFocus" (ByVal hWnd As Long) As Long

       Form3.ZOrder
       'Form3.SetFocus
       'SetActiveWindow Form3.hwnd
       'SetForegroundWindow Form3.hWnd
       'PutFocus Form3.hWnd



Во вложенном примере добавил еще Form4, код такой:
Код: 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.
'для событий Form2
Public Function NewForm2WindowProc _
 (ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
      
 Select Case Msg
   Case WM_XZ
     Debug.Print "WM_XZ"
     If FormLoadedByName("Form4") Then
       Form4.ZOrder
       'Form4.SetFocus
       'SetActiveWindow Form4.hwnd
       'SetForegroundWindow Form4.hWnd
       'PutFocus Form4.hWnd
     Else
       Form3.ZOrder
       'Form3.SetFocus
       'SetActiveWindow Form3.hwnd
       'SetForegroundWindow Form3.hWnd
       'PutFocus Form3.hWnd
     End If
   Case Else
  End Select 'Msg
  NewForm2WindowProc = CallWindowProc _
   (OldForm2WindowProc, hWnd, Msg, wParam, lParam)
End Function



Есть тонкость:

1) Form3 может вызывать другие ПСЕВДОмодальные, активной надо сделать ту, которая самая верхняя в данный момент.
Найти ее (следуя логике приложения) довольно легко:
Код: vbnet
1.
2.
3.
 If FormLoadedByName("Form4") Then
 else
   'Form3


2) В API -без которых можно обойтись я чуть подзарылся по след. причине:
Формой "верхнего уровня" может быть какой-нибудь диалог типа "Open File", вызываемый из Form3.
Тогда поможет что-то типа:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Public Function NewForm2WindowProc _
 (ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 
  Dim hwndTarget As Long
      
  Select Case Msg
    Case WM_XZ
      hwndTarget = FindWindow(vbNullString, "My Open File Dialog Caption")
      If hwndTarget <> 0 Then
        SetActiveWindow hwndTarget
      Else
        If FormLoadedByName("Form4") Then
          Form4.ZOrder
        Else
          Form3.ZOrder
        End If
      End If
    Case Else
  End Select 'Msg
  NewForm2WindowProc = CallWindowProc _
   (OldForm2WindowProc, hwnd, Msg, wParam, lParam)



Понять бы еще что это за WM_ХЗ... google не помог
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / 3 формы, 3-я должна быть модальной относит. 2-й но не перекрывать доступ к 1-й
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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