Reputation: 289
I have this type of situation:
Main window that is non-transparent, with semi-transparent blue child window, that have red child window.
How can I make red window non-transparent.
Right now i use this simple code, can you help me ?
procedure TNormalForm.CreateSecondWindow;
var
Style: LongInt;
begin
// semi-transparent window
SecondWindow := TForm.Create(Self);
// SecondWindow.BorderStyle := bsNone;
SecondWindow.Parent := Self;
SecondWindow.Color := clBlue;
SecondWindow.Width := 400;
SecondWindow.Height := 300;
SecondWindow.Left := 100;
SecondWindow.Top := 100;
// set layered
Style := GetWindowLong(SecondWindow.Handle, GWL_EXSTYLE);
SetWindowLong(SecondWindow.Handle, GWL_EXSTYLE, Style or WS_EX_LAYERED);
// set transparency (alfa = 200/255)
SetLayeredWindowAttributes(SecondWindow.Handle, 0, 200, LWA_ALPHA);
SecondWindow.Show;
end;
procedure TNormalForm.CreateThirdWindow;
var
Style: LongInt;
begin
// non-transparent window
ThirdWindow := TForm.Create(SecondWindow);
// ThirdWindow.BorderStyle := bsNone;
ThirdWindow.Parent := SecondWindow;
ThirdWindow.Color := clRed;
ThirdWindow.Width := 200;
ThirdWindow.Height := 150;
ThirdWindow.Left := 150;
ThirdWindow.Top := 150;
Style := GetWindowLong(ThirdWindow.Handle, GWL_EXSTYLE);
SetWindowLong(ThirdWindow.Handle, GWL_EXSTYLE, Style and not WS_EX_LAYERED);
RedrawWindow(ThirdWindow.Handle, Nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ALLCHILDREN);
ThirdWindow.Show;
end;
EDIT: I asked ChatGPT about how to draw non-transparent window on top of semi-transparent child form and i got this answear from ChatGPT:
procedure DrawLayeredWindow(AForm: TForm);
var
ScreenDC, MemDC: HDC;
Bitmap: HBITMAP;
OldBitmap: HBITMAP;
Blend: BLENDFUNCTION;
BitmapData: array of TRGBQuad;
BitmapInfo: TBitmapInfo;
Width, Height: Integer;
i, j: Integer;
PtSize, PtSrc: TPoint;
PtPos: TPoint;
begin
Width := AForm.Width;
Height := AForm.Height;
SetLength(BitmapData, Width * Height);
for j := 0 to Height - 1 do begin
for i := 0 to Width - 1 do begin
if (i > 0) and (i < 200) and (j > 0) and (j < 150) then begin
BitmapData[j * Width + i].rgbRed := 255; // red color
BitmapData[j * Width + i].rgbGreen := 0;
BitmapData[j * Width + i].rgbBlue := 0;
BitmapData[j * Width + i].rgbReserved := 255; // Alfa
end
else begin
BitmapData[j * Width + i].rgbRed := 0; // blue color
BitmapData[j * Width + i].rgbGreen := 0;
BitmapData[j * Width + i].rgbBlue := 255;
BitmapData[j * Width + i].rgbReserved := 128; // Alfa
end;
end;
end;
ScreenDC := GetDC(0);
MemDC := CreateCompatibleDC(ScreenDC);
Bitmap := CreateCompatibleBitmap(ScreenDC, Width, Height);
OldBitmap := SelectObject(MemDC, Bitmap);
FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
with BitmapInfo.bmiHeader do begin
biSize := SizeOf(TBitmapInfoHeader);
biWidth := Width;
biHeight := -Height;
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
end;
SetDIBits(MemDC, Bitmap, 0, Height, @BitmapData[0], BitmapInfo, DIB_RGB_COLORS);
Blend.BlendOp := AC_SRC_OVER;
Blend.BlendFlags := 0;
Blend.SourceConstantAlpha := 255;
Blend.AlphaFormat := AC_SRC_ALPHA;
PtPos := Point(AForm.Left, AForm.Top);
PtSize := Point(Width, Height);
PtSrc := Point(0, 0);
UpdateLayeredWindow(AForm.Handle, ScreenDC, @PtPos, @PtSize, MemDC, @PtSrc, 0, @Blend, ULW_ALPHA);
SelectObject(MemDC, OldBitmap);
DeleteObject(Bitmap);
DeleteDC(MemDC);
ReleaseDC(0, ScreenDC);
end;
procedure TNormalForm.CreateSecondWindow;
var
Style: LongInt;
begin
// semi-transparent window
SecondWindow := TForm.Create(Self);
SecondWindow.BorderStyle := bsNone;
SecondWindow.Parent := Self;
SecondWindow.Color := clBlue;
SecondWindow.Align := alClient;
DrawLayeredWindow(SecondWindow);
SecondWindow.Show;
end;
but now third window is not drawn at all, what can be done to fix this problem ?
Upvotes: 2
Views: 47
Reputation: 598029
SetLayeredWindowAttributes()
applies its attributes to an entire window as a whole, which is why the red window is not solid when it is a child of the translucent blue window. You simply can't achieve the effect you want by using this API function. You will have to use UpdateLayeredWindow()
instead, so that you have more control over each pixel's alpha and can decide exactly which pixels are opaque and which are translucent.
Also, keep in mind that child windows could not have the WS_EX_LAYERED
style until Windows 8, so if you need to support Windows 7 or earlier than you'll need to find a different solution.
Upvotes: 3