2012-07-23 44 views
4

我使用德爾福XE2的TButtonedEdit但我想補充的下拉列表中的歷史(如TComboBox)。我知道TComboBox是一個榮耀的TEdit,所以有消息可以發送給TButtonedEdit以添加此功能嗎?謝謝。是否可以添加一個歷史列表下拉列表到Delphi的TButtonedEdit?

+1

這是不是其實http://stackoverflow.com/questions/5465590/auto-append-complete-from-text-file-to-an-edit-box-delphi的副本Ken的答案是你應該使用的 – 2012-07-23 18:48:17

回答

10

可以使用IAutoComplete2接口來完成這個任務。

入住此示例代碼(適用於TButtonedEdit和Delphi XE2),從Ken White

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Winapi.ActiveX, Winapi.ShlObj, 
    Vcl.Mask, Vcl.ImgList; 


type 
    IACList = interface(IUnknown) 
    ['{77A130B0-94FD-11D0-A544-00C04FD7d062}'] 
    function Expand(pszExpand : POLESTR) : HResult; stdcall; 
    end; 

const 
    //options for IACList2 
    ACLO_NONE = 0;   // don't enumerate anything 
    ACLO_CURRENTDIR = 1; // enumerate current directory 
    ACLO_MYCOMPUTER = 2; // enumerate MyComputer 
    ACLO_DESKTOP = 4;  // enumerate Desktop Folder 
    ACLO_FAVORITES = 8;  // enumerate Favorites Folder 
    ACLO_FILESYSONLY = 16; // enumerate only the file system 

type 
    IACList2 = interface(IACList) 
    ['{470141a0-5186-11d2-bbb6-0060977b464c}'] 
    function SetOptions(dwFlag: DWORD): HResult; stdcall; 
    function GetOptions(var pdwFlag: DWORD): HResult; stdcall; 
    end; 

    IAutoComplete = interface(IUnknown) 
    ['{00bb2762-6a77-11d0-a535-00c04fd7d062}'] 
    function Init(hwndEdit: HWND; const punkACL: IUnknown; 
     pwszRegKeyPath, pwszQuickComplete: POLESTR): HResult; stdcall; 
    function Enable(fEnable: BOOL): HResult; stdcall; 
    end; 

const 
    //options for IAutoComplete2 
    ACO_NONE = 0; 
    ACO_AUTOSUGGEST = $1; 
    ACO_AUTOAPPEND = $2; 
    ACO_SEARCH = $4; 
    ACO_FILTERPREFIXES = $8; 
    ACO_USETAB = $10; 
    ACO_UPDOWNKEYDROPSLIST = $20; 
    ACO_RTLREADING = $40; 

type 
    IAutoComplete2 = interface(IAutoComplete) 
    ['{EAC04BC0-3791-11d2-BB95-0060977B464C}'] 
    function SetOptions(dwFlag: DWORD): HResult; stdcall; 
    function GetOptions(out pdwFlag: DWORD): HResult; stdcall; 
    end; 

    TEnumString = class(TInterfacedObject, IEnumString) 
    private 
    type 
    TPointerList = array[0..0] of Pointer; //avoid bug of Classes.pas declaration TPointerList = array of Pointer; 
    var 
    FStrings: TStringList; 
    FCurrIndex: integer; 
    public 
    //IEnumString 
    function Next(celt: Longint; out elt; 
     pceltFetched: PLongint): HResult; stdcall; 
    function Skip(celt: Longint): HResult; stdcall; 
    function Reset: HResult; stdcall; 
    function Clone(out enm: IEnumString): HResult; stdcall; 
    //VCL 
    constructor Create; 
    destructor Destroy;override; 
    end; 

    TACOption = (acAutoAppend, acAutoSuggest, acUseArrowKey); 
    TACOptions = set of TACOption; 

    TACSource = (acsList, acsHistory, acsMRU, acsShell); 


    TButtonedEdit = class(Vcl.ExtCtrls.TButtonedEdit) 
    private 

    FACList: TEnumString; 
    FAutoComplete: IAutoComplete; 
    FACEnabled: boolean; 
    FACOptions: TACOptions; 
    FACSource: TACSource; 
    function GetACStrings: TStringList; 
    procedure SetACEnabled(const Value: boolean); 
    procedure SetACOptions(const Value: TACOptions); 
    procedure SetACSource(const Value: TACSource); 
    procedure SetACStrings(const Value: TStringList); 
    protected 
    procedure CreateWnd; override; 
    procedure DestroyWnd; override; 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    published 
    property ACEnabled: boolean read FACEnabled write SetACEnabled; 
    property ACOptions: TACOptions read FACOptions write SetACOptions; 
    property ACSource: TACSource read FACSource write SetACSource; 
    property ACStrings: TStringList read GetACStrings write SetACStrings; 
    end; 


    TForm1 = class(TForm) 
    ButtonedEdit1: TButtonedEdit; 
    ImageList1: TImageList; 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm5; 

implementation 

{$R *.dfm} 


uses 
    System.Win.ComObj; 


procedure TForm1.FormCreate(Sender: TObject); 
begin 
    ButtonedEdit1.ACEnabled:=True; 
    ButtonedEdit1.ACOptions:=[acAutoAppend, acAutoSuggest, acUseArrowKey]; 
    ButtonedEdit1.ACSource:=acsList; 
    ButtonedEdit1.ACStrings.Add('string 1'); 
    ButtonedEdit1.ACStrings.Add('string 2'); 
    ButtonedEdit1.ACStrings.Add('string 3'); 
    ButtonedEdit1.ACStrings.Add('string 4'); 
end; 

{ TEnumString } 

