创建透明的窗体并移动它上面的子窗体

 

创建透明的窗体并移动它上面的子窗体

ByCorbin Dunn

    你也许见过带有透明区域的窗体,并想知道在Delphi里面如何实现。很简单,有几种不同的方法能取得下面的效果:

    第一种解决的方法是给窗体添加WS_EX_TRANSPARENT风格。这种方法可行,但是达不到期望的全部效果,Microsoft建议对生命短暂的模式窗体使用WS_EX_TRANSPARENT风格。

    第二种解决方法是使用Windows 2000新的分层窗口的功能。然而,这样会限制你的应用程序只能运行在Windows2000

    这篇文章选择了第三种方法。您可以调用Windows APISetWindowRgn来指定窗口的哪些区域是你想要看到的,难点之一是创建这个区域,它包含所有你想看到的所有子窗体。解决的办法是枚举窗体上所有可见的控件,把这些控件占的小区域合并成一个大区域。下面就是实现的代码:

 

procedure TForm1.SetRegions;
var
  I: Integer;
  RgnAll, RgnCtrl: HRGN;
begin
  RgnAll := 0;
  for I := 0 to ControlCount - 1 do
  begin
    with Controls[I] do
    begin
      if Visible then
      begin
        // Create a region for each given visible control
        RgnCtrl := CreateRectRgn(Left, Top, Left + Width, Top + Height);
        // Combine the region with all previous ones, if available
        if (RgnCtrl <> 0) and (RgnAll <> 0) then
        begin
          CombineRgn(RgnAll, RgnAll, RgnCtrl, RGN_OR);
          DeleteObject(RgnCtrl);
        end
        else
          RgnAll := RgnCtrl; // This is the first region being created
      end;
    end;
  end;
  // Now, set the RgnAll as what we see for the Window
  if RgnAll <> 0 then
  begin
    (*
      From SetWindowRgn in the help file:
       "After a successful call to SetWindowRgn,
       the operating system owns the region specified
       by the region handle hRgn. The operating system
       does not make a copy of the region. Thus, you
       should not make any further function calls with
       this region handle. In particular, do not close
       this region handle."
 
       So don't call DeleteObject on RgnAll after using
       it for SetWindowRgn (thanks to Richard Albury for
       pointing this out!) A previous version of this article
       made this mistake.
    *)
    SetWindowRgn(Handle, RgnAll, True);
  end;
end;

 

    注意我在使用完一个区域后调用了DeleteObject ,不这样做将导致Windows资源泄漏。API CreateRectRgn是创建矩形区域,如果你的形状不同,可以使用CreatePolygonRgn来精确定义窗口或控件的形状。

    移动窗体上的控件时你可能会遇到一个问题。如果编程移动控件(如在OnMouseMove事件里面),控件会超出上面创建的区域;此外,移动的时候也可能无法正确绘制控件。一个简单的解决办法是:移动的同时调用SetRegions,更新窗体的可见区域;并调用Control.Repaint,强制重绘控件。代码如下:

procedure TForm1.GenericMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  // If the control wasn't moved, then exit right away
  if (X - LastX = 0) and (Y - LastY = 0) then Exit;
  // Move the control
  with (Sender as TControl) do
  begin
    Left := Left + (X - LastX);
    Top := Top + (Y - LastY);
  end;
  SetRegions;
  (Sender as TControl).Repaint;
end;

    在你的应用程序中添加透明窗体,现在应该不成问题。

原文来源:http://edn.embarcadero.com/article/26277

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值