当滚动浏览组合框中的项目时,我们需要替换蓝色突出显示。
我们该怎么做?
我尝试了一个示例代码来处理下拉菜单的边框,以下是我的示例应用程序代码。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters,
cxContainer, cxEdit, cxTextEdit, cxMaskEdit, cxDropDownEdit, CXSComboBox, Vcl.StdCtrls;
type
TMycxComboBox = class (PDMCXSComboBox)
protected
procedure Loaded; override;
end;
PDMCXSComboBox = class (TMycxComboBox);
type
TForm1 = class(TForm)
cmbSelectionList: PDMCXSComboBox;
cxComboBox1: TcxComboBox;
procedure cmbSelectionListPropertiesInitPopup(Sender: TObject);
procedure cmbSelectionListPropertiesPopup(Sender: TObject);
procedure cmbSelectionListPropertiesDrawItem(AControl: TcxCustomComboBox; ACanvas: TcxCanvas; AIndex: Integer; const ARect: TRect; AState: TOwnerDrawState);
private
{ Private declarations }
public
{ Public declarations }
procedure DoCustomDrawBorder(AViewInfo: TcxContainerViewInfo; ACanvas: TcxCanvas; const R: TRect; var AHandled: Boolean;
out ABorderWidth: Integer);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TMycxComboBox.Loaded;
begin
inherited;
ContentParams.Offsets.Left := 20;
end;
procedure TForm1.cmbSelectionListPropertiesDrawItem(AControl: TcxCustomComboBox; ACanvas: TcxCanvas; AIndex: Integer; const ARect: TRect; AState: TOwnerDrawState);
Var
AFlags : LongInt;
R : TRect;
begin
if (Integer(AIndex) >= 0) and (odSelected in AState) then
begin
//ACanvas.Brush.Color := clRed;
//ACanvas.Font.Color := clHighlightText;
ACanvas.Brush.Color := clWhite;// $00E5DFD7; //clRed
ACanvas.Font.Color := $006c4e1f;
end;
ACanvas.FillRect(ARect);
if (AIndex >= 0) and (AIndex < AControl.Properties.Items.Count) then
begin
R := ARect;
AFlags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
if not UseRightToLeftAlignment then
Inc(R.Left,2)
else
Dec(R.Right,2);
with AControl.Properties do
DrawText(ACanvas.Handle,PChar(Items[AIndex]),Length(Items[AIndex]), R, AFlags);
end;
end;
procedure TForm1.cmbSelectionListPropertiesInitPopup(Sender: TObject);
begin
TcxComboBoxPopupWindow(PDMCXSComboBox(Sender).PopupWindow).ViewInfo.OnCustomDrawBorder := DoCustomDrawBorder;
end;
procedure TForm1.cmbSelectionListPropertiesPopup(Sender: TObject);
begin
TcxComboBoxListBox(PDMCXSComboBox(Sender).ILookupData.ActiveControl).Color := clWhite;
end;
procedure TForm1.DoCustomDrawBorder(AViewInfo: TcxContainerViewInfo;
ACanvas: TcxCanvas; const R: TRect; var AHandled: Boolean;
out ABorderWidth: Integer);
begin
AHandled := True;
ABorderWidth := 1;
ACanvas.FrameRect(R, $00E5DFD7);
end;
end.
PDMCXSComboBox是我的自定义组件,源自tcxcombobox。
对于此组合框,当我进行项目选择时,顶部和右侧边框也不可见:
组件代码如下:
unit CXSComboBox;
interface
uses
System.SysUtils, System.Classes, Vcl.Controls, cxControls, cxContainer, cxEdit, cxTextEdit,
cxMaskEdit, cxDropDownEdit, cxGraphics, Winapi.Messages, Winapi.Windows, OvcCmbx;// OvcTccbx;
const
ParamsLabel = 'Params: ';
SQLLabel = 'SQL: ';
type
TpMyKeyValue = ^TrMykeyValue;
TrMyKeyValue= record
key: string;
value: string;
end;
TKeyValueShowOption = (soShowValueOnly, soShowKeyOnly, soShowAll);
type
PDMCXSComboBox = class(TcxComboBox)
private
{ Private declarations }
FItemHeight: Integer;
FOnOwnDrawItem: TcxEditDrawItemEvent;
FOnPdmDrawItem: TcxEditDrawItemEvent;
StringListKey: TStringList;
StringListKey_SACOMBO: TStringList;
StringListOKey: TStringList;
FOldWndProc: pointer;
FHintWin : THintWindow;
FHintList : TStrings;
FAutoWidthDropDown:Boolean;
FShowItemsHint:Boolean;
FListHandle: HWND;
FUseDefaultValue: Boolean;
FDefaultValue: String;
FKeyValuePairs: Boolean;
FKeyValueShowOption: TKeyValueShowOption;
procedure CMFontChanged(var Message: TWMFontChange); message CM_FONTCHANGED;
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
procedure AdjustHeight;
procedure SetSelKey(const Value: string);
function GetListIndex: Integer;
procedure SetListIndex(Value: Integer);
procedure SetKeyValuePairs(const Value: Boolean);
function GetText_PDMADVCOMBO: string;
procedure SetKeyValueShowOption(const Value: TKeyValueShowOption);
protected
{ Protected declarations }
FMRUList : TOvcMRUList;
FList : TStringList;
FListIndex : Integer; {ItemIndex sans MRU Items}
function GetItemHt: Integer; //override;
procedure Loaded; override;
//procedure Loaded_PDMCOMBO;
procedure OwnDrawItem(Control: TcxCustomComboBox; Canvas:TCxCanvas; Index: Integer; const Rect: TRect; State: TOwnerDrawState);
property OnOwnDrawItem: TcxEditDrawItemEvent read FOnOwnDrawItem write FOnOwnDrawItem;
procedure PdmDrawItem(AControl: TcxCustomComboBox; ACanvas: TcxCanvas; AIndex: Integer; const ARect: TRect; AState: TOwnerDrawState);
property OnPdmDrawItem: TCxEditDrawItemEvent read FOnPdmDrawItem write FOnPdmDrawItem;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property Value: string read GetSelKey write SetSelKey;
property DefaultValue: string read FDefaultValue write FDefaultValue;
property UseDefaultValue: boolean read FUseDefaultValue write FUseDefaultValue;
property HintList: TStrings read FHintList write SetHintList;
property ListHandle: HWND read FListHandle write FListHandle;
property AutoWidthDropDown:Boolean read FAutoWidthDropDown write FAutoWidthDropDown;
property ShowItemsHint:Boolean read FShowItemsHint write FShowItemsHint;
property Align;
property KeyValuePairs: Boolean read FKeyValuePairs write SetKeyValuePairs default True;
property KeyValueShowOption: TKeyValueShowOption read FKeyValueShowOption write SetKeyValueShowOption default soShowValueOnly;
property TextPDMADVCOMBO: string read GetText_PDMADVCOMBO;
end;
function CompareValueinMyKeyValue(item1, item2:TpMyKeyValue): Integer;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('PDMCXComponents', [PDMCXSComboBox]);
end;
function CompareValueinMyKeyValue(item1,item2:TpMyKeyValue):integer;
begin
Result := CompareText(item1.value,item2.value);
end;
procedure PDMCXSComboBox.Loaded;
begin
inherited;
if not (csDesigning in ComponentState) then
begin
// chain OnDraw events
OnOwnDrawItem := Properties.OnDrawItem;
Properties.OnDrawItem := OwnDrawItem;
// chain OnDraw events
FOnPdmDrawItem := properties.OnDrawItem;
properties.OnDrawItem := PdmDrawItem;
end;
end;
{procedure PDMCXSComboBox.Loaded_PDMCOMBO;
begin
inherited;
if not (csDesigning in ComponentState) then
begin
// chain OnDraw events
FOnPdmDrawItem := properties.OnDrawItem;
properties.OnDrawItem := PdmDrawItem;
end;
end; }
procedure PDMCXSComboBox.OwnDrawItem(Control: TcxCustomComboBox; Canvas:TCxCanvas; Index: Integer;
const Rect: TRect; State: TOwnerDrawState);
var
LCanvas: TcxCanvas;
S: string;
lRect : TRect;
begin
lRect := Rect;
if not (csDestroying in ComponentState) then
begin
LCanvas := (Control as PDMCXSComboBox).Canvas;
LCanvas.FillRect(lRect);
S := PDMCXSComboBox(Control).Properties.Items[Index];
InflateRect(lRect, -2, -1);
DrawText(LCanvas.Handle, S, Length(S), lRect,
DT_LEFT or DT_NOCLIP or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX);
// call chained event handler
if Assigned(OnOwnDrawItem) then
OnOwnDrawItem(Control,LCanvas, Index, lRect, State);
end;
end;
procedure PDMCXSComboBox.PdmDrawItem(AControl: TcxCustomComboBox;
ACanvas: TcxCanvas; AIndex: Integer; const ARect: TRect;
AState: TOwnerDrawState);
var
S: string;
lRect : Trect;
begin
if not (csDestroying in ComponentState) then
begin
lRect := Arect;
ACanvas.FillRect(lRect);
S := PDMCXSComboBox(AControl).properties.Items[AIndex];
InflateRect(lRect, -2, -1);
DrawText(ACanvas.Handle, S, Length(S), lRect, DT_LEFT or DT_NOCLIP or DT_VCENTER or DT_SINGLELINE);
// maybe developer need another drawing
if Assigned(OnPdmDrawItem) then
OnPdmDrawItem(AControl,Acanvas, AIndex, lRect, AState);
end;
end;
constructor PDMCXSComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
StringListKey := TStringList.Create;
StringListKey_SACOMBO := TStringList.Create;
StringListOKey := TStringList.Create;
FHintList := TStringList.Create;
FHintWin := THintWindow.Create(Self);
autosize := false;
Height := 30;
properties.DropDownwidth := 0;
//Properties.ButtonGlyph.LoadFromFile('.\DROPDOWNICON.png');
style.Font.Size := 10;
style.Font.Name := 'Noto sans';
style.Font.Color := $00757575;
style.BorderStyle := ebssingle;
style.ButtonStyle := btsSimple;
style.BorderColor := $00e5dfd7;
style.LookAndFeel.NativeStyle:= false;
end;
destructor PDMCXSComboBox.Destroy;
begin
StringListKey.Free;
StringListOKey.Free;
FHintList.Free;
if Assigned(FHintWin) then
FHintWin.ReleaseHandle;
if FListHandle <> 0 then
SetWindowLong(FListHandle, GWL_WNDPROC, longint(FOldWndProc));
inherited Destroy;
end;
procedure PDMCXSComboBox.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style or CBS_OWNERDRAWVARIABLE;
end;
procedure PDMCXSComboBox.AdjustHeight;
var
I: Integer;
DC: HDC;
SaveFont: HFont;
SysMetrics, Metrics: TTextMetric;
begin
DC := GetDC(0);
try
GetTextMetrics(DC, SysMetrics);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
finally
ReleaseDC(0, DC);
end;
if NewStyleControls then
begin
if Ctl3D then I := 4 else I := 2;
I := GetSystemMetrics(SM_CYBORDER) * I;
end else
begin
I := SysMetrics.tmHeight;
if I > Metrics.tmHeight then I := Metrics.tmHeight;
I := I div 4 + GetSystemMetrics(SM_CYBORDER) * 4;
end;
FItemHeight := Metrics.tmHeight + I;
end;
procedure PDMCXSComboBox.CMFontChanged(var Message: TWMFontChange);
begin
AdjustHeight;
RecreateWnd;
end;
procedure PDMCXSComboBox.CNMeasureItem(var Message: TWMMeasureItem);
begin
Message.MeasureItemStruct.itemHeight := FItemHeight;// Properties.ItemHeight;
end;
end.
答案 0 :(得分:0)
我已经解决了该问题,它正在按预期运行。 我唯一要做的是我已经两次处理过OnDrawItem,因此必须在组件设计时禁用它。
unit CXSComboBox;
interface
uses
System.SysUtils, System.Classes, Vcl.Controls, cxControls, cxContainer, cxEdit, cxTextEdit,
cxMaskEdit, cxDropDownEdit, cxGraphics, Winapi.Messages, Winapi.Windows, OvcCmbx;// OvcTccbx;
const
ParamsLabel = 'Params: ';
SQLLabel = 'SQL: ';
type
TpMyKeyValue = ^TrMykeyValue;
TrMyKeyValue= record
key: string;
value: string;
end;
TKeyValueShowOption = (soShowValueOnly, soShowKeyOnly, soShowAll);
type
PDMCXSComboBox = class(TcxComboBox)
private
{ Private declarations }
FItemHeight: Integer;
StringListKey: TStringList;
StringListKey_SACOMBO: TStringList;
StringListOKey: TStringList;
FOldWndProc: pointer;
FHintWin : THintWindow;
FHintList : TStrings;
FAutoWidthDropDown:Boolean;
FShowItemsHint:Boolean;
FListHandle: HWND;
FUseDefaultValue: Boolean;
FDefaultValue: String;
FKeyValuePairs: Boolean;
FKeyValueShowOption: TKeyValueShowOption;
procedure CMFontChanged(var Message: TWMFontChange); message CM_FONTCHANGED;
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
procedure AdjustHeight;
procedure SetSelKey(const Value: string);
function GetListIndex: Integer;
procedure SetListIndex(Value: Integer);
procedure SetKeyValuePairs(const Value: Boolean);
function GetText_PDMADVCOMBO: string;
procedure SetKeyValueShowOption(const Value: TKeyValueShowOption);
protected
{ Protected declarations }
FMRUList : TOvcMRUList;
FList : TStringList;
FListIndex : Integer; {ItemIndex sans MRU Items}
function GetItemHt: Integer; //override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property Value: string read GetSelKey write SetSelKey;
property DefaultValue: string read FDefaultValue write FDefaultValue;
property UseDefaultValue: boolean read FUseDefaultValue write FUseDefaultValue;
property HintList: TStrings read FHintList write SetHintList;
property ListHandle: HWND read FListHandle write FListHandle;
property AutoWidthDropDown:Boolean read FAutoWidthDropDown write FAutoWidthDropDown;
property ShowItemsHint:Boolean read FShowItemsHint write FShowItemsHint;
property Align;
property KeyValuePairs: Boolean read FKeyValuePairs write SetKeyValuePairs default True;
property KeyValueShowOption: TKeyValueShowOption read FKeyValueShowOption write SetKeyValueShowOption default soShowValueOnly;
property TextPDMADVCOMBO: string read GetText_PDMADVCOMBO;
end;
function CompareValueinMyKeyValue(item1, item2:TpMyKeyValue): Integer;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('PDMCXComponents', [PDMCXSComboBox]);
end;
function CompareValueinMyKeyValue(item1,item2:TpMyKeyValue):integer;
begin
Result := CompareText(item1.value,item2.value);
end;
constructor PDMCXSComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
StringListKey := TStringList.Create;
StringListKey_SACOMBO := TStringList.Create;
StringListOKey := TStringList.Create;
FHintList := TStringList.Create;
FHintWin := THintWindow.Create(Self);
autosize := false;
Height := 30;
properties.DropDownwidth := 0;
//Properties.ButtonGlyph.LoadFromFile('.\DROPDOWNICON.png');
style.Font.Size := 10;
style.Font.Name := 'Noto sans';
style.Font.Color := $00757575;
style.BorderStyle := ebssingle;
style.ButtonStyle := btsSimple;
style.BorderColor := $00e5dfd7;
style.LookAndFeel.NativeStyle:= false;
end;
destructor PDMCXSComboBox.Destroy;
begin
StringListKey.Free;
StringListOKey.Free;
FHintList.Free;
if Assigned(FHintWin) then
FHintWin.ReleaseHandle;
if FListHandle <> 0 then
SetWindowLong(FListHandle, GWL_WNDPROC, longint(FOldWndProc));
inherited Destroy;
end;
procedure PDMCXSComboBox.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style or CBS_OWNERDRAWVARIABLE;
end;
procedure PDMCXSComboBox.AdjustHeight;
var
I: Integer;
DC: HDC;
SaveFont: HFont;
SysMetrics, Metrics: TTextMetric;
begin
DC := GetDC(0);
try
GetTextMetrics(DC, SysMetrics);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
finally
ReleaseDC(0, DC);
end;
if NewStyleControls then
begin
if Ctl3D then I := 4 else I := 2;
I := GetSystemMetrics(SM_CYBORDER) * I;
end else
begin
I := SysMetrics.tmHeight;
if I > Metrics.tmHeight then I := Metrics.tmHeight;
I := I div 4 + GetSystemMetrics(SM_CYBORDER) * 4;
end;
FItemHeight := Metrics.tmHeight + I;
end;
procedure PDMCXSComboBox.CMFontChanged(var Message: TWMFontChange);
begin
AdjustHeight;
RecreateWnd;
end;
procedure PDMCXSComboBox.CNMeasureItem(var Message: TWMMeasureItem);
begin
Message.MeasureItemStruct.itemHeight := FItemHeight;// Properties.ItemHeight;
end;
end.