mwcompletionproposal.pas

来自「本人买的<<VC++项目开发实例>>源代码配套光盘.」· PAS 代码 · 共 989 行 · 第 1/2 页

PAS
989
字号

procedure TCompletionProposal.SetOnPaintItem(const Value: TCompletionProposalPaintItem);
begin
  form.OnPaintItem:= Value;
end;

procedure TCompletionProposal.SetPosition(const Value: Integer);
begin
  form.Position:= Value;
end;

procedure TCompletionProposal.SetOnValidate(const Value: TNotifyEvent);
begin
  form.OnValidate:= Value;
end;

function TCompletionProposal.GetClSelect: TColor;
begin
  Result:= Form.ClSelect;
end;

procedure TCompletionProposal.SetClSelect(const Value: TColor);
begin
  Form.ClSelect:= Value;
end;

function TCompletionProposal.GetOnKeyDelete: TNotifyEvent;
begin
  result:= Form.OnKeyDelete;
end;

procedure TCompletionProposal.SetOnKeyDelete(const Value: TNotifyEvent);
begin
  form.OnKeyDelete:= Value;
end;

procedure TCompletionProposal.RFAnsi(const Value: boolean);
begin
  form.ffAnsi:= value;
end;

function TCompletionProposal.SFAnsi: boolean;
begin
  result:= form.ffansi;
end;

procedure Register;
begin
  RegisterComponents(MWS_ComponentsPage,
                     [TMwCompletionProposal, TmwAutoComplete]);
end;

Procedure PretyTextOut(c: TCanvas; x, y: integer; s: String);
var
  i: integer;
  b: TBrush;
  f: TFont;
Begin
  b:= TBrush.Create;
  b.Assign(c.Brush);
  f:= TFont.Create;
  f.Assign(c.Font);
  try
    i:= 1;
    while i<=Length(s) do
      case s[i] of
        #1: Begin C.Font.Color:= ord(s[i+1])+ord(s[i+2])*256+ord(s[i+3])*65536; inc(i, 4); end;
        #2: Begin C.Brush.Color:= ord(s[i+1])+ord(s[i+2])*256+ord(s[i+3])*65536; inc(i, 4); end;
        #3: Begin
              case s[i+1] of
                'B': c.Font.Style:= c.Font.Style+[fsBold];
                'b': c.Font.Style:= c.Font.Style-[fsBold];
                'U': c.Font.Style:= c.Font.Style+[fsUnderline];
                'u': c.Font.Style:= c.Font.Style-[fsUnderline];
                'I': c.Font.Style:= c.Font.Style+[fsItalic];
                'i': c.Font.Style:= c.Font.Style-[fsItalic];
              end;
              inc(i, 2);
            end;
        else
          C.TextOut(x, y, s[i]);
          x:= x+c.TextWidth(s[i]);
          inc(i);
      end;
  except
  end;
  c.Font.Assign(f);
  f.Free;
  c.Brush.Assign(b);
  b.Free;
end;

{ TMwCompletionProposal }

type
  TRecordUsedToStoreEachEditorVars = record
    kp: TKeyPressEvent;
    kd: TKeyEvent;
    NoNextKey: boolean;
  end;
  PRecordUsedToStoreEachEditorVars = ^TRecordUsedToStoreEachEditorVars;

procedure TMwCompletionProposal.backspace(Senter: TObject);
begin
  if (senter as TCompletionProposalForm).CurrentEditor <> nil then
    ((senter as TCompletionProposalForm).CurrentEditor as TmwCustomEdit).CommandProcessor(ecDeleteLastChar,#0,nil);
end;

procedure TMwCompletionProposal.Cancel(Senter: TObject);
begin
  if (senter as TCompletionProposalForm).CurrentEditor <> nil then
  begin
    if (((senter as TCompletionProposalForm).CurrentEditor as TmwCustomEdit).Owner) is TWinControl
    then TWinControl(((senter as TCompletionProposalForm).CurrentEditor as TmwCustomEdit).Owner).SetFocus;
    ((senter as TCompletionProposalForm).CurrentEditor as TmwCustomEdit).SetFocus;
  end;
end;

procedure TMwCompletionProposal.Validate(Senter: TObject);
begin
  if (senter as TCompletionProposalForm).CurrentEditor <> nil then
    with ((senter as TCompletionProposalForm).CurrentEditor as TmwCustomEdit) do
    Begin
      BlockBegin:= Point(CaretX - length(CurrentString) , CaretY);
      BlockEnd:= Point(CaretX, CaretY);
      SelText:= ItemList[position];
      SetFocus;
    end;
end;

Procedure TMwCompletionProposal.KeyPress(Sender: TObject; var Key: Char);
Begin
  if (sender as TCompletionProposalForm).CurrentEditor <> nil then
    with ((sender as TCompletionProposalForm).CurrentEditor as TmwCustomEdit) do
      CommandProcessor(ecChar, Key, NIL);
end;

procedure TMwCompletionProposal.SetEditor(const Value: TmwCustomEdit);
begin
  AddEditor(Value);
end;

procedure TMwCompletionProposal.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (fEditors.indexOf(AComponent)<>-1) then
    RemoveEditor(AComponent as tmwCustomEdit);
end;

Constructor TMwCompletionProposal.Create(AOwner: TComponent);
begin
  Inherited Create(AOwner);
  Form.OnKeyPress:= KeyPress;
  Form.OnKeyDelete:= backspace;
  Form.OnValidate:= validate;
  Form.OnCancel:= Cancel;
  FEndOfTokenChr:= '()[].';
  fEditors:= TList.Create;
  fEditstuffs:= TList.Create;
  fShortCut := Menus.ShortCut(Ord(' '), [ssCtrl]);
end;

procedure TMwCompletionProposal.SetShortCut(Value: TShortCut);
begin
  FShortCut := Value;
end;

procedure TMwCompletionProposal.EditorKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
var
  p: TPoint;
  i: integer;
  ShortCutKey: Word;
  ShortCutShift: TShiftState;
begin
  ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift);
  i:= fEditors.indexOf(Sender);
  if i<>-1 then
    with sender as TmwCustomEdit do
    begin
      if (Shift = ShortCutShift) and (Key = ShortCutKey) then
      Begin
        p := ClientToScreen(Point(CaretXPix, CaretYPix+LineHeight));
        Form.CurrentEditor:= Sender as TmwCustomEdit;
        Execute(GetPreviousToken(Sender as TmwCustomEdit), p.x, p.y);
        Key:= 0;
        TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey:= true;
      End;
      if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd) then
        TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd(sender, key, shift);
    end;
end;

function TMwCompletionProposal.GetPreviousToken(FEditor: TmwCustomEdit): string;
var
  s: String;
  i: integer;
begin
  if FEditor <> nil then
  Begin
    s:= FEditor.LineText;
    i:= FEditor.CaretX-1;
    if i>length(s) then
      result:= ''
    else begin
      while (i>0) and (s[i]>' ') and (pos (s[i], FEndOfTokenChr)=0) do dec(i);
      result:= copy(s, i+1, FEditor.CaretX-i-1);
    end;
  end else result:= '';
end;

procedure TMwCompletionProposal.EditorKeyPress(Sender: TObject; var Key: char);
var
  i: integer;
begin
  i:= fEditors.IndexOf(Sender);
  if i<>-1 then
  begin
    if TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey then
    Begin
      key:= #0;
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey:= false;
    end;
    if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp) then
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp(sender, key);
  end;
end;

destructor TMwCompletionProposal.destroy;
begin
  while fEditors.Count<>0 do
    RemoveEditor(tmwCustomEdit(fEditors.last));
  fEditors.Free;
  fEditstuffs.free;
  inherited;
end;

function TMwCompletionProposal.GetFEditor: TmwCustomEdit;
begin
  if EditorsCount>0 then
    result:= Editors[0]
  else
    result:= nil;
end;

procedure TMwCompletionProposal.AddEditor(Editor: TmwCustomEdit);
var
  p: PRecordUsedToStoreEachEditorVars;
begin
  if fEditors.IndexOf(Editor)=-1 then
  Begin
    fEditors.Add(Editor);
    new(p);
    p.kp:=Editor.OnKeyPress;
    p.kd:=Editor.OnKeyDown;
    p.NoNextKey:= false;
    fEditstuffs.add(p);
    Editor.FreeNotification(self);
    if not (csDesigning in ComponentState) then
    Begin
      Editor.OnKeyDown:= EditorKeyDown;
      Editor.OnKeyPress:= EditorKeyPress;
    end;
  end;
end;

function TMwCompletionProposal.EditorsCount: integer;
begin
  result:= fEditors.count;
end;

function TMwCompletionProposal.GetEditor(i: integer): TmwCustomEdit;
begin
  if (i<0) or (i>=EditorsCount) then
    result:= nil
  else
    result:= TmwCustomEdit(fEditors[i]);
end;

function TMwCompletionProposal.RemoveEditor(Editor: TmwCustomEdit): boolean;
var
  i: integer;
begin
  i:= fEditors.Remove(Editor);
  result:= i<>-1;
  if result then
  begin;
    dispose(fEditstuffs[i]);
    fEditstuffs.delete(i);
  end;
end;

{ TmwAutoComplete }

procedure TmwAutoComplete.AddEditor(Editor: TmwCustomEdit);
var
  p: PRecordUsedToStoreEachEditorVars;
begin
  if fEditors.IndexOf(Editor)=-1 then
  Begin
    fEditors.Add(Editor);
    new(p);
    p.kp:=Editor.OnKeyPress;
    p.kd:=Editor.OnKeyDown;
    p.NoNextKey:= false;
    fEditstuffs.add(p);
    Editor.FreeNotification(self);
    if not (csDesigning in ComponentState) then
    Begin
      Editor.OnKeyDown:= EditorKeyDown;
      Editor.OnKeyPress:= EditorKeyPress;
    end;
  end;
end;

constructor TmwAutoComplete.Create(AOwner: TComponent);
begin
  inherited;
  fEditors:= TList.Create;
  fEditstuffs:= TList.Create;
  FEndOfTokenChr:= '()[].';
  fAutoCompleteList:= TStringList.Create;
  fShortCut := Menus.ShortCut(Ord(' '), [ssShift]);
end;

procedure TmwAutoComplete.SetShortCut(Value: TShortCut);
begin
  FShortCut := Value;
end;

destructor TmwAutoComplete.destroy;
begin
  while feditors.count<>0 do
    RemoveEditor(feditors.last);
  fEditors.free;
  fEditstuffs.free;
  fAutoCompleteList.free;
  Inherited;
end;

procedure TmwAutoComplete.EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  i: integer;
  ShortCutKey: Word;
  ShortCutShift: TShiftState;
begin
  ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift);
  i:= fEditors.IndexOf(Sender);
  if i<>-1 then
  begin
    if (Shift = ShortCutShift) and (Key = ShortCutKey) then
    Begin
      Execute(GetPreviousToken(Sender as TmwCustomEdit), Sender as TmwCustomEdit);
      Key:= 0;
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey:= true;
    End;
    if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd) then
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd(sender, key, Shift);
  end;
end;

procedure TmwAutoComplete.EditorKeyPress(Sender: TObject; var Key: char);
var
  i: integer;
begin
  i:= fEditors.IndexOf(Sender);
  if i<>-1 then
  begin
    if TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey then
    Begin
      key:= #0;
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey:= false;
    end;
    if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp) then
      TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp(sender, key);
  end;
end;

function TmwAutoComplete.EditorsCount: integer;
begin
  result:= fEditors.count;
end;

procedure TmwAutoComplete.Execute(token: string; Editor: TmwCustomEdit);
Var
  Temp: string;
  i, j, prevspace: integer;
  StartOfBlock: tpoint;
Begin
  i:= AutoCompleteList.IndexOf(token);
  if i<>-1 then
  Begin
    TRecordUsedToStoreEachEditorVars(fEditstuffs[fEditors.IndexOf(Editor)]^).NoNextKey:= true;
    for j:= 1 to length(token) do
      Editor.CommandProcessor(ecDeleteLastChar, ' ', nil);
    inc(i);
    StartOfBlock:= Point(-1, -1);
    PrevSpace:= 0;
    while (i<AutoCompleteList.Count) and
          (length(AutoCompleteList[i])>0) and
          (AutoCompleteList[i][1]='=') do
    Begin
      for j:= 0 to PrevSpace-1 do
        Editor.CommandProcessor(ecDeleteLastChar, ' ', nil);
      Temp:= AutoCompleteList[i];
      PrevSpace:= 0;
      while (length(temp)>=PrevSpace+2) and (temp[PrevSpace+2]<=' ') do
        inc(PrevSpace);
      for j:=2 to length(Temp) do
      Begin
        Editor.CommandProcessor(ecChar, Temp[j], nil);
        if Temp[j]='|' then
          StartOfBlock:= Editor.CaretXY
      end;
      inc(i);
      if (i<AutoCompleteList.Count) and
         (length(AutoCompleteList[i])>0) and
         (AutoCompleteList[i][1]='=') then
         Editor.CommandProcessor(ecLineBreak, ' ', nil);
    end;
    if (StartOfBlock.x<>-1) and (StartOfBlock.y<>-1) then
    Begin
      Editor.CaretXY:= StartOfBlock;
      Editor.CommandProcessor(ecDeleteLastChar, ' ', nil);
    end;
  end;
end;

function TmwAutoComplete.GetEdit: TmwCustomEdit;
begin
  if EditorsCount>0 then
    result:= Editors[0]
  else
    result:= nil;
end;

function TmwAutoComplete.GetEditor(i: integer): TmwCustomEdit;
begin
  if (i<0) or (i>=EditorsCount) then
    result:= nil
  else
    result:= TmwCustomEdit(fEditors[i]);
end;

function TmwAutoComplete.GetPreviousToken(Editor: tmwCustomEdit): string;
var
  s: String;
  i: integer;
begin
  if Editor <> nil then
  Begin
    s:= Editor.LineText;
    i:= Editor.CaretX-1;
    if i>length(s) then
      result:= ''
    else begin
      while (i>0) and (s[i]>' ') and (pos(s[i], FEndOfTokenChr)=0) do dec(i);
      result:= copy(s, i+1, Editor.CaretX-i-1);
    end;
  end else result:= '';
end;

procedure TmwAutoComplete.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (fEditors.indexOf(AComponent)<>-1) then
    RemoveEditor(AComponent as tmwCustomEdit);
end;

function TmwAutoComplete.RemoveEditor(Editor: TmwCustomEdit): boolean;
var
  i: integer;
begin
  i:= fEditors.Remove(Editor);
  result:= i<>-1;
  if result then
  begin;
    dispose(fEditstuffs[i]);
    fEditstuffs.delete(i);
  end;
end;

procedure TmwAutoComplete.SetAutoCompleteList(List: TStrings);
begin
  fAutoCompleteList.Assign(List);
end;

procedure TmwAutoComplete.SetEdit(const Value: TmwCustomEdit);
begin
  AddEditor(Value);
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?