⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tntstdctrls.pas

📁 TNT Components Source
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    ComboBox.Items.Insert(Index, S)
  else begin
    if SendMessageW(ComboBox.Handle, CB_INSERTSTRING, Index, Longint(PWideChar(S))) < 0 then
      raise EOutOfResources.Create(SInsertLineError);
  end;
end;

procedure TTntComboBoxStrings.Delete(Index: Integer);
begin
  ComboBox.Items.Delete(Index);
end;

procedure TTntComboBoxStrings.Clear;
var
  S: WideString;
begin
  S := TntControl_GetText(ComboBox);
  SendMessage(ComboBox.Handle, CB_RESETCONTENT, 0, 0);
  TntControl_SetText(ComboBox, S);
  ComboBox.Update;
end;

procedure TTntComboBoxStrings.SetUpdateState(Updating: Boolean);
begin
  TAccessStrings(ComboBox.Items).SetUpdateState(Updating);
end;

function TTntComboBoxStrings.IndexOf(const S: WideString): Integer;
begin
  if (not IsWindowUnicode(ComboBox.Handle)) then
    Result := ComboBox.Items.IndexOf(S)
  else
    Result := SendMessageW(ComboBox.Handle, CB_FINDSTRINGEXACT, -1, LongInt(PWideChar(S)));
end;

{ TTntCustomComboBox }

type TAccessCustomComboBox = class(TCustomComboBox{TNT-ALLOW TCustomComboBox});

procedure TntCombo_AfterInherited_CreateWnd(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  Items: TTntStrings; var FSaveItems: TTntStrings; FSaveItemIndex: integer; PreInheritedAnsiText: AnsiString);
begin
  if (not Win32PlatformIsUnicode) then begin
    TAccessCustomComboBox(Combo).Text := PreInheritedAnsiText;
  end else begin
    with TAccessCustomComboBox(Combo) do
    begin
      if ListHandle <> 0 then begin
        // re-extract FDefListProc as a Unicode proc
        SetWindowLongA(ListHandle, GWL_WNDPROC, Integer(FDefListProc));
        FDefListProc := Pointer(GetWindowLongW(ListHandle, GWL_WNDPROC));
        // override with FListInstance as a Unicode proc
        SetWindowLongW(ListHandle, GWL_WNDPROC, Integer(FListInstance));
      end;
      SetWindowLongW(EditHandle, GWL_WNDPROC, GetWindowLong(EditHandle, GWL_WNDPROC));
    end;
    if FSaveItems <> nil then
    begin
      Items.Assign(FSaveItems);
      FreeAndNil(FSaveItems);
      if FSaveItemIndex <> -1 then
      begin
        if Items.Count < FSaveItemIndex then FSaveItemIndex := Items.Count;
        SendMessage(Combo.Handle, CB_SETCURSEL, FSaveItemIndex, 0);
      end;
    end;
    TntControl_SetText(Combo, TntControl_GetStoredText(Combo, TAccessCustomComboBox(Combo).Text));
  end;
end;

procedure TntCombo_BeforeInherited_DestroyWnd(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  Items: TTntStrings; var FSaveItems: TTntStrings; ItemIndex: integer; var FSaveItemIndex: integer;
    var SavedText: WideString);
begin
  Assert(not (csDestroyingHandle in Combo.ControlState));
  if (Win32PlatformIsUnicode) then begin
    SavedText := TntControl_GetText(Combo);
    if (Items.Count > 0) then
    begin
      FSaveItems := TTntStringList.Create;
      FSaveItems.Assign(Items);
      FSaveItemIndex:= ItemIndex;
      Items.Clear; { This keeps TCustomComboBox from creating its own FSaveItems. (this kills the original ItemIndex) }
    end;
  end;
end;

function TntCombo_ComboWndProc(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer; DoEditCharMsg: TWMCharMsgHandler): Boolean;

  procedure CallDefaultWindowProc;
  begin
    with Message do begin { call default wnd proc }
      if IsWindowUnicode(ComboWnd) then
        Result := CallWindowProcW(ComboProc, ComboWnd, Msg, WParam, LParam)
      else
        Result := CallWindowProcA(ComboProc, ComboWnd, Msg, WParam, LParam);
    end;
  end;

  function DoWideKeyPress(Message: TWMChar): Boolean;
  begin
    DoEditCharMsg(Message);
    Result := (Message.CharCode = 0);
  end;

