登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> 程序员学前班[不再更新,只读] >> 主题: [delphi/透明窗体]GDI+用PNG图片做半透明异型窗口[zt]     [回主站]     [分站链接]
标题
[delphi/透明窗体]GDI+用PNG图片做半透明异型窗口[zt]
clq
浏览(1) + 2008-12-23 11:03:34 发表 编辑

关键字:

[delphi/透明窗体]GDI+用PNG图片做半透明异型窗口[zt]

http://hi.baidu.com/bluew/blog/item/2ecbe58bf93a937d9f2fb4de.html

  我是用PNG图片Alpha透明的方式做的窗口,这种方法一个好处就是不用通过编程来控制窗口外观。Delphi7设置一下窗体的 BorderStyle、Color、Transparent、TransparentColor属性就可以搞定异型窗口,但不是半透明的。 UpdateLayeredWindow函数里设置Blend函数就可以实现半透明异型窗体。最近有个哥们网上弄来个老外用VC写的代码,他找人翻译成 BCB的,因为BCB本身就支持GDI+,而Delphi不支持,所以我又找GDI+的类,我又改写成Delphi版的了,程序编译运行候效果很不错。需要两个pas文件:GDIPAPI, GDIPOBJ网上都有,唯一缺点是无法放VCL组件!放了也看不到,我真是晕啊,各位也帮忙看一下怎么解决??以下是全部源码:
//======================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,
GDIPAPI, GDIPOBJ, Menus, StdCtrls; //http://www.progdigy.com/modules.php?name=gdiplus

type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
Close1: TMenuItem;
ChangeSkin1: TMenuItem;
About1: TMenuItem;
N1: TMenuItem;
N2: TMenuItem;
Edit1: TEdit;
Button1: TButton;
Stayontop1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Close1Click(Sender: TObject);
procedure ChangeSkin1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure Stayontop1Click(Sender: TObject);
private
m_Blend: BLENDFUNCTION;
procedure SetTransparent(lpSkinFile: WideString; nTran: integer);
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
m_Blend.BlendOp := AC_SRC_OVER; // the only BlendOp defined in Windows 2000
m_Blend.BlendFlags := 0; // Must be zero
m_Blend.AlphaFormat := AC_SRC_ALPHA;//This flag is set when the bitmap has an Alpha channel
m_Blend.SourceConstantAlpha := 255;
if(FileExists(ExtractFilePath(ParamStr(0)) + 'test.png')) then
SetTransparent(WideString(ExtractFilePath(ParamStr(0)) + 'test.png'), 100);
// Stay on top
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TForm1.SetTransparent(lpSkinFile: WideString; nTran: integer);
var
GPImage: TGPImage;
GPGraph: TGPGraphics;
m_Image: TGPImage;

m_hdcMemory: HDC;
hdcScreen: HDC;
hBMP: HBITMAP;

sizeWindow: SIZE;
rct: TRECT;
ptSrc: TPOINT;
begin
// Use GDI+ load image
GPImage:= TGPImage.Create();
m_Image:= GPImage.FromFile( lpSkinFile );

// Create Compatible Bitmap
hdcScreen := GetDC(0);
m_hdcMemory := CreateCompatibleDC(hdcScreen);
hBMP := CreateCompatibleBitmap(hdcScreen, m_Image.GetWidth(), m_Image.GetHeight());
SelectObject(m_hdcMemory, hBMP);

// Alpha Value
if (nTran<0) or (nTran >100) then
nTran := 100;
m_Blend.SourceConstantAlpha := round(nTran * 2.55); // 1~255
GetWindowRect(Handle, rct);

GPGraph:= TGPGraphics.Create(m_hdcMemory);
GPGraph.DrawImage(m_Image, 0, 0, m_Image.GetWidth(), m_Image.GetHeight());

sizeWindow.cx:= m_Image.GetWidth();
sizeWindow.cy:= m_Image.GetHeight();

ptSrc.x:= 0;
ptSrc.y:= 0;

// Set Window style
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);

