Вверх ↑
Ответов: 2415
Рейтинг: 691
#1: 2024-12-06 10:23:58 ЛС | профиль | цитата
nesco, смотри что нашел, может поможет. Тестирую на двух схемах из справки о MST_UseEditCtrl. Вот такой правкой (так для тестирования):

unit hiMST_UseEditCtrl;

interface

uses Windows, Messages, Kol, Share, Debug, hiMTStrTbl;

const
HDN_FIRST = -300; { Header }
HDN_ITEMCHANGEDA = HDN_FIRST-1;
HDN_ITEMCHANGEDW = HDN_FIRST - 21;

type
tagNMHEADERA = packed record
Hdr: TNMHdr;
Item: Integer;
Button: Integer;
PItem: PHDItemA;
end;
HD_NOTIFY = tagNMHEADERA;


type
THIMST_UseEditCtrl = class(TDebug)
private
sControl: PControl;
NewLine: integer;
FMSTControl: IMSTControl;
OldMessage: TOnMessage;
redaction: boolean;//test

procedure SetMSTControl(Value: IMSTControl);
procedure snewcuridx(value:integer);
function gnewcuridx: integer;
function fredaction: boolean;
function fctl3d: boolean;
public

_prop_KeyCellEnter: byte;
_prop_DblClick: boolean;
_data_Row: THI_Event;
_data_Col: THI_Event;
_event_onEscCell: THI_Event;
_event_onEnterCell: THI_Event;
_event_onCellSize: THI_Event;
_event_onClientRect: THI_Event;

property _prop_MSTControl: IMSTControl read FMSTControl write SetMSTControl;
property NewCurIdx:integer read gnewcuridx write snewcuridx;

procedure _work_doSetData(var _Data: TData; Index: word);
procedure _work_doClientRect(var _Data: TData; Index: word);
procedure _var_Index(var _Data: TData; Index: word);
procedure _var_Cell(var _Data: TData; Index: word);
procedure _var_SubItem(var _Data: TData; Index: word);
procedure _var_Matrix(var _Data: TData; Index: word);
protected
function _OnMessage(var Msg: TMsg; var Rslt: Integer): Boolean;
end;

implementation


//------------------------------------------------------------------------------
//
function THIMST_UseEditCtrl._OnMessage;
type
TMouseDownPt = packed record
X: Word;
Y: Word;
end;
var
R, ARect: TRect;
Pt: TMouseDownPt;
HTI: TLVHitTestInfo;
Data: TData;
mt: PMT;
l: TListViewOptions;

procedure InitOnEvent;
var
b: integer;
begin
if FRedaction then exit;
redaction := true;//test
R := sControl.LVSubItemRect(NewLine, NewCurIdx);
if NewCurIdx = 0 then
begin
ARect := sControl.LVItemRect(NewLine, lvipLabel);
R.Left := ARect.Left;
R.Right := ARect.Right;
end;
if fctl3d then
b := 2
else
b := 1;
l := sControl.LVOptions;

dtInteger(Data, R.Left + sControl.Left + b);
mt := mt_make(Data);
mt_int(mt, R.Top + sControl.Top + b);
mt_int(mt, R.Right - R.Left - 1);
mt_int(mt, R.Bottom - R.Top - 1);
_hi_OnEvent_(_event_onCellSize, Data);
mt_free(mt);
end;

procedure EscCell;
begin
if not redaction then exit;//test
redaction := false;//test
R := sControl.LVItemRect(NewLine, lvipBounds);
ARect := sControl.LVItemRect(NewLine, lvipLabel);
R.Left := ARect.Left;
InvalidateRect(sControl.Handle, @R, false);
if not FRedaction then
_hi_OnEvent(_event_onEscCell, sControl.LVItems[NewLine, NewCurIdx]);
end;

