いつもお世話になります。以下の事項について質問させてください。
ComboBoxの高さを高くしようと、3箇所に1行ずつコードを書きました。
概ね意図したとおりに動くのですが、コンボボックスの隣にある下向きの
三角の部分を押すと、その三角の部分の描画がおかしくなってしまいます。
これを綺麗に描画するにはどうすればよいでしょうか?
よろしくお願いします。(Delphi6を使用しています。)
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
SendMessage(ComboBox1.Handle, CB_SETITEMHEIGHT, -1, 16);
end;
procedure TForm1.ComboBox1CloseUp(Sender: TObject);
begin
SendMessage(ComboBox1.Handle, CB_SETITEMHEIGHT, -1, 16);
end;
procedure TForm1.ComboBox1Click(Sender: TObject);
begin
SendMessage(ComboBox1.Handle, CB_SETITEMHEIGHT, -1, 16);
end;
念のためもうひとつ。
全項目の高さも統一して変更すれば、意図したとおりに動くのでは?と考え、
次のコードも試してみましたが、やはりうまくいきませんでした。
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
// コンボボックスの全項目の高さを高くする。
for i := - 1 to ComboBox1.Items.Count - 1 do
SendMessage(ComboBox1.Handle, CB_SETITEMHEIGHT, i, 16)
end;
Fontサイズ変えれば自動的に高さも変わると思うけど?
コンボボックスはスタイルによって挙動が違いますが、使っているStyleは何でしょう?
StyleをcsOwnerDrawFixedにして、ItemHeightを使うのでは駄目なんでしょうか?
(OnDrawItemで自分で描画しなくちゃいけなくなりますけど)
ちなみに、CB_SETITEMHEIGHTも、オーナードローでない場合は
wParamに-1と0以外の値は指定できないとあります。
ご回答、どうもありがとうございます。
それで、Fontのサイズの件についてなのですが、先方から指摘されたサイズ
がありますので、それを遵守しなくてはなりません。今からの変更もちょっ
と難しいです。
それと、スタイルはcsDropDown(初期値)を使用しています。自由に入力
できる必要がある項目なので、これを使用しています。
wParamに-1 と0以外を指定できないことは勉強になりました。
一見利いていたように見えたのですが、無効な処理だったのですね。
お客さんのプログラムにみっともない処理をはさむところでした。ご指摘いただいて、本当に助かりました。m(__)m
やはり高さを変えることは難しいでしょうか?
いろいろ調べたりしていますが、まだできていません。
もし分かる方がいらっしゃれば、ぜひお願いいたします。
こんにちは.Mr.XRAYです.
だいぶ日にちが経過しているので,ネット等で調査済みだとは思いますが,
(それはやってみましたが... ということになるのかも知れませんが..)
OwnerDrawではどうですか.
ただし,動作確認は Delphi6(UP2) + Window XP(SP3)でXPテーマ無使用です.
XPテーマを有効にするとどうなるかは不明です.
また,どうしてもcsDropDownという場合はできないと思いますよ.
だって,Draw(描画)を変更しないんですから.
(Itemの)の高さを変えると言うことは,描画を変えるということですから.
//=============================================================================
// ComboBoxでオーナードロウする
// StyleプロパティをcsOwnerDrawFixedかcsOwnerDrawVariableにしないと無効
// ComboBoxの高さはItemHeightで変更する
//=============================================================================
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
TComboBox(Control).Canvas.FillRect(Rect);
if odFocused in State then
begin
TComboBox(Control).Canvas.Font.Color := clWhite;
end else
begin
TComboBox(Control).Canvas.Font.Color := clWindowText;
end;
//2や5の値はItemHeightよよっても体裁が変わるので適時変更する
//あるいは自動計算のコードを書く
TComboBox(Control).Canvas.TextOut(Rect.Left+2,
Rect.Top+5,
TComboBox(Control).Items[Index]);
end;
正当な手段はオーナードローにしてItemHeightを指定するなり
OnMeasureItemを処理することなんですけど、
それだと動作としてはcsDropDownList相当になるから駄目ということですね。
TComboBoxExを使って、Heightを目的の高さに設定したImageListを関連づけるとそれっぽくなります。これではどうでしょうか?
(DropDownCountとの関係がちょっと怪しくなるので調整がいりそうですが)
失礼しました.
この方法は既にtorさんがレスしていましたね.
Styleを変更したくないとのことですので,私のレスは忘れてください.
>Styleを変更したくないとのことですので,私のレスは忘れてください.
ただちょっと一言.
目的で達成できるのであれば,変更してもいいと思うんですが.
背景の色が同じパネルを用意して、
その中にコンボボックスを置いて、
FormCreateなどでコンボボックスの枠を
消すというのはどうでしょうか?
SetWindowRgn(ComboBox1.Handle, CreateRectRgn(2,2,ComboBox1.Width - 2, ComboBox1.Height - 2), True);
やや脱線しますが、コンボボックスでは本来、リストの動作を指定するスタイルとオーナー描画を指定するスタイルは独立しています。
・リストの動作: CBS_SIMPLE, CBS_DROPDOWN, CBS_DROPDOWNLIST
・オーナー描画: なし、CBS_OWNERDRAWFIXED, CBS_OWNERDRAWVARIABLE
本来なら3×3=9通りの組み合わせがあるはずなのですが、VCLではこれを一つのStyleに押し込めて5通りに制限してしまっています。
なので、リストの動作はcsSimpleまたはcsDropDownと同等で、かつオーナードローを有効にするということができないんですね。
そこで、ウィンドウスタイルを勝手にいじって、csDropDownの動作とオーナー描画を両立できないか試してみました。
カスタムコンポーネントを作ることになってしまいますけれど、まあ参考までに…
type
TMyComboBox = class(TComboBox)
public
procedure CreateParams(var Params: TCreateParams); override;
end;
procedure TMyComboBox.CreateParams(var Params: TCreateParams);
begin
inherited;
// デフォルトではCBS_DROPDOWNが設定されているはずなので
// これにオーナー描画スタイルを追加する
Params.Style := Params.Style or CBS_OWNERDRAWFIXED;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1 := TMyComboBox.Create(Self);
ComboBox1.Parent := Self;
ComboBox1.ItemHeight := 適当な高さ;
end;
高さを変えるだけなら、特にOnMeasureItemやOnDrawItemを実装しなくてもこれだけで動いてくれるようです。
ちなみに、こちらの方法だと文字列がボックスの上に張り付いたイメージになりますが、
先ほど提案したTComboBoxExだと逆に下に張り付いたようになりますね。
一晩立ったらこんなにレスが…
みなさん、本当にありがとうございます。つまらない質問に、こんなにも
いろいろと考えてくださって、本当に頭の下がる思いです。
今は出先なので、まだ確認できませんが、帰ったらご教示いただいた方法
をそれぞれ確認させていただきたいと思います。結果報告も必ずいたします
ので、もう少しお時間をください。
今、動作確認を行いました。結論から申し上げますと、最終的には
tor様の最後のご提案部分を利用させていただき、実現できました。
ほんの些細な変更だったのですが、画面上でコントロールを美しく
配置できるようになり、先方からも非常に喜ばれました。本当にあり
がとうございます。外国のサイトまで検索しても見つからず、ここ1ヶ
月以上悩んでいた案件でしたので、本当にうれしいです。
>deldel様
そのサンプル自体は入手していたのですが、後ろにパネルを置く、など
の対案までは思いつかなかったので、結局見送っていました。でも、今
やってみたら、私の要件を満たす見栄えを実現できそうな方法ですね。
今後、他の同様の場面で困ったときなど、そのアイデアを流用させて
いただきたいと思います。
>Mr.XRAY様
あなたのサンプルはいつも参考にさせていただいております。今回も
非常に多くの情報をご提示いただきまして、本当にありがとうございます。
この場をお借りして、日ごろの感謝もこめてお礼を申し上げます。
ツイート | ![]() |