Win API Delphi GDI+;:在子窗口中绘制字符串
在子窗口中使用GDI+绘制字符串时,文本不会显示。 但是,当我将子窗口更改为普通窗口时,文本将正常显示。所以这里 这就是我到目前为止所做的:Win API Delphi GDI+;:在子窗口中绘制字符串,delphi,winapi,gdi+,transparent,drawstring,Delphi,Winapi,Gdi+,Transparent,Drawstring,在子窗口中使用GDI+绘制字符串时,文本不会显示。 但是,当我将子窗口更改为普通窗口时,文本将正常显示。所以这里 这就是我到目前为止所做的: program Test_Program; Uses Windows, Messages, GdipObj, GdipApi, DirectDraw; var Msg: TMSG; LWndClass: TWndClass; hMainHandle: HWND; Function CreateChildWi
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.
致:
文本将被绘制!!到底是什么问题?
顺便说一句,我希望子窗口保持WS_EX_分层,因为我只希望文本显示在整个子窗口中。
UpdateLayeredWindow
仅支持顶级窗口,而不支持子窗口
然而,在Windows8中,MS也增加了对其他Windows的支持
好的,下面是创建透明VCL自定义控件的基本代码(无异常处理),该控件使用GDI+进行绘图。它是概念验证,并且可以转换回直接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;
类型
TPWinControl=等级(TWinControl);
tttransparentcontrol=class(TCustomControl)
受保护的
程序WMEraseBkgnd(var消息:TWmEraseBkgnd);消息WM_ERASEBKGND;
结束;
函数GetScreenClient(控件:TControl):TPoint;
变量
p:TPoint;
开始
p:=Control.ClientOrigin;
ScreenToClient(Control.Parent.Handle,p);
结果:=p;
结束;
过程TTTransparentControl.WMEraseBkgnd(var消息:TWmEraseBkgnd);
变量
Bmp:TBitmap;
DC:hDC;
i:整数;
p:TPoint;
作者:字符串;
AuthorPosX,AuthorPosY:单个;
大小:TSize;
图形:TGPGraphics;
位图:TGPBitmap;
字体:TGPFont;
FontFamily:TGPFontFamily;
SolidBrush:TGPSolidBrush;
开始
消息。结果:=1;
如果(message.DC.0)和已分配(父级),则
开始
DC:=message.DC;
i:=SaveDC(DC);
p:=GetScreenClient(Self);
移动窗口组织(DC,-p.x,-p.y);
SendMessage(Parent.Handle,WM_ERASEBKGND,DC,0);
TPWinControl(主)、PaintControls(直流、无);
恢复性糖尿病(DC,i);
Bmp:=TBitmap.Create;
Bmp.PixelFormat:=pf32位;
Bmp.Width:=宽度;
Bmp.Height:=高度;
BitBlt(Bmp.Canvas.Handle,0,0,宽度,高度,DC,0,0,srcopy);
SolidBrush:=TGPSolidBrush.Create($FF000000);
FontFamily:=TGPFontFamily.Create('Arial');
Font:=TGPFont.Create(FontFamily,18,FontStyleRegular,UnitPixel);
作者:='透明子窗口+GDI+文本';
AuthorPosX:=30;
作者:=40;
Size.cx:=600;
Size.cy:=80;
位图:=TGPBitmap.Create(Bmp.Handle);
Graphics:=TGPGraphics.Create(Bmp.Canvas.Handle);
Graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
图形.抽绳(作者、长度(作者)、字体、,
生成点(AuthorPosX、AuthorPosY)、SolidBrush);
图形。免费;
位图。免费;
绘制(0,0,Bmp);
Bmp.Free;
结束;
结束;
那些水平滚动条令人讨厌。请你编辑一下,让它更容易阅读。就像我刚才做的编辑一样。您可能会考虑对主程序代码执行同样的操作。我认为这里不需要真正的子窗口。什么是父窗口?您不使用VCL窗体和控件是否有原因?>“到底是什么问题?”>-第一个-最重要的-问题是您没有检查错误CreateWindowEx
返回0,您甚至没有子窗口-更不用说缺少文本了。。。这是因为您指定了WS_EX_LAYERED
样式-请参阅文档。是否有其他不使用UpdateLayeredWindow的解决方案?请使窗口透明,以便首先绘制其下方的窗口,然后在WM_PAINT(或OnPaint事件)中绘制代码。您可能需要禁用WM_橡皮擦BKGND消息。我制作了透明VCL控件,用于处理GDI+绘图。我的WinAPI技能目前有点生疏,所以我使用了更简单的方法。
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);
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;