begin
Result := false;
l:= sControl.LVOptions;
case Msg.message of
WM_NOTIFY:
if (HD_NOTIFY(Pointer(Msg.LParam)^).Hdr.code = HDN_ITEMCHANGEDA) or
(HD_NOTIFY(Pointer(Msg.LParam)^).Hdr.code = HDN_ITEMCHANGEDW) then
InitOnEvent;
WM_RBUTTONDOWN, WM_LBUTTONDOWN:
begin
Pt:= TMouseDownPt(Msg.lParam);
HTI.pt.x := Pt.X;
HTI.pt.y := Pt.Y;
sControl.Perform( LVM_SUBITEMHITTEST, 0, Integer( @HTI ) );
if (HTI.flags <> LVHT_ONITEMSTATEICON) and (HTI.iItem <> -1) then
begin
NewLine := HTI.iItem;
NewCurIdx := HTI.iSubItem;
end;
EscCell;
end;
WM_LBUTTONDBLCLK:
begin
Pt:= TMouseDownPt(Msg.lParam);
HTI.pt.x := Pt.X;
HTI.pt.y := Pt.Y;
sControl.Perform( LVM_SUBITEMHITTEST, 0, Integer( @HTI ) );
if (HTI.flags <> LVHT_ONITEMSTATEICON) and _prop_DblClick and (HTI.iItem <> -1) then
begin
InitOnEvent;
_hi_onEvent(_event_onEnterCell);
end;
end;
WM_HSCROLL, WM_VSCROLL:
EscCell;
WM_KEYDOWN:
begin
Case Msg.WParam of
VK_LEFT, VK_RIGHT:
begin
if (lvoRowSelect in l) then
begin
NewCurIdx := NewCurIdx + Msg.wParam - $26;
if NewCurIdx >= sControl.LVColCount then
NewCurIdx := sControl.LVColCount - 1
else
if NewCurIdx < 0 then NewCurIdx := 0;
EscCell;
end;
end;
VK_UP, VK_DOWN:
begin
NewLine := NewLine + Msg.wParam - $27;
if NewLine >= sControl.Count then
NewLine := sControl.Count - 1
else
if NewLine < 0 then
NewLine := 0;
EscCell;
end;
VK_RETURN:
if _prop_KeyCellEnter = 1 then
begin
InitOnEvent;
_hi_onEvent(_event_onEnterCell);
end;
VK_F2:
begin
InitOnEvent;
_hi_onEvent(_event_onEnterCell);
end;
VK_ESCAPE:
EscCell;
end;
end;
end;
Result := Result or _hi_OnMessage(OldMessage, Msg, Rslt);
end;

procedure THIMST_UseEditCtrl.snewcuridx;
begin
if not Assigned(_prop_MSTControl) then exit;
_prop_MSTControl.setnewcuridx(value);
end;

function THIMST_UseEditCtrl.gnewcuridx;
begin
if Assigned(_prop_MSTControl) then
Result := _prop_MSTControl.getnewcuridx
else
Result := 0;
end;

function THIMST_UseEditCtrl.fredaction;
begin
if Assigned(_prop_MSTControl) then
Result := _prop_MSTControl.getfredaction
else
Result := true;
end;

function THIMST_UseEditCtrl.fctl3d;
begin
if Assigned(_prop_MSTControl) then
Result := _prop_MSTControl.getfctl3d
else
Result := true;
end;

procedure THIMST_UseEditCtrl.SetMSTControl;
begin
if Value = nil then exit;
FMSTControl := Value;
sControl := FMSTControl.ctrlpoint;
FMSTControl.detachwndproc;

OldMessage:= sControl.OnMessage;
sControl.OnMessage := _OnMessage;
end;

procedure THIMST_UseEditCtrl._work_doSetData;
var
dControl: PControl;
begin
if not Assigned(_prop_MSTControl) then exit;
dControl := _prop_MSTControl.ctrlpoint;
dControl.LVItems[NewLine, NewCurIdx] := ToString(_Data);
end;

// Содержит индекс столбца выделенной ячейки
//
procedure THIMST_UseEditCtrl._var_SubItem;
begin
dtInteger(_Data, NewCurIdx);
end;

// Содержит значение выбранной ячейки под курсором
//
procedure THIMST_UseEditCtrl._var_Cell;
var
dControl: PControl;
begin
if not Assigned(_prop_MSTControl) then exit;
dControl := _prop_MSTControl.ctrlpoint;
dtString(_Data, dControl.LVItems[NewLine, NewCurIdx]);
end;

