Reputation: 75
When I draw a string using GDI+ in a child window, the text does not appear. But when I change the child window to a normal window, the text appears normally. So here is what I did so far:
program Test_Program;
Uses
Windows,
Messages,
GdipObj,
GdipApi,
DirectDraw;
var
Msg: TMSG;
LWndClass: TWndClass;
hMainHandle: HWND;
Function CreateChildWindow(hParent: hWnd): hWnd;
Var
WindowClass: TWndClass;
Begin
Result := 0;
WindowClass.lpszClassName := 'ChildWindow';
WindowClass.Style := cs_HRedraw or cs_VRedraw;
WindowClass.lpfnWndProc := @DefWindowProc;
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := HInstance;
WindowClass.hIcon := LoadIcon(0, idi_Application);
WindowClass.hCursor := LoadCursor(0, idc_Arrow);
WindowClass.hbrBackground := COLOR_BTNFACE + 1;
WindowClass.lpszMenuName := NIL;
WindowClass.lpszClassName := 's';
if RegisterClass(WindowClass)<>0 Then
Result := CreateWindowEx(WS_EX_CONTROLPARENT or WS_EX_LAYERED,
WindowClass.lpszClassName, '', WS_CHILD or WS_VISIBLE or WS_SYSMENU
or WS_CAPTION, 0, 0, 400, 300, hParent, 0, hInstance, nil);
End;
Function MainFormProc(hWnd, Msg: LongInt; wParam: WPARAM; lParam: LPARAM):LongInt;
stdcall;
var ChildhWnd: Integer;
Author : String;
AuthorPosX, AuthorPosY: Single;
SrcDC, DestDC: HDC;
BitmapHandle, PrevBitmap: HBITMAP;
BlendFunc: _BLENDFUNCTION;
Size: TSize;
POSS: TRect;
P, S: TPoint;
Graphics : TGPGraphics;
Bitmap : TGPBitmap;
Font : TGPFont;
FontFamily: TGPFontFamily;
SolidBrush: TGPSolidBrush;
Begin
Result := 0;
Case Msg of
WM_CREATE:
Begin
SolidBrush := TGPSolidBrush.Create($FF000000);
FontFamily := TGPFontFamily.Create('Arial');
Font := TGPFont.Create(FontFamily, 18, FontStyleRegular, UnitPixel);
ChildhWnd := CreateChildWindow(hWnd);
Author := 'Transparent Child Window + GDI+ Text';
AuthorPosX:= 30;
AuthorPosY:= 40;
Size.cx := 600;
Size.cy := 80;
Bitmap := TGPBitmap.Create(600, 80, PixelFormat32bppARGB);
Graphics := TGPGraphics.Create(Bitmap);
Graphics.SetTextRenderingHint(TextRenderingHintAntiAlias); {Set Text Anti Aliased}
S.X := 0;
S.Y := 0;
With BlendFunc Do
Begin
BlendOp := AC_SRC_ALPHA;
BlendFlags := 0;
SourceConstantAlpha := 250;
AlphaFormat := AC_SRC_ALPHA;
End;
Graphics.Clear(0);
Graphics.DrawString(Author, Length(Author), Font,
MakePoint(AuthorPosX, AuthorPosY), SolidBrush);
SrcDC := CreateCompatibleDC(0);
DestDC:= CreateCompatibleDC(SrcDC);
Bitmap.GetHBITMAP(0, BitmapHandle);
PrevBitmap := SelectObject(SrcDC, BitmapHandle);
GetWindowRect(ChildhWnd, POSS);
P.X := POSS.Left;
P.Y := POSS.Top;
UpdateLayeredWindow(ChildhWnd, DestDC, @P, @Size, SrcDC,
@S, 0, @BlendFunc, ULW_ALPHA);
SelectObject(SrcDC, PrevBitmap);
DeleteObject(BitmapHandle);
DeleteDC(DestDC);
DeleteDC(SrcDC);
ShowWindow(ChildhWnd, CmdShow);
UpdateWindow(ChildhWnd);
End;
WM_LBUTTONDOWN:
Begin
DefWindowProc(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
Result:=0;
End;
WM_DESTROY: ExitProcess(0);
else
Result := DefWindowProc(hWnd, Msg, wParam, lParam);
end;
end;
begin
LWndClass.hInstance := hInstance;
with LWndClass do
begin
lpszClassName := 'TMainForm';
Style := CS_PARENTDC or CS_BYTEALIGNCLIENT;
hIcon := LoadIcon(hInstance, 'MAINICON');
lpfnWndProc := @MainFormProc;
hbrBackground := COLOR_BTNFACE + 1;
hCursor := LoadCursor(0, IDC_ARROW);
end;
RegisterClass(LWndClass);
hMainHandle := CreateWindow(LWndClass.lpszClassName, 'Main Window',
WS_SYSMENU, (GetSystemMetrics(SM_CXSCREEN) div 2) - 400,
(GetSystemMetrics(SM_CYSCREEN) div 2) - 300, 800, 600,
0, 0, hInstance, nil);
ShowWindow(hMainHandle, SW_SHOW);
UpdateWindow(hMainHandle);
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end.
Changing the Child window to normal window the text will appear!!
Code From:
CreateWindowEx(WS_EX_CONTROLPARENT or WS_EX_LAYERED,
WindowClass.lpszClassName, '',
WS_CHILD or WS_VISIBLE or WS_SYSMENU or WS_CAPTION,
0, 0, 400, 300, hParent, 0, hInstance, nil);
To:
CreateWindowEx(WS_EX_CONTROLPARENT or WS_EX_LAYERED,
WindowClass.lpszClassName, '',
WS_VISIBLE or WS_SYSMENU or WS_CAPTION,
0, 0, 400, 300, hParent, 0, hInstance, nil);
The text will be drawn!! What's the problem exactly? BTW, I want the childwindow to stay WS_EX_LAYERED because I want only the text to appear not the whole child window.
Upvotes: 1
Views: 2083
Reputation: 28516
UpdateLayeredWindow
is only supported for top level windows and not child windows.
However, from Windows 8, MS added support for other windows too.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633556%28v=vs.85%29.aspx
Ok, here is rather basic code (no exception handling) for creating transparent VCL custom control that uses GDI+ for drawing. It is proof of concept, and it can be translated back to direct Windows API.
type
TPWinControl = class(TWinControl);
TTransparentControl = class(TCustomControl)
protected
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
end;
function GetScreenClient(Control: TControl): TPoint;
var
p: TPoint;
begin
p := Control.ClientOrigin;
ScreenToClient(Control.Parent.Handle, p);
Result := p;
end;
procedure TTransparentControl.WMEraseBkgnd(var Message: TWmEraseBkgnd);
var
Bmp: TBitmap;
DC: hDC;
i: integer;
p: TPoint;
Author: string;
AuthorPosX, AuthorPosY: Single;
Size: TSize;
Graphics: TGPGraphics;
Bitmap: TGPBitmap;
Font: TGPFont;
FontFamily: TGPFontFamily;
SolidBrush: TGPSolidBrush;
begin
message.Result := 1;
if (message.DC <> 0) and Assigned(Parent) then
begin
DC := message.DC;
i := SaveDC(DC);
p := GetScreenClient(Self);
MoveWindowOrg(DC, -p.x, -p.y);
SendMessage(Parent.Handle, WM_ERASEBKGND, DC, 0);
TPWinControl(Parent).PaintControls(DC, nil);
RestoreDC(DC, i);
Bmp := TBitmap.Create;
Bmp.PixelFormat := pf32bit;
Bmp.Width := Width;
Bmp.Height := Height;
BitBlt(Bmp.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SrcCopy);
SolidBrush := TGPSolidBrush.Create($FF000000);
FontFamily := TGPFontFamily.Create('Arial');
Font := TGPFont.Create(FontFamily, 18, FontStyleRegular, UnitPixel);
Author := 'Transparent Child Window + GDI+ Text';
AuthorPosX := 30;
AuthorPosY := 40;
Size.cx := 600;
Size.cy := 80;
Bitmap := TGPBitmap.Create(Bmp.Handle);
Graphics := TGPGraphics.Create(Bmp.Canvas.Handle);
Graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
Graphics.DrawString(Author, Length(Author), Font,
MakePoint(AuthorPosX, AuthorPosY), SolidBrush);
Graphics.Free;
Bitmap.Free;
Canvas.Draw(0, 0, Bmp);
Bmp.Free;
end;
end;
Upvotes: 2