Окно без полей с использованием Areo Snap, Shadow, Minimize Animation и Shake

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


person joshua-anderson    schedule 27.05.2013    source источник
comment
Я прочитал о DWMWA_ALLOW_NCPAINT. Итак, слово 2013 и VS2012 рисуют НАД границей, чтобы скрыть это?   -  person joshua-anderson    schedule 27.05.2013
comment
Многие люди ищут ответ на этот вопрос, как я вижу. Я был одним из них некоторое время назад. Я попробовал реализации, уже ответил в этом посте, и по причинам, которые они не подходят идеально. После некоторого времени гугления и модификации образца BodrelessWindow от deimos1877 я нашел более легкое решение для Qt. Это простой проект Qt с QMainWindow. Не стесняйтесь использовать и адаптировать его для своих нужд. Основное преимущество - нет прокси-классов между окном Qt и родным WinAPI, заголовок окна не мерцает при выключенном Aero. bitbucket.org/artem_bodrin/framless   -  person Artem Bodrin    schedule 08.12.2017


Ответы (3)


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

Чтобы скрыть границу окна, обработайте сообщение 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), через него будет видна небольшая рамка:

окно без полей с тенью и рамкой, отображаемой в клиентской области

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

Если все пойдет хорошо, то это должно выглядеть так:

введите здесь описание изображения

Вот небольшой пример проекта, F11 включает/выключает режим без полей/оконный режим, F12 включает и выключает тень без полей.

person melak47    schedule 18.07.2013
comment
Steam по-прежнему имеет тень, идентичную тени Aero. Он также имеет Aero Snap/Shake/Stuff, но ему не хватает анимации минимизации. - person Keavon; 18.07.2013
comment
@RandomUser Мое решение делает все, кроме минимизации перехода - результат стиля окна, необходимого для работы тени. Даже в Outlook 2013 этого нет, поэтому я не верю, что это возможно без подделки, как Visual Studio делает свое свечение. (иногда вы можете видеть, что рамка окна становится видимой внутри клиентской области, поэтому они действительно выглядят над рамкой) - person melak47; 21.07.2013
comment
Анимация минимизации в Visual Studio выглядит точно так же, как окно с рамкой. Они только что сделали действительно хорошую работу, подделывая это? Есть идеи, как мы могли бы подделать это? - person Keavon; 25.07.2013
comment
Это выглядит так. Я думаю, что для того, чтобы свернуть анимацию, потребуется много усилий — вы не получите аэротени; вам нужно будет нарисовать ваш собственная тень/свечение вместо рамки. Кроме того, может быть много особых случаев, которые необходимо обработать, чтобы сохранить обман отсутствия границы. Скажем, убедившись, что Alt+PrintScreen захватывает только клиентскую область, а не кадр, размер окна для аэродинамической привязки (чтобы не было зазора из-за прозрачной границы)... - person melak47; 25.07.2013
comment
Думаю, все, кроме анимации сворачивания. - person melak47; 30.08.2013
comment
@ melak47 melak47 Кажется, я не могу заставить это работать, не могли бы вы загрузить файлы своего проекта, чтобы мы могли увидеть это в действии. Это было бы очень полезно! Большое спасибо. - person Mathew Kurian; 13.09.2013
comment
@Keavon Я ошибся насчет заголовков, если вы добавите WS_CAPTION к стилю, вы также получите анимацию минимизации. - person melak47; 13.09.2013
comment
@melak47 Большое спасибо! Я попытался запустить его на VS2013 RC и столкнулся с небольшими проблемами. Так что я пошел дальше и открыл вопрос на Github, и мы надеемся продолжить этот разговор там. - person Mathew Kurian; 13.09.2013
comment
@melak47 melak47 Не возражаете, если мы используем часть вашего примера кода (на данный момент) в нашем приложении с открытым исходным кодом? - person joshua-anderson; 21.09.2013
comment
@joshua-anderson совсем нет :) - person melak47; 22.09.2013
comment
@ melak47 У меня все заработало :) Но я не вижу кнопок управления. это идет с самим заголовком? Могу ли я показать кнопки управления с этими конфигурациями? - person Morpheus; 30.05.2014
comment
@Morpheus был какой-то стиль окна, который отображал кнопки даже в режиме без полей, проверьте комментарии в моем коде, где я определяю стили. хотя они некрасивые, лучше нарисуй свои. - person melak47; 30.05.2014

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

Для тех, кто ищет пример C++/Qt, этот проект GitHub прекрасно справляется со своей задачей (спасибо deimos1877) на основе кода melak47! https://github.com/deimos1877/BorderlessWindow

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

person Kévin Renella    schedule 06.08.2014
comment
Я хотел бы сказать, что это лучший ответ, надеюсь, что сюда придут новые люди, чтобы использовать эту демонстрацию. - person lygstate; 28.10.2014
comment
С Qt5.8 вы получаете ошибку компилятора в qwinhost.cpp в строке 257, жалуясь на не найденный идентификатор qWinAppInst(). qWinAppInst() был удален из QtCore в Qt5.8 (см. здесь), поэтому вы надо заменить на GetModuleHandle(0) - person user2366975; 04.04.2017

Я создал тот, который реагирует как фотошоп.

BorderlessWindowQt-Modern-Gui

Image True WindowQt без полей

person Moussa Ball    schedule 15.01.2018
comment
Я не говорил минус, я просто хочу сказать вам, что ссылки должны быть только поддерживающими, потому что, если ссылка не работает, ваш ответ становится бесполезным. - person eyllanesc; 15.01.2018
comment
GPL2. Я предпочитаю реализовывать свои собственные. - person Konrad; 22.07.2019
comment
Он отлично работает и если у кого есть возможность улучшить его и многое другое. Он приветствуется. - person Moussa Ball; 15.08.2019