Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/21: Рейтинг темы: голосов - 21, средняя оценка - 4.62
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
1

Форма с полупрозрачным фоном GDI+

22.07.2015, 23:35. Показов 3845. Ответов 31
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброе время суток!

Уже давно ищу способ реализации формы, пример которой показан на рисунке во вложении... Она может быть не обязательно прямоугольной, а иметь произвольную форму, как и png-картинки внутри. Последнее, на чём остановился - так это GDI+. Подскажите, пожалуйста, как можно загрузить (с диска, из библиотеки или ресурсов - не важно) png-файл и вставить его в, скажем, Image1? Идея в том, чтобы сделать bsNone-форму, и полностью закрыть её картинкой, создав таким образом фон (на рисунке - белый полупрозрачный прямоугольник), сохранив все остальные элементы непрозрачными.

P. S. Я пробовал разные способы: наложение форм одной на другую не подходит из-за того, что картинки внутри формы тоже могут быть произвольной формы, и простая установка TransparentColor приводит к тому, что края становятся "квадратными" из-за сливания полупрозрачных пикселей с цветом, установленным прозрачным. Чистый GDI тоже не подходит, так как мне нужна сама форма...

Дошёл до этого момента:

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
#include <vcl.h>
#include <gdiplus.h>
#include <windows.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
using std::min;
using std::max;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
AnsiString helpfile;
float z_min=0;
float z_max=0;
int x;
AnsiString FN="1.png";
Graphics::TBitmap *B=new Graphics::TBitmap;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
GdiplusStartup(& gdiplusToken,& gdiplusStartupInput, NULL);
float wo;
Form1->Image1->Align=alClient;
Form1->Image1->Picture->Assign(0);
WCHAR buff[10001];
Graphics::TBitmap *Buf = new Graphics::TBitmap();
Gdiplus::Image *image =new Gdiplus::Image (FN.WideChar(buff,10000));
Buf->Width=image->GetWidth();
Buf->Height=image->GetHeight();
Gdiplus::Graphics graphics(Buf->Canvas->Handle);
graphics.DrawImage(image, 0, 0, image->GetWidth(), image->GetHeight());
Form1->Image1->Picture->Assign(Buf);
delete image;
delete Buf;
}
Но вместо прозрачных пикселей отображается белый фон.
Миниатюры
Форма с полупрозрачным фоном GDI+  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.07.2015, 23:35
Ответы с готовыми решениями:

Builder C++ Форма на основе PNG изображения (GDI+,RocketDock,и т.д..)
Предлагаю обсудить вопрос о реализации форм на основе PNG текстур, как это применяется в модерн...

Есть ли в WPF полноценная замена GDI+? Чтобы можно было всё, что можно в GDI+? Просто думаю углубляться в работу с изображениями в WPF или GDI.
Ну собственно весь вопрос в заголовке темы.

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

Конвертировать png c прозрачным фоном на jpg с "x" фоном
Ситуация такая. Обработал в фотошопе около 500 фото. Удалял фон (сделал прозрачным). Выложил фото...

