根据位图做出漂亮的不规则FORM  
 
文档内容 
2000年看到一篇文章做的演示代码,可以根据位图做出漂亮的不规则FORM,大家可以下载演示程序研究一下,包含DELPHI版和VC版。 //    
//      -'`"_         -'`" \ 
//     /     \       /      " 
//    /     /\\__   /  ___   \       西安科技?院143信箱 710054 
//   |      | \  -"`.-(   \   | 
//   |      |  |     | \"  |  |                万  重 
//   |     /  /  "-"  \  \    | 
//    \___/  /  (o o)  \  (__/       电邮: [email protected] 
//         __| _     _ |__ 
//        (      ( )      )          网址: http://www.delphibox.com 
//         \_\.-.___.-./_/ 
//           __  | |  __             QQ  : 6036742 
//          |  \.| |./  | 
//          | ''.   .'' | 
//          |__/ '"" \__|                     2001.3.1 
//        -/             \- 
// unit Unit1; interface uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  ExtCtrls, StdCtrls, Buttons; type 
  TForm1 = class(TForm) 
    Image1: TImage; 
    Button1: TButton; 
    procedure FormCreate(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
  private 
    function CreateRegion(wMask: TBitmap; wColor: TColor; 
      hControl: THandle): HRGN; 
    { Private declarations } 
  public 
    { Public declarations } 
  end; var 
  Form1: TForm1; implementation {$R *.DFM} 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.Bitmap); 
  w2:=w1.Canvas.Pixels[0,0]; 
  rgn := CreateRegion(w1,w2,Handle); 
  if rgn<>0 then 
  begin 
     SetWindowRgn(Handle, rgn, true); 
  end; 
  w1.Free; 
end; procedure TForm1.Button1Click(Sender: TObject); 
begin 
  Close; 
end; procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  ReleaseCapture; 
  SendMessage(Handle, WM_SYSCOMMAND, $F012, 0); 
end; end.

解决方案 »

  1.   

    jiaorg(jiaorg) :
       你好,我试了你的代码,没啥反应啊?。
      

  2.   


    下面是演示代码,在image2中放一张美人图,运行后,好好玩噢。
    //------------变形窗口 -----------------// unit Unit1;
        
        interface
        
        uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
        Dialogs, StdCtrls, Spin, ExtCtrls, Buttons, jpeg;
        type
        TForm1 = Class(TForm)
        Panel1: TPanel;
        Image2: TImage;
        SpeedButton3: TSpeedButton;
        SpeedButton2: TSpeedButton;
        SpeedButton4: TSpeedButton;
        SpeedButton5: TSpeedButton;
        SpeedButton1: TSpeedButton;
        SpinEdit1: TSpinEdit;
        SpeedButton6: TSpeedButton;
        SpeedButton7: TSpeedButton;
        procedure DrawRndRectRegion(wnd: HWND; rect: TRect);
        procedure DrawEllipticRegion(wnd: HWND; rect: TRect);
        procedure DrawPolygonRegion(wnd: HWND; rect: TRect; NumPoints: Integer; DoStarShape: Boolean);
        procedure Button5Click(Sender: TObject);
        procedure SpeedButton1Click(Sender: TObject);
        procedure SpeedButton2Click(Sender: TObject);
        procedure SpeedButton3Click(Sender: TObject);
        procedure SpeedButton4Click(Sender: TObject);
        procedure SpeedButton5Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure SpeedButton6Click(Sender: TObject);
        procedure SpeedButton7Click(Sender: TObject);
        private{ Private declarations }
        rgn: HRGN;
        rect: TRect;
        public
        { Public declarations }
        end;
        Var
        Form1: TForm1;
        implementation
        {$R *.DFM}
    // CreateEllipticRgn()功能是生成椭圆形区域;
    //  CreateRoundRectRgn()功能是生成圆角矩形区域;
    //CreatePolygonRgn()功能是生成多边形区域,Windows要确保使其顶点自动相连形成一封闭的区域。procedure TForm1.DrawRndRectRegion(wnd: HWND; rect: TRect);
    begin
        rgn:= CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 30, 30);
        SetWindowRgn(wnd, rgn, TRUE);
    end;
    procedure TForm1.DrawEllipticRegion(wnd: HWND; rect: TRect);
    begin
        rgn:= CreateEllipticRgn(rect.left, rect.top, rect.right, rect.bottom);
        SetWindowRgn(wnd, rgn, TRUE);
    end;
    procedure TForm1.DrawPolygonRegion(wnd: HWND; rect: TRect; NumPoints: Integer; DoStarShape: Boolean);
    const
        RadConvert = PI/180;
        Degrees = 360;
        MaxLines = 100;
    Var
        x, y,xCenter,yCenter,radius,pts,I: Integer;
        angle,rotation: Extended;
        arPts: Array[0..MaxLines] of TPoint;
    begin
          xCenter:= (rect.Right - rect.Left) div 2;
          yCenter:= (rect.Bottom - rect.Top) div 2;
        If DoStarShape Then
        begin
          rotation:= Degrees/(2*NumPoints);
          pts:= 2 * NumPoints;
        End
        Else
        begin
          rotation:= Degrees/NumPoints;//得到每个顶点的度数
          pts := NumPoints;
        end;
        radius:= yCenter;
        for I:= 0 to pts - 1 do begin
        If DoStarShape Then
        If (I Mod 2) = 0 Then
           radius:= Round(radius/2)
        Else
           radius:= yCenter;
           angle:= ((I * rotation) + 90) * RadConvert;
           x:= xCenter + Round(cos(angle) * radius);
           y:= yCenter - Round(sin(angle) * radius);
           arPts[I].X:= x;
           arPts[I].Y:= y;
        end;
        rgn:= CreatePolygonRgn(arPts, pts, WINDING);
        SetWindowRgn(wnd, rgn, TRUE);
    end;procedure TForm1.Button5Click(Sender: TObject);
    begin
        form1.Close;
    end;procedure TForm1.SpeedButton1Click(Sender: TObject);
    begin
       form1.Close ;
    end;procedure TForm1.SpeedButton2Click(Sender: TObject);
    begin
       DrawRndRectRegion(Form1.Handle, Form1.ClientRect);
    end;procedure TForm1.SpeedButton3Click(Sender: TObject);
    begin
        DrawEllipticRegion(Form1.Handle, Form1.ClientRect);
    end;procedure TForm1.SpeedButton4Click(Sender: TObject);
    begin
        DrawPolygonRegion(Panel1.Handle, Panel1.BoundsRect, SpinEdit1.Value, False);
    end;procedure TForm1.SpeedButton5Click(Sender: TObject);
    begin
        DrawPolygonRegion(Panel1.Handle, Panel1.BoundsRect, SpinEdit1.Value, True);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
        SpinEdit1.value = 40
        SpeedButton3Click(sender);
        SpeedButton5Click(sender);
    end;procedure TForm1.SpeedButton6Click(Sender: TObject);
    begin
         form1.WindowState :=   wsMaximized;
    end;procedure TForm1.SpeedButton7Click(Sender: TObject);
    begin
       form1.WindowState :=   wsNormal;
    end;end.
    //------------------------------------------//
      

  3.   

       补充:form1的borderstyle 设为bsnone.   望各位高手,看过以上代码运行效果后,指点一二。。
      

  4.   

    你得用作图软件,优化你的图片上面的例子,是把图片的左上角的像素的颜色定位默认颜色,程序启动画form的时候,遇上默认颜色就不画,所以你的form边界不光滑,就应该把边界上的多余的像素点改为和左上角的像素同一个颜色就行了。
      

  5.   

    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.Bitmap); //取得image1里的图片
      w2:=w1.Canvas.Pixels[0,0];        //取得图片左上角像素的颜色,定位背景颜色
      rgn := CreateRegion(w1,w2,Handle);
      if rgn<>0 then
      begin
         SetWindowRgn(Handle, rgn, true);//重绘窗体
      end;
      w1.Free;
    end;这是我给代码添加的一点注释
      

  6.   

    如果只是想要一个不规则窗口的话可以使用windows的SetWindowRgn API函数,当然首先得定义HRGN,具体的有SetWindowRoundRectRgn、SetWindowPolgyRgn、setwindowPolgypolgyRgn等函数,再加上区域的合并函数,理论上来说可以做出任意形状的窗体。(具体的API函数名可能有误,请自己查找MSDN库,不好意思)
      

  7.   

    是啊
    这主要是图片的问题
    你用photoshop把图片边缘处理
    让它和底色有很大区别
      

  8.   

    我在image 里放一张jpeg图片,试了你的代码,怎么一运行,就出现整个form的背景颜色,image 也被画掉了,form的背景颜色还是原来的颜色?而没有取得图片上像素的颜色,来定位背景颜色,为何?
      

  9.   

    图片边缘是用photoshop处理过了的
      

  10.   

    你留email,我发给你实例,d6编译通过的