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 + -
显示快捷键?