begin
  Result := False;
  try
    if (Message.Msg = WM_CHAR) then begin
      // WM_CHAR
      Result := True;
      if IsWindowUnicode(ComboWnd) then
        MakeWMCharMsgSafeForAnsi(Message);
      try
        if TAccessCustomComboBox(Combo).DoKeyPress(TWMKey(Message)) then Exit;
        if DoWideKeyPress(TWMKey(Message)) then Exit;
      finally
        if IsWindowUnicode(ComboWnd) then
          RestoreWMCharMsg(Message);
      end;
      with TWMKey(Message) do begin
        if ((CharCode = VK_RETURN) or (CharCode = VK_ESCAPE)) and Combo.DroppedDown then begin
          Combo.DroppedDown := False;
          Exit;
        end;
      end;
      CallDefaultWindowProc;
    end else if (IsWindowUnicode(ComboWnd)) then begin
      // UNICODE
      if IsTextMessage(Message.Msg)
      or (Message.Msg = EM_REPLACESEL)
      or (Message.Msg = WM_IME_COMPOSITION)
      then begin
        // message w/ text parameter
        Result := True;
        CallDefaultWindowProc;
      end else if (Message.Msg = WM_IME_CHAR) then begin
        // WM_IME_CHAR
        Result := True;
        with Message do { convert to WM_CHAR }
          Result := SendMessageW(ComboWnd, WM_CHAR, WParam, LParam);
      end;
    end;
  except
    Application.HandleException(Combo);
  end;
end;

function TntCombo_CNCommand(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; Items: TTntStrings; var Message: TWMCommand): Boolean;
begin
  Result := False;
  if Message.NotifyCode = CBN_SELCHANGE then begin
    Result := True;
    TntControl_SetText(Combo, Items[Combo.ItemIndex]);
    TAccessCustomComboBox(Combo).Click;
    TAccessCustomComboBox(Combo).Select;
  end;
end;

function TntCombo_GetSelStart(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}): Integer;
begin
  if Win32PlatformIsUnicode then
    Result := Combo.SelStart
  else
    Result := Length(WideString(Copy(TAccessCustomComboBox(Combo).Text, 1, Combo.SelStart)));
end;

procedure TntCombo_SetSelStart(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; const Value: Integer);
begin
  if Win32PlatformIsUnicode then
    Combo.SelStart := Value
  else
    Combo.SelStart := Length(AnsiString(Copy(TntControl_GetText(Combo), 1, Value)));
end;

function TntCombo_GetSelLength(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}): Integer;
begin
  if Win32PlatformIsUnicode then
    Result := Combo.SelLength
  else
    Result := Length(TntCombo_GetSelText(Combo));
end;

procedure TntCombo_SetSelLength(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; const Value: Integer);
var
  StartPos: Integer;
begin
  if Win32PlatformIsUnicode then
    Combo.SelLength := Value
  else begin
    StartPos := TntCombo_GetSelStart(Combo);
    Combo.SelLength := Length(AnsiString(Copy(TntControl_GetText(Combo), StartPos + 1, Value)));
  end;
end;

function TntCombo_GetSelText(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}): WideString;
begin
  if Win32PlatformIsUnicode then begin
    Result := '';
    if TAccessCustomComboBox(Combo).Style < csDropDownList then
      Result := Copy(TntControl_GetText(Combo), Combo.SelStart + 1, Combo.SelLength);
  end else
    Result := Combo.SelText
end;

procedure TntCombo_SetSelText(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; const Value: WideString);
begin
  if Win32PlatformIsUnicode then begin
    if TAccessCustomComboBox(Combo).Style < csDropDownList then
    begin
      Combo.HandleNeeded;
      SendMessageW(TAccessCustomComboBox(Combo).EditHandle, EM_REPLACESEL, 0, Longint(PWideChar(Value)));
    end;
  end else
    Combo.SelText := Value
end;

procedure TntCombo_BeforeKeyPress(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; var SaveAutoComplete: Boolean);
begin
  SaveAutoComplete := TAccessCustomComboBox(Combo).AutoComplete;
  TAccessCustomComboBox(Combo).AutoComplete := False;
end;

procedure TntCombo_AfterKeyPress(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; var SaveAutoComplete: Boolean);
begin
  TAccessCustomComboBox(Combo).AutoComplete := SaveAutoComplete;
end;

procedure TntCombo_DropDown_PreserveSelection(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox});
var
  OldSelStart, OldSelLength: Integer;
  OldText: WideString;
begin
  OldText := TntControl_GetText(Combo);
  OldSelStart := TntCombo_GetSelStart(Combo);
  OldSelLength := TntCombo_GetSelLength(Combo);
  Combo.DroppedDown := True;
  TntControl_SetText(Combo, OldText);
  TntCombo_SetSelStart(Combo, OldSelStart);
  TntCombo_SetSelLength(Combo ,OldSelLength);
end;

procedure TntComboBox_AddItem(Items: TTntStrings; const Item: WideString; AObject: TObject);
begin
  Items.AddObject(Item, AObject);
end;

procedure TntComboBox_CopySelection(Items: TTntStrings; ItemIndex: Integer;
  Destination: TCustomListControl);
begin
  if ItemIndex <> -1 then
    WideListControl_AddItem(Destination, Items[ItemIndex], Items.Objects[ItemIndex]);
end;

function TntCombo_FindString(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  StartPos: Integer; const Text: WideString): Integer;
var
  ComboFindString: ITntComboFindString;
