入题,在richedit编辑框中如何象delphi代码编辑器般出现代码提示框供选择

解决方案 »

  1.   

    楼主想开发一个比delphi还牛的 IDE!!
    up
      

  2.   

    是指怎么弹出那个窗口,还是指那个窗口中的内容如何组织?前者的话好像是设窗口为popup型的就可以了。
    后者的话要看你具体处理怎样的数据了,如果是代码的提示,可是要进行代码分析,看编译原理去,我也不会,呵呵。。
      

  3.   

    我的意思是如何弹出那个窗口
    关键有两点,首先是如何把richedit中的光标位置转化为窗体弹出的位置,这里涉及了插入点如何定位的问题
    其次,窗体弹出时是处于一个什么状态。从delphi的效果看,窗体中的大概是个listbox之类的东西,在弹出时获取了focus;但是此时主窗体也同样没有失去focus,怎么实现的呢
      

  4.   

    利用GetCaretPos()可以取到RichEdit光标的位置~~其他,可以参考VCL中Grids单元下拉选择的实现~~type
    { TPopupListbox }
      TPopupListbox = class(TCustomListbox)
      private
        FSearchText: String;
        FSearchTickCount: Longint;
      protected
        procedure CreateParams(var Params: TCreateParams); override;
        procedure CreateWnd; override;
        procedure KeyPress(var Key: Char); override;
        procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
      end;procedure TPopupListBox.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      with Params do
      begin
        Style := Style or WS_BORDER;
        ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST;
        AddBiDiModeExStyle(ExStyle);
        WindowClass.Style := CS_SAVEBITS;
      end;
    end;procedure TPopupListbox.CreateWnd;
    begin
      inherited CreateWnd;
      Windows.SetParent(Handle, 0);
      CallWindowProc(DefWndProc, Handle, wm_SetFocus, 0, 0);
    end;procedure TPopupListbox.Keypress(var Key: Char);
    var
      TickCount: Integer;
    begin
      case Key of
        #8, #27: FSearchText := '';
        #32..#255:
          begin
            TickCount := GetTickCount;
            if TickCount - FSearchTickCount > 2000 then FSearchText := '';
            FSearchTickCount := TickCount;
            if Length(FSearchText) < 32 then FSearchText := FSearchText + Key;
            SendMessage(Handle, LB_SelectString, WORD(-1), Longint(PChar(FSearchText)));
            Key := #0;
          end;
      end;
      inherited Keypress(Key);
    end;procedure TPopupListbox.MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer);
    begin
      inherited MouseUp(Button, Shift, X, Y);
      TInplaceEditList(Owner).CloseUp((X >= 0) and (Y >= 0) and
          (X < Width) and (Y < Height));
    end;
      

  5.   

    //如下是RxLib中实现计算器编辑框的部分代码~~type
      TPopupWindow = class(TCustomControl)
      private
        FEditor: TWinControl;
        FCloseUp: TCloseUpEvent;
        procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
      protected
        procedure CreateParams(var Params: TCreateParams); override;
    {$IFDEF WIN32}
        function Getvalue: Variant; virtual; abstract;
        procedure Setvalue(const value: Variant); virtual; abstract;
    {$ELSE}
        procedure CreateWnd; override;
        function Getvalue: string; virtual; abstract;
        procedure Setvalue(const value: string); virtual; abstract;
    {$ENDIF}
        procedure InvalidateEditor;
        procedure PopupMouseUp(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure CloseUp(Accept: Boolean); virtual;
      public
        constructor Create(AOwner: TComponent); override;
        function GetPopupText: string; virtual;
        procedure Hide;
        procedure Show(Origin: TPoint);
        property OnCloseUp: TCloseUpEvent read FCloseUp write FCloseUp;
      end;{ TPopupWindow }constructor TPopupWindow.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      FEditor := TWinControl(AOwner);
    {$IFDEF WIN32}
      ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable,
        csAcceptsControls];
    {$ELSE}
      ControlStyle := ControlStyle + [csAcceptsControls];
    {$ENDIF}
      Ctl3D := False;
      ParentCtl3D := False;
      Visible := False;
      Parent := FEditor;
      onMouseUp := PopupMouseUp;
    end;procedure TPopupWindow.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      with Params do begin
        Style := WS_POPUP or WS_BORDER or WS_CLIPCHILDREN;
    {$IFDEF WIN32}
        ExStyle := WS_EX_TOOLWINDOW;
    {$ENDIF}
        WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
      end;
    end;{$IFNDEF WIN32}
    procedure TPopupWindow.CreateWnd;
    begin
      inherited CreateWnd;
      if (csDesigning in ComponentState) then SetParent(nil);
    end;
    {$ENDIF}procedure TPopupWindow.WMMouseActivate(var Message: TMessage);
    begin
      Message.Result := MA_NOACTIVATE;
    end;function TPopupWindow.GetPopupText: string;
    begin
      Result := '';
    end;procedure TPopupWindow.InvalidateEditor;
    var
      R: TRect;
    begin
      if (FEditor is TCustomComboEdit) then begin
        with TCustomComboEdit(FEditor) do
          SetRect(R, 0, 0, ClientWidth - FBtnControl.Width - 2, ClientHeight + 1);
      end
      else R := FEditor.ClientRect;
      InvalidateRect(FEditor.Handle, @R, False);
      UpdateWindow(FEditor.Handle);
    end;procedure TPopupWindow.PopupMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then CloseUp(PtInRect(Self.ClientRect, Point(X, Y)));
    end;procedure TPopupWindow.CloseUp(Accept: Boolean);
    begin
      if Assigned(FCloseUp) then FCloseUp(Self, Accept);
    end;procedure TPopupWindow.Hide;
    begin
      SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
        SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
      Visible := False;
    end;procedure TPopupWindow.Show(Origin: TPoint);
    begin
      SetWindowPos(Handle, HWND_TOP, Origin.X, Origin.Y, 0, 0,
        SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
      Visible := True;
    end;
      

  6.   

    感谢伴水提供的代码,其实类似的效果我已经做的差不多了
    现在主要还是光标的位置难以确定
    用GetCaretPos()配合clienttoscreen确定光标位置是有偏差的
    我这里测试X坐标还不算很明显,但是Y坐标就差的比较远啦
    希望可以有更好的解决办法
      

  7.   

    Y 加上TRichEdit::SelAttributes::Height看看
      

  8.   

    如果是要对坐标做一些加减法的话,那么GetCaretPos的实际效用是什么啊
    从单步执行的效果看,Y方向的差距是很大的,而且那个值也不知是怎么算出来的
      

  9.   

    //try
    procedure TForm1.RichEdit1SelectionChange(Sender: TObject);
    var
      vPoint: TPoint;
    begin
      GetCaretPos(vPoint);
      vPoint := TRichEdit(Sender).ClientToScreen(vPoint);  Form2.Left := vPoint.X;
      Form2.Top := vPoint.Y + Trunc(TRichEdit(Sender).SelAttributes.Height * 1.3);
      SetFocus;
    end;procedure TForm1.FormShow(Sender: TObject);
    begin
      Form2.Show;
    end;
      

  10.   

    GetCaretPos 取的是光标的左上角的位置,但目前我还没找到怎么计算光标图形的高度~~
    误差个几个像素用户不会说啥的~~
      

  11.   

    zswangII(伴水清清)(职业清洁工) 的办法非常好,学习。。
      

  12.   

    SynEdit实现了这个功能,而且有源代码,
    值得参考呀
      

  13.   

    help u up============================================================Mark study
      

  14.   

    搞不懂难在哪里?1、能取得在richedit中的坐标,再加上richedit在窗体中的坐标不就行了?
    2、直接在richedit上显示一个listbox不久行了?
      

  15.   

    pandengzhe(无为) :可能你没有实践过还觉得不难吧,其实还是挺麻烦的。如果有好的方案请提出看法,或者把你的想法用代码实践让大家开开眼界吧