2013-05-27 3 views
26

Я делаю приложение с окном без полей в Windows. Однако, поскольку окно без полей, у меня нет тени теней, оснастки, минимизации анимации или тряски. Я огляделся и не нашел ни одного сайта, объясняющего, как это реализовать. Однако я знаю, что это возможно, потому что Office 2013, Visual Studio 2012 и Steam имеют эти функции и безграничны. Я специально использую QT и C++, но если вы решили это для другой библиотеки окон, я также хотел бы услышать ваши решения. или. И по тенью теней я не имею в виду тень с двух сторон, я имею в виду светящуюся тень со всех сторон всех активных приложений на окнах windows.Окно без полей с помощью Areo Snap, Shadow, Minimize Animation и Shake

+5

Ваше предположение, что они без границ просто неправильно. Программы VS2012 и Office 2013, конечно же, не являются тем, что вы можете видеть со Spy ++. Я предполагаю, что DwmSetWindowAttribute(), DWMWA_ALLOW_NCPAINT в частности. –

+1

Я прочитал на DWMWA_ALLOW_NCPAINT. Итак, слово 2013 и VS2012 нарисовать поверх границы, чтобы скрыть это? –

+0

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

ответ

32

После использования Spy ++ для проверки окна Steam (его стили окна, ответы на сообщения в окне) и попытки сопоставить все, что он делает, в сочетании с вызовами DWMAPI от этого C# borderless window behavior, я считаю, что я понял это.

Чтобы скрыть границу окна, обрабатывать WM_NCCALCSIZE сообщение в вашем WindowProc:

case WM_NCCALCSIZE: { 
    if (window->is_borderless) { 
     return 0; 
    } else { 
     return DefWindowProc(hwnd, msg, wparam, lparam); 
    } 
} 

Чтобы включить тень, все, что вам нужно сделать, это:

MARGINS borderless = {1,1,1,1}; 
DwmExtendFrameIntoClientArea(hwnd, &borderless); 

Чтобы включить его выключить, восстановить значения по умолчанию MARGINS windowed = {0,0,0,0};. Возможно, также введите SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE);, чтобы убедиться, что кадр перерисовывается.

Однако, похоже, что это не работает со всеми стилями окон, очевидно, что ваш стиль окна не должен содержать заголовок. Заголовки работают нормально, а добавление одного позволяет включить анимацию минимизации.

Простейший стиль окна, в котором я работал, с тенью для работы был WS_POPUP | WS_THICKFRAME, а также получить аэрообъектив, максимизацию, минимизацию и плавное уменьшение анимации. Я использовал WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION.

Изменение DWMWA_NCRENDERING_POLICY или DWMWA_ALLOW_NCPAINT через DwmSetWindowAttribute не похоже на необходимость, настройки по умолчанию, похоже, работают.

Предупреждение: DwmExtendFrameIntoClientArea делает то, что предлагает название, поэтому, если вы рисуете изображение с альфа-каналом непосредственно в своей клиентской области (скажем, с opengl, direct3d/2d), небольшой кадр будет виден через это:

borderless window with shadow and frame showing in client area

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

Если все идет хорошо, он должен выглядеть следующим образом:

enter image description here

Here is a small example project, F11 переключает без полей/оконный режим, F12 переключает без границ тени и выключаться.

+0

Steam по-прежнему имеет тень, идентичную тени Aero. Он также имеет Aero Snap/Shake/Stuff, но не хватает анимации минимума. – Keavon

+0

@RandomUser Мое решение делает все, кроме минимизирующего перехода - результат стиля окна, необходимый для работы тени. Даже в Outlook 2013 этого недостаточно, поэтому я не считаю, что это возможно, не притворяясь, как Visual Studio делает свое свечение. (иногда вы можете видеть, что рамка окна становится видимой внутри области «клиент» - поэтому они действительно появляются, чтобы рисовать над фреймом) – melak47

+0

Сведение к минимуму анимации Visual Studio похоже на окно с рамкой. Неужели они просто отлично справились с этим? Любая идея, как мы могли бы это сделать? – Keavon

9

Спасибо melak47 за ваш ответ.

Для людей, которые ищут пример C++/Qt, этот профиль GitHub делает работу как шарм (благодаря deimos1877) на основе кода melak47! https://github.com/deimos1877/BorderlessWindow

Обязательно используйте Visual Studio компилятор (> = 2010), чтобы получить нужную DLL, и он должен работать. Этот пример включает поддержку аэроснимков, окно без полей, минимизацию эффекта, аэродинамические тени.

+2

Я бы хотел сказать, что это лучший ответ, надеюсь, что новые люди придут сюда, чтобы использовать эту демонстрацию. – lygstate

+0

С Qt5.8 вы получаете ошибку компилятора в 'qwinhost.cpp' в строке 257, жалуясь на то, что не найден идентификатор' qWinAppInst() '. 'qWinAppInst()' был удален из QtCore в Qt5.8 (см. [здесь] (https://github.com/qtproject/qt-solutions/commit/master)), поэтому вам нужно заменить его на 'GetModuleHandle (0) ' – user2366975

-1

Я создал тот, который отвечает как фотошоп.

BorderlessWindowQt-Modern-Gui

Image True Borderless WindowQt

+0

Я не сказал нисходящее направление, я просто хочу сказать вам, что ссылки должны быть только поддерживающими, потому что, если ссылка сломана, ваш ответ становится бесполезным – eyllanesc