API SetParent: Помещение потомка позади родителя.

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 9:51

Фсем превед!
В целях создания муляжа аэровской прозрачности панели задач возникла необходимость помещать сразу за целевым окном (Shell_TrayWnd) свое окно, с отрисованным на нем размытым по Гауссу изображением фона. Однако, возникла трудность — следует поместить свое окно в точке 3, как показано на схеме.
Setparent по хендлу Progman'a помещает в точке 1, по хендлу Shell_TrayWnd — в точке 2, оба варианта, как вы понимаете, неприемлимы.
Следующая схема иллюстрирует расположение слоёв окон рабочего стола.
Изображение
P.S. Прошу администрацию рассмотреть возможность переноса этого топика в раздел для профессионалов, т.к. считаю этот вопрос неординарным.
Вложения
Zorder.png
Zorder.png (14.52 Кб) Просмотров: 1957
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 10:44

Делаю так (код в форме1):
Код: Выделить всё
Option Explicit

Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Private Const WS_EX_TOPMOST = &H8&
Private Const GWL_EXSTYLE = (-20)

Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
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

Dim Handle As Long
Dim HandleDT As Long
Dim wRect As RECT
Dim NewPW As Form

Private Sub Form_Load()

Set NewPW = New Form2
NewPW.Show

Handle = FindWindow("Shell_TrayWnd", vbNullString)
HandleDT = GetDesktopWindow
GetWindowRect Handle, wRect

NewPW.Top = wRect.Top * Screen.TwipsPerPixelY
NewPW.Left = wRect.Left * Screen.TwipsPerPixelX
NewPW.Width = (wRect.Right - wRect.Left) * Screen.TwipsPerPixelX
NewPW.Height = (wRect.Bottom - wRect.Top) * Screen.TwipsPerPixelY

Dim WL As Long

WL = GetWindowLong(NewPW.hwnd, GWL_EXSTYLE)
SetWindowLong NewPW.hwnd, GWL_EXSTYLE, WL Or WS_EX_TOPMOST

SetParent Handle, NewPW.hwnd

End Sub

Private Sub Form_Unload(Cancel As Integer)

SetParent Handle, HandleDT

Unload NewPW

End Sub


Но эффекты получаются поистине фейерические!!!
(сбивается позиция появления меню пуск, игнорируется мой topmost, позиция таскбара смещается к точке 3 на схеме и сам он перестает реагировать на клики мышки)
(чтобы увидеть Form2, сделайте любым способом таскбар полупрозрачным)
Есть идеи, как сделать правильно?
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Хакер » 22.10.2009 (Чт) 11:22

А какая связь между SetParent и Z-ордером?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 12:17

Хакер писал(а):А какая связь между SetParent и Z-ордером?

Z-order это же порядок размещения окон слоями по оси Z, я правильно понимаю? Если я понимаю неправильно, то поправьте.

Вообще, говоря "Z-order", я понимаю порядок по оси Z, а не свойство vb'шного класса, имеющего это свойство (извиняюсь за тавталогию).
Так же, говоря "окно", например, я не подразумеваю под этим только объект, порождаемый одним лишь vb'шным классом Form.
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Хакер » 22.10.2009 (Чт) 12:18

Z-order это же порядок размещения окон слоями по оси Z, я правильно понимаю? Если я понимаю неправильно, то поправьте.

Вообще, говоря "Z-order", я понимаю порядок по оси Z, а не свойство vb'шного класса, имеющего это свойство (извиняюсь за тавталогию).
Так же, говоря "окно", например, я не подразумеваю под этим только объект, порождаемый одним лишь vb'шным классом Form.

Да. Повторяю вопрос.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 13:50

Хакер писал(а):Да. Повторяю вопрос.


Хакер писал(а):А какая связь между SetParent и Z-ордером?


SetParent устанавливает эту связь между окном parent и окном child. Устанавливает таким образом, что Z child'a всегда болше чем Z parent'a. Нэ?

Если я устанавливаю тулбар child'ом своего окна, то нарушается правильная работа всего десктопа. Мне интересно одно из двух: либо сделать свое окно child'ом тулбара, но при этом поменять их Z-порядок, либо найти окно проводника, находящееся между тулбаром и десктопом, и сделать его parent'ом своего окна.
Либо третий, неведомый мне, вариант Ъ-гуру.
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Antonariy » 22.10.2009 (Чт) 17:18

