Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515

Перекрывающие полупрозрачные окна

25.10.2015, 20:09. Показов 1446. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Понадобилось создать такое дочернее окно, которое может иметь полупрозрачный фон. С этим разобрался, с начала использовал Gdi+, затем и с AlphaBlend разобрался. Далее, если под дочерним окном появляется другое дочернее окно, то тут жизнь усложняется: отрисовка дочерних окон идёт в порядке Z-order сверху вниз, поэтому визуальный порядок перекрывающих окон строго обратный (использование WS_CLIPSIBLINGS неприемлемо, так как окно будет отсекать ту свою часть что попала под другое окно, и никакой прозрачности не будет). Есть ли способ обойти стандартный порядок вызова отрисовки дочерних окон? Пока я только придумал не рисовать ничего в WM_PAINT дочерних окнах, а вызывать AlphaBlend для каждого memHDC в родительском WM_PAINT (вернее я даю дочернему окну HDC родителя, а оно само его заполняет как нужно, хоть напрямую рисует, хоть BitBlt) в нужном порядке. Какой-то "костыльный" метод получается, не проще ли тогда вообще отказаться от окон и просто хранить порядок отрисовки для "контролов"?

зы: пытался использовать BitBlt для HDC с альфа каналом, но безуспешно, пришлось вызывать AlphaBlend с прозрачностью 255, так и должно быть?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
25.10.2015, 20:09
Ответы с готовыми решениями:

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

Полупрозрачные грани?!
Рисую куб, на каждую с граней накладываю текстуру. В итоге, при вращении грани "просвечиваются"... Вот функция прорисовки: ...

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

7
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
26.10.2015, 18:33
Цитата Сообщение от Operok Посмотреть сообщение
сверху вниз
Разве?
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
28.10.2015, 10:27  [ТС]
Цитата Сообщение от castaway Посмотреть сообщение
Разве?
В общем-то да, первым WM_PAINT получает окно самое верхнее в Z-последовательности, самое нижнее окно рисуется последним.
Если в родительском окне без стиля WS_CLIPCHILDREN создать две (или несколько) кнопок перекрывающих друг друга, то первоначально "нижняя" кнопка будет отрисована полностью, как только "верхняя" кнопка изменит состояние (указатель мыши навели), она перерисуется полностью и перекроет "нижнюю". Если включить "нижней" кнопке стиль WS_CLIPSIBLINGS, то она теперь не будет мешаться и её недействительный регион не будет пересекаться с "верхней" кнопкой. Если включен стиль WS_CLIPCHILDREN у родителя, то он сам всем отсекает ненужные регионы в соответствии с Z-order, и в этом случае он не закрашивает фон дочерних окон.

Добавлено через 35 минут
Немного поправлю себя, WS_CLIPCHILDREN запрещает родителю закрашивать фон дочерних окон, но не влияет на отсечение невалидных регионов дочерних окно. Для последнего, как я уже упомянул, нужно определить стиль WS_CLIPSIBLINGS у дочернего окна, которое не должно "мешать" другим окнам.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
28.10.2015, 19:27
Подумаю над этим дома после работы...

Добавлено через 7 часов 21 минуту
Что-то ты намудрил...

При создании дочернего окна, оно помещается "на дно" (вниз) z-order, по умолчанию.
If the created window is a child window, its default position is at the bottom of the Z-order.
(CreateWindow)

Цитата Сообщение от Operok Посмотреть сообщение
отрисовка дочерних окон идёт в порядке Z-order сверху вниз
Нет. Отрисовка идёт от bottom к top, т.е. снизу вверх (и это логично) всегда при перерисовке области, на которую попадает элемент управления.

Исходя из этого, мне не понятна суть твоей проблемы, особенно без кода и скриншотов.
1
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
29.10.2015, 16:00  [ТС]
Цитата Сообщение от castaway Посмотреть сообщение
Нет. Отрисовка идёт от bottom к top, т.е. снизу вверх (и это логично) всегда при перерисовке области, на которую попадает элемент управления.
Решил не верить глазам и проверил порядок вызова WM_PAINT в отладчике. От Top к Bottom рисуются дочерние окна.
Цитата Сообщение от castaway Посмотреть сообщение
особенно без кода и скриншотов
скинул архив с VС++ проектом. Ну и пару скринов (Окно "1" по Z-order выше окна "2" и на момент наведения указателя прозрачность убирается)
Изображения
  