function TEnumString.Clone(out enm: IEnumString): HResult; 
begin 
    Result := E_NOTIMPL; 
    Pointer(enm) := nil; 
end; 

constructor TEnumString.Create; 
begin 
    inherited Create; 
    FStrings := TStringList.Create; 
    FCurrIndex := 0; 
end; 

destructor TEnumString.Destroy; 
begin 
    FStrings.Free; 
    inherited; 
end; 

function TEnumString.Next(celt: Integer; out elt; 
    pceltFetched: PLongint): HResult; 
var 
    I: Integer; 
    wStr: WideString; 
begin 
    I := 0; 
    while (I < celt) and (FCurrIndex < FStrings.Count) do 
    begin 
    wStr := FStrings[FCurrIndex]; 
    TPointerList(elt)[I] := CoTaskMemAlloc(2 * (Length(wStr) + 1)); 
    StringToWideChar(wStr, TPointerList(elt)[I], 2 * (Length(wStr) + 1)); 
    Inc(I); 
    Inc(FCurrIndex); 
    end; 
    if pceltFetched <> nil then 
    pceltFetched^ := I; 
    if I = celt then 
    Result := S_OK 
    else 
    Result := S_FALSE; 
end; 

function TEnumString.Reset: HResult; 
begin 
    FCurrIndex := 0; 
    Result := S_OK; 
end; 

function TEnumString.Skip(celt: Integer): HResult; 
begin 
    if (FCurrIndex + celt) <= FStrings.Count then 
    begin 
    Inc(FCurrIndex, celt); 
    Result := S_OK; 
    end 
    else 
    begin 
    FCurrIndex := FStrings.Count; 
    Result := S_FALSE; 
    end; 
end; 

{ TACEdit } 

constructor TButtonedEdit.Create(AOwner: TComponent); 
begin 
    inherited; 
    FACList := TEnumString.Create; 
    FACEnabled := True; 
    FACOptions := [acAutoAppend, acAutoSuggest, acUseArrowKey]; 
end; 

procedure TButtonedEdit.CreateWnd; 
var 
    Dummy: IUnknown; 
    Strings: IEnumString; 
begin 
    inherited; 
    if HandleAllocated then 
    begin 
    try 
     Dummy := CreateComObject(CLSID_AutoComplete); 
     if (Dummy <> nil) and 
     (Dummy.QueryInterface(IID_IAutoComplete, FAutoComplete) = S_OK) then 
     begin 
     case FACSource of 
      acsHistory: Strings := CreateComObject(CLSID_ACLHistory) as 
      IEnumString; 
      acsMRU: Strings := CreateComObject(CLSID_ACLMRU) as 
      IEnumString; 
      acsShell: Strings := CreateComObject(CLSID_ACListISF) as 
      IEnumString; 
     else 
      Strings := FACList as IEnumString; 
     end; 
     if S_OK = FAutoComplete.Init(Handle, Strings, nil, nil) then 
     begin 
      SetACEnabled(FACEnabled); 
      SetACOptions(FACOptions); 
     end; 
     end; 
    except 
     //CLSID_IAutoComplete is not available 
    end; 
    end; 
end; 

destructor TButtonedEdit.Destroy; 
begin 
    FACList := nil; 
    inherited; 
end; 

procedure TButtonedEdit.DestroyWnd; 
begin 
    if (FAutoComplete <> nil) then 
    begin 
    FAutoComplete.Enable(False); 
    FAutoComplete := nil; 
    end; 
    inherited; 
end; 

function TButtonedEdit.GetACStrings: TStringList; 
begin 
    Result := FACList.FStrings; 
end; 

procedure TButtonedEdit.SetACEnabled(const Value: Boolean); 
begin 
    if (FAutoComplete <> nil) then 
    begin 
    FAutoComplete.Enable(FACEnabled); 
    end; 
    FACEnabled := Value; 
end; 

procedure TButtonedEdit.SetACOptions(const Value: TACOptions); 
const 
    Options : array[TACOption] of integer = (ACO_AUTOAPPEND, 
              ACO_AUTOSUGGEST, 
              ACO_UPDOWNKEYDROPSLIST); 
var 
    Option:TACOption; 
    Opt: DWORD; 
    AC2: IAutoComplete2; 
begin 
    if (FAutoComplete <> nil) then 
    begin 
    if S_OK = FAutoComplete.QueryInterface(IID_IAutoComplete2, AC2) then 
    begin 
     Opt := ACO_NONE; 
     for Option := Low(Options) to High(Options) do 
     begin 
     if (Option in FACOptions) then 
      Opt := Opt or DWORD(Options[Option]); 
     end; 
     AC2.SetOptions(Opt); 
    end; 
    end; 
    FACOptions := Value; 
end; 

procedure TButtonedEdit.SetACSource(const Value: TACSource); 
begin 
    if FACSource <> Value then 
    begin 
    FACSource := Value; 
    RecreateWnd; 
    end; 
end; 

procedure TButtonedEdit.SetACStrings(const Value: TStringList); 
begin 
    if Value <> FACList.FStrings then 
    FACList.FStrings.Assign(Value); 
end; 

end. 

這是結果基於這個答案(Auto append/complete from text file to an edit box delphi)。

enter image description here

+0

哇。一段驚人的代碼。第一次工作。謝謝! – 2012-07-24 09:28:34

1

我不知道在XE2(我在2007年我自己),其具體的控制,但是,假設彈出菜單屬性是一個在你的控制,爲什麼不把窗體上創建一個彈出式菜單,並將其分配給那財產?那麼作爲你通過你的控制項目,你可以讓他們被添加到彈出式菜單中具有共同的onclick處理程序,需要重新加載之前的項目。

相關問題