Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2007.11.25;
Скачать: [xml.tar.bz2];

Вниз

Регион, процедура прорисовки окна   Найти похожие ветки 

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.11.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.041 c
2-1193911010
SveTTT
2007-11-01 12:56
2007.11.25
Вызов печати по нажатю комбинации кнопок


15-1193027871
Slider007
2007-10-22 08:37
2007.11.25
С днем рождения ! 22 октября 2007 понедельник


2-1193726020
IntruderLab
2007-10-30 09:33
2007.11.25
FastReport 3.0 переменные


2-1193932102
AlexanderMS
2007-11-01 18:48
2007.11.25
Как прочитать первую строку из текстового файла?


1-1188819375
vishnia
2007-09-03 15:36
2007.11.25
Как в процедуру передать имя функции?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский