不用第三方皮肤控件,单用贴图片的方法来构造软件界面,遇到几个问题,解决不了,请教高手解答。
先将Form1的borderstyle设为none,然后进行贴图,问题来了:1、边框用画有圆角的图片来实现,而图片放在panel中,但panel的角是直角,那如何实现圆角?类似qq2008的圆角界面。
2、将边框去掉以后,如何实现窗体拉伸功能?
3、网上有没有做得比较好看一点的界面例程?最好是模仿vista风格的,满世界找都没找到。请提供线索。当然,不能使用第三方皮肤控件。
很急!感谢!

解决方案 »

  1.   

    将窗体设置成透明的(属性alphablend以及alphablendvalue),然后赋予底图,这样看上去好像就是异形窗体了
    当然也是可以通过代码来实现异形窗体的
      

  2.   

    你可以用一些区域api函数,比如这个 CreateRoundRectRgn
    还有其他类似的函数,要配合起来用。你可以搜一下msdn,关键字 rgn,理论上能弄出任何形状的控件或者窗体
    我用这些函数弄了一个圆角矩形的stringgrid
      

  3.   

    bdmh 神速啊,我打字的功夫
      

  4.   

    bdmh一直都是超速打字中………………关于这个问题,可以使用DX组件具体资料,我去万一的博客剽窃一下
      

  5.   

    bdmh你好,你说的方法我试了一下,好像不太可行,因为贴图是很多块组成的。
    alphablend:=true;
    alphablendvalue:=0;
    连贴图都看不见了。
    异性窗体源码很多,但是都是使用的单张图片实现的。
      

  6.   

    wzzwwz你好,画圆角的方法我也试过,
    比如:
    var  hr :thandle;
    hr:=createroundrectrgn(0,0,width,height,6,6);
    setwindowrgn(handle,hr,true);窗体的确能实现圆角,但是效果并不太好,并且对窗体拉伸之类的操作有冲突。
      

  7.   

    只要不是异形窗体,很简单的,使用一个带有透明度调节的panel即可
    。 
      

  8.   

    皮皮鲁的方法,画圆角应该没问题。主要是画完圆角后调用拖拉程序时会不正常??
    怎么不正常了?正常得很!
    这个函数在Form的onmousemove中调用即可。int __fastcall TDocBookMainForm::CheckMouseInBorder(int X,int Y)
    {
    //判断当前鼠标的位置,是否在边界上,以改变鼠标并进行拖拉
    //并返回所处的位置。
    X = X - Left;
    Y = Y - Top; //最大化时不处理。
    if(WindowState == wsMaximized) return HTCLIENT; if(X<=10 && Y<=10) return HTTOPLEFT; //左上角
    if(X<=10 && Y>=ClientHeight-10) return HTBOTTOMLEFT;//左下角
    if(X<=2) return HTLEFT; //左边
    if(X>=ClientWidth-10 && Y<=10) return HTTOPRIGHT; //右上角
    if(X>=ClientWidth-10 && Y>=ClientHeight-10)
    return HTBOTTOMRIGHT;//右下角
    if(X>=ClientWidth-2) return HTRIGHT; //右边
    if(Y>=ClientHeight-2) return HTBOTTOM; //下边
    if(Y<=2) return HTTOP; //上边
        return HTCLIENT;
    }
    //---------------------------------------------------------------------------
      

  9.   

    为何不能编辑俺自己写的东西?这些代码,都是《资料收集库》里的代码。void __fastcall TDocBookMainForm::WndProc(Messages::TMessage &Msg)
    {
    TForm::WndProc(Msg);
    switch(Msg.Msg)
    {
    case WM_NCHITTEST:
    {
    Msg.Result = CheckMouseInBorder(Msg.LParamLo,Msg.LParamHi);
    break;
    }
    }
    }
      

  10.   

    楼上的翻译成delphi语言可以吗?做好人做到底
      

  11.   

    那我坏人做到家吧,拿小象的代码改的,亲测OKunit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;type
      TForm1 = class(TForm)
        procedure FormResize(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        OldWndProc: TWndMethod;
        function CheckMouseInBorder(X, Y: Integer;
          var AResult: Integer): Boolean;
        procedure NewWndProc(var AMsg: TMessage);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure RoundRgn(frm: TCustomForm);
    var
      hRgn1: HRGN;
    begin
      BeginPath(frm.Canvas.Handle);
      RoundRect(frm.Canvas.Handle, 1, 1, frm.Width, frm.Height, 50, 50);
      EndPath(frm.Canvas.Handle);
      hRgn1 := PathToRegion(frm.Canvas.Handle);
      SetWindowRgn(frm.Handle, hRgn1, True);
    end;function TForm1.CheckMouseInBorder(X, Y: Integer;
      var AResult: Integer): Boolean;
    begin
      Result := False;
      //判断当前鼠标的位置,是否在边界上,以改变鼠标并进行拖拉
      //并返回所处的位置。
      X := X - Left;
      Y := Y - Top;  //最大化时不处理。
      if (WindowState = wsMaximized) then
      begin
        Exit;
      end;  if (X<=10) and (Y<=10) then
        aResult := HTTOPLEFT     //左上角
      else if (X<=10) and (Y>=ClientHeight-10) then
        aResult := HTBOTTOMLEFT //左下角
      else if (X<=2) then
        aResult := HTLEFT         //左边
      else if(X>=ClientWidth-10) and (Y<=10) then
        aResult := HTTOPRIGHT     //右上角
      else if(X>=ClientWidth-10) and (Y>=ClientHeight-10) then
        aResult := HTBOTTOMRIGHT //右下角
      else if(X>=ClientWidth-2) then
        aResult := HTRIGHT         //右边
      else if(Y>=ClientHeight-2) then
        aResult := HTBOTTOM     //下边
      else if(Y<=2) then
        aResult := HTTOP         //上边
      else
        Exit;  Result := True;
    end;procedure TForm1.FormResize(Sender: TObject);
    begin
      RoundRgn(Self);
    end;procedure TForm1.NewWndProc(var AMsg: TMessage);
    var
      ret: Integer;
    begin
      OldWndProc(AMsg);
      if (AMsg.Msg = WM_NCHITTEST) and
        CheckMouseInBorder(aMsg.LParamLo, aMsg.LParamHi, ret) then
          AMsg.Result := ret;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      OldWndProc := WindowProc;
      WindowProc := NewWndProc;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      WindowProc := OldWndProc;
    end;end.
      

  12.   

    当然,我说的所谓画完圆角后拖拉窗体不正常,是因为贴图以后就不能拉伸了。
    皮皮鲁,我是这样做的:在窗体下部放置一个panel,Align:=Bottom,panel里放一个image,Align:=Client。加载一张图片。然后在FormCreate事件里让窗体画成圆角,圆角实现后,鼠标移到边框处无法拉伸。当然,不贴图就没有这种情况。
    请问大虾们,这是什么原因呢?
      

  13.   

    1. 用圆角窗体
    2. 不需要Panel, 窗体本身有canvas可以画图的
    3. 鼠标在周边的事件转换成窗体边框的事件  procedure OnHitTest(var msg: TMEssage); message WM_NCHITTEST;procedure TForm1.OnHitTest(var msg: TMEssage);
    const
      CORNER_WIDTH = 12;
      htvalues: array [0..2, 0..2] of THitWindow =
      (
      (HTTOPLEFT, HTTOP, HTTOPRIGHT),
      (HTLEFT, HTCLIENT, HTRIGHT),
      (HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT)
      );
    var
      P: TPoint;
      ctrl: TControl;
      idx: integer;
      idy: integer;
    begin
      p.x := msg.LParamLo - Left;
      p.y := msg.LParamHi - Top;
      ctrl := ControlAtPos(p, True, False);
      if (ctrl = nil) and (Align <> alClient) then
      begin
        if (p.x < CORNER_WIDTH) and (p.y < CORNER_WIDTH) then
        begin
          idx := 0;
          idy := 0;
        end
        else if (p.x < CORNER_WIDTH) and (p.y > Height - CORNER_WIDTH) then
        begin
          idx := 0;
          idy := 2;
        end
        else if (p.x > Width - CORNER_WIDTH) and (p.y < CORNER_WIDTH) then
        begin
          idx := 2;
          idy := 0;
        end
        else if (p.x > Width - CORNER_WIDTH) and (p.y > Height - CORNER_WIDTH) then
        begin
          idx := 2;
          idy := 2;
        end
        else
        begin
          if p.x < 4 then
            idx := 0
          else if p.x > Width - 4 then
            idx := 2
          else
            idx := 1;
          if p.y < 4 then
            idy := 0
          else if p.y > Height - 4 then
            idy := 2
          else
            idy := 1;
        end;
        msg.Result := integer(htvalues[idy, idx]);
      end
      else
        inherited;
    end;