Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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;
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;
Что это за убогая функция такая? :-0

Работать будет скорее всего быстрее чем твой вариант, но раза в 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.54 MB
Время: 0.015 c
2-1193756302
Галинка
2007-10-30 17:58
2007.11.25
двоичное представление числа


6-1174900201
StrangerMX
2007-03-26 13:10
2007.11.25
RSS


6-1164519806
DRtM
2006-11-26 08:43
2007.11.25
Как определить по редиректу реальное имя файла в сети


2-1193806138
San1712
2007-10-31 07:48
2007.11.25
Нет доступа к компоненту Edit


2-1194235125
Bess
2007-11-05 06:58
2007.11.25
Вставить свой пункт в меню IE