Unicode対応のTComboBox
TComboBoxの表示だけをUnicode対応に。
Unicodeに対応させるためにUnicodeをリストに持たせるTMyWStringsを活用します。
type
{TMyComboBox}
TMyComboBox = class(TCustomComboBox)
private
F_slList: TMyWStrings;
function GetText: WideString;
procedure SetText(sWText: WideString);
protected
procedure SetStyle(csStyle: TComboBoxStyle); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
procedure Clear; override;
procedure AddItem(Item: WideString; AObject: TObject); reintroduce;
published
property AutoComplete default True;
property AutoDropDown default False;
property BevelEdges;
property BevelInner;
property BevelKind default bkNone;
property BevelOuter;
property Anchors;
property BiDiMode;
property CharCase;
property Color;
property Constraints;
property Ctl3D;
property DragCursor;
property DragKind;
property DragMode;
property DropDownCount;
property Enabled;
property Font;
property ImeMode;
property ImeName;
property ItemHeight;
property ItemIndex default -1;
property MaxLength;
property ParentBiDiMode;
property ParentColor;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Sorted;
property TabOrder;
property TabStop;
property Visible;
property OnChange;
property OnClick;
property OnCloseUp;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnDrawItem;
property OnDropDown;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMeasureItem;
property OnSelect;
property OnStartDock;
property OnStartDrag;
property Style;
property Items: TMyWStrings read F_slList;
property Text: WideString read GetText write SetText;
end;
TCustomComboBoxから派生させます。
TComboBoxのメソッドやプロパティからUnicodeの表示に関連しそうなものをピックアップしていきます。CreateとDestroy、DrawItem、Clear、AddItem、SetStyleのメソッドにStyleとItems、Textプロパティを実装しました。
CreateとDestroy、DrawItem、Clearの四つのメソッドはoverrideします。AddItemとSetStyleはoverrideできない(SetStyleをoverrideするとスタックオーバーフローになってしまう)ので置き換えます。
reintroduce指令をつけることで警告メッセージを抑えています。
あとはStyleとItems、Textのプロパティを置き換えます。
//------------------------------------------------------------------------------
{TMyComboBox}
constructor TMyComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
F_slList := TMyWideStringList.Create(inherited Items);
end;
destructor TMyComboBox.Destroy;
begin
F_slList.Free;
inherited Destroy;
end;
procedure TMyComboBox.SetStyle(csStyle: TComboBoxStyle);
begin
if (csStyle = csDropDownList) then begin
//csDropDwonListはDrawItemイベントが起きないのでcsOwnerDrawFixedにする
csStyle := csOwnerDrawFixed;
end;
inherited SetStyle(csStyle);
end;
//DrawItem
procedure TMyComboBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
lrc_Rect: TRect;
begin
if (Style in [csOwnerDrawFixed, csOwnerDrawVariable]) and (Assigned(OnDrawItem)) then begin
OnDrawItem(Self, Index, Rect, State);
end else begin
with Canvas do begin
FillRect(Rect);
lrc_Rect := Rect;
Inc(lrc_Rect.Left);
DrawTextW(Handle, PWideChar(F_slList.Strings[Index]), -1, lrc_Rect, DT_VCENTER or DT_NOPREFIX or DT_SINGLELINE);
end;
end;
end;
//Clear
procedure TMyComboBox.Clear;
begin
F_slList.Clear;
ItemIndex := -1;
end;
procedure TMyComboBox.AddItem(Item: WideString; AObject: TObject);
begin
F_slList.AddObject(Item, AObject);
end;
//Text
function TMyComboBox.GetText: WideString;
begin
Result := F_slList.Strings[ItemIndex];
end;
procedure TMyComboBox.SetText(sWText: WideString);
begin
F_slList.Strings[ItemIndex] := sWText;
end;
F_slListのCreateで引数にTCustomComboBoxのItemsを指定しているので、F_slListを通してWideStringからStringに変換したリストをTCustomComboBoxに実装されている(String型の)Itemsに保持させています。
StyleはcsDropDownを選んだときにcsOwnerDrawFixedに変換します。
これはDrawItemメソッドがcsOwnerDrawFixedとcsOwnerDrawVariableの時にしか呼ばれないからです。
そのため残念ながら編集ボックスつきのcsSimpleとcsDropDownを選択した時はDrawItemが呼ばれないのでUnicodeの表示には非対応になります。
どうしてもUnicodeの入力と表示のComboBoxが必要ならばCreateWindowW APIで作成するか、Unicode対応のEditとこのTMyComboBoxのStyleをcsOwnerDrawFixedにして組み合わせるかになるかと思います。
またこのコンポーネントをインストールして、設計時にフォームへドロップした場合StyleのデフォルトプロパティはcsDropDownのままなのでUnicodeの表示をするためにはcsOwnerDrawFixedかcsOwnerDrawVariableにする必要があります。
myComboBox.pas - ソースコードです。
制限
TComboBoxのリストの表示をUnicode対応にしますが、エディタでの入力は残念ながらUnicode非対応です。
TComboBoxのStyleでcsSimpleとcsDropDownを指定した場合は入力はもちろんのこと表示もUnicode非対応となります。
Unicode対応になるのはcsOwnerDrawFixedとcsOwnerDrawVariableだけです。
csDropDownListを指定した場合は自動的にcsOwnerDrawFixedに変更されます。
またプロパティのBevelEdgesやBevelInnerなんてのはいら〜ん、と思ってpublishedに書かなかったら「必要なプロパティがない」と怒られてプログラムが落ちてしまいました。
少なくともpublicにはしないとだめなようです。
だったら最初からpublicにしとくべきなんではないのかなぁ、、と思ってしまうわけですが、まぁ色々あるのでしょう。
2008-07-06: