我在.net framework 1.1上创建了自定义组合框,我可以自定义绘制下拉项目,但我无法在中左设置或绘制组合框文本,组合框文本总是渲染到左上角,但我需要文本应该渲染在左边中间。
[ToolboxBitmap(typeof(ComboBox))]
public class MenComboBox :ComboBox
{
private Image _image = Image.FromFile("Expand.png");
public MenComboBox()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
this.BackColor = Color.White;
this.ItemHeight = 18;
this.Font = new Font("Arial",12f,FontStyle.Regular);
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (!DesignMode)
{
if (e.Index > -1)
{
int textHeight = (int)e.Graphics.MeasureString(this.Items[e.Index].ToString(), e.Font).Height;
Point textPos = new Point(e.Bounds.X + 4, e.Bounds.Y + ((this.ItemHeight - textHeight) / 2));
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(Brushes.Blue, e.Bounds);
e.Graphics.DrawString(this.Items[e.Index].ToString(),e.Font,Brushes.White,textPos);
}
else
{
e.Graphics.FillRectangle(Brushes.White, e.Bounds);
e.Graphics.DrawString(this.Items[e.Index].ToString(),e.Font,Brushes.Black,textPos);
}
}
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x000F)
{
using (Graphics g = this.CreateGraphics())
{
g.FillRectangle(new SolidBrush(BackColor), this.ClientRectangle);
g.DrawRectangle(Pens.Blue, new Rectangle(this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1));
Rectangle rect = new Rectangle(this.Width - 15, 3, 12, this.Height - 6);
g.FillRectangle(new SolidBrush(BackColor), rect);
g.DrawImage(this._image, this.Width - 16, (this.Height - 8) / 2);
g.Dispose();
}
}
}
}
答案 0 :(得分:2)
在所有者抽奖ComboBox
中,无论Edit
的高度如何,控件的ItemHeight
部分的文字都将始终显示在左上角。
要将Edit
部分垂直放置在中间位置,您可以使用Edit
找到GetComboBoxInfo
元素,然后使用SetWindowPos
设置新位置以使其垂直竖立中间的ComboBox
。
当控件大小更改时,您需要重新定位它。您还需要使用颜色填充ComboBox
的背景。
以下是我使用的代码:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyComboBox : ComboBox
{
public MyComboBox()
{
SetStyle(ControlStyles.ResizeRedraw, true);
DrawMode = DrawMode.OwnerDrawFixed;
ItemHeight = 40;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public int Width { get { return Right - Left; } }
public int Height { get { return Bottom - Top; } }
}
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_SHOWWINDOW = 0x0040;
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, int uFlags);
[DllImport("user32.dll")]
public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
[StructLayout(LayoutKind.Sequential)]
public struct COMBOBOXINFO
{
public int cbSize;
public RECT rcItem;
public RECT rcButton;
public int stateButton;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
SetupEdit();
Invalidate();
}
private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0xF)
{
using (var g = this.CreateGraphics())
{
var r = new Rectangle(2, 2,
ClientRectangle.Width - buttonWidth - 2,
ClientRectangle.Height - 4);
g.FillRectangle(Brushes.White, r);
}
}
base.WndProc(ref m);
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
SetupEdit();
}
private void SetupEdit()
{
var info = new COMBOBOXINFO();
info.cbSize = Marshal.SizeOf(info);
GetComboBoxInfo(this.Handle, ref info);
SetWindowPos(info.hwndEdit, IntPtr.Zero, 3,
(this.Height - Font.Height) / 2,
ClientRectangle.Width - buttonWidth - 3,
ClientRectangle.Height - Font.Height - 4,
SWP_NOZORDER);
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
e.DrawBackground();
var txt = "";
if (e.Index >= 0)
txt = GetItemText(Items[e.Index]);
TextRenderer.DrawText(e.Graphics, txt, Font, e.Bounds,
ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
}
答案 1 :(得分:1)
好的,下面的代码没有回答关于Text部分的实际问题;汉斯像往常一样做对了。
我保留了答案,因为我认为它比OP代码做了一些更好的事情。
if (!DesignMode)
{
if (e.Index > -1)
{
using (StringFormat fmt = new StringFormat()
{ Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center })
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(SystemBrushes.MenuHighlight, e.Bounds);
e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(),
e.Font,SystemBrushes.HighlightText, e.Bounds, fmt);
}
else
{
e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(),
e.Font, SystemBrushes.MenuText,e.Bounds, fmt);
}
}
}
}
不是计算居中位置,而是使用带有目标矩形的DrawString
重载,并在两个方向上添加StringFormat
。 {。1}}自.Net 1.1以来就可用,而且确实是StringFormat
,所以我们应该创建每个IDisposable
子句,最好用using
子句。
请注意,对于绘图控件,鼓励使用TextRenderer
,但仅使用.Net 2.0。
另请注意,我将Brushes
替换为SystemBrushes
..
另外:我的ComboBox不会将文本放在文本部分左上角但左中角。也许旧的.Net1.1控件是罪魁祸首?