Текущий архив: 2007.11.25;
Скачать: CL | DM;
Вниз
Регион, процедура прорисовки окна Найти похожие ветки
← →
Iv_ © (2007-05-08 12:39) [0]Есть форма в виде битмапа, не квадратной формы (процедура делает розовый цвет прозрачным делая регион). Подскажите, пожалуйста, куда вставить эту процедуру??? Если я ее вставляю до появления формы, то ничего не происходит(розовый цвет, виден, вместо того, чтобы быть прозрачным), а если вставляю после появления формы, то после ее появления проходит где-то секунда, прежде чем розовый цвет заменяется на прозрачный. Что делать??
← →
homm © (2007-05-08 22:04) [1]Создавать регион до создания формы, применять его к окнц непосредственно после создания, до показа.
← →
Iv_ © (2007-05-10 08:29) [2]
> Создавать регион до создания формы
я рисую регион, по битмапу, который находится на форме, если я эту форму не создам, то как я тогда создам регион????
← →
homm © (2007-05-10 11:34) [3]> я рисую регион, по битмапу, который находится на форме
Откудато же он на ворме береться? Вывод: получать егно ДО того как создаеться форма, и делать по нему регион :-|
← →
Iv_ © (2007-05-11 08:14) [4]Вот исходник(15,7 Кб), поглядите пожалуйста :)
http://files.buq.ru?go=region.rar
← →
homm © (2007-05-11 09:57) [5]
Procedure RunSettings;
var
fon: THandle;
dc1: hdc;
begin
fon:=LoadBitmap(hInstance,makeintresource(4));
dc1 := GetDC(0);
dc := CreateCompatibleDC(dc1);
ReleaseDC(0, dc1);
SelectObject(DC, fon);
TmpRgn := BitmapToRegion(dc,0,0,$FF10FF,500,500);
Win := CreateDialog(hInstance,PCHar(100),0,@SettingsDlgProc);
//--------------------------
H_EXIT:=GetDlgItem(Win,ID_EXIT);
H_QUET:=GetDlgItem(Win,ID_QUET);
SetWindowLong(H_EXIT, GWL_USERDATA,
SetWindowLong(H_EXIT, GWL_WNDPROC, LongInt(@BtnWinProc)));
SetWindowLong(H_QUET, GWL_USERDATA,
SetWindowLong(H_QUET, GWL_WNDPROC, LongInt(@BtnWinProc)));
b_QUET_U:=LoadBitmap(hInstance,makeintresource(9013));
b_QUET_O:=LoadBitmap(hInstance,makeintresource(9014));
b_QUET_D:=LoadBitmap(hInstance,makeintresource(9015));
//.....................................................
b_EXIT_U:=LoadBitmap(hInstance,makeintresource(9002));
b_EXIT_O:=LoadBitmap(hInstance,makeintresource(9001));
b_EXIT_D:=LoadBitmap(hInstance,makeintresource(9003));
//.....................................................
DeleteDC (dc);
SendMessage(win, WM_paint,0,0);
SetWindowRgn(win,TmpRgn,true);
DeleteObject(TmpRgn);
Showwindow(Win,SW_SHOW);
UpdateWindow(Win);
//AnimateWindow(win, 1000,AW_CENTER or AW_SLIDE);
SendMessage(win, WM_MOUSEMOVE,0,0);
end;
Комментарии удалил, при вставке из дельфи вместо них появились иероглифы.
Насчет BitmapToRegion: GetPixel — очень и очень плохой способ работы с изображениями. Нужно использовать GetDIBits или аналоги.
← →
homm © (2007-05-11 09:59) [6]А еше лучше, если бы ты разобрался внутренем формате региона, с которым можно работать через функции GetRegionData и ExtCreateRegion, было бы раз в 100 быстрее, чем сейчас.
← →
Iv_ © (2007-05-11 14:46) [7]а примерчик можешь дать?? плиз :))) иль ссылочку
← →
Iv_ © (2007-05-11 14:47) [8]из всего инета процедуру получения региона из битмапа нашел только эту (та что в исходниках) :(((
← →
homm © (2007-05-11 15:25) [9]> а примерчик можешь дать??
Понимаешь, если я начну писать, это же будет ассемблер с применением MMX, как минимум :) Некогда.
← →
Iv_ © (2007-05-11 15:35) [10]:)))) а как тебе вот это(нарыл тут где то :)))
function CreateRgnFromBitmap(Bitmap: TBitmap): HRGN;
. . .
implementation
. . .
// Создать регион, опираясь на точечный рисунок Bitmap
// Цвет левого верхнего пиксела считается прозрачным.
function CreateRgnFromBitmap(Bitmap: TBitmap): HRGN;
const
// Начальное резервируемое количество прямоугольников в регионе.
// Можно присвоить и другое число.
dCount = 500;
var
PLine: Pointer; // Указатель на строку в рисунке
PPixel: PLongint; // Указатель на пиксел в рисунке
DataMem: PRgnData; // Здесь будут храниться данные о регионе
H: THandle; // Дескриптор области памяти
MaxRects: DWORD; // Резервируемое количество прямоугольников в регионе
X,StartX,FinishX,Y: integer; // Понадобятся при добавлении прямоугольников
TransColor: TColor; // Прозрачный цвет
TransR,TransG,TransB: Byte; // Значения R, G и B прозрачного цвета
TempBitmap: TBitmap; // Временный Bitmap
// Функция возвращает true, если цвет Pixel совпадает с прозрачным
function IsTrans(Pixel: Longint): boolean;
var
R,G,B: Byte;
begin
R:=GetBValue(Pixel);
G:=GetGValue(Pixel);
B:=GetRValue(Pixel);
Result:=(TransR = R) and (TransG = G) and (TransB = B);
end;
// Процедура добавляет прямоугольник (StartX, Y, FinishX, Y+1) к региону
procedure AddRect;
var
Rect: PRect;
begin
Rect:=@DataMem^.Buffer[DataMem^.rdh.nCount*SizeOf(TRect)];
SetRect(Rect^,StartX,Y,FinishX,Y+1);
Inc(DataMem^.rdh.nCount);
end;
begin
MaxRects:=dCount; // Начальное значение MaxRects
// Определяем прозрачный цвет
TransColor:=GetPixel(Bitmap.Canvas.Handle,0,0);
TransR:=GetRValue(TransColor);
TransG:=GetGValue(TransColor);
TransB:=GetBValue(TransColor);
// Формируем временный Bitmap, с которым будем работать
TempBitmap:=TBitmap.Create;
TempBitmap.Assign(Bitmap);
TempBitmap.PixelFormat:=pf24bit; // 24 бита на пиксель
// Выделяем память на данные для региона и получаем указатель на нее
H:=GlobalAlloc(GMEM_MOVEABLE,SizeOf(TRgnDataHeader)+
SizeOf(TRect)*MaxRects);
DataMem:=GlobalLock(H);
// Заполняем заголовок
// Обнуляем все поля в заголовке
ZeroMemory(@DataMem^.rdh,SizeOf(TRgnDataHeader));
DataMem^.rdh.dwSize:=SizeOf(TRgnDataHeader); // Заполняем поле dwSize
DataMem^.rdh.iType:=RDH_RECTANGLES; // Заполняем поле iType
// Начинаем цикл обхода рисунка по точкам. Будем двигаться слева-направо,
// сверху-вниз. В переменных X и Y будем хранить текущее значение
// координат.
// В переменной StartX - начало нового прямоугольника, FinishX -
// соответственно конец прямоугольника.
for Y:=0 to TempBitmap.Height-1 do begin // Цикл по строкам
PLine:=TempBitmap.ScanLine[Y];// Получаем указатель на строку
PPixel:=PLongint(PLine); // Получаем указатель на первую точку в строке
X:=0; StartX:=0; FinishX:=0; // Обнуляем X, StartX, FinishX
while X<TempBitmap.Width do begin // Цикл по столбцам
Inc(X); // Увеличиваем текущее значение координаты X
// Если цвет точки отличен от прозрачного,
// то надо включить ее в новый прямоугольник
if not IsTrans(PPixel^) then FinishX:=X
else begin
// Цвет точки равен прозрачному. Значит нужно завершить формирование
// прямоугольника, если он не пустой, то добавить его к региону и начать
// формирование нового прямоугольника. Если количество прямоугольников
// в регионе достигло MaxRects, то увеличиваем MaxRects на dCount, и
// выделяем память под данные о регионе заново
if DataMem^.rdh.nCount>=MaxRects then
begin
Inc(MaxRects,dCount);
GlobalUnlock(H);
H:=GlobalReAlloc(H,SizeOf(TRgnDataHeader)+SizeOf(TRect)*MaxRects,
GMEM_MOVEABLE);
DataMem:=GlobalLock(H);
end;
// Если прямоугольник не пустой, добавляем его к региону
if FinishX>StartX then AddRect;
// Устанавливаем значения StartX, FinishX для формирования нового
// прямоугольника
StartX:=X;
FinishX:=X;
end;
Inc(PByte(PPixel),3); // Получаем указатель не следующую точку рисунка
end;
// Возможен следующий случай: если цвет последней точки в строке не равен
// прозрачному, то FinishX будет больше, чем StartX, однако прямоугольник
// не будет добавлен к региону, так так добавление нового прямоугольника
// происходит только если встретился прозрачный пиксель. Это нужно учесть.
if FinishX>StartX then AddRect;
end;
// Временный Bitmap больше не нужен
TempBitmap.Free;
try
// Формируем регион по данным из DataMem^
Result:=ExtCreateRegion(nil,SizeOf(TRgnDataHeader)+
SizeOf(TRect)*DataMem^.rdh.nCount,DataMem^);
finally
GlobalFree(H); // Освобождаем выделенную память
end;
end;
← →
homm © (2007-05-11 15:39) [11]
function IsTrans(Pixel: Longint): boolean;
Что это за убогая функция такая? :-0
var
R,G,B: Byte;
begin
R:=GetBValue(Pixel);
G:=GetGValue(Pixel);
B:=GetRValue(Pixel);
Result:=(TransR = R) and (TransG = G) and (TransB = B);
end;
Работать будет скорее всего быстрее чем твой вариант, но раза в 2-3 всего. Видно, что у автора и здесь опыта ноль.
← →
Iv_ © (2007-05-11 15:47) [12]я тебя наверное уже задолбал? :))
вот еще нашел:
function CreateBitmapRgn(DC: hDC; Bitmap: hBitmap; TransClr: TColorRef): hRgn;
var
bmInfo: TBitmap; //структура BITMAP WinAPI
W, H: Integer; //высота и ширина растра
bmDIB: hBitmap; //дискрептор независимого растра
bmiInfo: BITMAPINFO; //структура BITMAPINFO WinAPI
lpBits, lpOldBits: PRGBTriple; //указатели на структуры RGBTRIPLE WinAPI
lpData: PRgnData; //указатель на структуру RGNDATA WinAPI
X, Y, C, F, I: Integer; //переменные циклов
Buf: Pointer; //указатель
BufSize: Integer; //размер указателя
rdhInfo: TRgnDataHeader; //структура RGNDATAHEADER WinAPI
lpRect: PRect; //указатель на TRect (RECT WinAPI)
begin
Result:=0;
if Bitmap=0 then Exit; //если растр не задан, выходим
GetObject(Bitmap, SizeOf(bmInfo), @bmInfo); //узнаем размеры растра
W:=bmInfo.bmWidth; //используя структуру BITMAP
H:=bmInfo.bmHeight;
I:=(W*3)-((W*3) div 4)*4; //определяем смещение в байтах
if I<>0 then I:=4-I;
//Пояснение: растр Windows Bitmap читается снизу вверх, причем каждая строка
//дополняется нулевыми байтами до ее кратности 4.
//для 32-х битный растров такой сдвиг делать не надо.
//заполняем BITMAPINFO для передачи в CreateDIBSection
bmiInfo.bmiHeader.biWidth:=W; //ширина
bmiInfo.bmiHeader.biHeight:=H; //высота
bmiInfo.bmiHeader.biPlanes:=1; //всегда 1
bmiInfo.bmiHeader.biBitCount:=24; //три байта на пиксель
bmiInfo.bmiHeader.biCompression:=BI_RGB; //без компрессии
bmiInfo.bmiHeader.biSizeImage:=0; //размер не знаем, ставим в ноль
bmiInfo.bmiHeader.biXPelsPerMeter:=2834; //пикселей на метр, гор.
bmiInfo.bmiHeader.biYPelsPerMeter:=2834; //пикселей на метр, верт.
bmiInfo.bmiHeader.biClrUsed:=0; //палитры нет, все в ноль
bmiInfo.bmiHeader.biClrImportant:=0; //то же
bmiInfo.bmiHeader.biSize:=SizeOf(bmiInfo.bmiHeader); //размер структруы
bmDIB:=CreateDIBSection(DC, bmiInfo, DIB_RGB_COLORS,
Pointer(lpBits), 0, 0);
//создаем независимый растр WxHx24, без палитры, в указателе lpBits получаем
//адрес первого байта этого растра. bmDIB - дискрептор растра
//заполняем первые шесть членов BITMAPINFO для передачи в GetDIBits
bmiInfo.bmiHeader.biWidth:=W; //ширина
bmiInfo.bmiHeader.biHeight:=H; //высота
bmiInfo.bmiHeader.biPlanes:=1; //всегда 1
bmiInfo.bmiHeader.biBitCount:=24; //три байта на пиксель
bmiInfo.bmiHeader.biCompression:=BI_RGB; //без компресси
bmiInfo.bmiHeader.biSize:=SizeOf(bmiInfo.bmiHeader); //размер структуры
GetDIBits(DC, Bitmap, 0, H-1, lpBits, bmiInfo, DIB_RGB_COLORS);
//конвертируем исходный растр в наш с его копированием по адресу lpBits
lpOldBits:=lpBits; //запоминаем адрес lpBits
//первый проход - подсчитываем число прямоугольников, необходимых для
//создания региона
C:=0; //сначала ноль
for Y:=H-1 downto 0 do //проход снизу вверх
begin
X:=0;
while X<W do //от 0 до ширины-1
begin
//пропускаем прзрачный цвет, увеличивая координату и указатель
while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)=TransClr) and (X<W) do
begin
Inc(lpBits);
X:=X+1;
end;
//если нашли не прозрачный цвет, то считаем, сколько точек в ряду он идет
if RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)<>TransClr then
begin
while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)<>TransClr) and (X<W) do
begin
Inc(lpBits);
X:=X+1;
end;
C:=C+1; //увиличиваем счетчик прямоугольников
end;
end;
//ряд закончился, необходимо увеличить указатель до кратности 4
PChar(lpBits):=PChar(lpBits)+I;
end;
lpBits:=lpOldBits; //восстанавливаем значение lpBits
//Заполняем структуру RGNDATAHEADER
rdhInfo.iType:=RDH_RECTANGLES; //будем использовать прямоугольники
rdhInfo.nCount:=C; //их количество
rdhInfo.nRgnSize:=0; //размер выделяем памяти не знаем
rdhInfo.rcBound:=Rect(0, 0, W, H); //размер региона
rdhInfo.dwSize:=SizeOf(rdhInfo); //размер структуры
//выделяем память для струтуры RGNDATA:
//сумма RGNDATAHEADER и необходимых на прямоугольников
BufSize:=SizeOf(rdhInfo)+SizeOf(TRect)*C;
GetMem(Buf, BufSize);
lpData:=Buf; //ставим указатель на выделенную память
lpData.rdh:=rdhInfo; //заносим в память RGNDATAHEADER
//Заполдяенм память прямоугольниками
lpRect:=@lpData.Buffer; //первый прямоугольник
for Y:=H-1 downto 0 do
begin
X:=0;
while X<W do
begin
while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)=TransClr) and (X<W) do
begin
Inc(lpBits);
X:=X+1;
end;
if RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)<>TransClr then
begin
F:=X;
while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
lpBits.rgbtBlue)<>TransClr) and (X<W) do
begin
Inc(lpBits);
X:=X+1;
end;
lpRect^:=Rect(F, Y, X, Y+1); //заносим координаты
Inc(lpRect); //переходим к следующему
end;
end;
PChar(lpBits):=PChar(lpBits)+I;
end;
//после окночания заполнения структуры RGNDATA можно создавать регион.
//трансформации нам не нужны, ставим в nil, указываем размер
//созданной структуры и ее саму.
Result:=ExtCreateRegion(nil, BufSize, lpData^); //создаем регион
FreeMem(Buf, BufSize); //теперь структура RGNDATA больше не нужна, удаляем
DeleteObject(bmDIB); //созданный растр тоже удаляем
end;
я просто с VCL недавно перелез, нифига еще не понимаю :)))
← →
homm © (2007-05-11 16:18) [13]Не знаю, нужно тестировать на глаз не могу сказать какая из двух последних кревее, но они явно лучше первого варианта :)
← →
Iv_ © (2007-05-14 14:24) [14]Ну вот, ни одну из этих юзать не стал, нашел еще один исходник более менее разобрался, вроде хорошо робит, спасибо огромное за советы, респект тебе homm :))
Страницы: 1 вся ветка
Текущий архив: 2007.11.25;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.041 c