// Содержит индекс выделенной строки
//
procedure THIMST_UseEditCtrl._var_Index;
var
sControl: PControl;
begin
if not Assigned(_prop_MSTControl) then exit;
sControl := _prop_MSTControl.ctrlpoint;
dtInteger(_Data, sControl.CurIndex);
end;

// Матрица строк
//
procedure THIMST_UseEditCtrl._var_Matrix;
begin
if not Assigned(_prop_MSTControl) then exit;
_prop_MSTControl.matrix(_Data);
end;

procedure THIMST_UseEditCtrl._work_doClientRect;
var
Row,Col: integer;
R, ARect: TRect;
dTop, dWidth, dHeight, Data: TData;
b: integer;
sControl: PControl;
begin
Row := ReadInteger(_Data, _data_Row);
Col := ReadInteger(_Data, _data_Col);
if not Assigned(_prop_MSTControl) then exit;
sControl := _prop_MSTControl.ctrlpoint;

R := sControl.LVSubItemRect(Row, Col);
if Col = 0 then
begin
ARect := sControl.LVItemRect(Row, lvipLabel);
R.Left := ARect.Left;
R.Right := ARect.Right;
end;
if fctl3d then
b := 2
else
b := 1;

dtInteger(Data, R.Left + sControl.Left + b);
dtInteger(dWidth, R.Right - R.Left - 1);
dtInteger(dTop, R.Top + sControl.Top + b);
dtInteger(dHeight, R.Bottom - R.Top - 1);

Data.ldata:= @dTop;
dTop.ldata:= @dWidth;
dWidth.ldata:= @dHeight;
_hi_OnEvent_(_event_onClientRect, Data);
end;

end.
Так вот в схеме With_EditCtrl.sha происходит одно лишнее срабатывание onEscCell из-за приходящих WM_NOTIFY. Достаточно выбрать другую строку. Если отключить Менеджер маленьких иконок (SmallIconsManager ), то сообщения WM_NOTIFY перестают приходить. В другой схеме из справки, лишнего срабатывания onEscCell нет.

nesco писал(а):
По крайней мере, в коде именно так -- выдает ячейку, по которой клацнули, а не которую редактировали. Так и в описании к точке написано -- выдает в поток содержимое текущей ячейки, а текущей ячейкой будет как раз та, по которой клацнули.

Мне эти данные не нужны и не могу себе представить для чего они. Нужны данные до начала редактирования и в конце редактирования конкретно той ячейки которую редактируют сторонние контролы. До начала редактирования можно получить с Cell сохранив в Memory, а данные после редактирования можно получить с Memory перед внесением в ячейку doSetData.
Как по мне то onEscCell должен выдавать данные после редактирования редактированной ячейки. Это будет полезно если нужно сравнить данные до редактирования и после. Зачем нужны данные новой выбранной ячейки не понятно.

Вот такая схема нужна чтоб узнать нужно ли вносить данные в базу данных, если данные ячейки были изменены. И ложные срабатывания onEscCell вносят ненужные записи.
Add(MST_UseEditCtrl,5561109,294,168)
{
link(onEnterCell,5484721:doValue,[])
link(onEscCell,16568077:doCompare,[(338,188)(338,265)])
}
Add(Memory,5484721,357,175)
{
Point(Data)
link(Data,5561109:Cell,[(363,163)(342,163)(342,212)(321,212)])
}
Add(Memory,10271330,252,168)
{
link(onData,5561109:doSetData,[])
}
Add(If_else,16568077,350,259)
{
@Hint=#52:Проверка на разницу данных до редактирования и после|
link(Op1,10271330:Value,[(356,229)(258,229)])
link(Op2,5484721:Value,[])
AddHint(-147,43,182,26,@Hint)
}

Еще думаю не помешало бы doStop что бы принудительно завершить редактирование и вызвать onEscCell.
карма: 11

0
Редактировалось 2 раз(а), последний 2024-12-06 10:49:37