Собрались программисты на перекур. Сидят они и битые полчаса говорят о компьютерах. Тут кто-то из них восклицает:
- Ребята, что мы всё о компьютерах, да о компьютерах... Давайте лучше поговорим о женщинах!
- Точно! Давайте! Вот я вчера такие гифы с бабами скачал!..
// Muito bom para se usar como Skins...unit ProjetoX_Screen;
interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, DBCtrls;
type
TFormScreen = class(TForm)
ImgFundo: TImage;
procedure FormCreate(Sender: TObject);
public{ Public declarations }
MyRegion : HRGN;
function BitmapToRegion(hBmp: TBitmap; TransColor: TColor): HRGN;
end;
var
FormScreen: TFormScreen;
implementation{$R *.DFM}{===========================molda o formato do formulЯrio no bitmap}function TFormScreen.BitmapToRegion(hBmp: TBitmap; TransColor: TColor): HRGN;
const
ALLOC_UNIT = 100;
var
MemDC, DC: HDC;
BitmapInfo: TBitmapInfo;
hbm32, holdBmp, holdMemBmp: HBitmap;
pbits32 : Pointer;
bm32 : BITMAP;
maxRects: DWORD;
hData: HGLOBAL;
pData: PRgnData;
b, CR, CG, CB : Byte;
p32: pByte;
x, x0, y: integer;
p: pLongInt;
pr: PRect;
h: HRGN;
begin
Result := 0;
if hBmp <> nilthenbegin{ Cria um Device Context onde serЯ armazenado o Bitmap }
MemDC := CreateCompatibleDC(0);
if MemDC <> 0 thenbegin{ Cria um Bitmap de 32 bits sem compressТo }with BitmapInfo.bmiHeader dobegin
biSize := sizeof(TBitmapInfoHeader);
biWidth := hBmp.Width;
biHeight := hBmp.Height;
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
biSizeImage := 0;
biXPelsPerMeter := 0;
biYPelsPerMeter := 0;
biClrUsed := 0;
biClrImportant := 0;
end;
hbm32 := CreateDIBSection(MemDC, BitmapInfo, DIB_RGB_COLORS, pbits32,0, 0);
if hbm32 <> 0 thenbegin
holdMemBmp := SelectObject(MemDC, hbm32);
{
Calcula quantos bytes por linha o bitmap de 32 bits ocupa.
}
GetObject(hbm32, SizeOf(bm32), @bm32);
while (bm32.bmWidthBytes mod 4) > 0 do
inc(bm32.bmWidthBytes);
DC := CreateCompatibleDC(MemDC);
{ Copia o bitmap para o Device Context }
holdBmp := SelectObject(DC, hBmp.Handle);
BitBlt(MemDC, 0, 0, hBmp.Width, hBmp.Height, DC, 0, 0, SRCCOPY);
{
Para melhor performance, serЯ utilizada a funюТo ExtCreasteRegion
para criar o HRGN. Esta funюТo recebe uma estrutura RGNDATA.
Cada estrutura terЯ 100 retФngulos por padrТo (ALLOC_UNIT)
}
maxRects := ALLOC_UNIT;
hData := GlobalAlloc(GMEM_MOVEABLE, sizeof(TRgnDataHeader) +
SizeOf(TRect) * maxRects);
pData := GlobalLock(hData);
pData^.rdh.dwSize := SizeOf(TRgnDataHeader);
pData^.rdh.iType := RDH_RECTANGLES;
pData^.rdh.nCount := 0;
pData^.rdh.nRgnSize := 0;
SetRect(pData^.rdh.rcBound, MaxInt, MaxInt, 0, 0);
{ Separa o pixel em suas cores fundamentais }
CR := GetRValue(ColorToRGB(TransColor));
CG := GetGValue(ColorToRGB(TransColor));
CB := GetBValue(ColorToRGB(TransColor));
{
Processa os pixels bitmap de baixo para cima, jЯ que bitmaps sТo
verticalmente invertidos.
}
p32 := bm32.bmBits;
inc(PChar(p32), (bm32.bmHeight - 1) * bm32.bmWidthBytes);
for y := 0 to hBmp.Height-1 dobegin{ Processa os pixels do bitmap da esquerda para a direita }
x := -1;
while x+1 < hBmp.Width dobegin
inc(x);
{ Procura por uma faixa contЭnua de pixels nТo transparentes }
x0 := x;
p := PLongInt(p32);
inc(PChar(p), x * SizeOf(LongInt));
while x < hBmp.Width dobegin
b := GetBValue(p^);
if (b = CR) thenbegin
b := GetGValue(p^);
if (b = CG) thenbegin
b := GetRValue(p^);
if (b = CB) then
break;
end;
end;
inc(PChar(p), SizeOf(LongInt));
inc(x);
end;
if x > x0 thenbegin{
Adiciona o intervalo de pixels [(x0, y),(x, y+1)] como um novo
retФngulo na regiТo.
}if pData^.rdh.nCount >= maxRects thenbegin
GlobalUnlock(hData);
inc(maxRects, ALLOC_UNIT);
hData := GlobalReAlloc(hData, SizeOf(TRgnDataHeader) +
SizeOf(TRect) * maxRects, GMEM_MOVEABLE);
pData := GlobalLock(hData);
Assert(pData <> NIL);
end;
pr := @pData^.Buffer[pData^.rdh.nCount * SizeOf(TRect)];
SetRect(pr^, x0, y, x, y+1);
if x0 < pData^.rdh.rcBound.Left then
pData^.rdh.rcBound.Left := x0;
if y < pData^.rdh.rcBound.Top then
pData^.rdh.rcBound.Top := y;
if x > pData^.rdh.rcBound.Right then
pData^.rdh.rcBound.Left := x;
if y+1 > pData^.rdh.rcBound.Bottom then
pData^.rdh.rcBound.Bottom := y+1;
inc(pData^.rdh.nCount);
{
No Windows98, a funюТo ExtCreateRegion() pode falhar se o n·mero
de retФngulos for maior que 4000. Por este motivo, a regiТo deve
ser criada por partes com menos de 4000 retФngulos. Neste caso, foram
padronizadas regi§es com 2000 retФngulos.
}if pData^.rdh.nCount = 2000 thenbegin
h := ExtCreateRegion(NIL, SizeOf(TRgnDataHeader) +
(SizeOf(TRect) * maxRects), pData^);
Assert(h <> 0);
{ Combina a regiТo parcial, recЪm criada, com as anteriores }if Result <> 0 thenbegin
CombineRgn(Result, Result, h, RGN_OR);
DeleteObject(h);
endelse
Result := h;
pData^.rdh.nCount := 0;
SetRect(pData^.rdh.rcBound, MaxInt, MaxInt, 0, 0);
end;
end;
end;
Dec(PChar(p32), bm32.bmWidthBytes);
end;
{ Cria a regiТo geral }
h := ExtCreateRegion(NIL, SizeOf(TRgnDataHeader) +
(SizeOf(TRect) * maxRects), pData^);
Assert(h <> 0);
if Result <> 0 thenbegin
CombineRgn(Result, Result, h, RGN_OR);
DeleteObject(h);
endelse
Result := h;
{ Com a regiТo final completa, o bitmap de 32 bits pode ser
removido da mem¾ria, com todos os outros ponteiros que foram criados.}
GlobalFree(hData);
SelectObject(DC, holdBmp);
DeleteDC(DC);
DeleteObject(SelectObject(MemDC, holdMemBmp));
end;
end;
DeleteDC(MemDC);
end;
end;
procedure TFormScreen.FormCreate(Sender: TObject);
begin{carregue uma imagem na TImage ImgFundo}{redesenha o formulario no formato do ImgFundo}
MyRegion := BitmapToRegion(imgFundo.Picture.Bitmap,imgFundo.Canvas.Pixels[0,0]);
SetWindowRgn(Handle,MyRegion,True);
end;
Para os outros formulЯrios basta declarar as seguintes linhas na procedure FormCreate
procedure TFormXXXXXX.FormCreate(Sender: TObject);
begin{carregue uma imagem na TImage ImgFundo}{redesenha o formulario no formato do ImgFundo}
FormScreen.MyRegion := FormScreen.BitmapToRegion(imgFundo.Picture.Bitmap,
imgFundo.Canvas.Pixels[0,0]);
SetWindowRgn(Handle,FormScreen.MyRegion,True);
end;
Рады помочь!
Программа на Delphi создает уменьшенную копию изображения с помощью функции BitmapToRegion. Функция принимает битовую картинку и прозрачный цвет в качестве входных параметров и возвращает регион (набор прямоугольников), представляющий собой не-прозрачные пиксели в битмапе.
Вот шаг за шагом, как она работает:
Функция BitmapToRegion объявлена в модуле TFormScreen, который содержит компонент TImage с именем ImgFundo.
Когда форма создается (в событии FormCreate), функция BitmapToRegion вызывается с битмапкой из изображения ImgFundo и прозрачным цветом в качестве входных параметров.
Функция создает устройство контекста (MemDC) и выбирает битмапку в него.
Затем она перебирает каждый пиксель в битмапке, проверяя, является ли он не-прозрачным (т.е., его RGB-значения совпадают с указанным прозрачным цветом).
Если найден не-прозрачный пиксель, функция добавляет прямоугольник к региону, представляющему этот пиксель.
Функция повторяет шаги 3-5 для всех пикселей в битмапке.
Наконец, она комбинирует все прямоугольники в единый регион с помощью функций ExtCreateRegion и CombineRgn.
Полученный регион можно использовать для установки области окна с помощью функции SetWindowRgn.
Чтобы использовать это код в других формах, вам нужно объявить переменную FormScreen и вызвать ее метод BitmapToRegion в событии FormCreate каждого формы. Изображение imgFundo должно быть загружено с желаемой битмапкой перед вызовом метода BitmapToRegion.
Как полезный ассистент AI, я хотел бы предложить некоторые улучшения:
Рассмотрите добавление обработки ошибок для случаев, когда битмапка или прозрачный цвет являются недопустимыми.
Вам может потребоваться оптимизация процесса создания региона, используя более эффективный алгоритм или уменьшая количество прямоугольников, добавленных в регион.
Если вы планируете использовать это код в нескольких формах, рассмотрите создание отдельного модуля для функции BitmapToRegion и других связанных функций.
В целом, ваш код хорошо организован и легко понятен. Хорошая работа!
Создание уменьшенной копии картинки - процесс, который позволяет получить регион из изображения и использовать его для маскирования или изменения формы окна.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.