SetParent устанавливает эту связь между окном parent и окном child.
Ничего похожего. SetParent делает одно окно контейнером другого. А z-index определяет видимость нескольких потомков в рамках одного контейнера, поэтому для пары родитель-потомок вообще не имеет смысла. Потомок не может быть ЗА родителем.

Мне интересно одно из двух
Вот почему чуть менее, чем все избретатели улучшалок интерфейса стараются сломать то, что работает и к чему все привыкли, чтобы заменить своим улучшизмом? Почему нельзя дополнить, не трогая того, что и так работает?

сделать свое окно child'ом тулбара, но при этом поменять их Z-порядок
Невозможно. И слава богу.
найти окно проводника, находящееся между тулбаром и десктопом
Не понятно. С какой стати там должно быть окно проводника?

Кстати картинка в первом посте тоже лишена смысла. Не считая того, в ней нет различия между z и контейнерами, десктоп является окном самого верхнего уровня и за ним никакого progman быть не может.
Лучший способ понять что-то самому — объяснить это другому.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 18:30

Antonariy писал(а):SetParent делает одно окно контейнером другого. А z-index определяет видимость нескольких потомков в рамках одного контейнера


Я это и имел ввиду, только сформулировать не мог. Я рассматривал случай: одно окно — один контейнер.

Antonariy писал(а):Вот почему чуть менее, чем все избретатели улучшалок интерфейса стараются сломать то, что работает и к чему все привыкли, чтобы заменить своим улучшизмом? Почему нельзя дополнить, не трогая того, что и так работает?


Не переживай, я всего лишь эксперементирую, и не собираюсь, как сами-знаете-кто, выпускать в народ нестабильный продукт.

Antonariy писал(а):С какой стати там должно быть окно проводника?


Не буду разводить демагогию, отвечая вопросом на вопрос, скажу сразу: окно процесса explorer.exe. Это можно проверить в любом альтернативном диспетчере задач, хоть в Spy++

Antonariy писал(а):Кстати картинка в первом посте тоже лишена смысла. Не считая того, в ней нет различия между z и контейнерами, десктоп является окном самого верхнего уровня и за ним никакого progman быть не может.


А вот и нет, Progman, это окно, в котором лежит бэкграунд и его потомком является, например, SysListView32, содержащий в себе иконки рабочего стола. Это тоже легко проверить в альтернативном диспетчере задач. (Я использую плагин AceHelper для TotalCmd)
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Antonariy » 22.10.2009 (Чт) 18:52

Не буду разводить демагогию, отвечая вопросом на вопрос, скажу сразу: окно процесса explorer.exe.
Таскбар сам пренадлежит explorer.exe. А в иерархии окон является потомком десктопа. Так что смысла в этой фразе нет.

А вот и нет, Progman, это окно, в котором лежит бэкграунд и его потомком является, например, SysListView32, содержащий в себе иконки рабочего стола. Это тоже легко проверить в альтернативном диспетчере задач. (Я использую плагин AceHelper для TotalCmd)
Налицо неспособность интерпретировать показания Spy++. А так же тот факт, что ты не разу не сравнил значение, возвращаемое GetDesktopWindow с хендлом того, что вытыкаешь мышкой кагбэ с рабочего стола. В интерфейсе Spy++ Desktop всегда находится в корне иерархии окон и имеет только FIRST_CHILD, что само по себе символизирует.

Простейший тест: заверши все процессы exprorer.exe и попробуй найти десктоп и progman. После него станет несложно сделать единственно верный логический вывод, что на самом деле progman это проводник, у которого оставили лишь список файлов (листвью), растянули его на весь экран и сделали прозрачным.
Лучший способ понять что-то самому — объяснить это другому.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 19:15

А тебе лишь бы поспорить? Проводник, это не окна проводника. Проводник это процесс explorer.exe
Я ж говорю, пользуюсь AceHelper'ом. Вот окна о которых я говорил:
Изображение
Изображение
Окно десктопа не нашел, буду рад, если ткнут носом.
Вложения
001.png
001.png (24.37 Кб) Просмотров: 1904
002.png
002.png (23.92 Кб) Просмотров: 1906
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Antonariy » 22.10.2009 (Чт) 19:20

