richmemo: win32 + holding selection direction for GetXXX operations (that are strictly selection based).

reduce the number of redundant OnChange events, only call them on real event happening.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5117 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
skalogryz
2016-09-02 03:25:11 +00:00
parent 433408c2f1
commit 2123ae7101
2 changed files with 89 additions and 29 deletions

View File

@ -250,9 +250,25 @@ begin
Result:=false; // we need to catch just notifications, Result:=false; // we need to catch just notifications,
// any other message should be handled in a "Default" manner // any other message should be handled in a "Default" manner
// So, default result is false; // So, default result is false;
hdr:=PNMHDR(LParam);
case Msg of case Msg of
WM_COMMAND: begin
case HIWORD(WParam) of
EN_UPDATE: begin
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb761687(v=vs.85).aspx
// EN_UPDATE is just a notification, that the edit is to be redrawn
Result:=true;
end;
EN_CHANGE: begin
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh768384(v=vs.85).aspx
// Despite of what documentation claims (WM_NOTIFY), EN_CHANGE is notified by WM_COMMAND
if Assigned(AWinControl) and (AWinControl is TCustomRichMemo) then
TIntCustomRichMemo(AWinControl).Change;
Result:=true;
end;
end;
end;
WM_NOTIFY: begin WM_NOTIFY: begin
hdr:=PNMHDR(LParam);
case hdr^.code of case hdr^.code of
EN_SELCHANGE: EN_SELCHANGE:
begin begin
@ -539,7 +555,7 @@ begin
FinishCreateWindow(AWinControl, Params, false); FinishCreateWindow(AWinControl, Params, false);
eventmask := SendMessage(AWinControl.Handle, EM_GETEVENTMASK, 0, 0); eventmask := SendMessage(AWinControl.Handle, EM_GETEVENTMASK, 0, 0);
eventmask := eventmask or ENM_SELCHANGE or ENM_LINK; eventmask := eventmask or ENM_SELCHANGE or ENM_LINK or ENM_CHANGE;
SendMessage(AWinControl.Handle, EM_SETEVENTMASK, 0, eventmask); SendMessage(AWinControl.Handle, EM_SETEVENTMASK, 0, eventmask);
// Limitless text. However, the value would be overwritten by a consequent // Limitless text. However, the value would be overwritten by a consequent
@ -581,8 +597,7 @@ end;
class function TWin32WSCustomRichMemo.GetTextAttributes(const AWinControl: TWinControl; class function TWin32WSCustomRichMemo.GetTextAttributes(const AWinControl: TWinControl;
TextStart: Integer; var Params: TIntFontParams): Boolean; TextStart: Integer; var Params: TIntFontParams): Boolean;
var var
OrigStart : Integer; Orig : TCHARRANGE;
OrigLen : Integer;
eventmask : LongWord; eventmask : LongWord;
begin begin
if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin
@ -592,12 +607,14 @@ begin
InitFontParams(Params); InitFontParams(Params);
eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0); eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0);
RichEditManager.GetSelection(AWinControl.Handle, OrigStart, OrigLen);
LockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle); LockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle);
RichEditManager.GetSelRange(AWinControl.Handle, Orig);
RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1); RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1);
Result := RichEditManager.GetSelectedTextStyle(AWinControl.Handle, Params ); Result := RichEditManager.GetSelectedTextStyle(AWinControl.Handle, Params );
RichEditManager.SetSelection(AWinControl.Handle, OrigStart, OrigLen);
RichEditManager.SetSelRange(AWinControl.Handle, Orig);
UnlockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle, false); UnlockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle, false);
RichEditManager.SetEventMask(AWinControl.Handle,eventmask); RichEditManager.SetEventMask(AWinControl.Handle,eventmask);
@ -669,8 +686,7 @@ class function TWin32WSCustomRichMemo.GetStyleRange(
const AWinControl: TWinControl; TextStart: Integer; var RangeStart, const AWinControl: TWinControl; TextStart: Integer; var RangeStart,
RangeLen: Integer): Boolean; RangeLen: Integer): Boolean;
var var
OrigStart : Integer; Orig : TCharRange;
OrigLen : Integer;
eventmask : longword; eventmask : longword;
begin begin
if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin
@ -679,17 +695,17 @@ begin
end; end;
eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0); eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0);
RichEditManager.GetSelection(AWinControl.Handle, OrigStart, OrigLen);
LockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle); LockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle);
RichEditManager.GetSelRange(AWinControl.Handle, Orig);
RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1); RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1);
try try
Result := RichEditManager.GetStyleRange(AWinControl.Handle, TextStart, RangeStart, RangeLen); Result := RichEditManager.GetStyleRange(AWinControl.Handle, TextStart, RangeStart, RangeLen);
except except
end; end;
RichEditManager.SetSelection(AWinControl.Handle, OrigStart, OrigLen); RichEditManager.SetSelRange(AWinControl.Handle, Orig);
UnlockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle, false); UnlockRedraw(TCustomRichMemo(AWinControl), AWinControl.Handle, false);
RichEditManager.SetEventMask(AWinControl.Handle, eventmask); RichEditManager.SetEventMask(AWinControl.Handle, eventmask);
@ -724,8 +740,7 @@ end;
class function TWin32WSCustomRichMemo.GetTextUIParams(const AWinControl: TWinControl; TextStart: Integer; class function TWin32WSCustomRichMemo.GetTextUIParams(const AWinControl: TWinControl; TextStart: Integer;
var ui: TTextUIParam): Boolean; var ui: TTextUIParam): Boolean;
var var
OrigStart : Integer; Orig : TCHARRANGE;
OrigLen : Integer;
eventmask : Integer; eventmask : Integer;
begin begin
if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin if not Assigned(RichEditManager) or not Assigned(AWinControl) then begin
@ -734,12 +749,14 @@ begin
end; end;
eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0); eventmask := RichEditManager.SetEventMask(AWinControl.Handle, 0);
RichEditManager.GetSelection(AWinControl.Handle, OrigStart, OrigLen);
LockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle); LockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle);
RichEditManager.GetSelRange(AWinControl.Handle, Orig);
RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1); RichEditManager.SetSelection(AWinControl.Handle, TextStart, 1);
RichEditManager.GetTextUIStyle(AWinControl.Handle, ui); RichEditManager.GetTextUIStyle(AWinControl.Handle, ui);
RichEditManager.SetSelection(AWinControl.Handle, OrigStart, OrigLen);
RichEditManager.SetSelRange(AWinControl.Handle, Orig);
UnlockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle); UnlockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle);
RichEditManager.SetEventMask(AWinControl.Handle, eventmask); RichEditManager.SetEventMask(AWinControl.Handle, eventmask);
@ -774,6 +791,8 @@ begin
eventmask:=RichEditManager.SetEventMask(AWinControl.Handle, 0); eventmask:=RichEditManager.SetEventMask(AWinControl.Handle, 0);
LockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle);
RichEditManager.GetPara2(AWinControl.Handle, TextStart, para); RichEditManager.GetPara2(AWinControl.Handle, TextStart, para);
case para.wAlignment of case para.wAlignment of
PFA_CENTER: AAlign:=paCenter; PFA_CENTER: AAlign:=paCenter;
@ -782,6 +801,7 @@ begin
else else
AAlign:=paLeft; AAlign:=paLeft;
end; end;
UnlockRedraw( TCustomRichMemo(AWinControl), AWinControl.Handle );
RichEditManager.SetEventMask(AWinControl.Handle, eventmask); RichEditManager.SetEventMask(AWinControl.Handle, eventmask);
Result:=true; Result:=true;
@ -1063,6 +1083,7 @@ class function TWin32WSCustomRichMemo.GetSubText(
var utxt: UnicodeString): Boolean; var utxt: UnicodeString): Boolean;
var var
eventmask : Integer; eventmask : Integer;
Orig : TCharRange;
OrigStart : Integer; OrigStart : Integer;
OrigLen : Integer; OrigLen : Integer;
NeedLock : Boolean; NeedLock : Boolean;
@ -1078,7 +1099,7 @@ begin
NeedLock := (OrigStart <> TextStart) or (OrigLen <> TextLen); NeedLock := (OrigStart <> TextStart) or (OrigLen <> TextLen);
if NeedLock then begin if NeedLock then begin
LockRedraw( TCustomRichMemo(AWinControl), Hnd); LockRedraw( TCustomRichMemo(AWinControl), Hnd);
RichEditManager.SetSelection(Hnd, TextStart, TextLen); RichEditManager.GetSelRange(Hnd, Orig);
end; end;
isUnicode:=AsUnicode; isUnicode:=AsUnicode;
@ -1089,7 +1110,7 @@ begin
end; end;
if NeedLock then begin if NeedLock then begin
RichEditManager.SetSelection(Hnd, OrigStart, OrigLen); RichEditManager.SetSelRange(Hnd, Orig);
UnlockRedraw( TCustomRichMemo(AWinControl), Hnd); UnlockRedraw( TCustomRichMemo(AWinControl), Hnd);
end; end;
RichEditManager.SetEventMask(Hnd, eventmask); RichEditManager.SetEventMask(Hnd, eventmask);

