Cocoa: Fix #40623, TCustomComboBox is not referenced to avoid the issue of APP directly calling TControl.Free() in event handler without using Application.ReleaseComponent()

This commit is contained in:
rich2014 2023-12-03 10:40:34 +08:00
parent b78b524b5b
commit 1898a84c34
2 changed files with 45 additions and 23 deletions

View File

@ -1379,7 +1379,7 @@ begin
begin begin
// ComboBox.Text will be set to the List Item value after comboBox_indexOfItemWithStringValue() // ComboBox.Text will be set to the List Item value after comboBox_indexOfItemWithStringValue()
// so if cbactRetainPrefixCase set, ComboBox.Text should be reset Async // so if cbactRetainPrefixCase set, ComboBox.Text should be reset Async
TComboBoxAsyncHelper.ResetTextIfNecessary(lclCmb, lclString); TComboBoxAsyncHelper.ResetTextIfNecessary(self, lclString);
Result := idx; Result := idx;
end; end;
end; end;

View File

@ -61,16 +61,16 @@ type
TComboBoxAsyncHelper = class TComboBoxAsyncHelper = class
private private
cmb: TCustomComboBox; _cocoaCmb: NSObject;
newText: String; _newText: String;
private private
procedure AsyncResetText(Data:PtrInt); procedure AsyncResetText(Data:PtrInt);
procedure AsyncSetLastIndex(Data:PtrInt); procedure AsyncSetLastIndex(Data:PtrInt);
public public
constructor Create(ACmb:TCustomComboBox); constructor Create(cocoaCmb:NSObject);
public public
class procedure ResetTextIfNecessary(AObject:TObject; ANewText:String); class procedure ResetTextIfNecessary(cocoaCmb:NSObject; ANewText:String);
class procedure SetLastIndex(AObject:TObject); class procedure SetLastIndex(cocoaCmb:NSObject);
end; end;
{ TLCLComboboxCallback } { TLCLComboboxCallback }
@ -722,42 +722,64 @@ end;
{ TComboBoxAsyncHelper } { TComboBoxAsyncHelper }
constructor TComboBoxAsyncHelper.Create(ACmb:TCustomComboBox); constructor TComboBoxAsyncHelper.Create(cocoaCmb:NSObject);
begin begin
cmb:= ACmb; _cocoaCmb:= cocoaCmb;
_cocoaCmb.retain;
end; end;
procedure TComboBoxAsyncHelper.AsyncResetText(Data:PtrInt); procedure TComboBoxAsyncHelper.AsyncResetText(Data:PtrInt);
var
cmb: TCustomComboBox;
begin begin
TCocoaWSCustomComboBox.SetText(cmb, newText); try
cmb.SelStart:= UTF8Length(newText); cmb:= TCustomComboBox(_cocoaCmb.lclGetTarget);
cmb.SelLength:= 0; if not Assigned(cmb) then
Free; exit;
TCocoaWSCustomComboBox.SetText(cmb, _newText);
cmb.SelStart:= UTF8Length(_newText);
cmb.SelLength:= 0;
finally
_cocoaCmb.release;
Free;
end;
end; end;
procedure TComboBoxAsyncHelper.AsyncSetLastIndex(Data:PtrInt); procedure TComboBoxAsyncHelper.AsyncSetLastIndex(Data:PtrInt);
var
cmb: TCustomComboBox;
begin begin
TCocoaWSCustomComboBox.SetItemIndex(cmb, TCocoaReadOnlyComboBox(cmb.Handle).lastSelectedItemIndex); try
Free; cmb:= TCustomComboBox(_cocoaCmb.lclGetTarget);
if not Assigned(cmb) then
exit;
TCocoaWSCustomComboBox.SetItemIndex(cmb, TCocoaReadOnlyComboBox(_cocoaCmb).lastSelectedItemIndex);
finally
_cocoaCmb.release;
Free;
end;
end; end;
class procedure TComboBoxAsyncHelper.ResetTextIfNecessary(AObject:TObject; ANewText:String); class procedure TComboBoxAsyncHelper.ResetTextIfNecessary(cocoaCmb:NSObject; ANewText:String);
var var
helper: TComboBoxAsyncHelper; helper: TComboBoxAsyncHelper;
ACmb: TCustomComboBox absolute AObject; cmb: TCustomComboBox;
begin begin
if not (cbactRetainPrefixCase in ACmb.AutoCompleteText) then exit; cmb:= TCustomComboBox(cocoaCmb.lclGetTarget);
helper:= TComboBoxAsyncHelper.Create(ACmb); if not Assigned(cmb) then
helper.newText:= ANewText; exit;
if not (cbactRetainPrefixCase in cmb.AutoCompleteText) then
exit;
helper:= TComboBoxAsyncHelper.Create(cocoaCmb);
helper._newText:= ANewText;
Application.QueueAsyncCall(@helper.AsyncResetText, 0); Application.QueueAsyncCall(@helper.AsyncResetText, 0);
end; end;
class procedure TComboBoxAsyncHelper.SetLastIndex(AObject:TObject); class procedure TComboBoxAsyncHelper.SetLastIndex(cocoaCmb:NSObject);
var var
helper: TComboBoxAsyncHelper; helper: TComboBoxAsyncHelper;
ACmb: TCustomComboBox absolute AObject;
begin begin
helper:= TComboBoxAsyncHelper.Create(ACmb); helper:= TComboBoxAsyncHelper.Create(cocoaCmb);
Application.QueueAsyncCall(@helper.AsyncSetLastIndex, 0); Application.QueueAsyncCall(@helper.AsyncSetLastIndex, 0);
end; end;
@ -1911,7 +1933,7 @@ begin
rocmb.setTarget(rocmb); rocmb.setTarget(rocmb);
rocmb.setAction(objcselector('comboboxAction:')); rocmb.setAction(objcselector('comboboxAction:'));
rocmb.lastSelectedItemIndex:= -1; rocmb.lastSelectedItemIndex:= -1;
TComboBoxAsyncHelper.SetLastIndex(AWinControl); TComboBoxAsyncHelper.SetLastIndex(rocmb);
rocmb.callback:=TLCLComboboxCallback.Create(rocmb, AWinControl); rocmb.callback:=TLCLComboboxCallback.Create(rocmb, AWinControl);
Result:=TLCLHandle(rocmb); Result:=TLCLHandle(rocmb);
rocmb.isOwnerDrawn := ComboBoxIsOwnerDrawn(TCustomComboBox(AWinControl).Style); rocmb.isOwnerDrawn := ComboBoxIsOwnerDrawn(TCustomComboBox(AWinControl).Style);