Конференция "Основная" » Прозрачность окна [D6, WinXP]
 
  • webpauk © (29.01.08 17:09) [0]
    Делаю окно полупрозрачным.
    Как делаю - не понимаю.
    Точнее понимаю как, но не понимаю почему это происходит.
    Привожу код:


    unit Unit1;

    interface

    uses
     Windows, Messages, Classes, Graphics, Forms;

    type
     TRGB = record
       B, G, R: Byte;
     end;
     pRGB = ^TRGB;

     TForm1 = class(TForm)
       procedure FormPaint(Sender: TObject);
       procedure FormCreate(Sender: TObject);
       procedure FormDestroy(Sender: TObject);
     private
       fBmp: TBitmap;

       PrevParentWndProc: Pointer;
       procedure NewParentWndProc(var Msg: TMessage);
     end;

    var
     Form1: TForm1;
     FTransparency: Integer;
     FTranspColor: TColor;

    implementation

    {$R *.dfm}

    {Ñìåøèâàíèå öâåòîâ}
    function MixBytes(FG, BG, TRANS: byte): byte;
     asm
       push bx
       push cx
       push dx
       mov DH,TRANS
       mov BL,FG
       mov AL,DH
       mov CL,BG
       xor AH,AH
       xor BH,BH
       xor CH,CH
       mul BL
       mov BX,AX
       xor AH,AH
       mov AL,DH
       xor AL,$FF
       mul CL
       add AX,BX
       shr AX,8
       pop dx
       pop cx
       pop bx      
    end;

    {Âûçîâ ïðîöåäóðû ñìåøèâàíèÿ öâåòîâ äëÿ êàæäîãî pixel}
    procedure MixColors(Bitmap: TBitmap; Color: TColor);
    var
     x, y: Integer;
     Dest: pRGB;
     fR, fG, fB: Byte;
    begin
     fR:=GetRValue(FTranspColor);
     fG:=GetGValue(FTranspColor);
     fB:=GetBValue(FTranspColor);

     for y := 0 to Bitmap.Height - 1 do
     begin
       Dest := Bitmap.ScanLine[y];
       for x := 0 to Bitmap.Width - 1 do
       begin
         with Dest^ do
         begin
           R:=MixBytes(fR, R, FTransparency);
           G:=MixBytes(fG, G, FTransparency);
           B:=MixBytes(fB, B, FTransparency);
         end;
         Inc(Dest);
       end;
     end;
    end;

    {çàõâàò DC è îòðèñîâêà íà Canvas}
    procedure TForm1.FormPaint(Sender: TObject);
    var
     DC: hDC;
     P, A: Tpoint;
    begin
     P:=Point(0, 0);
     A:=ClientToScreen(P);

     DC:=GetDC(0);
     BitBlt(fBmp.Canvas.Handle, 0, 0, ClientWidth, ClientHeight, DC, A.X, A.Y, SrcCopy);
     ReleaseDC(0, DC);

     MixColors(fBmp, FTranspColor);
     BitBlt(Canvas.Handle, P.X, P.Y, fBmp.Width, fBmp.Height, fBmp.canvas.Handle, 0, 0, SRCCOPY);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    var
     p: Pointer;
    begin
     TransparentColorValue:=$00000001;
     TransparentColor:=True;

     FTransparency:=150;
     FTranspColor:=clBlue;

     fBmp:=TBitmap.Create;
     fBmp.Width:=ClientWidth;
     fBmp.Height:=ClientHeight;
     fBmp.PixelFormat := pf24Bit;

     PrevParentWndProc:=Pointer(GetWindowLong(Handle, GWL_WNDPROC));
     p:=MakeObjectInstance(NewParentWndProc);
     SetWindowLong(Handle, GWL_WNDPROC, LongInt(p));
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
     fBmp.Free;
     if HandleAllocated then SetWindowLong(Handle, GWL_WNDPROC, LongInt(PrevParentWndProc));
    end;

    procedure TForm1.NewParentWndProc(var Msg: TMessage);
    begin
     Msg.Result:=CallWindowProc(PrevParentWndProc, Handle, Msg.Msg, Msg.WParam, Msg.LParam);

     case Msg.Msg of
       wm_Move, WM_ACTIVATE: Paint;
      end;
    end;

    end.



    развивалось следующим образом:
    1. сначала скрывалось окно, потом захватывался DC, потом окно отображалось и на нем рисовалась часть DC.
    2. Возникла идея не скрывать окно, а вырезать его часть, захватывая DC.
    3. Вырезать можно используя TransparentColor. Собственно говоря данный пример и должен был сначала Canvas заливать TransparentColorValue, захватывать DC, потом заливать не TransparentColorValue и рисовать часть контекста. Но в данном примере ничего не вырезается!!!! И всё работает!!!!
    Может кто-нибудь поймет почему?
  • homm © (29.01.08 17:11) [1]
    > [0] webpauk ©   (29.01.08 17:09)
    > Как делаю - не понимаю.

    +1!
  • webpauk © (29.01.08 17:14) [2]

    > homm ©   (29.01.08 17:11) [1]

    8(
    сам того же мнения
  • webpauk © (29.01.08 17:15) [3]
    TransparentColor:=False;


    тогда ничего не работает. Почему?
  • Dimaxx © (29.01.08 17:35) [4]
  • webpauk © (29.01.08 17:55) [5]

    > Dimaxx ©   (29.01.08 17:35) [4]

    цитата из ссылки: "При необходимости перерисовать полупрозрачное окно надо это окно ненадолго убрать с экрана"

    Это не мой вариант!!!

    > webpauk ©   (29.01.08 17:09)  
    развивалось следующим образом:
    1. сначала скрывалось окно, потом захватывался DC, потом окно отображалось и на нем рисовалась часть DC.
    2. Возникла идея не скрывать окно, а вырезать его часть, захватывая DC.
    3. Вырезать можно используя TransparentColor. Собственно говоря данный пример и должен был сначала Canvas заливать TransparentColorValue, захватывать DC, потом заливать не TransparentColorValue и рисовать часть контекста. Но в данном примере ничего не вырезается!!!! И всё работает!!!!
    Может кто-нибудь поймет почему?


    Вопрос не раскрыт: TransparentColor:=False/True - не работает/работает. Почему? Ведь нигде не производится заливка!
  • Dimaxx © (29.01.08 17:57) [6]
    Вот как реализовано в KOL:

    procedure TControl.SetAlphaBlend(const Value: Integer);
    const
     LWA_COLORKEY=$00000001;
     LWA_ALPHA=$00000002;
     ULW_COLORKEY=$00000001;
     ULW_ALPHA=$00000002;
     ULW_OPAQUE=$00000004;
     WS_EX_LAYERED=$00080000;
    type
     TSetLayeredWindowAttributes=
       function( hwnd: Integer; crKey: TColor; bAlpha: Byte; dwFlags: DWORD )
       : Boolean; stdcall;
    var
     SetLayeredWindowAttributes: TSetLayeredWindowAttributes;
     User32: THandle;
     dw: DWORD;
    begin
     if Value = fAlphaBlend then Exit;
     fAlphaBlend := Value;
     User32 := GetModuleHandle( 'User32' );
     SetLayeredWindowAttributes := GetProcAddress( User32,
                                'SetLayeredWindowAttributes' );
     if Assigned( SetLayeredWindowAttributes ) then
     begin
       dw := GetWindowLong( GetWindowHandle, GWL_EXSTYLE );
       if Byte( Value ) < 255 then
       begin
         SetWindowLong( fHandle, GWL_EXSTYLE, dw or WS_EX_LAYERED );
         SetLayeredWindowAttributes( fHandle, 0, Value and $FF, LWA_ALPHA);
       end
          else
         SetWindowLong( fHandle, GWL_EXSTYLE, dw and not WS_EX_LAYERED );
     end;
    end;



    Раз у тебя ХРюша - это как раз то.
  • webpauk © (29.01.08 18:01) [7]

    > Dimaxx ©   (29.01.08 17:57) [6]

    AlphaBlend-устанавливает прозрачность для ВСЕЙ формы. Мне нужна часть!!!
  • webpauk © (29.01.08 18:04) [8]
    и еще непонятка.
    если поместить прозрачную форму над другой прозрачной, то нижняя - вообще не отображается!!!
  • webpauk © (29.01.08 18:11) [9]

    > webpauk ©   (29.01.08 18:04) [8]

    непонятка исчезла, когда изменил Form.ClassName
  • webpauk © (29.01.08 18:58) [10]
    а вот еще один метод прозрачности:
    есть две формы одна со включенным alphablend, а вторая нет.
    на одну из форм цепляем процедуры:

     private
       procedure WMPOCHANGE(var Msg: TMessage); message WM_WINDOWPOSCHANGED;
       procedure wmhittest(var Msg: TMessage); message WM_NCHITTEST;

    procedure TForm1.WMPOCHANGE(var Msg: TMessage);
    begin
     inherited;
     if Form2=nil then exit;

     Form2.Left:=Left+20;
     Form2.Top:=Top+20;
     form2.BringToFront;

    end;

    procedure TForm1.wmhittest(var Msg: TMessage);
    var
     P: TPoint;
    begin
     inherited;

     p := Point(msg.LParamLo, msg.LParamHi);
     p := ScreenToClient(p);
     if PtInRect(Rect(0, 0, Width, 20), P) then Msg.Result:=HTCAPTION;
    end;

  • Fredy314 © (29.01.08 20:32) [11]
    Любители сложных решений, блин.
    Вы ето
    gif  с прозрачными областями,
    png с переменной прозрачностью
    или вообще psd со всеми наворотами для скинов не думали прикрутить?
    Удачных вам подводных камней.
  • han_malign © (31.01.08 12:20) [12]

    > Ведь нигде не производится заливка!

    WM_ERASEBKGND
 
Конференция "Основная" » Прозрачность окна [D6, WinXP]
Есть новые Нет новых   [134482   +35][b:0][p:0.003]