I am trying to customize default windows scrollbar in combobox like below.
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);
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class NativeListWindow : NativeWindow
{
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;
}
[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)
{
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);
}
}
}
In the above code, I did the following 1. created a NativeWindow to catch the messages of combobox listcontrol by assigning combInfo.hwndList handle. 2. Placed my custom scrollbar(ScrollBarEx) in the non-client area of combobox listcontrol.
But my custom scrollbar(ScrollBarEx) doesn't receives any messages or focus. It looks like it is dead. Please look into this code and share some idea to make the scrollbar live.
|