mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-08 06:58:29 +02:00
1319 lines
41 KiB
PHP
1319 lines
41 KiB
PHP
{%MainUnit ../stdctrls.pp}
|
|
|
|
{******************************************************************************
|
|
TCustomComboBox
|
|
******************************************************************************
|
|
|
|
*****************************************************************************
|
|
This file is part of the Lazarus Component Library (LCL)
|
|
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
}
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.CreateWnd
|
|
Params: ---
|
|
Returns: Nothing
|
|
|
|
Create the underlying interface-object.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.InitializeWnd;
|
|
var
|
|
NewStrings: TStrings;
|
|
ASelStart, ASelLength : integer;
|
|
begin
|
|
inherited InitializeWnd;
|
|
|
|
// get the interface based item list
|
|
NewStrings:= TWSCustomComboBoxClass(WidgetSetClass).GetItems(Self);
|
|
// then delete internal list
|
|
if (FItems<>NewStrings) and (FItems<>nil) then
|
|
begin
|
|
NewStrings.Assign(FItems);
|
|
if NewStrings is TStringList then
|
|
TStringList(NewStrings).Sorted:= self.Sorted;
|
|
FItems.Free;
|
|
end;
|
|
// and use the interface based list
|
|
FItems := NewStrings;
|
|
|
|
if (FItemIndex > -1) and (FItemIndex < FItems.Count) then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetItemIndex(Self, FItemIndex);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetStyle(Self, FStyle);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetArrowKeysTraverseList(Self, FArrowKeysTraverseList);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetReadOnly(Self, FReadOnly);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetMaxLength(Self, FMaxLength);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetDropDownCount(Self, FDropDownCount);
|
|
if WidgetSet.GetLCLCapability(lcTextHint) = LCL_CAPABILITY_YES then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetTextHint(Self, FTextHint)
|
|
else
|
|
ShowEmulatedTextHintIfYouCan;
|
|
|
|
if FSelLength<>0 then
|
|
begin
|
|
ASelStart:= FSelStart;
|
|
ASelLength:= FSelLength;
|
|
SelStart:= ASelStart;
|
|
SelLength:= ASelLength;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.DestroyWnd
|
|
Params: ---
|
|
Returns: Nothing
|
|
|
|
Destroy the underlying interface-object.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.DestroyWnd;
|
|
var
|
|
NewStrings: TStrings;
|
|
begin
|
|
if not HandleAllocated then LazTracer.RaiseGDBException('');
|
|
// store itemindex
|
|
FItemIndex := TWSCustomComboBoxClass(WidgetSetClass).GetItemIndex(Self);
|
|
// create an internal list for storing items internally
|
|
NewStrings := TStringList.Create;
|
|
// copy from interface based list
|
|
if FItems <> nil then
|
|
begin
|
|
NewStrings.Assign(FItems);
|
|
// delete interface based list
|
|
TWSCustomComboBoxClass(WidgetSetClass).FreeItems(FItems);
|
|
end;
|
|
// and use the internal list
|
|
FItems := NewStrings;
|
|
TStringList(FItems).Sorted := Sorted;
|
|
|
|
inherited DestroyWnd;
|
|
end;
|
|
|
|
procedure TCustomComboBox.DoAutoAdjustLayout(
|
|
const AMode: TLayoutAdjustmentPolicy; const AXProportion, AYProportion: Double
|
|
);
|
|
begin
|
|
inherited;
|
|
|
|
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
|
|
begin
|
|
if Style.IsOwnerDrawn and (FItemHeight > 0) then
|
|
ItemHeight := Round(ItemHeight * AYProportion);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.DrawItem(Index: Integer; Rect: TRect;
|
|
State: TOwnerDrawState);
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.DrawItem(Index: Integer; ARect: TRect;
|
|
State: TOwnerDrawState);
|
|
begin
|
|
//TControlCanvas(FCanvas).UpdateTextFlags;
|
|
if Assigned(FOnDrawItem) then
|
|
FOnDrawItem(Self, Index, ARect, State)
|
|
else
|
|
begin
|
|
if not (odBackgroundPainted in State) then
|
|
FCanvas.FillRect(ARect);
|
|
InternalDrawItem(Self, FCanvas, ARect, Items[Index])
|
|
end;
|
|
end;
|
|
|
|
class function TCustomComboBox.GetControlClassDefaultSize: TSize;
|
|
begin
|
|
Result.CX := 100;
|
|
Result.CY := 25;
|
|
end;
|
|
|
|
procedure TCustomComboBox.DoEnter;
|
|
begin
|
|
inherited DoEnter;
|
|
//AutoSelect when DoEnter is fired by keyboard
|
|
if not Style.HasEditBox then Exit;//Non editable style
|
|
if (FAutoSelect and not (csLButtonDown in ControlState)) then
|
|
begin
|
|
SelectAll;
|
|
if (SelText = Text) then FAutoSelected := True;
|
|
end;//End if (((Style = csDropDown) or.........
|
|
end;
|
|
|
|
procedure TCustomComboBox.DoExit;
|
|
begin
|
|
FAutoSelected := False;
|
|
inherited DoExit;
|
|
end;
|
|
|
|
// this is a select triggered by autocomplete
|
|
procedure TCustomComboBox.DoAutoCompleteSelect;
|
|
begin
|
|
Select;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetSorted
|
|
Params: val - true means "sort" the combo
|
|
Returns: Nothing
|
|
|
|
Set the "sorted" property of the combobox and Sort the current entries.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetSorted(Val : boolean);
|
|
begin
|
|
if (Val <> FSorted) then
|
|
begin
|
|
FSorted := Val;
|
|
UpdateSorted;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetMaxLength
|
|
Params: val -
|
|
Returns: Nothing
|
|
|
|
Set the maximum length for user input.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetMaxLength(AValue: integer);
|
|
begin
|
|
if AValue < 0 then
|
|
AValue := 0;
|
|
if AValue <> MaxLength then
|
|
begin
|
|
FMaxlength := AValue;
|
|
if HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetMaxLength(Self, AValue);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.GetMaxLength
|
|
Params: ---
|
|
Returns: the maximum length of user input
|
|
|
|
Get the maximum length for user input.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetMaxLength: integer;
|
|
begin
|
|
if HandleAllocated then
|
|
FMaxLength := TWSCustomComboBoxClass(WidgetSetClass).GetMaxLength(Self);
|
|
Result := FMaxLength;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.LMChanged
|
|
Params: msg -
|
|
Returns: Nothing
|
|
|
|
Call handler for "OnChange"-event if one is assigned.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.LMChanged(var Msg);
|
|
begin
|
|
Change;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.Change;
|
|
|
|
Called on change
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.Change;
|
|
begin
|
|
inherited Changed;
|
|
if Assigned(FOnChange) then FOnChange(Self);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.Select;
|
|
|
|
Called whenever User changes the ItemIndex
|
|
For Delphi compatibility ignore when user unselects by changing Text.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.Select;
|
|
begin
|
|
if Assigned(FOnSelect) and (ItemIndex >= 0) then
|
|
FOnSelect(Self);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.DropDown;
|
|
|
|
Called whenever the list popups.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.DropDown;
|
|
begin
|
|
if Assigned(FOnDropDown) then FOnDropDown(Self);
|
|
end;
|
|
|
|
procedure TCustomComboBox.GetItems;
|
|
begin
|
|
if Assigned(FOnGetItems) then FOnGetItems(Self);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.CloseUp;
|
|
|
|
Called whenever the list hides.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.CloseUp;
|
|
begin
|
|
if [csLoading,csDestroying,csDesigning]*ComponentState<>[] then exit;
|
|
if Style.HasEditBox then
|
|
begin
|
|
EditingDone;
|
|
FEditingDone := False;
|
|
end;
|
|
if Assigned(FOnCloseUp) then FOnCloseUp(Self);
|
|
if FAutoSelect then
|
|
begin
|
|
SelectAll;
|
|
if (SelText = Text) then FAutoSelected := True;
|
|
end;//End if FAutoSelect
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.AdjustDropDown;
|
|
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.AdjustDropDown;
|
|
var
|
|
Count, MinItemsWidth, MinItemsHeight: Integer;
|
|
begin
|
|
if (not HandleAllocated) then exit;
|
|
Count := Items.Count;
|
|
if Count > DropDownCount then Count := DropDownCount;
|
|
if Count < 1 then Count := 1;
|
|
MinItemsWidth := ItemWidth;
|
|
MinItemsHeight := Count * ItemHeight;
|
|
SetComboMinDropDownSize(Handle, MinItemsWidth, MinItemsHeight, Count);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.IntfGetItems
|
|
|
|
Called whenever the items can be just-in-time populated.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.IntfGetItems;
|
|
begin
|
|
GetItems;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.GetSelText
|
|
Params: ---
|
|
Returns: selected text
|
|
|
|
Returns the selected part of text-field.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetSelText: string;
|
|
begin
|
|
//debugln('TCustomComboBox.GetSelText ');
|
|
if FStyle.HasEditBox then
|
|
Result:= UTF8Copy(Text, SelStart + 1, SelLength)
|
|
else
|
|
Result:= '';
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetSelText
|
|
Params: val - new string for text-field
|
|
Returns: nothings
|
|
|
|
Replace the selected part of text-field with "val".
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetSelText(const Val: string);
|
|
var
|
|
OldText, NewText: string;
|
|
OldSelStart: integer;
|
|
begin
|
|
//debugln('TCustomComboBox.SetSelText ',Val);
|
|
if FStyle.HasEditBox then
|
|
begin
|
|
OldText := Text;
|
|
OldSelStart := SelStart;
|
|
NewText := UTF8Copy(OldText, 1, OldSelStart) +
|
|
Val +
|
|
UTF8Copy(OldText, OldSelStart + SelLength + 1, MaxInt);
|
|
Text := NewText;
|
|
SelStart := OldSelStart;
|
|
SelLength := UTF8Length(Val);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.GetSelStart
|
|
Params: ---
|
|
Returns: starting index of selected text
|
|
|
|
Returns starting index of selected text
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetSelStart : integer;
|
|
begin
|
|
if HandleAllocated then
|
|
FSelStart := TWSCustomComboBoxClass(WidgetSetClass).GetSelStart(Self);
|
|
Result := FSelStart;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetSelStart
|
|
Params: val -
|
|
Returns: nothing
|
|
|
|
Sets starting index for selected text.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetSelStart(Val : integer);
|
|
begin
|
|
FSelStart := Val;
|
|
if HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetSelStart(Self, Val);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.GetSelLength
|
|
Params: ---
|
|
Returns: length of selected text
|
|
|
|
Returns length of selected text
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetSelLength : integer;
|
|
begin
|
|
if HandleAllocated then
|
|
FSelLength := TWSCustomComboBoxClass(WidgetSetClass).GetSelLength(Self);
|
|
Result := FSelLength;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetSelLength
|
|
Params: val -
|
|
Returns: nothing
|
|
|
|
Sets length of selected text.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetSelLength(Val : integer);
|
|
begin
|
|
FSelLength := Val;
|
|
if HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetSelLength(Self, Val);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SelectAll
|
|
Params: -
|
|
Returns: nothing
|
|
|
|
Select entire text.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SelectAll;
|
|
var
|
|
CurText: String;
|
|
begin
|
|
//debugln('TCustomComboBox.SelectAll ');
|
|
if FStyle.HasEditBox then
|
|
begin
|
|
CurText := Text;
|
|
if (CurText <> '') then
|
|
begin
|
|
SetSelStart(0);
|
|
SetSelLength(UTF8Length(CurText));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetStyle
|
|
Params: val - new style for combobox
|
|
Returns: nothing
|
|
|
|
Sets a new style for the combobox.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetStyle(Val : TComboBoxStyle);
|
|
begin
|
|
if Val <> FStyle then
|
|
begin
|
|
FStyle:= Val;
|
|
if HandleAllocated and ([csLoading,csDestroying]*ComponentState=[]) then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetStyle(Self, Val);
|
|
end;
|
|
end;
|
|
|
|
function TCustomComboBox.RealGetText: TCaption;
|
|
begin
|
|
if FEmulatedTextHintStatus = thsShowing then
|
|
Result := ''
|
|
else
|
|
Result := inherited RealGetText;
|
|
end;
|
|
|
|
procedure TCustomComboBox.RealSetText(const AValue: TCaption);
|
|
// If the text AValue occurs in the list of strings, then sets the itemindex,
|
|
// otherwise does the default action
|
|
begin
|
|
UpdateItemIndex(AValue);
|
|
if AValue<>'' then
|
|
HideEmulatedTextHint;
|
|
inherited;
|
|
end;
|
|
|
|
function TCustomComboBox.MatchListItem(const AValue: TCaption): Integer;
|
|
var
|
|
matchText: String;
|
|
caseSensitive: Boolean;
|
|
i: Integer;
|
|
|
|
function match( itemText:String): Boolean;
|
|
begin
|
|
if not caseSensitive then
|
|
itemText := UTF8UpperCase(itemText);
|
|
Result:= (matchText=itemText);
|
|
end;
|
|
begin
|
|
Result:= -1;
|
|
if AValue='' then Exit;
|
|
if FItems.Count=0 then Exit;
|
|
caseSensitive:= cbactSearchCaseSensitive in FAutoCompleteText;
|
|
if caseSensitive then
|
|
matchText:= AValue
|
|
else
|
|
matchText := UTF8UpperCase(AValue);
|
|
if cbactSearchAscending in FAutoCompleteText then
|
|
begin
|
|
for i := 0 to FItems.Count - 1 do
|
|
begin
|
|
if match(FItems[i]) then
|
|
begin
|
|
Result:= i;
|
|
break;
|
|
end;
|
|
end;
|
|
end else
|
|
begin
|
|
for i := FItems.Count - 1 downto 0 do
|
|
begin
|
|
if match(FItems[i]) then
|
|
begin
|
|
Result:= i;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.SetArrowKeysTraverseList(Value : Boolean);
|
|
begin
|
|
if Value <> FArrowKeysTraverseList then
|
|
begin
|
|
FArrowKeysTraverseList := Value;
|
|
if HandleAllocated and ([csLoading, csDestroying] * ComponentState=[]) then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetArrowKeysTraverseList(Self, Value);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.WMChar(var Message: TLMChar);
|
|
begin
|
|
// all normal characters are handled by the ComboBox
|
|
//debugln('TCustomEdit.WMChar ',DbgSName(Self),' ',dbgs(Message.CharCode));
|
|
if KeyDataToShiftState(Message.KeyData) * [ssCtrl, ssAlt] = [] then
|
|
Message.Result := 1 // eat normal keys, so they don't trigger accelerators
|
|
else
|
|
inherited WMChar(Message);
|
|
end;
|
|
|
|
procedure TCustomComboBox.WMKillFocus(var Message: TLMKillFocus);
|
|
begin
|
|
inherited WMKillFocus(Message);
|
|
ShowEmulatedTextHintIfYouCan;
|
|
end;
|
|
|
|
procedure TCustomComboBox.WMSetFocus(var Message: TLMSetFocus);
|
|
begin
|
|
HideEmulatedTextHint;
|
|
inherited WMSetFocus(Message);
|
|
end;
|
|
|
|
procedure TCustomComboBox.SetCharCase(eccCharCase: TEditCharCase);
|
|
begin
|
|
if (FCharCase <> eccCharCase) then
|
|
begin
|
|
FCharCase := eccCharCase;
|
|
case FCharCase of
|
|
ecUpperCase: Text := UTF8UpperCase(Text);
|
|
ecLowerCase: Text := UTF8Lowercase(Text);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
class procedure TCustomComboBox.WSRegisterClass;
|
|
begin
|
|
inherited WSRegisterClass;
|
|
RegisterCustomComboBox;
|
|
RegisterPropertyToSkip(TCustomComboBox, 'BevelInner', 'VCL compatibility property', '');
|
|
RegisterPropertyToSkip(TCustomComboBox, 'BevelKind', 'VCL compatibility property', '');
|
|
RegisterPropertyToSkip(TCustomComboBox, 'BevelOuter', 'VCL compatibility property', '');
|
|
RegisterPropertyToSkip(TCustomComboBox, 'ImeMode', 'VCL compatibility property', '');
|
|
end;
|
|
|
|
function TCustomComboBox.CanShowEmulatedTextHint: Boolean;
|
|
begin
|
|
Result := HandleAllocated and
|
|
(WidgetSet.GetLCLCapability(lcTextHint)=LCL_CAPABILITY_NO) and
|
|
(([csDesigning,csLoading] * ComponentState) = []) and
|
|
(FTextHint <> '') and (Text = '') and not Focused;
|
|
end;
|
|
|
|
procedure TCustomComboBox.CreateParams(var Params: TCreateParams);
|
|
const
|
|
ComboBoxStyles: array[TComboBoxStyle] of dword = (
|
|
CBS_DROPDOWN, CBS_SIMPLE, CBS_DROPDOWNLIST,
|
|
CBS_OWNERDRAWFIXED or CBS_DROPDOWNLIST, CBS_OWNERDRAWVARIABLE or CBS_DROPDOWNLIST,
|
|
CBS_OWNERDRAWFIXED or CBS_DROPDOWN, CBS_OWNERDRAWVARIABLE or CBS_DROPDOWN);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
Params.Style := Params.Style or (WS_VSCROLL or CBS_AUTOHSCROLL or CBS_HASSTRINGS) or
|
|
ComboBoxStyles[Style];
|
|
|
|
if Sorted then
|
|
Params.Style := Params.Style or CBS_SORT;
|
|
end;
|
|
|
|
procedure TCustomComboBox.KeyDown(var Key: Word; Shift: TShiftState);
|
|
var
|
|
UserDropDown, PreventDropDown: Boolean;
|
|
begin
|
|
FEditingDone := Key = VK_RETURN;
|
|
UserDropDown := (Key = VK_DOWN) and (ssAlt in Shift);
|
|
if Style = csSimple then
|
|
PreventDropDown := Key in [VK_RETURN, VK_ESCAPE]
|
|
else
|
|
PreventDropDown := Key in [VK_TAB, VK_RETURN, VK_ESCAPE];
|
|
if PreventDropDown then
|
|
begin
|
|
DroppedDown := False;
|
|
end;
|
|
// if AutoDropDown then don't close DropDown, like in Delphi, issue #31247
|
|
if AutoDropDown then
|
|
PreventDropDown := PreventDropDown or (ssAlt in Shift)
|
|
or (not (Key in [VK_SPACE, VK_PRIOR, VK_NEXT, VK_UP, VK_DOWN, VK_0..VK_Z, VK_NUMPAD0..VK_DIVIDE]));
|
|
|
|
if AutoDropDown or UserDropDown or FReturnArrowState then
|
|
begin
|
|
if PreventDropDown then
|
|
begin
|
|
if FReturnArrowState then
|
|
begin
|
|
ArrowKeysTraverseList := False; //we need?? this here, else we cannot traverse popup list
|
|
FReturnArrowState := False;
|
|
end;
|
|
end
|
|
else begin
|
|
if not ArrowKeysTraverseList then
|
|
begin
|
|
ArrowKeysTraverseList := True; //we need?? this here, else we cannot traverse popup list
|
|
FReturnArrowState := True;
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
DroppedDown := True;
|
|
if UserDropDown then
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
end;
|
|
if Key <> VK_UNKNOWN then
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TCustomComboBox.KeyUp(var Key: Word; Shift: TShiftState);
|
|
var
|
|
iSelStart: Integer; // char position
|
|
sText, sCompleteText, sPrefixText: string;
|
|
begin
|
|
inherited KeyUp(Key, Shift);
|
|
sText := Text;
|
|
//SelectAll when hitting return key for AutoSelect feature
|
|
if (Key = VK_RETURN) then
|
|
begin
|
|
if AutoComplete and Style.HasEditBox then
|
|
begin
|
|
// Only happens with alpha-numeric keys and return key and editable Style
|
|
SelectAll;
|
|
end;
|
|
if FAutoSelect then
|
|
begin
|
|
SelectAll;
|
|
if (SelText = sText) then FAutoSelected := True;
|
|
end;
|
|
end
|
|
else
|
|
if AutoComplete and Style.HasEditBox then
|
|
begin
|
|
//Only happens with alpha-numeric keys and return key and editable Style
|
|
//DebugLn(['TCustomComboBox.KeyUp ',Key,' ',IsEditableTextKey(Key)]);
|
|
if IsEditableTextKey(Key) then
|
|
begin
|
|
iSelStart := SelStart;//Capture original cursor position
|
|
//DebugLn(['TCustomComboBox.UTF8KeyPress SelStart=',SelStart,' Text=',Text]);
|
|
//End of line completion
|
|
if (iSelStart < UTF8Length(sText)) and (cbactEndOfLineComplete in FAutoCompleteText) then
|
|
Exit;
|
|
sPrefixText := UTF8Copy(sText, 1, iSelStart);
|
|
sCompleteText := GetCompleteText(sText, iSelStart,
|
|
cbactSearchCaseSensitive in FAutoCompleteText,
|
|
cbactSearchAscending in FAutoCompleteText, Items);
|
|
//DebugLn(['TCustomComboBox.UTF8KeyPress sCompleteText=',sCompleteText,' Text=',Text]);
|
|
// !! must check ItemIndex to be updated, see #41358
|
|
// check `Utf8TextLen = 1` is unnecessary, issue #34566 is covered
|
|
if UpdateItemIndex(sCompleteText) or (sCompleteText <> sText) then
|
|
begin
|
|
sText := sCompleteText;
|
|
if [cbactEndOfLineComplete, cbactRetainPrefixCase] <= FAutoCompleteText then
|
|
begin //Retain Prefix Character cases
|
|
UTF8Delete(sText, 1, iSelStart);
|
|
UTF8Insert(sPrefixText, sText, 1);
|
|
end;
|
|
Text := sText;
|
|
SelStart := iSelStart;
|
|
SelLength := UTF8Length(sText);
|
|
DoAutoCompleteSelect;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.UTF8KeyPress(var UTF8Key: TUTF8Char);
|
|
begin
|
|
//First invoke OnUtf8KeyPress, or else CharCase may be reverted again
|
|
inherited UTF8KeyPress(UTF8Key);
|
|
//Convert character cases if FCharCase is not ecNormalCase
|
|
case FCharCase of
|
|
ecLowerCase: UTF8Key := UTF8LowerCase(UTF8Key);
|
|
ecUpperCase: UTF8Key := UTF8UpperCase(UTF8Key);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.MouseUp(Button: TMouseButton; Shift:TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
//AutoSelect when left mouse is clicked for the 1st time after having focus
|
|
if (Button = mbLeft) then
|
|
begin
|
|
if (FAutoSelect and not FAutoSelected) then
|
|
begin
|
|
SelectAll;
|
|
if (SelText = Text) then FAutoSelected := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomComboBox.SelectItem(const AnItem: String): Boolean;
|
|
|
|
Selects the item with the Text of AnItem
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.SelectItem(const AnItem: String): Boolean;
|
|
var
|
|
i: integer;
|
|
ValueChanged: boolean;
|
|
begin
|
|
i:=Items.IndexOf(AnItem);
|
|
if i>=0 then
|
|
begin
|
|
Result := True;
|
|
ValueChanged := ItemIndex <> i;
|
|
ItemIndex := i;
|
|
Text := Items[i];
|
|
if ValueChanged then
|
|
begin
|
|
Click;
|
|
Select;
|
|
end;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TCustomComboBox.ShouldAutoAdjust(var AWidth, AHeight: Boolean);
|
|
begin
|
|
AWidth := True;
|
|
AHeight := not AutoSize;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomComboBox.GetItemCount: Integer;
|
|
|
|
Returns the number of items
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetItemCount: Integer;
|
|
begin
|
|
Result:=Items.Count;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomComboBox.GetItemHeight: Integer;
|
|
|
|
Gets default ItemHeight.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetItemHeight: Integer;
|
|
begin
|
|
// FItemHeight is not initialized at class creating. we can, but with what value?
|
|
// so, if it still uninitialized (=0), then we ask widgetset
|
|
if FStyle.IsOwnerDrawn and (FItemHeight > 0) or not HandleAllocated then
|
|
Result := FItemHeight
|
|
else
|
|
begin
|
|
Result := TWSCustomComboBoxClass(WidgetSetClass).GetItemHeight(Self);
|
|
if (FItemHeight = 0) then
|
|
FItemHeight := Result;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.SetDropDownCount(const AValue: Integer);
|
|
|
|
Sets the number of items that fits into the drop down list.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetDropDownCount(const AValue: Integer);
|
|
begin
|
|
if AValue = FDropDownCount then
|
|
exit;
|
|
FDropDownCount := AValue;
|
|
if HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetDropDownCount(Self, AValue);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.SetItemHeight(const AValue: Integer);
|
|
|
|
Sets default ItemHeight. 0 or negative values are ignored.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetItemHeight(const AValue: Integer);
|
|
begin
|
|
if AValue = FItemHeight then
|
|
exit;
|
|
FItemHeight := AValue;
|
|
if not HandleAllocated then
|
|
exit;
|
|
if Style.IsOwnerDrawn then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetItemHeight(Self, FItemHeight);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomComboBox.GetDroppedDown: Boolean;
|
|
|
|
Returns true, if list is shown.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetDroppedDown: Boolean;
|
|
begin
|
|
if HandleAllocated then
|
|
Result := TWSCustomComboBoxClass(WidgetSetClass).GetDroppedDown(Self)
|
|
else
|
|
Result := FDroppedDown;
|
|
end;
|
|
|
|
function TCustomComboBox.GetAutoComplete: boolean;
|
|
begin
|
|
Result := cbactEnabled in AutoCompleteText;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomComboBox.GetItemWidth: Integer;
|
|
|
|
The ItemWidth is the minimum pixels, that is allocated for the items in the
|
|
dropdown list.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetItemWidth: Integer;
|
|
begin
|
|
Result:=FItemWidth;
|
|
end;
|
|
|
|
procedure TCustomComboBox.SetAutoComplete(const AValue: boolean);
|
|
begin
|
|
if AutoComplete=AValue then exit;
|
|
if AValue then
|
|
AutoCompleteText := AutoCompleteText + [cbactEnabled]
|
|
else
|
|
AutoCompleteText := AutoCompleteText - [cbactEnabled]
|
|
end;
|
|
|
|
procedure TCustomComboBox.SetDroppedDown(const AValue: Boolean);
|
|
begin
|
|
if GetDroppedDown = AValue then
|
|
Exit;
|
|
if (not HandleAllocated) or (csLoading in ComponentState) then
|
|
Exit;
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetDroppedDown(Self, AValue);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.SetItemWidth(const AValue: Integer);
|
|
|
|
The ItemWidth is the minimum pixels, that is allocated for the items in the
|
|
dropdown list.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetItemWidth(const AValue: Integer);
|
|
begin
|
|
if FItemWidth=AValue then exit;
|
|
FItemWidth:=AValue;
|
|
AdjustDropDown;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetItems
|
|
Params: value - stringlist with items for combobox
|
|
Returns: nothing
|
|
|
|
Assigns items for ComboBox from a stringlist.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetItems(const Value : TStrings);
|
|
begin
|
|
if (Value <> FItems) then
|
|
FItems.Assign(Value);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.Create
|
|
Params: AOwner - owner of the object
|
|
Returns: reference to the newly created object
|
|
|
|
Creates the object.
|
|
------------------------------------------------------------------------------}
|
|
constructor TCustomComboBox.Create(TheOwner : TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
|
|
fCompStyle := csComboBox;
|
|
with GetControlClassDefaultSize do
|
|
SetInitialBounds(0, 0, CX, CY);
|
|
FItems := TStringListUTF8Fast.Create;
|
|
FItemIndex := -1;
|
|
FItemWidth := 0;
|
|
FMaxLength := 0;
|
|
FDropDownCount := 8;
|
|
FCanvas := TControlCanvas.Create;
|
|
TControlCanvas(FCanvas).Control := Self;
|
|
ArrowKeysTraverseList := True;
|
|
TabStop := True;
|
|
ParentColor := False;
|
|
FAutoCompleteText := DefaultComboBoxAutoCompleteText;
|
|
FAutoSelect := True;
|
|
FAutoSelected := False;
|
|
FCharCase := ecNormal;
|
|
|
|
{ AutoSize must be true by default to provide good cross-platform
|
|
development experience as some widgetsets (win32, wince) ignore the
|
|
combobox height and others (gtk2) look ugly with a too small height }
|
|
AutoSize := True;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.Destroy
|
|
Params: ---
|
|
Returns: nothing
|
|
|
|
Destroys the object.
|
|
------------------------------------------------------------------------------}
|
|
destructor TCustomComboBox.Destroy;
|
|
begin
|
|
if HandleAllocated then DestroyHandle;
|
|
FCanvas.Free;
|
|
FCanvas:=nil;
|
|
FItems.Free;
|
|
FItems:=nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.AddItem(const Item: String; AnObject: TObject);
|
|
|
|
Adds an Item with an associated object to Items
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.AddItem(const Item: String; AnObject: TObject);
|
|
begin
|
|
Items.AddObject(Item,AnObject);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.AddHistoryItem(const Item: string;
|
|
MaxHistoryCount: integer; SetAsText, CaseSensitive: boolean);
|
|
|
|
Adds an Item as first item. Removes the Item from old positions and removes
|
|
last item if history is full.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.AddHistoryItem(const Item: string;
|
|
MaxHistoryCount: integer; SetAsText, CaseSensitive: boolean);
|
|
begin
|
|
AddHistoryItem(Item,nil,MaxHistoryCount,SetAsText,CaseSensitive);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.AddHistoryItem(const Item: string;
|
|
AnObject: TObject; MaxHistoryCount: integer;
|
|
SetAsText, CaseSensitive: boolean);
|
|
|
|
Adds an Item as first item. Removes the Item from old positions and removes
|
|
last item if history is full.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.AddHistoryItem(const Item: string; AnObject: TObject;
|
|
MaxHistoryCount: integer; SetAsText, CaseSensitive: boolean);
|
|
var i: integer;
|
|
begin
|
|
// insert as first
|
|
if (Items.Count=0)
|
|
or (not CaseSensitive and (AnsiCompareText(Items[0],Item)<>0))
|
|
or (CaseSensitive and (Items[0]<>Item)) then
|
|
begin
|
|
Items.InsertObject(0,Item,AnObject);
|
|
end;
|
|
// delete old
|
|
for i:=Items.Count-1 downto 1 do begin
|
|
if (not CaseSensitive and (AnsiCompareText(Items[i],Item)=0))
|
|
or (CaseSensitive and (Items[i]=Item)) then
|
|
Items.Delete(i);
|
|
end;
|
|
// delete overflow items
|
|
while Items.Count>MaxHistoryCount do
|
|
Items.Delete(Items.Count-1);
|
|
// set as text
|
|
if SetAsText then
|
|
Text:=Item;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.Clear;
|
|
|
|
Removes all Items
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.Clear;
|
|
begin
|
|
Items.Clear;
|
|
Text:='';
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.ClearSelection;
|
|
|
|
Unselects all items.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.ClearSelection;
|
|
begin
|
|
ItemIndex := -1;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.MeasureItem(Index: Integer; var TheHeight: Integer);
|
|
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.MeasureItem(Index: Integer; var TheHeight: Integer);
|
|
begin
|
|
if Assigned(OnMeasureItem) then
|
|
OnMeasureItem(Self,Index,TheHeight);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.GetItemIndex
|
|
Params: ---
|
|
Returns: index of the currently selected item
|
|
|
|
Returns index of the currently selected item in the combobox. -1 is returned
|
|
if no item is currently selected.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomComboBox.GetItemIndex : integer;
|
|
begin
|
|
if not (csDestroyingHandle in ControlState) and HandleAllocated then
|
|
// WidgetSet must be called even when csDestroying for at least TIniPropStorage's needs.
|
|
FItemIndex:= TWSCustomComboBoxClass(WidgetSetClass).GetItemIndex(Self);
|
|
Result := FItemIndex;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCustomComboBox.SetItemIndex
|
|
Params: Val -
|
|
Returns: nothing
|
|
|
|
Sets ths index of the currently selected item in the combobox.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.SetItemIndex(const Val : integer);
|
|
begin
|
|
//if CompareText(Name,'TextToFindComboBox')=0 then
|
|
// debugln('TCustomComboBox.SetItemIndex A ',DbgSName(Self),' Text="',Text,'"');
|
|
if Val < -1 then Exit;
|
|
if Val = GetItemIndex then exit;
|
|
if (Val >= Items.Count) and (not (csLoading in ComponentState)) then exit;
|
|
|
|
FItemIndex := Val;
|
|
if csLoading in ComponentState then Exit;
|
|
|
|
if HandleAllocated then
|
|
begin
|
|
if Val = -1 then
|
|
ShowEmulatedTextHintIfYouCan
|
|
else
|
|
HideEmulatedTextHint;
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetItemIndex(Self, FItemIndex);
|
|
end
|
|
else
|
|
begin
|
|
// remember text, in case one reads text without creating handle
|
|
if Val = -1 then
|
|
Text := ''
|
|
else
|
|
Text := FItems.Strings[FItemIndex];
|
|
end;
|
|
|
|
//if CompareText(Name,'TextToFindComboBox')=0 then
|
|
// debugln('TCustomComboBox.SetItemIndex END ',DbgSName(Self),' Text="',Text,'"');
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.LMDrawListItem(var TheMessage : TLMDrawListItem);
|
|
|
|
Handler for custom drawing items.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.LMDrawListItem(var TheMessage : TLMDrawListItem);
|
|
begin
|
|
with TheMessage.DrawListItemStruct^ do
|
|
begin
|
|
FCanvas.Handle := DC;
|
|
if Font<>nil then
|
|
begin
|
|
FCanvas.Font := Font;
|
|
FCanvas.Font.PixelsPerInch := Font.PixelsPerInch;
|
|
end;
|
|
if Brush<>nil then
|
|
FCanvas.Brush := Brush;
|
|
if (ItemID <> UINT(-1)) and (odSelected in ItemState) then
|
|
begin
|
|
FCanvas.Brush.Color := clHighlight;
|
|
FCanvas.Font.Color := clHighlightText
|
|
end;
|
|
DrawItem(ItemID, Area, ItemState);
|
|
if odFocused in ItemState then
|
|
{DrawFocusRect(hDC, rcItem)};
|
|
FCanvas.Handle := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.LMMeasureItem(var TheMessage: TLMMeasureItem);
|
|
var
|
|
AHeight: Integer;
|
|
begin
|
|
with TheMessage.MeasureItemStruct^ do
|
|
begin
|
|
// don't call ItemHeight since this cause recursieve message sending on windows
|
|
if FItemHeight <> 0 then
|
|
AHeight := FItemHeight
|
|
else
|
|
AHeight := ItemHeight;
|
|
if FStyle.IsVariable then
|
|
MeasureItem(Integer(ItemId), AHeight);
|
|
if AHeight > 0 then
|
|
ItemHeight := AHeight;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.LMSelChange(var TheMessage);
|
|
begin
|
|
if [csLoading, csDestroying, csDesigning] * ComponentState <> [] then
|
|
exit;
|
|
Select;
|
|
end;
|
|
|
|
procedure TCustomComboBox.KeyUpAfterInterface(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyUpAfterInterface(Key, Shift);
|
|
if (Key = VK_RETURN) and (FEditingDone) then
|
|
EditingDone;
|
|
FEditingDone := False;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.CNCommand(var TheMessage: TLMCommand);
|
|
|
|
Handler for various notifications.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.CNCommand(var TheMessage: TLMCommand);
|
|
begin
|
|
case TheMessage.NotifyCode of
|
|
CBN_DROPDOWN:
|
|
begin
|
|
FDroppedDown:=true;
|
|
DropDown;
|
|
AdjustDropDown;
|
|
end;
|
|
CBN_CLOSEUP:
|
|
begin
|
|
FDroppedDown:=false;
|
|
CloseUp;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.SetReadOnly(const AValue: Boolean);
|
|
begin
|
|
if FReadOnly = AValue then
|
|
Exit;
|
|
FReadOnly := AValue;
|
|
if (not HandleAllocated) or (csLoading in ComponentState) then
|
|
Exit;
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetReadOnly(Self, FReadOnly);
|
|
end;
|
|
|
|
// TextHint stuff
|
|
|
|
procedure TCustomComboBox.SetTextHint(const AValue: TTranslateString);
|
|
begin
|
|
if (FTextHint = AValue) then Exit;
|
|
FTextHint := AValue;
|
|
if (WidgetSet.GetLCLCapability(lcTextHint) = LCL_CAPABILITY_YES) and HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetTextHint(Self, AValue);
|
|
if FTextHint = '' then
|
|
HideEmulatedTextHint
|
|
else
|
|
ShowEmulatedTextHintIfYouCan;
|
|
end;
|
|
|
|
procedure TCustomComboBox.ShowEmulatedTextHintIfYouCan;
|
|
begin
|
|
if CanShowEmulatedTextHint then
|
|
ShowEmulatedTextHint;
|
|
end;
|
|
|
|
procedure TCustomComboBox.ShowEmulatedTextHint;
|
|
var
|
|
HintFont: TFont;
|
|
begin
|
|
FEmulatedTextHintStatus := thsChanging;
|
|
HintFont := CreateEmulatedTextHintFont(Self);
|
|
try
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetFont(Self, HintFont);
|
|
finally
|
|
HintFont.Free;
|
|
end;
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetText(Self, Self.TextHint);
|
|
FEmulatedTextHintStatus := thsShowing;
|
|
end;
|
|
|
|
procedure TCustomComboBox.HideEmulatedTextHint;
|
|
begin
|
|
if FEmulatedTextHintStatus<>thsShowing then
|
|
Exit;
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetFont(Self, Font);
|
|
TWSCustomComboBoxClass(WidgetSetClass).SetText(Self, '');
|
|
FEmulatedTextHintStatus := thsHidden;
|
|
end;
|
|
|
|
function TCustomComboBox.UpdateItemIndex(const AValue: TCaption): Boolean;
|
|
var
|
|
I: integer;
|
|
begin
|
|
// when items have same text, FItems.IndexOf(AValue) gives wrong index. Issue #28683.
|
|
// Items can contain an empty string, set ItemIndex in that case too. Issue #39366
|
|
I := ItemIndex;
|
|
if (I < 0) or (I >= FItems.Count) or (FItems[I] <> AValue) then
|
|
if not (csLoading in ComponentState) then
|
|
ItemIndex := MatchListItem(AValue);
|
|
Result:= (I <> ItemIndex);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomComboBox.UpdateSorted;
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomComboBox.UpdateSorted;
|
|
var
|
|
lText: string;
|
|
lIndex: integer;
|
|
begin
|
|
if HandleAllocated then
|
|
TWSCustomComboBoxClass(WidgetSetClass).Sort(Self, Items, FSorted)
|
|
else if FItems is TStringList then
|
|
begin
|
|
// remember text
|
|
lText := Text;
|
|
TStringList(FItems).Sorted := FSorted;
|
|
lIndex := FItems.IndexOf(lText);
|
|
if lIndex >= 0 then
|
|
ItemIndex := lIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomComboBox.CMWantSpecialKey(var Message: TCMWantSpecialKey);
|
|
begin
|
|
{$ifdef darwin}
|
|
// don't allow LCL to handle arrow keys for edit controls
|
|
if Message.CharCode in [VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN] then
|
|
Message.Result := 1
|
|
else
|
|
{$endif}
|
|
inherited;
|
|
end;
|
|
|
|
{ TComboBoxStyleHelper }
|
|
|
|
function TComboBoxStyleHelper.HasEditBox: Boolean;
|
|
const
|
|
ArrHasEditBox: array[TComboBoxStyle] of Boolean = (
|
|
True, // csDropDown
|
|
True, // csSimple
|
|
False, // csDropDownList
|
|
False, // csOwnerDrawFixed
|
|
False, // csOwnerDrawVariable
|
|
True, // csOwnerDrawEditableFixed
|
|
True // csOwnerDrawEditableVariable
|
|
);
|
|
begin
|
|
Result := ArrHasEditBox[Self];
|
|
end;
|
|
|
|
function TComboBoxStyleHelper.IsOwnerDrawn: Boolean;
|
|
const
|
|
ArrIsOwnerDrawn: array[TComboBoxStyle] of Boolean = (
|
|
False, // csDropDown
|
|
False, // csSimple
|
|
False, // csDropDownList
|
|
True, // csOwnerDrawFixed
|
|
True, // csOwnerDrawVariable
|
|
True, // csOwnerDrawEditableFixed
|
|
True // csOwnerDrawEditableVariable
|
|
);
|
|
begin
|
|
Result := ArrIsOwnerDrawn[Self];
|
|
end;
|
|
|
|
function TComboBoxStyleHelper.IsVariable: Boolean;
|
|
const
|
|
ArrIsVariable: array[TComboBoxStyle] of Boolean = (
|
|
False, // csDropDown
|
|
False, // csSimple
|
|
False, // csDropDownList
|
|
False, // csOwnerDrawFixed
|
|
True, // csOwnerDrawVariable
|
|
False, // csOwnerDrawEditableFixed
|
|
True // csOwnerDrawEditableVariable
|
|
);
|
|
begin
|
|
Result := ArrIsVariable[Self];
|
|
end;
|
|
|
|
function TComboBoxStyleHelper.SetEditBox(const AHasEditBox: Boolean): TComboBoxStyle;
|
|
const
|
|
ArrSetEditBox: array[Boolean, TComboBoxStyle] of TComboBoxStyle = (
|
|
(csDropDownList, // csDropDown
|
|
csDropDownList, // csSimple
|
|
csDropDownList, // csDropDownList
|
|
csOwnerDrawFixed, // csOwnerDrawFixed
|
|
csOwnerDrawVariable, // csOwnerDrawVariable
|
|
csOwnerDrawFixed, // csOwnerDrawEditableFixed
|
|
csOwnerDrawVariable), // csOwnerDrawEditableVariable
|
|
(csDropDown, // csDropDown
|
|
csSimple, // csSimple
|
|
csDropDown, // csDropDownList
|
|
csOwnerDrawEditableFixed, // csOwnerDrawFixed
|
|
csOwnerDrawEditableVariable, // csOwnerDrawVariable
|
|
csOwnerDrawEditableFixed, // csOwnerDrawEditableFixed
|
|
csOwnerDrawEditableVariable) // csOwnerDrawEditableVariable
|
|
);
|
|
begin
|
|
Result := ArrSetEditBox[AHasEditBox, Self];
|
|
end;
|
|
|
|
// included by stdctrls.pp
|