Мне лишь бы научить кого-нибудь уму-разуму, потому что такие опусы только поначалу вызывают смех, а потом только слезы.
"Окна проводника" в данном случае это окна (хендлы), принадлежащие процессу explorer.exe.
Окно десктопа не нашел, буду рад, если ткнут носом.
Оно в этой еретической проге не указано.
Лучший способ понять что-то самому — объяснить это другому.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 22.10.2009 (Чт) 19:38

Antonariy писал(а):Оно в этой еретической проге не указано.

Подозреваю, что это виртуальное окно, как, например, виртуальная папка рабочего стола. Как там де факто подставляется реальная папка в каталоге с профилем, так и тут подставляется хендл окна, какой-нибудь системной службы. Например, ну... например... эээ... нет, у winlogon'a вообще окон нет. Надо поискать по хендлу.
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Хакер » 22.10.2009 (Чт) 23:04

Виртуальных окон не существует в концепции окон Windows. Есть другие интересные вещи, как, например MessageOnly-окна, у которых нет Z-порядка, ассоциированного DC, которые не перечисляются Enum-функциями (но с успехом ищутся Find-функциями) и т.д, но виртуальных окон нет.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Joo
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 762
Зарегистрирован: 14.08.2008 (Чт) 11:55
Откуда: Казахстан

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Joo » 23.10.2009 (Пт) 6:39

В общем можно сделать так: (правда тут .NET код, я его писал для свлих часиков)

Поместить окно на задний план:
Код: Выделить всё
SetWindowPos(Me.Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)


Запретить окну перемещаться на верхний план:
Код: Выделить всё
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = WM_WINDOWPOSCHANGING Then
                    Dim wp As WINDOWPOS
                    wp = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(WINDOWPOS)), WINDOWPOS)
                    wp.hwndInsertAfter = HWND_BOTTOM
                    Marshal.StructureToPtr(wp, m.LParam, True)
        End If
        MyBase.WndProc(m)
    End Sub


Код: Выделить всё
Public Const WM_WINDOWPOSCHANGING = &H46
Public Const HWND_BOTTOM = 1
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOMOVE = &H2

<StructLayout(LayoutKind.Sequential)> _
Public Structure WINDOWPOS
            Public hwnd As IntPtr
            Public hwndInsertAfter As IntPtr
            Public x As Integer
            Public y As Integer
            Public cx As Integer
            Public cy As Integer
            Public flags As Integer
End Structure
"Им будет не просто, тем кто полагается на истину авторитета, вместо того чтобы полагаться на авторитет Истины"
Джеральд Месси, Египтолог

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 23.10.2009 (Пт) 8:01

WndProc

Запахло сабклассингом...
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Joo
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 762
Зарегистрирован: 14.08.2008 (Чт) 11:55
Откуда: Казахстан

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Joo » 23.10.2009 (Пт) 8:45

Денис писал(а):
WndProc

Запахло сабклассингом...


Да... я уже забыл что VB6 чуть немного сложнее с этим, но все равно довольно просто.
Таким образом если я правильно понял можно сделать окно не только под всеми окнами но и под конкроетным окном. Если не прав поправьте.
"Им будет не просто, тем кто полагается на истину авторитета, вместо того чтобы полагаться на авторитет Истины"
Джеральд Месси, Египтолог

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Денис » 23.10.2009 (Пт) 9:14

Теперь я понял, почему Aero™ жрёт так много ресурсов!

Представьте себе, в процедуре перерисовки каждого окна, которая может происходить по нескольку десятков раз в секунду (по ситуации), надо скриншотить всё что под окном, применять к полученному скрину гаусса, отрисовывать на окне, а еще ведь есть эффекты подсветки!

В общем, сейчас вы все конечно подумаете, что я сабклассинга испугался, но должен заявить, что я оставлю эту затею, пихать под таскбар окно и пытаться реализовать на нем вышеописанное. Висты под рукой щас нет, поэтому пощупать не могу, но сдаётся мне, это все отрисовывается на целевом окне, а не на подложке.
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: API SetParent: Помещение потомка позади родителя.

Сообщение Antonariy » 23.10.2009 (Пт) 10:25

это все отрисовывается на целевом окне, а не на подложке
Ага, в окне чужого процесса (десктоп пренадлежит вообще crss) ты толком ничего отрисовать не сможешь — процесс перерисует его в соответствии с собственными представлениями о том, что там должно находиться.
Лучший способ понять что-то самому — объяснить это другому.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 84

    TopList