View File

@ -173,6 +173,11 @@ type
class function GetStyleRange(RichEditWnd: Handle; TextStart: Integer; var RangeStart, RangeLen: Integer): Boolean; virtual; class function GetStyleRange(RichEditWnd: Handle; TextStart: Integer; var RangeStart, RangeLen: Integer): Boolean; virtual;
class procedure GetSelection(RichEditWnd: Handle; var TextStart, TextLen: Integer); virtual; class procedure GetSelection(RichEditWnd: Handle; var TextStart, TextLen: Integer); virtual;
class procedure SetSelection(RichEditWnd: Handle; TextStart, TextLen: Integer); virtual; class procedure SetSelection(RichEditWnd: Handle; TextStart, TextLen: Integer); virtual;
// WARNING: GetSelRange, is causing changes in Selection!
class procedure GetSelRange(RichEditWnd: Handle; var sr: TCHARRANGE); virtual;
class procedure SetSelRange(RichEditWnd: Handle; const sr: TCHARRANGE); virtual;
class procedure SetHideSelection(RichEditWnd: Handle; AValue: Boolean); virtual; class procedure SetHideSelection(RichEditWnd: Handle; AValue: Boolean); virtual;
class function LoadRichText(RichEditWnd: Handle; ASrc: TStream): Boolean; virtual; class function LoadRichText(RichEditWnd: Handle; ASrc: TStream): Boolean; virtual;
class function SaveRichText(RichEditWnd: Handle; ADst: TStream): Boolean; virtual; class function SaveRichText(RichEditWnd: Handle; ADst: TStream): Boolean; virtual;
@ -647,6 +652,38 @@ begin
SendMessage(RichEditWnd, EM_EXSETSEL, 0, PtrInt(@Range)); SendMessage(RichEditWnd, EM_EXSETSEL, 0, PtrInt(@Range));
end; end;
class procedure TRichEditManager.GetSelRange(RichEditWnd: Handle; var sr: TCHARRANGE);
var
st: Integer;
begin
sr.cpMax := 0;
sr.cpMin := 0;
st:=0;
SendMessage(RichEditWnd, EM_EXGETSEL, 0, PtrInt(@sr));
// EM_EXGETSEL - always returns min and max, in the math order
// (where math is lower, than max)
// This, however, doesn't match the seletion direction.
// Selection direction is done by either mouse (right to left) and (left to right)
// or by holding SHIFT key and moving left to right.
// EM_EXSETSEL - repsects the specified sr.cpMax and sr.cpMin order
// Resetting the selection.
// This is a bit hacky, BUT the selection would be reset
// towards the direction of the selection
SendMessage(RichEditWnd, EM_SETSEL, -1, 0);
SendMessage(RichEditWnd, EM_GETSEL, WPARAM(@st), 0);
if st=sr.cpMin then begin // right-to-left selection
sr.cpMin:=sr.cpMax;
sr.cpMax:=st;
end;
end;
class procedure TRichEditManager.SetSelRange(RichEditWnd: Handle; const sr: TCHARRANGE);
begin
SendMessage(RichEditWnd, EM_EXSETSEL, 0, PtrInt(@sr));
end;
class procedure TRichEditManager.SetHideSelection(RichEditWnd: Handle; AValue: Boolean); class procedure TRichEditManager.SetHideSelection(RichEditWnd: Handle; AValue: Boolean);
var var
style : LResult; style : LResult;
@ -720,9 +757,9 @@ class procedure TRichEditManager.SetText(RichEditWnd:Handle;
var var
AnsiText : AnsiString; AnsiText : AnsiString;
txt : PChar; txt : PChar;
s, l : Integer; sr : TCHARRANGE;
begin begin
GetSelection(RichEditWnd, s, l); GetSelRange(RichEditWnd, sr);
SetSelection(RichEditWnd, TextStart, ReplaceLength); SetSelection(RichEditWnd, TextStart, ReplaceLength);
txt:=nil; txt:=nil;
@ -735,7 +772,7 @@ begin
SendMessageA(RichEditWnd, EM_REPLACESEL, 0, LPARAM(txt)); SendMessageA(RichEditWnd, EM_REPLACESEL, 0, LPARAM(txt));
end; end;
SetSelection(RichEditWnd, s, l); SetSelRange(RichEditWnd, sr);
end; end;
class function TRichEditManager.GetTextW(RichEditWnd: Handle; class function TRichEditManager.GetTextW(RichEditWnd: Handle;
@ -801,9 +838,9 @@ end;
class procedure TRichEditManager.GetPara2(RichEditWnd: Handle; TextStart: Integer; class procedure TRichEditManager.GetPara2(RichEditWnd: Handle; TextStart: Integer;
var para: PARAFORMAT2); var para: PARAFORMAT2);
var var
s, l : Integer; sr : TCHARRANGE;
begin begin
GetSelection(RichEditWnd, s, l); GetSelRange(RichEditWnd, sr);
SetSelection(RichEditWnd, TextStart, 0); SetSelection(RichEditWnd, TextStart, 0);
@ -811,18 +848,20 @@ begin
para.cbSize:=sizeof(para); para.cbSize:=sizeof(para);
SendMessagea(RichEditWnd, EM_GETPARAFORMAT, 0, LPARAM(@para)); SendMessagea(RichEditWnd, EM_GETPARAFORMAT, 0, LPARAM(@para));
SetSelection(RichEditWnd, s, l); SetSelRange(RichEditWnd, sr);
end; end;
class procedure TRichEditManager.SetPara2(RichEditWnd: Handle; class procedure TRichEditManager.SetPara2(RichEditWnd: Handle;
TextStart, TextLen: Integer; const para: PARAFORMAT2); TextStart, TextLen: Integer; const para: PARAFORMAT2);
var var
s, l : Integer; sr : TCHARRANGE;
begin begin
GetSelection(RichEditWnd, s, l); GetSelRange(RichEditWnd, sr);
SetSelection(RichEditWnd, TextStart, TextLen); SetSelection(RichEditWnd, TextStart, TextLen);
SendMessagea(RichEditWnd, EM_SETPARAFORMAT, 0, LPARAM(@para)); SendMessagea(RichEditWnd, EM_SETPARAFORMAT, 0, LPARAM(@para));
SetSelection(RichEditWnd, s, l);
SetSelRange(RichEditWnd, sr);
end; end;
class function TRichEditManager.Find(RichEditWnd: THandle; const ANiddle: WideString; const ASearch: TIntSearchOpt): Integer; overload; class function TRichEditManager.Find(RichEditWnd: THandle; const ANiddle: WideString; const ASearch: TIntSearchOpt): Integer; overload;