Включение Aero Glass в настраиваемом заголовке окна (WM_NCPAINT, DwmSetWindowAttribute)

Несколько лет назад мы разработали компонент ActiveX под названием CaptionX (Домашняя страница CaptionX). Это позволяет разработчикам размещать настраиваемые интерактивные графические кнопки в строке заголовка окна. Все работает нормально в любой Windows, кроме Vista и Windows 7, когда Aero Glass включен - строка заголовка с нашими настраиваемыми значками отображается так, как если бы мы использовали тему Windows Basic без эффекта прозрачности для границ окна.

Люди хотели бы использовать CaptionX в последних версиях ОС, но мы не можем заставить его работать. Все поиски в Интернете говорят нам, что нам нужно включить Aero Glass, когда мы используем пользовательский рисунок в заголовке окна с помощью вызова API DwmSetWindowAttribute с атрибутом DWMWA_NCRENDERING_POLICY, но нам не удалось заставить его работать.

Наш код, который рисует неклиентскую поверхность окна, выглядит так (извините, это старый VB6 :):

Friend Function WindowProc(ByVal lPrevWndProc As Long, ByVal hwnd As Long, ByVal iMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

   Select Case iMsg

   Case WM_NCPAINT
      DoNCPaint lPrevWndProc, wParam
      WindowProc = 0
      Exit Function

   Case WM_...
      ' Other message handlers

   End Select

   WindowProc = CallWindowProc(lPrevWndProc, hwnd, iMsg, wParam, lParam)
End Function

Мы добавили следующий звонок

DwmSetWindowAttribute m_hwnd, DWMWA_NCRENDERING_POLICY, DWMNCRP_ENABLED, 4

во многие места в нашем коде, но это не имеет никакого эффекта. Мы можем отключить эффект Aero Glass, если он используется по умолчанию в окне с помощью DwmSetWindowAttribute, но не может его включить.

Что мы делаем не так? Нужно ли нам добавлять в наш код дополнительные вызовы API, и если да, то где?


person 10Tec    schedule 02.02.2012    source источник


Ответы (2)


При вызове может быть ошибка, вам не следует передавать простое значение DWMNCRP_ENABLED в API, вместо этого вы должны передать ссылку на структуру DWMNCRENDERINGPOLICY.

person Dandy Cheung    schedule 04.02.2012
comment
Объявление DwmSetWindowAttribute выглядит следующим образом: «Public Declare Function DwmSetWindowAttribute Lib dwmapi.dll (ByVal hWnd As Long, ByVal dwAttribute As Long, ByRef pvAttribute As Long, ByVal cbAttribute As Long) As Long», поэтому третий параметр передается по ссылке . И DWMWINDOWATTRIBUTE (а не DWMNCRENDERINGPOLICY, как вы написали) на самом деле является целочисленным флагом. И этот вызов работает для флага отключения :) - person 10Tec; 06.02.2012
comment
comment
Прочтите мой ответ, почему DwmSetWindowAttribute не может помочь. - person TecMan; 17.03.2016

Этот старый подход не работает в последних версиях Windows, начиная с Vista, из-за нового диспетчера окон рабочего стола (DWM), отвечающего за отрисовку рамки окна. Вот еще один интересный блог, найденный на web.archive.org, который объясняет природу проблемы:

Часто задаваемые вопросы об оконной рамке Aero Basic

Соответствующий отрывок следующий:

У DWM нет никаких проблем с наследием, потому что приложения не могут рисовать внутри стеклянной рамки, так как она отображается и управляется совершенно другим процессом. Если приложение попытается это сделать, Windows обнаружит это и полностью удалит стеклянную рамку (и, следовательно, вернется к базовой рамке), чтобы приложение могло рисовать то, что оно хочет рисовать.

Чтобы изменить строку заголовка окна в Windows Vista, 7 и т. Д., Нам нужно использовать новый DWM API.

person TecMan    schedule 17.03.2016