Вложения
Тип файла: zip WindowsProject1.zip (11.2 Кб, 13 просмотров)
1
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
29.10.2015, 19:29
Может конечно я что-то напутал или не понимаю...
Так а в чём смысл? Какой цели необходимо достигнуть? Просто поменять порядок отрисовки дочерних окон на обратный? Если да, тогда их можно просто создать в обратном порядке. А если нужно изменить z-order окна, то можно воспользоваться функцией SetWindowPos.
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
29.10.2015, 20:45  [ТС]
Создание окон в обратном порядке приведёт лишь к визуальному "порядку". Скажем так, окно, которое визуально будет находиться под всеми остальными, системой будет считаться как topmost и ловить все события.
Я же нашёл один способ это обойти, это не рисовать дочерние окна в WM_PAINT вообще, а вызывать некую функцию Draw для каждого окна в нужном порядке. Тут возникает некоторые минусы: когда нужно перерисовать дочернее окно, я вызываю InvidateRect для Top level окна с нужным прямоугольником, тогда это окно отправляет сообщение WM_PAINT только тем дочерним окнам, что попали в этот прямоугольник, а мой обработчик WM_PAINT для главного окна так пока не умеет (вызывает Draw для всех окон, "виновных и невинных").
Вот я предположил, что может отказаться от окон (дочерних) вообще, хранить в привязанном к главному окну контейнере объекты, которые будут содержать методы отрисовки "контрола", его свойства и обработчики событий. Будут эти "контролы" рисоваться в контексте главного окна, которое в свою очередь будет отлавливать события и маршрутизировать их.
Тут нужно подумать, чего я в этом случае могу лишиться