begin
  if Combo.GetInterface(ITntComboFindString, ComboFindString) then
    Result := ComboFindString.FindString(Text, StartPos)
  else if IsWindowUnicode(Combo.Handle) then
    Result := SendMessageW(Combo.Handle, CB_FINDSTRING, StartPos, Integer(PWideChar(Text)))
  else
    Result := SendMessageA(Combo.Handle, CB_FINDSTRING, StartPos, Integer(PAnsiChar(AnsiString(Text))))
end;

function TntCombo_FindUniqueString(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  StartPos: Integer; const Text: WideString): Integer;
var
  Match_1, Match_2: Integer;
begin
  Result := CB_ERR;
  Match_1 := TntCombo_FindString(Combo, -1, Text);
  if Match_1 <> CB_ERR then begin
    Match_2 := TntCombo_FindString(Combo, Match_1, Text);
    if Match_2 = Match_1 then
      Result := Match_1;
  end;
end;

function TntCombo_AutoSelect(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox}; Items: TTntStrings;
  const SearchText: WideString; UniqueMatchOnly: Boolean; UseDataEntryCase: Boolean): Boolean;
var
  Idx: Integer;
  ValueChange: Boolean;
begin
  if UniqueMatchOnly then
    Idx := TntCombo_FindUniqueString(Combo, -1, SearchText)
  else
    Idx := TntCombo_FindString(Combo, -1, SearchText);
  Result := (Idx <> CB_ERR);
  if Result then begin
    if TAccessCustomComboBox(Combo).Style = csDropDown then
      ValueChange := not WideSameStr(TntControl_GetText(Combo), Items[Idx])
    else
      ValueChange := Idx <> Combo.ItemIndex;
    {$IFDEF COMPILER_7_UP}
    // auto-closeup
    if Combo.AutoCloseUp and (Items.IndexOf(SearchText) <> -1) then
      Combo.DroppedDown := False;
    {$ENDIF}
    // select item
    Combo.ItemIndex := Idx;
    // update edit
    if (TAccessCustomComboBox(Combo).Style in [csDropDown, csSimple]) then begin
      if UseDataEntryCase then begin
        // preserve case of characters as they are entered
        TntControl_SetText(Combo, SearchText + Copy(Items[Combo.ItemIndex], Length(SearchText) + 1, MaxInt));
      end else begin
        TntControl_SetText(Combo, Items[Idx]);
      end;
      // select the rest of the string
      TntCombo_SetSelStart(Combo, Length(SearchText));
      TntCombo_SetSelLength(Combo, Length(TntControl_GetText(Combo)) - TntCombo_GetSelStart(Combo));
    end;
    // notify events
    if ValueChange then begin
      TAccessCustomComboBox(Combo).Click;
      TAccessCustomComboBox(Combo).Select;
    end;
  end;
end;

procedure TntCombo_AutoSearchKeyPress(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  Items: TTntStrings; var Message: TWMChar; var FFilter: WideString; var FLastTime: Cardinal);
var
  Key: WideChar;
begin
  if TAccessCustomComboBox(Combo).Style in [csSimple, csDropDown] then
    exit;
  if not Combo.AutoComplete then
    exit;
  Key := GetWideCharFromWMCharMsg(Message);
  try
    case Ord(Key) of
      VK_ESCAPE:
        exit;
      VK_TAB:
        if Combo.AutoDropDown and Combo.DroppedDown then
          Combo.DroppedDown := False;
      VK_BACK:
        Delete(FFilter, Length(FFilter), 1);
      else begin
        if Combo.AutoDropDown and (not Combo.DroppedDown) then
          Combo.DroppedDown := True;
        // reset FFilter if it's been too long (1.25 sec) { Windows XP is actually 2 seconds! }
        if GetTickCount - FLastTime >= 1250 then
          FFilter := '';
        FLastTime := GetTickCount;
        // if AutoSelect works, remember new FFilter
        if TntCombo_AutoSelect(Combo, Items, FFilter + Key, False, True) then begin
          FFilter := FFilter + Key;
          Key := #0;
        end;
      end;
    end;
  finally
    SetWideCharForWMCharMsg(Message, Key);
  end;
end;

procedure TntCombo_AutoCompleteKeyPress(Combo: TCustomComboBox{TNT-ALLOW TCustomComboBox};
  Items: TTntStrings; var Message: TWMChar;
    AutoComplete_UniqueMatchOnly, AutoComplete_PreserveDataEntryCase: Boolean);
var
  Key: WideChar;
  FindText: WideString;
begin
  Assert(TAccessCustomComboBox(Combo).Style in [csSimple, csDropDown], 'Internal Error: TntCombo_AutoCompleteKeyPress is only for csSimple and csDropDown style combo boxes.');
  if not Combo.AutoComplete then exit;
  Key := GetWideCharFromWMCharMsg(Message);
  try
    case Ord(Key) of
      VK_ESCAPE:
        exit;
      VK_TAB:
        if Combo.AutoDropDown and Combo.DroppedDown then
          Combo.DroppedDown := False;
      VK_BACK:
        exit;
      else begin
        if Combo.AutoDropDown and (not Combo.Dropp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -