Мужики, а как сделать форму со скругленными углами ?
Спасибо
Posted via RSDN NNTP Server 2.0
Re: форма со скругленными углами
От:
Аноним
Дата:
19.02.06 05:27
Оценка:
Hi.
Элементарно, Ватсон...
var
tmpReg: HRGN;
begin
tmpRgn := CreateRoundRectRgn(X, Y, X1, Y1, XA, YA);
SetWindowsRgn(Self.Handle, tmpRgn);
end;
где X, Y, X1, Y1 — сам прямоугольник формы (отсчет от левого верхнего угла формы)
XA, YA — размер эллипса закругления углов по горизонтали и вретикали соответственно.
Эксперементируй. И пробуй также:
> var > tmpReg: HRGN; > begin > tmpRgn := CreateRoundRectRgn(X, Y, X1, Y1, XA, YA); > SetWindowsRgn(Self.Handle, tmpRgn); > end; > > где X, Y, X1, Y1 — сам прямоугольник формы (отсчет от левого верхнего угла > формы) > XA, YA — размер эллипса закругления углов по горизонтали и вретикали > соответственно. > Эксперементируй.
Пасиб
Что делать ? — Cмотрится отвратительно, но заказчик хочет, чтобы углы были
скругленные ;(
Hello CR-LF, you wrote:
> Что делать ? — Cмотрится отвратительно, но заказчик хочет, чтобы углы были > скругленные ;(
Вам ненравятся лесенка? Тогда нужно смотреть в сторону layered windows — с их помощью можно сделать гладкие края. Для примера можно посмотреть Winamp 5.
Hello CR-LF, you wrote:
> Что делать ? — Cмотрится отвратительно, но заказчик хочет, чтобы углы были > скругленные ;(
Вам ненравятся лесенка? Тогда нужно смотреть в сторону layered windows — с их помощью можно сделать гладкие края. Для примера можно посмотреть Winamp 5.
Hello CR-LF, you wrote:
> Что делать ? — Cмотрится отвратительно, но заказчик хочет, чтобы углы были > скругленные ;(
Тут ко мне на аську кто-то стучался, но из-за того что у него старая, видимо миранда, он моих ответов не видит. Поэтому продуюлирую свою ответ сюда:
"Появились в Вин2000. См. msdn.
Поддреживают альфаканал — поэтому с окном можно делать что тебе вздумается.
Подробности в МСДН. Я не имею привычки использовать аську для советов. Есть вопросы — спрашивай в RSDN."
> Тут ко мне на аську кто-то стучался, но из-за того что у него старая, > видимо миранда, он моих ответов не >видит. Поэтому продуюлирую свою ответ сюда: > "Появились в Вин2000. См. msdn. > Поддреживают альфаканал — поэтому с окном можно делать что тебе > вздумается. > Подробности в МСДН.
Я и стучался, раз уж ты указываешь свой номер.
У меня нету msdn.
Можешь прислать инфу про это ?
Что такое альфаканал ?
Hello bayonet1971, you wrote:
>> Тут ко мне на аську кто-то стучался, но из-за того что у него старая, >> видимо миранда, он моих ответов не >> видит. Поэтому продуюлирую свою ответ сюда: >> "Появились в Вин2000. См. msdn. >> Поддреживают альфаканал — поэтому с окном можно делать что тебе >> вздумается. >> Подробности в МСДН.
> Я и стучался, раз уж ты указываешь свой номер.
Это не значит, что я собираюсь выступать в роли справочного бюро отвечая по ней на вопросы по программированию. Для этого я использую группы новостей и форумы. Т.к. туда я захожу и отвечаю когда мне удобно и когда мне хочется.
> У меня нету msdn. > Можешь прислать инфу про это?
Здравствуйте, bayonet1971, Вы писали:
B>Мужики, а как сделать форму со скругленными углами ? B>Спасибо
Можно. Делаешь битмапку со скругленными углами, цвет, который должен быть прозрачным, выбираешь таким, чтобы его не было больше нигде на рисунке, загружаешь рисунок в TImage, вызываешь функцию
HRGN __fastcall BitmapToRegion (HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance)
{
HRGN hRgn = NULL;
if (hBmp)
{
// Create a memory DC inside which we will scan the bitmap content
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC)
{
// Get bitmap size
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
// Create a 32 bits depth bitmap and select it into the memory DC
BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
sizeof(BITMAPINFOHEADER), // biSize
bm.bmWidth, // biWidth;
bm.bmHeight, // biHeight;
1, // biPlanes;
32, // biBitCount
BI_RGB, // biCompression;
0, // biSizeImage;
0, // biXPelsPerMeter;
0, // biYPelsPerMeter;
0, // biClrUsed;
0 // biClrImportant;
};
VOID * pbits32;
HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
if (hbm32)
{
HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
// Create a DC just to copy the bitmap into the memory DC
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
// Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
BITMAP bm32;
GetObject(hbm32, sizeof(bm32), &bm32);
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
// Copy the bitmap into the memory DC
HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
// For better performances, we will use the ExtCreateRegion() function to create the
// region. This function take a RGNDATA structure on entry. We will add rectangles by
// amount of ALLOC_UNIT number in this structure.#define ALLOC_UNIT 100
DWORD maxRects = ALLOC_UNIT;
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
pData->rdh.iType = RDH_RECTANGLES;
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
// Keep on hand highest and lowest values for the "transparent" pixels
BYTE lr = GetRValue(cTransparentColor);
BYTE lg = GetGValue(cTransparentColor);
BYTE lb = GetBValue(cTransparentColor);
BYTE hr = min(0xff, lr + GetRValue(cTolerance));
BYTE hg = min(0xff, lg + GetGValue(cTolerance));
BYTE hb = min(0xff, lb + GetBValue(cTolerance));
// Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
for (int y = 0; y < bm.bmHeight; y++)
{
// Scan each bitmap pixel from left to rightfor (int x = 0; x < bm.bmWidth; x++)
{
// Search for a continuous range of "non transparent pixels"int x0 = x;
LONG *p = (LONG *)p32 + x;
while (x < bm.bmWidth)
{
BYTE b = GetRValue(*p);
if (b >= lr && b <= hr)
{
b = GetGValue(*p);
if (b >= lg && b <= hg)
{
b = GetBValue(*p);
if (b >= lb && b <= hb)
// This pixel is "transparent"break;
}
}
p++;
x++;
}
if (x > x0)
{
// Add the pixels (x0, y) to (x, y+1) as a new rectangle in the regionif (pData->rdh.nCount >= maxRects)
{
GlobalUnlock(hData);
maxRects += ALLOC_UNIT;
hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
pData = (RGNDATA *)GlobalLock(hData);
}
RECT *pr = (RECT *)&pData->Buffer;
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
if (x0 < pData->rdh.rcBound.left)
pData->rdh.rcBound.left = x0;
if (y < pData->rdh.rcBound.top)
pData->rdh.rcBound.top = y;
if (x > pData->rdh.rcBound.right)
pData->rdh.rcBound.right = x;
if (y+1 > pData->rdh.rcBound.bottom)
pData->rdh.rcBound.bottom = y+1;
pData->rdh.nCount++;
// On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
// large (ie: > 4000). Therefore, we have to create the region by multiple steps.if (pData->rdh.nCount == 2000)
{
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
pData->rdh.nCount = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
}
}
}
// Go to next row (remember, the bitmap is inverted vertically)
p32 -= bm32.bmWidthBytes;
}
// Create or extend the region with the remaining rectangles
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
// Clean up
GlobalFree(hData);
SelectObject(hDC, holdBmp);
DeleteDC(hDC);
}
DeleteObject(SelectObject(hMemDC, holdBmp));
}
DeleteDC(hMemDC);
}
}
return hRgn;
}
//---------------------------------------------------------------------------
>Можно. Делаешь битмапку со скругленными углами, цвет, который должен быть >прозрачным, выбираешь >таким, чтобы его не было больше нигде на рисунке, загружаешь рисунок в >TImage, вызываешь функцию
"bayonet1971" <49237@users.rsdn.ru> wrote in message news:1687945@news.rsdn.ru... > Действительно, все гениальное просто > А на Паскале у тебя нет такой функции ?
B>Правда есть большой минус — из-за этой bmp-шки серъезно растет размер B>иполняемого файла
>Сохраняйте в PNG, как вариант. Для загрузки из PNG есть IImgCtx, который >идет начиная с IE 4.0.
Че за IImgCtx такой и какая связь с IE 4.0 ?
Здравствуйте, bayonet1971, Вы писали:
B>Действительно, все гениальное просто
Ничего себе просто! Если требуется не произвольная форма, а просто прямоугольник со скругленными краями, то CreateRoundRectRgn куда лучше. Все равно создание региона на основе битмапа не решает проблемы зазубренных краев.
B>А на Паскале у тебя нет такой функции ?
Я себе сделал порт, бери если надо:
function BitmapToRegion(hBmp: HBITMAP; cTransparentColor, cTolerance: COLORREF): HRGN;
function Min(a, b: Byte): Byte;
begin
if a < b then
Result := a
else Result := b;
end;
const
ALLOC_UNIT = 100;
var
hMemDC, hMemDC2: HDC;
bm, bm32: Windows.TBitmap;
RGB32BITSBITMAPINFO: TBitmapInfo;
pbits32: Pointer;
hbm32, holdBmp, holdBmp2: HBITMAP;
maxRects: LongWord;
hData: THandle;
pData: PRgnData;
lr, lg, lb, hr, hg, hb, b: Byte;
p32: PByte;
x, y, x0: Integer;
p: PLongInt;
pr: PRect;
h: HRGN;
begin
Result := 0;
if hBmp <> 0 then begin// Create a memory DC inside which we will scan the bitmap content
hMemDC := CreateCompatibleDC(0);
if hMemDC <> 0 then begin// Get bitmap size
GetObject(hBmp, SizeOf(bm), @bm);
// Create a 32 bits depth bitmap and select it into the memory DC
FillChar(RGB32BITSBITMAPINFO.bmiHeader, SizeOf(RGB32BITSBITMAPINFO.bmiHeader), 0);
with RGB32BITSBITMAPINFO.bmiHeader do begin
biSize := SizeOf(TBitmapInfoHeader);
biWidth := bm.bmWidth;
biHeight := bm.bmHeight;
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
end;
hbm32 := CreateDIBSection(hMemDC, RGB32BITSBITMAPINFO, DIB_RGB_COLORS, pbits32, 0, 0);
if hbm32 <> 0 then begin
holdBmp := SelectObject(hMemDC, hbm32);
// Create a DC just to copy the bitmap into the memory DC
hMemDC2 := CreateCompatibleDC(hMemDC);
if hMemDC2 <> 0 then begin// Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
GetObject(hbm32, SizeOf(bm32), @bm32);
while bm32.bmWidthBytes mod 4 <> 0 do
Inc(bm32.bmWidthBytes);
// Copy the bitmap into the memory DC
holdBmp2 := SelectObject(hMemDC2, hBmp);
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC2, 0, 0, SRCCOPY);
// For better performances, we will use the ExtCreateRegion() function to create the
// region. This function take a RGNDATA structure on entry. We will add rectangles by
// amount of ALLOC_UNIT number in this structure.
maxRects := ALLOC_UNIT;
hData := GlobalAlloc(GMEM_MOVEABLE, SizeOf(TRgnDataHeader) + (SizeOf(TRect) * maxRects));
pData := GlobalLock(hData);
with pData^ do begin
rdh.dwSize := SizeOf(TRgnDataHeader);
rdh.iType := RDH_RECTANGLES;
rdh.nCount := Ord(rdh.nRgnSize = 0);
SetRect(rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
end;
// Keep on hand highest and lowest values for the "transparent" pixels
lr := GetRValue(cTransparentColor);
lg := GetGValue(cTransparentColor);
lb := GetBValue(cTransparentColor);
hr := Min($ff, lr + GetRValue(cTolerance));
hg := Min($ff, lg + GetGValue(cTolerance));
hb := Min($ff, lb + GetBValue(cTolerance));
// Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
p32 := PByte(Longint(bm32.bmBits) + (bm32.bmHeight - 1) * bm32.bmWidthBytes);
for y := 0 to bm.bmHeight - 1 do begin// Scan each bitmap pixel from left to right
x := 0;
while x < bm.bmWidth do begin// Search for a continuous range of "non transparent pixels"
x0 := x;
p := PLongint(Longint(p32) + x * SizeOf(Longint));
while x < bm.bmWidth do begin
b := GetRValue(p^);
if (b >= lr) and (b <= hr) then begin
b := GetGValue(p^);
if (b >= lg) and (b <= hg) then begin
b := GetBValue(p^);
if (b >= lb) and (b <= hb) then// This pixel is "transparent"
Break;
end;
end;
Inc(p);
Inc(x);
end;
if x > x0 then begin// Add the pixels (x0, y) to (x, y+1) as a new rectangle in the regionif pData^.rdh.nCount >= maxRects then begin
GlobalUnlock(hData);
Inc(maxRects, ALLOC_UNIT);
hData := GlobalReAlloc(hData, SizeOf(TRgnDataHeader) + (SizeOf(TRect) * maxRects), GMEM_MOVEABLE);
pData := PRgnData(GlobalLock(hData));
end;
pr := @(pData^.Buffer);
SetRect(PRect(Longint(pr) + pData^.rdh.nCount * SizeOf(TRect))^, 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.right := x;
if y + 1 > pData^.rdh.rcBound.bottom then
pData^.rdh.rcBound.bottom := y + 1;
Inc(pData^.rdh.nCount);
// On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
// large (ie: > 4000). Therefore, we have to create the region by multiple steps.if pData^.rdh.nCount = 2000 then begin
h := ExtCreateRegion(nil, SizeOf(TRgnDataHeader) + (SizeOf(TRect) * maxRects), pData^);
if Result <> 0 then begin
CombineRgn(Result, Result, h, RGN_OR);
DeleteObject(h);
end
else
Result := h;
pData^.rdh.nCount := 0;
SetRect(pData^.rdh.rcBound, High(Longint), High(Longint), 0, 0);
end;
end;
Inc(x);
end;
// Go to next row (remember, the bitmap is inverted vertically)
Dec(p32, bm32.bmWidthBytes);
end;
// Create or extend the region with the remaining rectangles
h := ExtCreateRegion(nil, SizeOf(TRgnDataHeader) + (SizeOf(TRect) * maxRects), pData^);
if Result <> 0 then begin
CombineRgn(Result, Result, h, RGN_OR);
DeleteObject(h);
end
else
Result := h;
// Clean up
GlobalFree(hData);
SelectObject(hMemDC2, holdBmp2);
DeleteDC(hMemDC2);
end;
DeleteObject(SelectObject(hMemDC, holdBmp));
end;
DeleteDC(hMemDC);
end;
end;
end;
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Здравствуйте, bayonet1971, Вы писали:
>>Сохраняйте в PNG, как вариант. Для загрузки из PNG есть IImgCtx, который >>идет начиная с IE 4.0. B>Че за IImgCtx такой и какая связь с IE 4.0 ?
>>Сохраняйте в PNG, как вариант. Для загрузки из PNG есть IImgCtx, который >>идет начиная с IE 4.0. B>Че за IImgCtx такой и какая связь с IE 4.0 ?
>В поиск трудно залезть? http://gzip.rsdn.ru/search/?q=IImgCtx&mode=rank
Ну посмотрел там у народа какие-то траблы с этим IImgCtx, а что же это за
зверь такой и где его взять я так и не понял.
Это че, компонент такой для Delphi ?
[]
B>Ну посмотрел там у народа какие-то траблы с этим IImgCtx, а что же это за B>зверь такой и где его взять я так и не понял. B>Это че, компонент такой для Delphi ?
Ну неужели _так_ сложно почитать то, что уже писали, а? Это такой COM-объект, который идет в поставке IE, начиная с версии 4.0. В общем, это не компонент для Дельфи (тьфу).
B>Ну посмотрел там у народа какие-то траблы с этим IImgCtx, а что же это за B>зверь такой и где его взять я так и не понял. B>Это че, компонент такой для Delphi ?
>Ну неужели _так_ сложно почитать то, что уже писали, а? Это такой >COM-объект, который идет в поставке IE, начиная с версии 4.0. В >общем, это не компонент для Дельфи (тьфу).
А где он находится и как его использовать ?