我正在使用Delphi7,我想要一个带分隔符项目的ComboBox(就像在弹出菜单中一样)。
我已经在Mozilla Sunbird(我知道,它不是Delphi ......)中看到了这个以下方式:
分隔项是一条简单的灰线 在项目的中心绘制
如果将鼠标悬停在分隔符上 鼠标,选择没有 出现
如果用户点击了分隔符, 它也没有被选中 combobox没特写。
没有。可以使用DrawItem实现1。我可以没有第二名,因为我不知道。
对于3号,我正在寻求你的帮助。我发现在关闭CBN_CLOSEUP消息后直接发送到组合框。
我想过挂钩窗口proc并且如果CBN_CLOSEUP被发送到某个组合框然后反击它。但我不确定这是否是最好的解决方案,或者还有其他更优雅的方式?
无论解决方案是什么,我都希望有一个标准的ComboBox,它可以正确支持WinXP / Vista / 7主题。
谢谢!
编辑:对于工作组件,请参阅此主题:
Can you help translating this very small C++ component to Delphi?
答案 0 :(得分:1)
你想要的是一个拥有者绘制的组合框。请参阅:http://delphi.about.com/od/vclusing/a/drawincombobox.htm
此外,这似乎解决了使项目无法解决的问题: http://borland.newsgroups.archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html
据我所知,没有VCL方法可以做到这一点,所以你必须将组合框子类化。创建封装这些功能的组件会很好,这样您就可以轻松地重用它们。
上帝保佑
答案 1 :(得分:1)
我玩弄了无法点击的分隔符项目(如this answer中所述)并遇到了几个UI故障。问题是,组合框的行为有几个方面很难完全正确:
确保已禁用的分隔符项不响应这些事件中的任何(加上我可能遗失的任何其他事件,例如屏幕阅读器?)似乎充满了错误。
相反,我正在使用的方法是将分隔符绘制为项目的一部分:
这是完成此任务的一些C ++ Builder代码;把它翻译成Delphi应该很容易。
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
bool draw_separator = NeedsSeparator(Index) &&
!State.Contains(odComboBoxEdit);
TCanvas *canvas = dynamic_cast<TCustomCombo*>(Control)->Canvas;
canvas->FillRect(Rect);
TRect text_rect = Rect;
// Add space for separator if needed.
if (draw_separator) {
text_rect.Top += 3;
}
canvas->TextOut(text_rect.Left + 3,
(text_rect.Top + text_rect.Bottom) / 2 -
canvas->TextHeight(ComboBox1->Items->Strings[Index]) / 2),
ComboBox1->Items->Strings[Index]);
// Draw a separator line above the item if needed.
if (draw_separator) {
canvas->Pen->Color = canvas->Font->Color;
canvas->MoveTo(Rect.Left, Rect.Top + 1);
canvas->LineTo(Rect.Right, Rect.Top + 1);
}
}
void __fastcall TForm1::ComboBox1MeasureItem(
TWinControl * /* Control */, int Index, int &Height)
{
Height = ComboBox1->ItemHeight;
// Add space for the separator if needed.
if (Index != -1 && NeedsSeparator(Index)) {
Height += 3;
}
}
答案 2 :(得分:0)
如果您希望控件看起来不错,请使用免费SpTBXLib。它支持组合样式组件,弹出带有行的弹出菜单。