我想创建一个表单,但只是使用它来保存图像。 (就像一个泼水形式)
要创建这样的表单,请使用以下行:
SetWindowLong(Handle, GWL_EXSTYLE, LexStyle or WS_EX_LAYERED);
UpdateLayeredWindow(Handle, 0, nil, @LBitmapSize, LBitmap.Canvas.Handle, 0,
@LBlendFunction, ULW_ALPHA);
此图像是带透明层的PNG图像。
表单必须具有父表单,或者必须具有包含表单的表单的行为。
这就是问题,如果我在这个表单上添加一些组件,这只是不显示组件。 如果我将父表单设置为它,则会失去透明度。
但我需要在此添加组件,我需要为表单设置父级。
有人知道其他方法吗?
答案 0 :(得分:2)
您不能在子窗口上使用WS_EX_LAYERED样式,例如分配了父窗体的窗体。您将不得不使用SetWindowRgn()。
答案 1 :(得分:2)
您可以尝试不直接设置Parent属性,但使用子类化...
假设TParentForm是父形式,TAlphaForm是带有图像的形式。
创建TAlphaForm实例时,将TParentForm的实例作为Owner参数传递,并在构造函数中更改所有者表单的WndProc。
接下来是TAlphaForm的示例代码:
type
TAlphaForm = class(TForm)
private
FParentWndProc : TWndMethod;
FParentForm : TCustomForm;
procedure HookWindowProc(var Message: TMessage);
public
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
end;
实现:
constructor TAlphaForm.Create(AOwner: TComponent);
begin
inherited;
if(Assigned(AOwner) and (Owner is TCustomForm)) then begin
FParentForm := TCustomForm(Owner);
// Subclass owner window
FParentWndProc := FParentForm.WindowProc;
FParentForm.WindowProc := HookWindowProc;
// Need to repaint to show initial picture
if(FParentForm.HandleAllocated) then FParentForm.Invalidate;
end else begin
FParentForm := nil;
FParentWndProc := nil;
end;
end;
destructor TAlphaForm.Destroy;
begin
if(Assigned(FParentForm)) then begin
// Restore original WndProc and repaint to restore original look if available
FParentForm.WindowProc := FParentWndProc;
if(FParentForm.HandleAllocated) then FParentForm.Invalidate;
FParentForm := nil;
FParentWndProc := nil;
end;
inherited;
end;
procedure TAlphaForm.HookWindowProc(var Message: TMessage);
begin
if( not (Assigned(FParentForm) and Assigned(FParentWndProc)) )
then exit;
FParentWndProc(Message);
if(Message.Msg = WM_PAINT) then begin
// Paint alpha image here on Owner's form canvas
// Here is sample painting
FParentForm.Canvas.Pen.Width := 3;
FParentForm.Canvas.Pen.Color := clRed;
FParentForm.Canvas.Ellipse(FParentForm.ClientRect);
end else if(Message.Msg = WM_SIZE) then begin
// Needed because the whole form must be repainted
FParentForm.Invalidate;
end;
end;
对我来说,解决方案适用于此父表单代码:
type
TForm1 = class(TForm)
Button2: TButton;
Button3: TButton;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
FAlpha : TForm;
public
{ Public declarations }
constructor Create(AOwner : TComponent); override;
end;
实现:
procedure TForm1.Button2Click(Sender: TObject);
begin
if(not Assigned(FAlpha)) then FAlpha := TAlphaForm.Create(Self);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
FreeAndNil(FAlpha);
end;
constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
FAlpha := nil;
end;
答案 2 :(得分:0)
假设同一个应用程序中的两个表单,您是否尝试过构建一个可以作为选项处理程序的公共方法?类似的东西:
function TForm1.UpdateForm(Action: Integer/[Enumerated Type]/[etc]; Parameters: TStringList): Boolean;
在里面有适当的处理代码可以得到你所需要的,而不必诉诸api回调或需要处理信息。