我正在尝试自定义组合框中的默认窗口滚动条,如下所示。
public partial class ComboEx : ComboBox
{
internal ScrollbarEx vScrollBar;
NativeListWindow listControl;
public ComboEx()
{
InitializeComponent();
DropDownHeight = 100;
vScrollBar = new ScrollbarEx();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
COMBOBOXINFO combInfo = new COMBOBOXINFO();
combInfo.cbSize = Marshal.SizeOf(combInfo);
Win32.GetComboBoxInfo( this.Handle, ref combInfo );
listControl = new NativeListWindow(this, combInfo.hwndList);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == (Win32.WM_REFLECT + Win32.WM_COMMAND))
{
if (Win32.HIWORD( (int)m.WParam ) == Win32.CBN_DROPDOWN)
{
COMBOBOXINFO combInfo = new COMBOBOXINFO();
combInfo.cbSize = Marshal.SizeOf(combInfo);
Win32.GetComboBoxInfo( this.Handle, ref combInfo );
vScrollBar.Location = new Point( this.Width-23, 1 );
vScrollBar.Size = new Size( 23, DropDownHeight );
vScrollBar.Visible = true;
Win32.SetParent(vScrollBar.Handle, combInfo.hwndList);
Win32.ShowWindow(vScrollBar.Handle, ShowWindowCommands.Show);
Win32.SetWindowPos(vScrollBar.Handle,HWND.TopMost, 155, 1, 23, 105, SetWindowPosFlags.SWP_SHOWWINDOW);
}
}
base.WndProc(ref m);
}
// MyNativeWindow class to create a window given a class name.
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class NativeListWindow : NativeWindow
{
// Constant values were found in the "windows.h" header file.
private const int WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000,
WM_ACTIVATEAPP = 0x001C;
private int windowHandle;
private ComboEx parent;
public NativeListWindow(ComboEx owner,IntPtr handle)
{
AssignHandle(handle);
parent = owner;
}
// Listen to when the handle changes to keep the variable in sync
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void OnHandleChange()
{
windowHandle = (int)this.Handle;
}
private void AdjustClientRect(ref RECT rect)
{
rect.right -= 23;
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message message)
{
// Listen for messages that are sent to the button window. Some messages are sent
// to the parent window instead of the button's window.
switch (message.Msg)
{
case Win32.NCCALCSIZE:
{
if (message.WParam != IntPtr.Zero)
{
NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(message.LParam, typeof(NCCALCSIZE_PARAMS));
AdjustClientRect(ref rcsize.rect0);
Marshal.StructureToPtr(rcsize, message.LParam, false);
}
else
{
RECT rcsize = (RECT)Marshal.PtrToStructure(message.LParam, typeof(RECT));
AdjustClientRect(ref rcsize);
Marshal.StructureToPtr(rcsize, message.LParam, false);
}
message.Result = new IntPtr(1);
return;
break;
}
case Win32.WM_NCMOUSEMOVE:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
break;
}
case Win32.WM_NCLBUTTONDOWN:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
}
case Win32.WM_NCACTIVATE:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
}
case Win32.WM_NCMOUSELEAVE:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
}
case Win32.WM_NCLBUTTONUP:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
}
case Win32.WM_NCHITTEST:
{
base.WndProc(ref message);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
break;
}
case Win32.WM_MOUSEMOVE:
{
base.WndProc(ref message);
if ((int)message.LParam > 0)
{
int x = Win32.LOWORD((int)message.LParam);
int y = Win32.HIWORD((int)message.LParam);
RECT rect = new RECT(); ;
Win32.GetWindowRect(new HandleRef(parent.vScrollBar, parent.vScrollBar.Handle),out rect);
Rectangle rc = new Rectangle(parent.vScrollBar.Location.X, parent.vScrollBar.Location.Y,
(rect.right - rect.left), (rect.bottom - rect.top));
if (rc.Contains(new Point(x, y)))
{
Win32.SetFocus(parent.vScrollBar.Handle);
Win32.SetWindowPos(parent.vScrollBar.Handle, HWND.TopMost, 155, 1, 23, 105, SetWindowPosFlags.SWP_SHOWWINDOW);
Win32.SendMessage(parent.vScrollBar.Handle, (uint)message.Msg, message.WParam, message.LParam);
}
}
break;
}
}
base.WndProc(ref message);
}
}
}
在上面的代码中,我做了以下操作 1.创建一个NativeWindow,通过分配combInfo.hwndList句柄来捕获组合框listcontrol的消息。 2.将我的自定义滚动条(ScrollBarEx)放在combobox listcontrol的非客户区域中。
但我的自定义滚动条(ScrollBarEx)不会收到任何消息或焦点。它看起来已经死了。 请查看此代码并分享一些想法以使滚动条生效。