В чем разница между SetWindowLongPtr(GWL_HWNDPARENT) и SetParent?

#api #winapi #window #watermark

#API #winapi #окно #водяной знак

Вопрос:

Мне нужно создать окно водяного знака (markHwnd) для окон некоторых приложений на рабочем столе, стиль окна водяного знака:

             uint dwStyle = Win32API.WS_CLIPSIBLINGS |
                          Win32API.WS_CLIPCHILDREN |
                          Win32API.WS_POPUP;
            uint dwExStyle = Win32API.WS_EX_LAYERED |
                            Win32API.WS_EX_TRANSPARENT |
                            Win32API.WS_EX_NOACTIVATE |
                            Win32API.WS_EX_NOPARENTNOTIFY |
                            Win32API.WS_EX_TOOLWINDOW;
            markHwnd = Win32API.CreateWindowEx(dwExStyle, wndclassRegResult, ti.ToString(), dwStyle, 0, 0, 0, 0,IntPtr.Zero, IntPtr.Zero, wndclasshInstance, IntPtr.Zero);
  

Затем я установлю, что это будет собственное окно окна приложения (targetHwnd), есть два варианта:

  • SetWindowLongPtr(markHwnd, (int)Win32API.GWL.GWL_HWNDPARENT, targetHwnd);
  • SetParent(markHwnd, targetHwnd);

Какой из них предлагается?

Комментарии:

1. Особой разницы нет: любой из них завершится неудачей. Смотрите Законно ли иметь межпроцессные отношения родитель / потомок или владелец / принадлежащее окно?

Ответ №1:

В SetWindowLongPtr() документации говорится:

Не вызывайте SetWindowLongPtr с индексом GWLP_HWNDPARENT для изменения родительского элемента дочернего окна. Вместо этого используйте функцию SetParent.

На что ссылается эта документация, так это на то, что GWLP_HWNDPARENT фактически меняется владелец окна верхнего уровня, а не родительский элемент дочернего окна. По словам Рэймонда Чена:

У окна может быть родительский элемент или владелец, но не оба сразу

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

И он продолжает объяснять, как CreateWindow/Ex() назначается владелец по сравнению с родительским в зависимости от того, имеет ли новое окно WS_CHILD стиль или нет.

В SetParent() документации говорится:

По соображениям совместимости SetParent не изменяет стили окон WS_CHILD или WS_POPUP окна, родительский элемент которого изменяется.

Итак, SetWindowLongPtr(GWLP_HWNDPARENT) используется для изменения владельца окна верхнего уровня и SetParent() используется для изменения родителя дочернего окна.

Комментарии:

1. однако SetWindowLongPtr с GWLP_HWNDPARENT также есть видимый эффект — он фактически устанавливает владельца (но не родительский). и в отличие от этого, стиль SetParent не меняется WS_CHILD . для Windows верхнего уровня я бы посоветовал использовать GWLP_HWNDPARENT более подходящее сравнение SetParent . что и почему говорится в документации, это уже другая история