// perform the alpha blend
UpdateLayeredWindow(Handle, hdcScreen, nil,
@sizeWindow, m_hdcMemory, @ptSrc, 0, @m_Blend, ULW_ALPHA);
//Release resources
GPGraph.ReleaseHDC(m_hdcMemory);
ReleaseDC(0, hdcScreen);
hdcScreen := 0;

DeleteObject(hBMP);

DeleteDC(m_hdcMemory);
m_hdcMemory := 0;

m_Image.Free;
GPGraph.Free;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if(Button = mbLeft) then
begin
ReleaseCapture();
Perform(WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0);
end;
end;

procedure TForm1.Close1Click(Sender: TObject);
begin
Close();
end;

procedure TForm1.ChangeSkin1Click(Sender: TObject);
var
dlgOpen: TOpenDialog;
begin
dlgOpen := TOpenDialog.Create(Self);
dlgOpen.Filter := 'PNG file(*.png)|*.png';
if(dlgOpen.Execute()) then
begin
SetTransparent(WideString(dlgOpen.FileName), 100);
Invalidate();
end;
dlgOpen.Free;
end;

procedure TForm1.About1Click(Sender: TObject);
begin
MessageDlg('GDI plus API by: http://www.progdigy.com '#13 +
'C++Builder example by: http://www.ccrun.com '#13 +
'Delphi example by: http://www.handsomesoft.com ',mtInformation, [mbOK], 0);
end;

