Конференция "Media" » Форма окна по картинке [D7, WinXP]
 
  • master_asasin (13.09.07 14:26) [0]
    Доброго времени суток! Может кто знает как форму окна по
    картинке, типа как в заставке к CorelDraw, но так что бы
    при загрузке фотографии не было белых краев, а край формы был гладким.
  • Dib@zol © (13.09.07 14:41) [1]
    Пользуй регионы.

    function GBS(B: HBITMAP):SIZE;
    var buf : BITMAP;
    begin
     FillChar(buf, SizeOf(BITMAP), 0);
     GetObject(B, SizeOf(BITMAP), @buf);
     result.cx:=buf.bmWidth;
     result.cy:=buf.bmHeight;
    end;

    function GetBmpRgn(var BMP:HBITMAP):HRGN;
    var
     RG : HRGN;
     TC:COLORREF;
     i, j, L, R, H, W : integer;

    begin
     Result:=0;
     DC:=CreateCompatibleDC(0);
     SelectObject(DC, BMP);
     sz:=GBS(BMP);

     W:=sz.cx;
     H:=sz.cy;

     TC:=GetPixel(DC, 0, 0);

     for i:=0 to H-1 do begin
       L:=-1;
       for j:=0 to W-1 do begin
         if L<0 then begin
           if GetPixel(DC, j, i)<>TC then
             L:=j;
         end else
         if GetPixel(DC, j, i)=TC then begin
           R:=j;
           RG:=CreateRectRgn(L, i, R, i+1);
           if Result=0 then
             Result:=RG
           else begin
             CombineRgn(Result, Result, RG, RGN_OR);
             DeleteObject(RG);
           end;
           L:=-i;
         end;
       end;

       if L>=0 then begin
         RG:=CreateRectRgn(L, i, W, i+1);
         if Result=0 then
           Result:=RG
         else begin
           CombineRgn(Result, Result, RG, RGN_OR);
           DeleteObject(RG);
         end;
       end;
     end;  

     ReleaseDC(BMP, DC);
     DeleteDC(DC);
    end;

    После вызова этой функции проставляешь окну регион с помощью SetWindowRgn и радуешься жизни :)
    Когда будешь дестроить окно, не забудь DeleteObject'ом удалить регион.
  • antonn © (13.09.07 16:46) [2]
    окно с альфаканалом
    http://desksoft.ru/index.php?forum=13&th=47
  • Инс © (14.09.07 23:13) [3]
    Этот вариант побыстрее будет:
    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;
    . . .
    end.



    Только советую от Global-функций избавится, заменить на аналоги, были проблемы с ними.
  • Инс © (14.09.07 23:15) [4]

    > Когда будешь дестроить окно, не забудь DeleteObject'ом удалить
    > регион.

    Не нужно. Справочку по SetWindowRgn читаем.
  • master_asasin (15.09.07 12:50) [5]
    Спасибо всем! Вроде разобрался.
  • antonn © (15.09.07 22:03) [6]
    особенно гладкими края будут с регионами:)
  • Инс © (15.09.07 22:46) [7]

    > [6] antonn ©   (15.09.07 22:03)

    Layered - это конечно хорошо, но не панацея, полно ограничений.
  • antonn © (16.09.07 09:13) [8]

    > Инс ©   (15.09.07 22:46) [7]

    ограничений нет, была бы фантазия:)
    к тому же автору нужно сделать заставку "наподобие корела"
  • Инс © (16.09.07 11:40) [9]

    > [8] antonn ©   (16.09.07 09:13)

    Есть, Win2000 - минимум, и если использовать UpdateLayeredWindow и на форме лежат другие контролы, то их придется отрисовывать самому.
  • antonn © (16.09.07 14:50) [10]
    а у автора WinXP в запросе :Р
    контролы это конечно минус, зато можно свои рисовать:)
  • Инс © (16.09.07 18:01) [11]

    > а у автора WinXP в запросе :Р

    А у пользователя какая система автор не указал? :)
 
Конференция "Media" » Форма окна по картинке [D7, WinXP]
Есть новые Нет новых   [133929   +477][b:0][p:0.004]