unit CoolEdit;
interface
uses
 Windows, Messages, Classes, Forms,Controls, Graphics, StdCtrls;
type
    //用设定边缘的空白
   TPosition=record  //指定光标的行和列
     row:longint;
     col:longint;
   end;
   TCoolEdit=class(TCustomEdit)
   private
     FMargin:byte;  //边距的大小
     FEdgeColor:TColor;//边框的颜色
     FEnterColor:TColor;//鼠标进入时边框内侧的框颜色
     MouseIn: Boolean;
     FExitColor: TColor; //标识鼠标是否进入
     function getPosition:TPosition;//光标的行和列
     procedure setMargin(value:byte);
     procedure setEdgeColor(Value:TColor);
     procedure setEnterColor(Value:TColor);
     //下面两个获得Delphi的内部消息,鼠标进入和离开时发生
     procedure CMMouseEnter (var Message: TMessage); message CM_MOUSEENTER;
     procedure CMMouseLeave (var Message: TMessage); message CM_MOUSELEAVE;
     //当一个窗口的外观必须被画时,应用程序发送这个消息给该窗口
     procedure WMPaint (var Message: TMessage); message WM_PAINT;
     //窗体需要计算位置和尺寸时触发
     //我们用这个的目的主要是将客户区缩小三个象素,以便画组件时不会画到客户区。
    procedure WMNCCalcSize (var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  protected
   //画窗体的边框,使其看起来更美观.
     procedure drawBorder;
   public
     constructor Create (AOwner: TComponent); override;
     property Position:TPosition read getPosition;
     property Margin:byte read FMargin write setMargin default 0;
   published
    property EdgeColor:TColor read FEdgeColor write SetEdgeColor default $ff0000;
    property EnterColor:TColor read FEnterColor write SetEnterColor default $0000ff;
    //显式化父类的属性
    property Anchors;
    property AutoSelect;
    property AutoSize;
    property BevelEdges;
    property BevelInner;
    property BevelKind default bkNone;
    property BevelOuter;
    property BiDiMode;
    property BorderStyle;
    property CharCase;
    property Color;
    property Constraints;
    property Ctl3D;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property Font;
    property HideSelection;
    property ImeMode;
    property ImeName;
    property MaxLength;
    property OEMConvert;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PasswordChar;
    property PopupMenu;
    property ReadOnly;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Text;
    property Visible;
    property OnChange;
    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;
   end;procedure Register;
implementation  procedure Register;
begin
  RegisterComponents('Samples', [TCoolEdit]);
end;constructor TCoolEdit.Create(AOwner:TComponent);
begin
  inherited Create(Aowner);
  ControlStyle := ControlStyle - [csFramed];
  ParentFont := True;
  FEdgeColor := $00A56E3A;
  FEnterColor := $0000ff;
  //设定外观,平面无边形
  Ctl3D := False;
  FMargin:=0;
  BorderStyle:=bsNone;
  height:=21;
  width:=120;
end;
procedure TCoolEdit.setMargin(Value:byte);
var
  Rect: TRect;
begin
//该消息取得客户区的尺寸
  SendMessage(Handle, EM_GETRECT, 0, Longint(@Rect));
  //以下是重新确定尺寸
  Rect.Top := Value;
  Rect.Left := Value;
  Rect.Right := Width -Value;
  Rect.Bottom := Height -Value;
//该消息设定客户区的大小
  SendMessage(Handle, EM_SETRECT, 0, Longint(@Rect));
  Fmargin:=value;
end;function TCoolEdit.getPosition:TPosition;
var
  row,Col:longint;
  CBLines:longint;
  str:WideString;
begin
//该消息取得光标所在的行,
  row:= SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
  //该消息取得光标所在行开始的位置,位置从第一行的0开始计数,
  //每过一个字符增加1,
  CBLines:=SendMessage(Handle,EM_LINEINDEX,row,0);
  //得到光标的所在行的所在列
  Col:=SelStart-CBLines;
  //为了解决中文的问题,需要用宽字符型来取得光标所在行
  //,行中光标所在列之前的字符串,这样可以解决中文列数的确定问题.
  //str:=Copy(Lines[row],1,col);
  col:=Length(Str)+1;
  result.row:=row+1;
  result.col:=col;
end;procedure TCoolEdit.setEdgeColor(Value:TCOlor);
begin
 if FEdgeColor<>value then
 begin
  FEdgeColor:=value;
  drawBorder;
 end;
end;procedure TCoolEdit.setEnterColor(Value:TColor);
begin
 if FEnterColor<>value then
 begin
   FEnterColor:=value;
  drawBorder;
 end;
end;procedure TCoolEdit.CMMouseEnter(var Message: TMessage);
begin
  inherited;
    MouseIn:= True;
    drawBorder;
end;procedure TCoolEdit.CMMouseLeave(var Message:TMessage);
begin
  inherited;
  MouseIn:=False;
  drawBorder;
end;procedure TCoolEdit.WMPaint (var Message: TMessage);
begin
  inherited;
  drawBorder;
end;procedure TCoolEdit.WMNCCalcSize (var Message: TWMNCCalcSize);
begin
  inherited;
  InflateRect(Message.CalcSize_Params^.rgrc[0], -3, -3);
end;procedure TCoolEdit.drawBorder;
var
  DC: HDC;  //设备描述表
  R: TRect; //客户区
  EnterBrush,OuterBrush,BorderBrush:HBRUSH;  //画笔句柄,API
begin
  DC:= GetWindowDC(Handle);  //取得该组件的设备描述表
  try
    GetWindowRect(Handle, R);  //取得该组件的客户区尺寸
    OffsetRect(R, -R.Left, -R.Top); //左上偏移
    //创建画笔,两个,分别代码边框,边框内,白色画笔
    BorderBrush := CreateSolidBrush(ColorToRGB(FEdgeColor));
    EnterBrush:= CreateSolidBrush(ColorToRGB(FEnterColor));
    OuterBrush:=CreateSolidBrush(ColorToRGB(clWhite));
   //not(csDesigning in ComponentState保证在设计期不变
    if (not(csDesigning in ComponentState)) and
    (MouseIn=true) then  //如果鼠标进入
    begin
     //画一个矩形框,用BorderBrush画笔
      FrameRect(DC, R, BorderBrush);
      //把R缩小一个象素
      InflateRect(R, -1, -1);
      //画一个矩形框,用outerBrush画笔
      FrameRect(DC, R, outerBrush);
      InflateRect(R, -1, -1);
      //FrameRect(DC, R, EnterBrush);
      FrameRect(DC, R, outerBrush);
    end
    else  //如果鼠标没有进入
    begin
      FrameRect(DC, R, BorderBrush);
      InflateRect(R, -1, -1);
      FrameRect(DC, R, outerBrush);
      InflateRect(R, -1, -1);
      FrameRect(DC, R, outerBrush);
    end;
  finally
    ReleaseDC(Handle, DC);  //释放设备描述表
  end;
  DeleteObject(BorderBrush);   //释放画笔
  DeleteObject(EnterBrush);
  DeleteObject(OuterBrush);
end;
end.
问题是在设计时,如果不选择该控件时,为什么控件的内则还会有六个选择点呢??

解决方案 »

  1.   

    楼主,你也太狠了吧,拿我做的控件稍改一下就叫你自己开发的,还叫人试用??只从Memo改成Edit。还名字都一样,我的是CoolMemo,你的是CoolEdit
    再看看里面的代码,里面的解释,几乎没有变。大家看这个:http://dev.csdn.net/article/32/32315.shtm
    注意看源代码部分,看是不是一样。我也不说你什么了,但你不能说是自己开发的啊,那可是我两个晚上熬出来的啊,
    尊重一下我的劳动成果好不好,做人要厚道。
      

  2.   

    to  linzhengqun(风) :对不起,这本来是一个朋友发过来的,叫本人看看,发现一个问题
    就来此请教, linzhengqun(风) 真的对不起了。
      

  3.   

    也没有什么,只是不平。
    我既然发到文档中去,也想给大家分享。
    下面这个不会了:
    unit CoolEdit;
    interface
    uses
     Windows, Messages, Classes, Forms,Controls, Graphics, StdCtrls;
    type
        //用设定边缘的空白
      { TPosition=record  //指定光标的行和列
         row:longint;
         col:longint;
       end; }
       TCoolEdit=class(TCustomEdit)
       private
         FMargin:byte;  //边距的大小
         FEdgeColor:TColor;//边框的颜色
         FEnterColor:TColor;//鼠标进入时边框内侧的框颜色
         MouseIn: Boolean;//标识鼠标是否进入
        // FExitColor: TColor;
         function getPosition:integer;//光标的行和列
         procedure setMargin(value:byte);
         procedure setEdgeColor(Value:TColor);
         procedure setEnterColor(Value:TColor);
         //下面两个获得Delphi的内部消息,鼠标进入和离开时发生
         procedure CMMouseEnter (var Message: TMessage); message CM_MOUSEENTER;
         procedure CMMouseLeave (var Message: TMessage); message CM_MOUSELEAVE;
         //当一个窗口的外观必须被画时,应用程序发送这个消息给该窗口
         procedure WMPaint (var Message: TMessage); message WM_NCPAINT;
         //窗体需要计算位置和尺寸时触发
         //我们用这个的目的主要是将客户区缩小三个象素,以便画组件时不会画到客户区。
        procedure WMNCCalcSize (var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
      protected
       //画窗体的边框,使其看起来更美观.
         procedure drawBorder;
       public
         constructor Create (AOwner: TComponent); override;
         //property Position:TPosition read getPosition;
         property Position:Integer read getPosition;
         property Margin:byte read FMargin write setMargin default 0;
       published
        property EdgeColor:TColor read FEdgeColor write SetEdgeColor default $ff0000;
        property EnterColor:TColor read FEnterColor write SetEnterColor default $0000ff;
        //显式化父类的属性
        property Anchors;
        property AutoSelect;
        property AutoSize;
        property BevelEdges;
        property BevelInner;
        property BevelKind default bkNone;
        property BevelOuter;
        property BiDiMode;
        property BorderStyle;
        property CharCase;
        property Color;
        property Constraints;
        property Ctl3D;
        property DragCursor;
        property DragKind;
        property DragMode;
        property Enabled;
        property Font;
        property HideSelection;
        property ImeMode;
        property ImeName;
        property MaxLength;
        property OEMConvert;
        property ParentBiDiMode;
        property ParentColor;
        property ParentCtl3D;
        property ParentFont;
        property ParentShowHint;
        property PasswordChar;
        property PopupMenu;
        property ReadOnly;
        property ShowHint;
        property TabOrder;
        property TabStop;
        property Text;
        property Visible;
        property OnChange;
        property OnClick;
        property OnContextPopup;
        property OnDblClick;
        property OnDragDrop;
        property OnDragOver;
        property OnEndDock;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseMove;
        property OnMouseUp;
        property OnStartDock;
        property OnStartDrag;
       end;procedure Register;
    implementation  procedure Register;
    begin
      RegisterComponents('Wind', [TCoolEdit]);
    end;constructor TCoolEdit.Create(AOwner:TComponent);
    begin
      inherited Create(Aowner);
      ControlStyle := ControlStyle - [csFramed];
      ParentFont := True;
      FEdgeColor := $ff0000;
      FEnterColor := $0000ff;
      //设定外观,平面无边形
      Ctl3D := False;
      FMargin:=0;
      BorderStyle:=bsNone;
      height:=21;
      width:=120;
    end;
    procedure TCoolEdit.setMargin(Value:byte);
    var
      Rect: TRect;
    begin
    //该消息取得客户区的尺寸
      SendMessage(Handle, EM_GETRECT, 0, Longint(@Rect));
      //以下是重新确定尺寸
      Rect.Top := Value;
      Rect.Left := Value;
      Rect.Right := Width -Value;
      Rect.Bottom := Height -Value;
    //该消息设定客户区的大小
      SendMessage(Handle, EM_SETRECT, 0, Longint(@Rect));
      Fmargin:=value;
    end;function TCoolEdit.getPosition:integer;
    var
      row,Col:longint;
      CBLines:longint;
      str:WideString;
    begin
    //该消息取得光标所在的行,
      row:= SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
      //该消息取得光标所在行开始的位置,位置从第一行的0开始计数,
      //每过一个字符增加1,
      CBLines:=SendMessage(Handle,EM_LINEINDEX,row,0);
      //得到光标的所在行的所在列
      Col:=SelStart-CBLines;
      //为了解决中文的问题,需要用宽字符型来取得光标所在行
      //,行中光标所在列之前的字符串,这样可以解决中文列数的确定问题.
      str:=Copy(text,1,col);
      col:=Length(Str)+1;
      //result.row:=row+1;
      result:=col;
    end;procedure TCoolEdit.setEdgeColor(Value:TCOlor);
    begin
     if FEdgeColor<>value then
     begin
      FEdgeColor:=value;
      drawBorder;
     end;
    end;procedure TCoolEdit.setEnterColor(Value:TColor);
    begin
     if FEnterColor<>value then
     begin
       FEnterColor:=value;
      drawBorder;
     end;
    end;procedure TCoolEdit.CMMouseEnter(var Message: TMessage);
    begin
      inherited;
        MouseIn:= True;
        drawBorder;
    end;procedure TCoolEdit.CMMouseLeave(var Message:TMessage);
    begin
      inherited;
      MouseIn:=False;
      drawBorder;
    end;procedure TCoolEdit.WMPaint (var Message: TMessage);
    begin
      inherited;
      drawBorder;
    end;procedure TCoolEdit.WMNCCalcSize (var Message: TWMNCCalcSize);
    begin
      inherited;
      InflateRect(Message.CalcSize_Params^.rgrc[0], -3, -3);
    end;procedure TCoolEdit.drawBorder;
    var
      DC: HDC;  //设备描述表
      R: TRect; //客户区
      EnterBrush,OuterBrush,BorderBrush:HBRUSH;  //画笔句柄,API
    begin
      DC:= GetWindowDC(Handle);  //取得该组件的设备描述表
      try
        GetWindowRect(Handle, R);  //取得该组件的客户区尺寸
        OffsetRect(R, -R.Left, -R.Top); //左上偏移
        //创建画笔,两个,分别代码边框,边框内,白色画笔
        BorderBrush := CreateSolidBrush(ColorToRGB(FEdgeColor));
        EnterBrush:= CreateSolidBrush(ColorToRGB(FEnterColor));
        OuterBrush:=CreateSolidBrush(ColorToRGB(clWhite));
       //not(csDesigning in ComponentState保证在设计期不变
        if (not(csDesigning in ComponentState)) and
        (MouseIn=true) then  //如果鼠标进入
        begin
         //画一个矩形框,用BorderBrush画笔
          FrameRect(DC, R, BorderBrush);
          //把R缩小一个象素
          InflateRect(R, -1, -1);
          //画一个矩形框,用outerBrush画笔
          FrameRect(DC, R, outerBrush);
          InflateRect(R, -1, -1);
          FrameRect(DC, R, EnterBrush);
          //FrameRect(DC, R, outerBrush);
        end
        else  //如果鼠标没有进入
        begin
          FrameRect(DC, R, BorderBrush);
          InflateRect(R, -1, -1);
          FrameRect(DC, R, outerBrush);
          InflateRect(R, -1, -1);
          FrameRect(DC, R, outerBrush);
        end;
      finally
        ReleaseDC(Handle, DC);  //释放设备描述表
      end;
      DeleteObject(BorderBrush);   //释放画笔
      DeleteObject(EnterBrush);
      DeleteObject(OuterBrush);
    end;
    end.
      

  4.   

    号召全体会员向linzhengqun(风),学习致敬,但没有看懂你改什么地方,你高手可以指教以下吗?? !
      

  5.   

    只改了这里:
    procedure WMPaint (var Message: TMessage); message WM_NCPAINT;
    你对照原来的看一下就明白了。
    WM_PAINT改成WM_NCPAINT这也是我的CoolMemo的一个Bug,还要多谢你提醒,我才能及时意识到。
      

  6.   

    另外,向风请教个问题,WM_NCPAINT和WM_PAINT有什么不同捏?
      

  7.   

    快要成讨论贴了。
    我也是看着MSDN搞出来的,NC类的消息的优先级比较高。
    反正看帮助,慢慢摸索,我也不知从何说起。An application sends the WM_NCPAINT message to a window when its frame(框架) must be painted. An application sends the WM_PAINT message when Windows or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function.