procedure TForm1.Stayontop1Click(Sender: TObject);
var
mi: TMenuItem;
WindowPos: HWND;
begin
mi := Sender as TMenuItem;
mi.Checked := not mi.Checked;
if mi.Checked then
WindowPos:= HWND_TOPMOST
else
WindowPos:= HWND_NOTOPMOST;
SetWindowPos(Handle, WindowPos,
0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end;

end.

clq
2008-12-23 11:05:00 发表 编辑

迅雷 在打开过后一段时间会有一个Flash广告,这个flash是透明的,我见过它还可是做成动画形式的.
clq
2008-12-23 11:20:35 发表 编辑

UpdateLayeredWindow
--------------------------------------------------

问题: 实时的透明窗体!!help help me !! ( 积分: 50 )
分类: 图形图象

来自: bestlive, 时间: 2001-04-18 21:01:00, ID: 508518
我想做一个透明窗体,但这个窗体上放了一个image控件。
image可以变得透明。
但如何让窗体也变得透明呢,而且在拖动窗体时背景要时实变化。
如果这个窗体是一个子窗体呢,如何也让这个子窗体变得透明(实时拖动).


来自: htw, 时间: 2001-04-19 0:11:00, ID: 508738
找个控件吧,程序员大本营2000(荟萃版)上有这种控件,去买正版或D版吧。
你也可到 www.csdn.net 上去找

来自: 左轻侯, 时间: 2001-04-19 2:54:19, ID: 508798
关注此题

来自: xiuguo, 时间: 2001-04-19 11:24:00, ID: 509034
你可以自己用“透明”搜索一下,我就是从delphibbs上面搜索下来的!


来自: 卷起千堆雪tyn, 时间: 2001-04-19 23:11:00, ID: 509911
transparent form ?
哈哈...我为你做好了,你参考吧.
{Add a button to a form and try this:}
procedure TForm1.FormCreate(Sender: TObject);
var
FullRgn, ClientRgn, ButtonRgn: THandle;
Margin, X, Y: Integer;
begin
Margin := (Width - ClientWidth) div 2;
FullRgn := CreateRectRgn(0, 0, Width, Height);
X := Margin;
Y := Height - ClientHeight - Margin;
ClientRgn := CreateRectRgn(X, Y, X + ClientWidth, Y + ClientHeight);
CombineRgn(FullRgn, FullRgn, ClientRgn, RGN_DIFF);
X := X + Button1.Left;
Y := Y + Button1.Top;
ButtonRgn := CreateRectRgn(X, Y, X + Button1.Width, Y + Button1.Height);
CombineRgn(FullRgn, FullRgn, ButtonRgn, RGN_OR);
SetWindowRgn(Handle, FullRgn, True);
end;

来自: bbboy, 时间: 2001-04-19 23:27:00, ID: 509930
窗体透明有很多的方法,其中一种就是上面"卷起千堆雪tyn",的方法,这个方法并不是典型的
不规则窗体,另外还有一种透明窗体的实现方法类似于抓屏,也就是将窗体后面的内容抓取
下来,再复制到程序上面,金山词霸就是使用的这种方法.

来自: bbcoll, 时间: 2001-04-22 10:24:00, ID: 513078
卷起千堆雪tyn:
这种方法我用过,但是这个窗体完全透明了,连上面的image也不见了,所有控件都没有用了。
我希望可以窗体是透明的而窗体上的image中的图片可以看见的,
而且这个用法在子窗体里不透明。
我要风掉了。


来自: coao, 时间: 2001-04-22 23:29:49, ID: 514037
关注此题

来自: jzx, 时间: 2001-04-23 0:18:00, ID: 514058
你可以试试 BITRGN 这个组件,我用的就是这个,挺好用的。你要的话我给你发过去

来自: tonylk, 时间: 2001-04-23 12:27:00, ID: 514375
我做了个小程序,有你类似的功能:以下是部分代码:
procedure TSprite.SaveBackGround();
var
SC:TCanvas;
begin
SetWindowPos(FormMain.Handle,HWND_BOTTOM,FormMain.Left,FormMain.Top,FormMain.Width,FormMain.Height,SWP_HIDEWINDOW);
SC:=TCanvas.Create;
try
SC.Handle:=GetDC(0);
FOldBmp.Canvas.CopyRect(Rect(0,0,SPWIDTH,SPHEIGHT),SC,Rect(FPosition.X,FPosition.Y,FPosition.X+SPWIDTH,FPosition.Y+SPHEIGHT));
FNewBmp.Assign(FOldBmp);
ReleaseDC(0,Sc.Handle);
finally
SC.Free;
end;
FormMain.Canvas.Draw(0,0,FOldBmp);//this line here let the form be transparent when the form create
SetWindowPos(FormMain.Handle,HWND_TOPMOST,FormMain.Left,FormMain.Top,FormMain.Width,FormMain.Height,SWP_NOMOVE+SWP_SHOWWINDOW);
end;

procedure TSprite.Paint(X,Y:integer;Image:TBitmap);
function XslateRect(R:Trect;X,Y:integer):TRect;
begin
with R do Result:=Rect(Left-X,Top-Y,Right-X,Bottom-Y);
end;//XslateRect(R:Trect;X,Y:integer):TRect;
var
SC:TCanvas;
OrgRect,OldRect,NewRect,TmpRect:TRect;
OldRgn,NewRgn,TmpRgn:HRgn;
TmpWindow:Hwnd;
begin
OrgRect:=Rect(0,0,SPWIDTH,SPHEIGHT);
OldRect:=Rect(FPosition.X,FPosition.Y,FPosition.X+SPWIDTH,FPosition.Y+SPHEIGHT);
NewRect:=Rect(X,Y,X+SPWIDTH,Y+SPHEIGHT);

OldRgn:=CreateRectRgnIndirect(OldRect);
NewRgn:=CreateRectRgnIndirect(NewRect);
TmpRgn:=CreateRectRgnIndirect(OldRect);

TmpWindow:=GetForeGroundWindow();
if (TopWindow<>TmpWindow) and (TmpWindow<>FormMain.Handle) and (TmpWindow<>Application.Handle) then begin
SaveBackground();
TopWindow:=TmpWindow;
end;

try
SC:=TCanvas.Create();
try
SC.Handle:=GetDC(0);
FNewBmp.Canvas.CopyRect(OrgRect,SC,NewRect);
CombineRgn(TmpRgn,NewRgn,OldRgn,RGN_AND);
GetRgnBox(TmpRgn,TmpRect);
FNewBmp.Canvas.CopyRect(XslateRect(OldRect,X,Y),FOldBmp.Canvas,OrgRect);
FOldBmp.Canvas.CopyRect(OrgRect,FNewBmp.Canvas,OrgRect);
FNewBmp.Canvas.Draw(0,0,Image);
FormMain.Canvas.Draw(0,0,FNewBmp);
ReleaseDC(0,SC.Handle);
finally
SC.Free;
end;
finally
DeleteObject(TmpRgn);
DeleteObject(NewRgn);
DeleteObject(OldRgn);
end;
FPosition.X:=X;FPosition.Y:=Y;
end;//Paint(X,Y:integer;Image:TBitmap);


你也可以写信给我,我把完整程序给你。。

来自: datasoft, 时间: 2001-04-23 13:02:00, ID: 514411
透明窗口的设计   
运行环境:Delphi 3 及其以上版本, Windows 2000

  我们以前都看过许多介绍设计透明窗口的文章,它们大多数实用的是将指定的区域用背景填充的方法。下面我们来看一下怎样使用Windows 2000 中的 GUI 功能--也被叫做"分层窗口",来实现完全的透明窗口。
  透明窗口的一个很好的例子是在Windows 2000 的菜单和开始菜单中使用的淡入效果。
  要创建一个分层窗口,当调用 Create WindowEx 函数时,我们要指定 WS_EX_LAYERED 来扩展窗口的风格,或者在窗口创建以后调用SetWindowLong 函数设定WS_EX_LAYERED的值。在函数Create WindowEx 被调用后,分层窗口并不会变得可见,而是要等到对这个窗口调用SetLayeredWindowAttributes 或者UpdateLayeredWindow 后。
  WS_EX_LAYERED是一个新的常量,所以我们必须事先对它声明。还有几个和Alpha 组合的常量也要事先声明。

  const WS_EX_LAYERED = $80000;
  AC_SRC_OVER = $0;
  AC_SRC_ALPHA = $1;
  AC_SRC_NO_PREMULT_ALPHA = $1;
  AC_SRC_NO_ALPHA = $2;
  AC_DST_NO_PREMULT_ALPHA = $10;
  AC_DST_NO_ALPHA = $20;
  LWA_COLORKEY = $1;
  LWA_ALPHA = $2;
  ULW_COLORKEY = $1
  ULW_ALPHA =$2
  ULW_OPAQUE = $4

  下面是对新函数的声明:
  function SetLayeredWindowAttributes(hwnd:HWND; crKey:Longint; bAlpha:byte;
  dwFlags:longint ):longint; stdcall; external user32;

  要使用这个新功能创建一个新的窗口, 在创建事件句柄中(Create evert handle)输入以下代码:
  procedure TForm1.FormCreate(Sender: TObject);
  var l:longint;
  begin
  l:=getWindowLong(Handle, GWL_EXSTYLE);
  l := l Or WS_EX_LAYERED;
  SetWindowLong (handle, GWL_EXSTYLE, l);
  SetLayeredWindowAttributes (handle, 0, 180, LWA_ALPHA);
  end;

  SetLayeredWindowAttributes 的第二个参数是crKey. 这是一个指向颜色值(ColorRef value) 的指针,它标示的是透明处的象素颜色,我把它设置为0。第三个参数bAlpha是一个表示窗口不透明程度的变量,它的值在0~255之间。例如,0代表的是完全透明,而255代表的是完全不透明。第四个参数dwFlags 指定窗口使用crKey 还是bAlpha。LWA_ALPHA表示使用bAlpha来确定窗口的透明程度。另一个值是LWA_COLORKEY,它表示使用crKey来确定窗口的透明程度。
  运行这个程序,你就会得到一个透明的窗口。现在,如果你在窗口上放置按钮(button),文本框(textbox) 或是其它控件,它们也会变成透明的!

  请注意,分层窗口占用很大的系统资源,至少要在Pentium 200 或者以上的机器上运行。我用的是PⅡ 600 MHZ,但是如果窗口太大的话,它还是不能在屏幕上很平滑的移动。千万不要把所有的窗口都设计成透明的,如果那样的话,每次刷新窗口的时候,你都要等上半小时。

  这只是一个很简单的介绍,关于本文中用到的API 函数,你可以访问www.msdn.mircosoft.com 网站,或是 www.microsoft.com/china/msdn 以获取更详细的信息。


来自: ZhuHongQing, 时间: 2001-05-19 2:25:00, ID: 535898
用这个就行:
function Tform1.CreateRegion(wMask:TBitmap;wColor:TColor;hControl:THandle): HRGN;
var
dc, dc_c: HDC;
rgn: HRGN;
x, y: integer;
coord: TPoint;
line: boolean;
color: TColor;
begin
dc := GetWindowDC(hControl);
dc_c := CreateCompatibleDC(dc);
SelectObject(dc_c, wMask.Handle);
BeginPath(dc);
for x:=0 to wMask.Width-1 do
begin
line := false;
for y:=0 to wMask.Height-1 do
begin
color := GetPixel(dc_c, x, y);
if not (color = wColor) then
begin
if not line then
begin
line := true;
coord.x := x;
coord.y := y;
end;
end;
if (color = wColor) or (y=wMask.Height-1) then
begin
if line then
begin
line := false;
MoveToEx(dc, coord.x, coord.y, nil);
LineTo(dc, coord.x, y);
LineTo(dc, coord.x + 1, y);
LineTo(dc, coord.x + 1, coord.y);
CloseFigure(dc);
end;
end;
end;
end;
EndPath(dc);
rgn := PathToRegion(dc);
ReleaseDC(hControl, dc);
Result := rgn;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
w1:TBitmap;
w2:TColor;
rgn: HRGN;
begin
w1:=TBitmap.Create;
w1.Assign(image1.Picture);
w2:=w1.Canvas.Pixels[0,0];
rgn := CreateRegion(w1,w2,Handle);
if rgn<>0 then
begin
SetWindowRgn(Handle, rgn, true);
end;
w1.Free;

end;

来自: smilboy, 时间: 2001-10-01 0:02:00, ID: 653490
delphi 怎么实现Foxmail消息一样的半透明窗体呢?请讨论

来自: free_knight, 时间: 2001-10-22 12:34:00, ID: 685520
将form的color 属性设成 clGray
transparentcolor 设成 true
transparentcolorvalue 设成 和 color 一样的

来自: free_knight, 时间: 2001-10-22 12:38:00, ID: 685527
还有把 form 的 borderstyle 设成 bsNone

来自: varphone, 时间: 2001-10-22 16:42:00, ID: 686010
Blend Window require the Windows 2000 or later version!
Use the SetWindowLong(..GWL_ALPHA);
SetLayeredWindowAttributes(Handle...);

来自: pengyt, 时间: 2001-10-22 18:12:00, ID: 686237
你是要完全透明还是半透明:
如果是完全透明,就用卷起千堆雪tyn的方法,这实际上是做异型窗体,
如果是半透明,而且要求是实时的话,必须在win2000/win Xp平台上才行
具体做法(必须是delphi6):
alphablend:=true,
alphablendvalue:=你需要的值(如 200)
就是这么简单!!
以上两个属性可以在object inspector 中直接修改,一行代码都不用写

来自: yy, 时间: 2001-10-23 15:37:00, ID: 687536
to ZhuHongQing,
还是不能显示图象。

来自: hgbdelphi, 时间: 2001-10-29 20:08:00, ID: 695098
下面有一个源程序,可以满足你的要求!
<a href="http://www.vclxx.org/DELPHI/D32SAMPL/XPFORM.ZIP">xpform</a>

来自: 狂龙, 时间: 2001-10-29 20:11:00, ID: 695103
在DELPHI6中可以很方便地实现窗体透明的效果

来自: wjiachun, 时间: 2003-04-17 21:34:00, ID: 1779592
接受答案了.

得分大富翁: tonylk


clq
2008-12-23 11:25:48 发表 编辑

直接在 delphi 中设置相比 createrectrgn 来说可以是动态的不透明区域.

总数:3 页次:1/1 首页 尾页  
总数:3 页次:1/1 首页 尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1