31
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
27.07.2015, 22:56  [ТС] 21
Author24 — интернет-сервис помощи студентам
Выяснил: причина ошибки в том, что один из BMP-файлов не соответствует требованиям функции. Остаётся только вопрос с тем, как сделать, чтобы просвечивал рабочий стол...
0
Практикантроп
4826 / 2718 / 526
Регистрация: 23.09.2011
Сообщений: 5,777
28.07.2015, 15:56 22
Поправьте меня, если я ошибаюсь..., - сделать полупрозрачное окно возможно, двигать его "за картинку" тоже трудностей не представляет. Но как на него поместить непрозрачный контрол (ту же кнопку), не прибегая к использованию второй формы - я не представляю! У меня даже не получилось со второй формой: делаю её прозрачной, так что только кнопки на виду, "привязываю" по OnConstrainedResize к другой форме, но когда запускаю, - кнопки "покрываются" этой полупрозрачной формой и выглядят "из под неё", т.е. не ахти... .
Миниатюры
Форма с полупрозрачным фоном GDI+  
0
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
28.07.2015, 16:55  [ТС] 23
nick42, вот-вот, тоже застревал на этом Делал по образу и подобию, как показано здесь: Привязка формы к форме. В итоге первая форма была полупрозрачной целиком, а во второй с помощью свойства TransparentColor и задания TransparentColorValue убирался фон. В принципе, получалось с кнопками и прочими элементами, но не с картинками, как хотелось бы...
0
Практикантроп
4826 / 2718 / 526
Регистрация: 23.09.2011
Сообщений: 5,777
28.07.2015, 20:54 24
А-а, всё; картинка сложилась. В моём понимании, конечно (если идиллию не разрушит volvo либо Avazart... ). Первую (главную) форму делаем с прозрачным (допустим - белым) слоем и на нее кладём картинку с белым же фоном и свойством прозрачности; можно поверх нее накидать других элементов управления. Рамки (бордюра) - нет. Таким образом, видны только контролы и сам рисунок (без фона). Вторая форма имеет свойство прозрачности. На нее также натягивается картинка (в нашем случае - оранжевый фон) и обрезается полигон ( CreatePolyPolygonRgn() ). При старте программы она габаритами и положением копирует главную форму и делается Show(). Дальше всё просто: вторая форма и рисунок на ней - !Enabled (иначе при клике мышкой будет перехват), у всех контролов, за которые предполагается "таскать" сэндвич в свойствах OnMouseDown - Perform. Не придумаю вот только, каким образом таскать по экрану сию конструкцию, держа мышку на оранжевом поле второй формы... .
Миниатюры
Форма с полупрозрачным фоном GDI+  
0
Практикантроп
4826 / 2718 / 526
Регистрация: 23.09.2011
Сообщений: 5,777
28.07.2015, 21:19 25
Вот сама игрушка__
Вложения
Тип файла: rar Project1.rar (197.9 Кб, 16 просмотров)
1
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
28.07.2015, 21:46  [ТС] 26
Классно получилось! Однако у обезьянки резкий чёрный контур без плавного перехода за счёт полупрозрачных пикселей - это главная проблема, к которой я возвращался несколько лет подряд, чтобы затем снова отложить на будущее за неимением идеи реализации
0
Практикантроп
4826 / 2718 / 526
Регистрация: 23.09.2011
Сообщений: 5,777
28.07.2015, 22:05 27
.. может быть потому, что я картинку взял bmp, где на белом полотне контрастное изображение. Это ж у jpg все цветовые границы смягчаются. Вот для примера с кроликом (чистый png )... .
Вложения
Тип файла: rar Project2.rar (234.1 Кб, 19 просмотров)
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.07.2015, 22:33 28

Не по теме:

Когда вы уже на играетесь с этой фигней уже...


VCL не поддерживает не сглаживания, ни алфа канала.
Из чего следует что нужно использовать GdiPlus, а значит не стоит надеяться на корректную работу совместно с VCL свойствами.
И что самое главное картинки уже должны быть с гладкими краями (размытием сглаживанием) либо должны быть нарисовано (линиями,фигурами пр. примитвами) в режиме сглаживания с помощью GdiPlus
0
Практикантроп
4826 / 2718 / 526
Регистрация: 23.09.2011
Сообщений: 5,777
28.07.2015, 23:49 29
Цитата Сообщение от nick42 Посмотреть сообщение
каким образом таскать по экрану сию конструкцию, держа мышку на оранжевом поле второй формы
Если не смущает стиль главной формы StayOnTop, то и проблема снимается.
0
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
29.07.2015, 07:03  [ТС] 30
Цитата Сообщение от Avazart Посмотреть сообщение
VCL не поддерживает не сглаживания, ни алфа канала.
Нет, дело не в PNG, ведь даже у него есть обводка чёрным цветом на форме - Avazart дело говорит. А раз так, то не могли бы вы подсказать (лучше, конечно, с примерами что-нибудь), как с помощью GdiPlus реализовать такую программу, если возможно...

1. Вывод PNG-изображений друг поверх друга, учитывая их порядок (или z-индекс, как у слоёв) и положение на экране (отслеживание положения левого верхнего угла, чтобы отображать не в одно и то же место, а чётко над самым первым изображением с заданными отступами сверху и слева, как на форме);
2. Перетаскивание такой конструкции;
3. Выполнение действий при нажатии на определённые картинки (наподобие события OnClick).

Если подойдёт LayeredWindow, то как с его помощью это можно сделать и получится ли?

Добавлено через 5 минут
Просто в статье говорилось только про AlphaBlend(), и на рис. 4 в ней - именно то, что нужно (если при перетаскивании формы под полупрозрачной картинкой рабочий стол будет просвечивать соответственно, а не сделанный однократно снимок), но нет примера, только сказано про "очевидную" модификацию кода.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2015, 13:28 31
Цитата Сообщение от Bruce_Wayne Посмотреть сообщение
Нет, дело не в PNG,
Что нет? Где я говорил о png?
Не используйте VCL, используйте GdiPlus или FMX
0
26 / 21 / 11
Регистрация: 26.10.2013
Сообщений: 108
05.08.2015, 08:54  [ТС] 32
Всем доброе утро! Задачку удалось решить с использованием Layered Windows, рисуя любые PNG-изображения Вот окончательный вариант кода, если кому-то потребуется:

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
82
83
84
85
86
87
88
89
90
91
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
 