Добавлено через 44 минуты
Кстати, на Win7 (с темой Aero не упрошенной) AlphaBlend при любом SCA < 255 делает чёрные пиксили полностью прозрачными. Знает кто-нибудь почему?
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
16.11.2015, 20:21  [ТС]
Продолжаю возиться с графикой windows средствами GDI. На этот раз выбор пал на градиент, в рамках RGB цвета, GradientFill замечательно справляется, если совместить его с AlphaBlend, тут уже есть некоторые ограничения, сделать переход от одного непрозрачного цвета к полностью прозрачному можно, но если делать переход от одного ARGB цвета к другому ARGB цвету, то ничего не выйдет. Повозился с ручным заполнением DIB, вот что получилось, пока сыровато, думаю можно и нужно оптимизировать вычисления:
AlphaGradientFill
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
VOID AlphaGradientFill(HDC hdc, const RECT* lpcrect, COLORREF color_s, COLORREF color_e, BYTE alpha_s, BYTE alpha_e, DWORD fillType)
{
    LONG bmWidth = lpcrect->right - lpcrect->left;
    LONG bmHeight = lpcrect->bottom - lpcrect->top;
    SIZE_T byteCount = bmWidth * bmHeight;
    BITMAPINFO bmi;
    void* pvBits1, *pvBits2;
 
    ZeroMemory(&bmi, 0);
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = bmWidth;
    bmi.bmiHeader.biHeight = bmHeight;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = byteCount * 4;
 
    //контекст в памяти
    HDC memDC1 = CreateCompatibleDC(hdc);
 
    HBITMAP memBM1 = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits1, NULL, 0x0);
 
    BYTE red_s = (BYTE)(color_s);
    BYTE red_e = (BYTE)(color_e);
    BYTE green_s = (BYTE)(color_s >> 8);
    BYTE green_e = (BYTE)(color_e >> 8);
    BYTE blue_s = (BYTE)(color_s >> 16);
    BYTE blue_e = (BYTE)(color_e >> 16);
 
    if (!fillType) {    //GRADIENT_FILL_RECT_H
        FLOAT alpha_step = ((FLOAT)alpha_e - (FLOAT)alpha_s) / (FLOAT)bmWidth;
        FLOAT red_step = ((FLOAT)red_e -(FLOAT)red_s) / (FLOAT)bmWidth;
        FLOAT green_step = ((FLOAT)green_e - (FLOAT)green_s) / (FLOAT)bmWidth;
        FLOAT blue_step = ((FLOAT)blue_e - (FLOAT)blue_s) / (FLOAT)bmWidth;
        for (UINT i = 0; i < bmWidth; ++i) {
            BYTE alpha = alpha_s + (BYTE)(alpha_step * (FLOAT)i);
            BYTE red = alpha * ((FLOAT)red_s + (red_step * (FLOAT)i)) / 255.0;
            BYTE green = alpha * ((FLOAT)green_s + (green_step * (FLOAT)i)) / 255.0;
            BYTE blue = alpha * ((FLOAT)blue_s + (blue_step * (FLOAT)i)) / 255.0;
            for (UINT j = 0; j < bmHeight; ++j)
                ((UINT32*)pvBits1)[i + j * bmWidth] = (UINT32)alpha << 24 | RGB(red, green, blue);
        }
    }
    else if (fillType & GRADIENT_FILL_RECT_V) {
        FLOAT alpha_step = ((FLOAT)alpha_e - (FLOAT)alpha_s) / (FLOAT)bmHeight;
        FLOAT red_step = ((FLOAT)red_e - (FLOAT)red_s) / (FLOAT)bmHeight;
        FLOAT green_step = ((FLOAT)green_e - (FLOAT)green_s) / (FLOAT)bmHeight;
        FLOAT blue_step = ((FLOAT)blue_e - (FLOAT)blue_s) / (FLOAT)bmHeight;
        for (UINT i = 0; i < bmHeight; ++i) {
            BYTE alpha = alpha_s + (BYTE)(alpha_step * (FLOAT)i);
            BYTE red = alpha * ((FLOAT)red_s + (red_step * (FLOAT)i)) / 255.0;
            BYTE green = alpha * ((FLOAT)green_s + (green_step * (FLOAT)i)) / 255.0;
            BYTE blue = alpha * ((FLOAT)blue_s + (blue_step * (FLOAT)i)) / 255.0;
            for (UINT j = 0; j < bmWidth; ++j)
                ((UINT32*)pvBits1)[j + i * bmWidth] = (UINT32)alpha << 24 | (UINT32)red << 16 | (UINT32)green << 8 | (UINT32)blue;
        }
    }
    
    HGDIOBJ old1 = SelectObject(memDC1, memBM1);
    BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 0xFF;
    bf.AlphaFormat = AC_SRC_ALPHA;
    BOOL res = AlphaBlend(
        hdc,
        lpcrect->left,
        lpcrect->top,
        bmWidth,
        bmHeight,
        memDC1,
        0,
        0,
        bmWidth,
        bmHeight,
        bf);
 
    SelectObject(memDC1, old1);
    DeleteDC(memDC1);
    DeleteObject(memBM1);
}

Если есть какие предложения по алгоритму заполнения DIB секции градиентом, буду очень рад.
Как лучше заполнять DIB радиальным градиентом?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.11.2015, 20:21
Помогаю со студенческими работами здесь

Как отрезать полупрозрачные рамки?
Доброго времени суток У меня имеется некоторый графический файл он имеет не ровные границ я хотел бы его сохранить именно по контуру а не...

Полупрозрачные тени от окон - возможно ли?
Подскажите, как создать полупрозрачные тени с плавными переходами (как в XP на менюшках) только не предлагайте SPI_SETDROPSHADOW - т.к. все...

Какие-то сероватые полупрозрачные квадратики на мониторе
я не знаю что, либо моник либо видюха, но как бы я не пытался поменять драва и ось ни чего не получаеться, выступают полупрозрачные...

Стали полупрозрачные буквы в текстах в Opera
как вернуть первоначальный вид буквам на сайтах в опере? буквы стали как прострелянные, т.е. плохо читаемые. В других браузерах с буквами...

Полупрозрачные цилиндры из шестиугольников вложенные друг в друга.
Доброго дня, читатель, освещаю свою проблему: столкнулся с необходимостью создать 3D модель многостенной углеродной нанотрубки, которая...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru