如何利用Image来创建不规则窗体?(100分)

  • 主题发起人 主题发起人 DDeveloper
  • 开始时间 开始时间
D

DDeveloper

Unregistered / Unconfirmed
GUEST, unregistred user!
以前也用过,但忘记在哪里能找到了,急着寻求答案,望各位HIGH MAN指点迷经!
 
参考
http://cnprogram.myrice.com/article/cbuilder/cbuilder58.html
 
看怎麼個不規則法,如果僅僅是Circle.....則可以
var r1:longint;.....
r1:=CreateRoundRectRgn(0,0,Form2.Width,Form2.Height,40,40);
SetWindowRgn(Form2.Handle,r1,True);
 
我写的三个函数,大奉献!! 记得要给分啊!!
███████████████████████████

//此函数通过一张位图来创建一个区域,支持bmp格式和jpg格式
//位图中黑色的地方将不透明,非黑色的地方透明,
//创建完毕后可以通过SetWindowRgn函数设置窗口或控件的形状,如:
//setWindowRgn(handle,zjs_createImageRegion('c:/goomoo.bmp'),true);
uses jpeg;
function zjs_createImageRegion(imageFile:TFilename):HRGN;
var
bitmap:TBitmap; //位图对象
jpg:TJpegImage;
hRegion,hTmpRegion:HRGN; //hRegion: 最终区域 hTmpRegion 临时区域
h,l,left,right:integer; //h:行 l:列 left:临时区域的左边 right:临时区域的右边
started:Boolean; //是否开始记录
ext:String; //图片扩展名
begin
if not fileExists(imageFile) then
begin
result:=0;
exit; //文件不存在则退出,并返回0
end;
bitmap:=TBitmap.Create;
try
ext:=extractFileExt(imageFile); ext:=lowerCase(ext);
if (ext='.jpg') or (ext='.jpeg') then //如果是jpg图片
begin
jpg:=TJpegImage.Create;
try
jpg.LoadFromFile(imageFile);
bitmap.Assign(jpg); //从Jpg中把位图拷贝过来
finally
jpg.Free; //及时释放jpg
end;
end
else if ext='.bmp' then
bitmap.LoadFromFile(imageFile) //载入位图
else
begin
result:=0;
exit;
end;

hRegion:=createRectRgn(0,0,0,0); //创建一个初始的空的区域
//初始化变量,消除警告信息
left:=0; right:=0;
//开始扫描图片的每个像素
for h:=0 to bitmap.Height-1 do
begin
started:=false;
for l:=0 to bitmap.Width-1 do
begin
if bitmap.Canvas.Pixels[l,h]=clBlack then //黑色为不透明区域,其他颜色为透明区域
begin
if not started then
begin
started:=true; //开始记录右边
left:=l; right:=l+1;
end
else //started
begin
right:=l;
end;
end
else
begin
if started then //如果已经开始并且该点的颜色不是黑色
begin
started:=false; //结束记录右边
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
end;
if started then //到了图片的右边还没有结束
begin
if right>bitmap.Width-1 then right:=bitmap.Width-1;
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
finally
bitmap.Free;
end;
Result:=hRegion;
end;
 
███████████████████████████
我写的三个函数,大奉献!! 记得要给分啊!!
███████████████████████████

//此函数通过一张emf图片来确定窗口的形状。emf文件比bmp和jpg文件都小得多,而且因为
//是矢量图形,可以无限缩放。你需要指定你需要的宽和高(注意不是图片本身的宽和高)
//用法:
//region:=zjs_createEmfRegion('c:/goomoo.emf',640,480);
//setWindowRgn(handle,region,true);
function zjs_createEmfRegion(emfFilename:TFilename;_Width,_Height:integer):HRGN;
var
emf:TMetaFile;
bitmap:TBitmap;
hRegion,hTmpRegion:HRGN; //hRegion: 最终区域 hTmpRegion 临时区域
h,l,left,right:integer; //h:行 l:列 left:临时区域的左边 right:临时区域的右边
started:Boolean; //是否开始记录
begin
if (not fileExists(emfFilename)) or (lowerCase(extractFileExt(emfFilename))<>'.emf') then
begin
result:=0;
exit;
end;

hRegion:=CreateRectRgn(0,0,0,0);
//初始化变量,消除警告信息
left:=0; right:=0;

emf:=TMetafile.Create;
bitmap:=TBitmap.Create;
try
emf.LoadFromFile(emfFilename);
emf.Width:=_Width;
emf.Height:=_Height;
bitmap.Width:=_Width;
bitmap.Height:=_Height;
bitmap.Canvas.Draw(0,0,emf);
emf.Free;
//开始扫描图片的每个像素
for h:=0 to bitmap.Height-1 do
begin
started:=false;
for l:=0 to bitmap.Width-1 do
begin
if bitmap.Canvas.Pixels[l,h]=clBlack then //黑色为不透明区域,其他颜色为透明区域
begin
if not started then
begin
started:=true; //开始记录右边
left:=l; right:=l+1;
end
else //started
begin
right:=l;
end;
end
else
begin
if started then //如果已经开始并且该点的颜色不是黑色
begin
started:=false; //结束记录右边
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
end;
if started then //到了图片的右边还没有结束
begin
if right>bitmap.Width-1 then right:=bitmap.Width-1;
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
finally
bitmap.Free;
end;
result:=hRegion;
end;
 
███████████████████████████
我写的三个函数,大奉献!! 记得要给分啊!!
███████████████████████████

//下面这个函数是新的算法,速度很要很多(差不多是原来的三分之一),不过并不适合所有的图片,只适合Y轴无凹形的图片(比如葫芦形)。
//思路如下:
// 1.找到开始有黑色的一行,并将行号存入currentRow中。并将该行中的左端点和右端点分别存放于 lastLeft 和 lastRight 变量中。然后跳出循环。
// 2.进入下一行。依据上一行的left和right来搜索本行的left和right。这样很快。找到后就合并区域。
// 3.循环直到有一行没有找到left和right(也就是没有黑色)就跳出。
//这个算法因为没有搜索图片的所有像素,所以快很多。希望能起个抛砖引玉的作用。
//此函数通过Y轴无凹形的图片(比如葫芦形)来创建区域。
function zjs_CreateYProtrudeImageRgn(imageFile:TFilename):HRGN;
label
firstLineFounded,L_leftFound,L_rightFound;
var
hRegion,hTmpRegion:HRGN; //hRegion:最终区域 hTmpRegion:临时区域
bitmap:TBitmap; //位图对象
left,right,lastLeft,lastRight,row,col,currentRow:integer;
started,leftFound,rightFound:boolean; //started:是否开始记录
begin
//初始化变量
started:=false;
currentRow:=0;
left:=-1; right:=-1;
hRegion:=createRectRgn(0,0,0,0);
bitmap:=TBitmap.Create;
try
bitmap.LoadFromFile(imageFile);
//找到第一行的left和right
for row:=0 to bitmap.Height-1 do
begin
for col:=0 to bitmap.Width-1 do
begin
if bitmap.Canvas.Pixels[col,row]=clBlack then //找到第一个黑点
begin
if not Started then
begin
started:=true;
left:=col; right:=col+1;
currentRow:=row; //记下当前是第几行
continue;
end
else
right:=col;
end;
end; { for col}
if started then
begin
hTmpRegion:=createRectRgn(left,row,right,row+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
goto firstLineFounded;
end;
end; {for row}
firstLineFounded:
if (left<>-1) then //确认已经找到了第一条黑线
begin
lastLeft:=left; lastRight:=right;
for row:=currentRow+1 to bitmap.Height-1 do
begin
leftFound:=false;
rightFound:=false;

//找到本行的左边
if bitmap.Canvas.Pixels[0,row]=clBlack then
begin
left:=0;
leftFound:=true;
goto L_leftFound;
end
else
begin
col:=lastLeft;
while col>=0 do //往左搜索
begin
if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then
begin
left:=col;
leftFound:=true;
goto L_leftFound;
end;
col:=col-1;
end;
col:=lastLeft;
while col<lastRight do //往右搜索
begin
if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then
begin
left:=col;
leftFound:=true;
goto L_leftFound; //跳出循环
end;
col:=col+1;
end;
end;
L_leftFound:

//找到本行的右边
if bitmap.Canvas.Pixels[bitmap.Width-1,row]=clBlack then
begin
right:=bitmap.Width-1;
rightFound:=true;
goto L_rightFound;
end
else
begin
col:=lastRight;
while col<bitmap.Width-1 do //往右搜索
begin
if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then
begin
right:=col+1;
rightFound:=true;
goto L_rightFound;
end;
col:=col+1;
end;
while col>lastLeft do //往左搜索
begin
if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then
begin
right:=col+1;
rightFound:=true;
goto L_rightFound;
end;
col:=col-1;
end;
end;
L_rightFound:

if leftFound and rightFound then
begin
lastLeft:=left; lastRight:=right;
hTmpRegion:=createRectRgn(left,row,right,row+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end
else
break;
end; {for row}
end;
finally
bitmap.Free;
end;
result:=hRegion;
end;
 
有一点不明……
这样创建出一个窗体,想要把原来的位图用Form.Canvas.Draw画上去,但是没有效果,
如果用IMAGE控件,可以显示位图,但是遮住了主窗体,所以下面的全窗体拖动过程无
效……
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
begin
if ssleft in shift then begin
releasecapture;
form1.Perform(WM_syscommand,$f012,0);
end;
end;
小弟初学,还请各位指点了……
 
用我写的那三个函数,不需要Image控件.
 
后退
顶部