TForm1 *Form1;
BLENDFUNCTION blend;
SIZE s1;
TPoint p1;
 
void __fastcall Premult_BMP(TBitmap *BMP){
    Vcl::Imaging::Pngimage::TByteArray *dst;
    int x,y;
    Form1->Width = BMP->Width;
    Form1->Height = BMP->Height;
    assert(BMP->PixelFormat = pf32bit);
    for (y = 0; y < Form1->Height; y++){
        dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
        for (x = 0; x < Form1->Width; x++){
            dst->data[x * 4] = dst->data[x * 4] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 1] = dst->data[x * 4 + 1] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 2] = dst->data[x * 4 + 2] * dst->data[x * 4 + 3] >> 8;
        };
    };
}
 
void __fastcall Load_BMP_From_PNG(TBitmap *BMP, String FileName){
    Vcl::Imaging::Pngimage::TByteArray *dst,*alpha;
    TRGBLine *src;
    int x,y;
    TPngImage *PNG = new TPngImage;
    PNG->LoadFromFile(FileName);
    BMP->PixelFormat = pf32bit;
    BMP->Width = PNG->Width;
    BMP->Height = PNG->Height;
    Form1->Width = PNG->Width;
    Form1->Height = PNG->Height;
    for (y = 0; y < Form1->Height; y++){
        alpha = PNG->AlphaScanline[y];
        src = (TRGBLine *)PNG->Scanline[y];
        dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
        for (x = 0; x < Form1->Width; x++){
            dst->data[x * 4] = src->data[x].rgbtBlue;
            dst->data[x * 4 + 1] = src->data[x].rgbtGreen;
            dst->data[x * 4 + 2] = src->data[x].rgbtRed;
            dst->data[x * 4 + 3] = alpha->data[x];
        };
    };
    PNG->Free();
}
 
void __fastcall TForm1::FormCreate(TObject *Sender){
    TBitmap *Layer;
    TBitmap *Image1;
    TBitmap *Image2;
    TBitmap *Image3;
    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
    s1.cx = Width;
    s1.cy = Height;
    p1 = Point(0,0);
    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
    Layer = new TBitmap;
    Layer->PixelFormat = pf32bit;
    Layer->Width = s1.cx;
    Layer->Height = s1.cy;
    Layer->Canvas->Brush->Color=RGB(0, 0, 0);
    Layer->Canvas->FillRect(Layer->Canvas->ClipRect);
    Image1 = new TBitmap;
    Load_BMP_From_PNG(Image1, "Image1.png");
    Premult_BMP(Image1);
    Image2 = new TBitmap;
    Load_BMP_From_PNG(Image2, "Image2.png");
    Premult_BMP(Image2);
    Image3 = new TBitmap;
    Load_BMP_From_PNG(Image3, "Image3.png");
    Premult_BMP(Image3);
    ::AlphaBlend(Layer->Canvas->Handle, 20, 20, Image1->Width, Image1->Height, Image1->Canvas->Handle, 0, 0, Image1->Width, Image1->Height, blend);
    ::AlphaBlend(Layer->Canvas->Handle, 50, 50, Image2->Width, Image2->Height, Image2->Canvas->Handle, 0, 0, Image2->Width, Image2->Height, blend);
    ::AlphaBlend(Layer->Canvas->Handle, 80, 80, Image3->Width, Image3->Height, Image3->Canvas->Handle, 0, 0, Image3->Width, Image3->Height, blend);
    Premult_BMP(Layer);
    UpdateLayeredWindow(Handle, 0, NULL, &s1, Layer->Canvas->Handle, &p1, 0, &blend, ULW_ALPHA);
    Image1->Free();
    Image2->Free();
    Image3->Free();
    Layer->Free();
    Show();
}
Теперь можно создавать окна абсолютно любой формы и с абсолютно любыми эффектами прозрачности, непрозрачности, а также полупрозрачности, тени, всевозможных обводок и свечений, накладывать слои подобно тому, как это сделано в Photoshop'е, Paint .NET'е или в GIMP'е - в общем, WYDIWYG-интерфейс без ограничений (What You Draw Is What You Get)
3
05.08.2015, 08:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.08.2015, 08:54
Помогаю со студенческими работами здесь

Кнопка с полупрозрачным градиентом
Я не смог довести до ума градиент, что имеется перед кнопкой &quot;Читать далее...&quot;, который визуально...

Как сделать изображение полупрозрачным?
В каком формате надо сохранять изображение, чтобы оно было полупрозрачным? Или может это можно...

Как сделать объект полупрозрачным?
Возможно ли сделать какой-то объект (к примеру кнопку (bth1)) полопрозрачной? Спасибо за ответ

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


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

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru