265 lines
6.2 KiB
ObjectPascal
265 lines
6.2 KiB
ObjectPascal
unit ListEdit;
|
|
|
|
interface
|
|
uses KOL, Windows, Messages, objects;
|
|
|
|
const
|
|
WM_JUSTFREE = WM_USER + 51;
|
|
WM_EDITFREE = WM_USER + 52;
|
|
WM_DBLCLICK = WM_USER + 53;
|
|
WM_ROWCHANG = WM_USER + 54;
|
|
|
|
type
|
|
|
|
PListEdit =^TListEdit;
|
|
TKOLListEdit = PControl;
|
|
TListEdit = object(Tobj)
|
|
EList: PList;
|
|
Enter: boolean;
|
|
LView: PControl;
|
|
TabSave: boolean;
|
|
TabStrt: boolean;
|
|
OldWind: longint;
|
|
NewWind: longint;
|
|
CurEdit: integer;
|
|
destructor destroy; virtual;
|
|
procedure SetEvents(LV: PControl);
|
|
procedure NewWndProc(var Msg: TMessage);
|
|
procedure LVPaint;
|
|
procedure LVDblClk;
|
|
procedure LVChange(Store: boolean);
|
|
procedure PostFree(var Key: integer);
|
|
procedure EDChar(Sender: PControl; var Key: integer; Sh: Cardinal);
|
|
procedure EDPres(Sender: PControl; var Key: integer; Sh: Cardinal);
|
|
procedure EDentr(Sender: PObj);
|
|
end;
|
|
|
|
function NewListEdit(AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
|
|
ImageListSmall, ImageListNormal, ImageListState: PImageList): PControl;
|
|
|
|
implementation
|
|
|
|
function NewListEdit;
|
|
var p: PListEdit;
|
|
begin
|
|
Result := NewListView(AParent, Style, Options, ImageListSmall, ImageListNormal, ImageListState);
|
|
Result.CreateWindow;
|
|
New(p, create);
|
|
AParent.Add2AutoFree(p);
|
|
p.LView := Result;
|
|
p.SetEvents(PControl(Result));
|
|
end;
|
|
|
|
destructor TListEdit.destroy;
|
|
begin
|
|
LVChange(False);
|
|
EList.Free;
|
|
SetWindowLong(LView.Handle, GWL_WNDPROC, OldWind);
|
|
FreeObjectInstance(Pointer(NewWind));
|
|
inherited;
|
|
end;
|
|
|
|
procedure TListEdit.SetEvents;
|
|
begin
|
|
EList := NewList;
|
|
Enter := False;
|
|
TabStrt := False;
|
|
OldWind := GetWindowLong(LV.Handle, GWL_WNDPROC);
|
|
NewWind := LongInt(MakeObjectInstance(NewWndProc));
|
|
SetWindowLong(LV.Handle, GWL_WNDPROC, NewWind);
|
|
end;
|
|
|
|
procedure TListEdit.NewWndProc;
|
|
var e: boolean;
|
|
begin
|
|
e := EList.Count > 0;
|
|
case Msg.Msg of
|
|
WM_LBUTTONDOWN:
|
|
begin
|
|
LVChange(True);
|
|
CurEdit := 0;
|
|
if e then PostMessage(LView.Handle, WM_DBLCLICK, 0, 0);
|
|
end;
|
|
WM_LBUTTONDBLCLK:
|
|
begin
|
|
LVDblClk;
|
|
end;
|
|
WM_KEYDOWN:
|
|
begin
|
|
if Msg.WParam = 13 then begin
|
|
LVDblClk;
|
|
end else
|
|
{ if Msg.WParam = 27 then begin
|
|
LVChange(False);
|
|
end else begin
|
|
LVChange(True);
|
|
if e then PostMessage(LView.Handle, WM_DBLCLICK, 0, 0);
|
|
end;}
|
|
end;
|
|
WM_NCPAINT:
|
|
begin
|
|
LVPaint;
|
|
end;
|
|
WM_JUSTFREE:
|
|
begin
|
|
LVChange(Msg.WParam <> 27);
|
|
end;
|
|
WM_EDITFREE:
|
|
begin
|
|
LVChange(Msg.WParam <> 27);
|
|
if e then PostMessage(LView.Handle, WM_DBLCLICK, 0, 0);
|
|
end;
|
|
WM_DBLCLICK:
|
|
begin
|
|
LVDblClk;
|
|
end;
|
|
WM_PAINT:
|
|
begin
|
|
LVPaint;
|
|
end;
|
|
end;
|
|
Msg.Result := CallWindowProc(Pointer(OldWind), LView.Handle, Msg.Msg, Msg.wParam, Msg.lParam);
|
|
end;
|
|
|
|
procedure TListEdit.LVPaint;
|
|
var i: integer;
|
|
r: TRect;
|
|
l: integer;
|
|
e: PControl;
|
|
p: TPoint;
|
|
begin
|
|
with LView^ do begin
|
|
SendMessage(Handle, WM_SETFONT, Font.Handle, 0);
|
|
l := 0;
|
|
p := LVItemPos[0];
|
|
for i := 0 to EList.Count - 1 do begin
|
|
r := LVItemRect(LVCurItem, lvipBounds);
|
|
r.Left := l + p.X;
|
|
r.Right := l + LVColWidth[i] + p.X;
|
|
Dec(r.Top);
|
|
Inc(r.Bottom);
|
|
e := EList.Items[i];
|
|
e.BoundsRect := r;
|
|
l := l + LVColWidth[i];
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.LVDblClk;
|
|
var i: integer;
|
|
e: PControl;
|
|
r: TRect;
|
|
l: integer;
|
|
a: PControl;
|
|
p: TPoint;
|
|
o: TPoint;
|
|
begin
|
|
with LView^ do begin
|
|
if EList.Count <> 0 then LVChange(True);
|
|
if enter then exit;
|
|
enter := true;
|
|
l := 0;
|
|
a := nil;
|
|
GetCursorPos(p);
|
|
p := Screen2Client(p);
|
|
o := LVItemPos[0];
|
|
for i := 0 to LVColCount - 1 do begin
|
|
r := LVItemRect(LVCurItem, lvipBounds);
|
|
r.Left := l + o.X;
|
|
r.Right := l + LVColWidth[i] + o.X;
|
|
l := l + LVColWidth[i];
|
|
Dec(r.Top);
|
|
Inc(r.Bottom);
|
|
e := NewEditBox(LView, []);
|
|
EList.Add(e);
|
|
e.BoundsRect := r;
|
|
e.DoubleBuffered := True;
|
|
e.Tabstop := True;
|
|
e.Font.FontHeight := LView.Font.FontHeight;
|
|
e.Font.FontCharset := 204;
|
|
e.Text := LVItems[LVCurItem, i];
|
|
e.OnKeyDown := EDChar;
|
|
e.OnKeyUp := EDPres;
|
|
e.OnEnter := EDEntr;
|
|
e.Show;
|
|
if a = nil then a := e;
|
|
if (CurEdit <> 0) then
|
|
if (EList.Count = CurEdit) then a := e else else
|
|
if (r.Left <= p.x) and (r.Right >= p.x) then
|
|
a := e;
|
|
end;
|
|
if a <> nil then a.Focused := True;
|
|
TabSave := TabStop;
|
|
TabStop := False;
|
|
TabStrt := True;
|
|
enter := false;
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.LVChange;
|
|
var e: PControl;
|
|
i: integer;
|
|
g: boolean;
|
|
begin
|
|
with LView^ do begin
|
|
if enter then exit;
|
|
enter := true;
|
|
g := False;
|
|
for i := 0 to EList.Count - 1 do begin
|
|
e := EList.Items[i];
|
|
if Store then begin
|
|
g := g or (LVItems[LVCurItem, i] <> e.Text);
|
|
LVItems[LVCurItem, i] := e.Text;
|
|
end;
|
|
if e.Focused then CurEdit := i + 1;
|
|
e.Free;
|
|
end;
|
|
EList.Clear;
|
|
enter := false;
|
|
if TabStrt then TabStop := TabSave;
|
|
if g then
|
|
SendMessage(Parent.Handle, WM_ROWCHANG, LVCurItem, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.PostFree;
|
|
begin
|
|
with LView^ do begin
|
|
if Key = 27 then
|
|
PostMessage(Handle, WM_JUSTFREE, key, 0);
|
|
if Key = 13 then
|
|
PostMessage(Handle, WM_EDITFREE, key, 0);
|
|
if ((key = 40) and (LView.LVCurItem < LView.LVCount - 1)) or
|
|
((key = 38) and (LView.LVCurItem > 0)) then begin
|
|
PostMessage(Handle, WM_EDITFREE, key, 0);
|
|
PostMessage(Handle, wm_keydown, Key, 0);
|
|
PostMessage(Handle, wm_keyup, Key, 0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.EDChar;
|
|
begin
|
|
case key of
|
|
13,
|
|
27,
|
|
38,
|
|
40: PostFree(key);
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.EDPres;
|
|
begin
|
|
case key of
|
|
38,
|
|
40: key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TListEdit.EDentr;
|
|
begin
|
|
PControl(Sender).SelectAll;
|
|
end;
|
|
|
|
end.
|