delphi - 如何在自定义样式的所有者绘制 TComboBox 中检测 ODS_COMBOBOXEDIT
问题描述
使用德尔福 10.3:
在带有 的所有者绘制TComboBox
中Style=csOwnerDrawFixed
,我希望 DropDown 列表中所有者绘制的项目与组合的静态部分不同。为了区分这两种情况,我检查odComboBoxEdit
了State
参数,如下所述:
procedure TStylePanel.TargetArrowComboDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
if (odComboBoxEdit in State) then
begin
// Paint static control
end
else
begin
// Paint item in dropped down list
end;
end;
只要没有自定义 VCL 样式处于活动状态,它就可以很好地工作。但是,对于自定义样式,这不再可靠。检查源代码,在Vcl.StdCtrls.pas
我TComboBoxStyleHook
看来,原因在于以下组合:
procedure TComboBoxStyleHook.WMPaint(...)
procedure TComboBoxStyleHook.DrawItem(...)
当没有编辑句柄时(就是 的情况csOwnerDrawFixed
),DrawItem()
组装一个TDrawItemStruct
永远不会包含ODS_COMBOBOXEDIT
的 ,因此CN_DRAWITEM
处理程序永远不会odComboBoxEdit
设置。
我可以覆盖TComboBoxStyleHook
,但我需要一种方法来检测该项目是静态项目还是列表中的项目。
作为一种解决方法,我检查了Combo.DroppedDown
,但这并不相同:即使下拉,我希望静态部分的绘制方式与列表中的项目不同。
所以问题是,我如何(在自定义绘制处理程序或样式挂钩中)检测到自定义绘制项是静态区域而不是列表中的项?
解决方案
通过为 TComboBox 添加一个无条件包含ODS_COMBOBOXEDIT
. 假设TComboBoxStyleHook.DrawItem
仅在需要自定义绘制静态项目时调用TComboBoxStyleHook.WMPaint
,下拉列表不在那里处理。似乎没有不需要的副作用。
type
TComboBoxStyleHookFix = class(TComboBoxStyleHook)
strict protected
procedure DrawItem(Canvas: TCanvas; Index: Integer; const R: TRect; Selected: Boolean); override;
end;
procedure TComboBoxStyleHookFix.DrawItem(Canvas: TCanvas; Index: Integer; const R: TRect; Selected: Boolean);
var
DIS: TDrawItemStruct;
begin
FillChar(DIS, SizeOf(DIS), 0);
DIS.CtlType := ODT_COMBOBOX;
DIS.CtlID := GetDlgCtrlID(Handle);
DIS.itemAction := ODA_DRAWENTIRE;
DIS.hDC := Canvas.Handle;
DIS.hwndItem := Handle;
DIS.rcItem := R;
DIS.itemID := Index;
DIS.itemData := SendMessage(ListHandle, LB_GETITEMDATA, 0, 0);
if (Control is TComboBox) and (TComboBox(Control).Style = csOwnerDrawFixed) then
DIS.itemState := ODS_COMBOBOXEDIT;
if Selected then
DIS.itemState := DIS.itemState or ODS_FOCUS or ODS_SELECTED;
SendMessage(Handle, WM_DRAWITEM, Handle, LPARAM(@DIS));
end;
procedure InitComboStyleHookFix();
begin
TCustomStyleEngine.RegisterStyleHook(TComboBox, TComboBoxStyleHookFix);
end;
推荐阅读
- java - 在适用于 Eclipse 的 Google Cloud 工具上运行 Objectify 时出现“projectId 必须匹配以下模式”异常
- ruby-on-rails - 回复按钮(用户只能回复一次)
- javascript - 如何在 Chromeless 中操作由 ul 和 li 元素组成的下拉菜单
- eclipse - Github Master 变成 HEAD 我不能再往上游推了
- vue.js - 更改 vue-cli 的公共目录
- vba - Excel VBA 错误 13“类型不匹配”
- c# - 如何在 JsonConverter 中注入/访问 HttpContext?
- python - 如何从 Python 中的命名列表生成 json 文件?
- c++ - 用于自附加的字符串反向迭代器的持久性
- javascript - ostrio:files & Meteor 删除文件