Windows sends the WM_MOUSESCROLL message to the control with the focus. If the control doesn't use it then it gets sent to the parent of the control. Eventually that will be your form which then uses it to scroll itself.
ComboBox is however quite happy to use the message itself. When the dropdown is shown, it scrolls the dropdown list. It also captures the mouse so that it can see you clicking outside of the list. Which closes the list and keeps the focus on the ComboBox. Which then uses the message to scroll the items through the text box portion. In other words, when the CB has the focus, you'll never get the scroll the form.
You can mess with this by using IMessageFilter. My code in this thread shows an example. You'll have to doctor it, the code was made to do something else. You can replace the m.HWnd field with the form's Handle property value for example so all mouse scroll messages go to the form instead. Or you can use the code as-is, it is perhaps more intuitive.
Be careful with this, your user might well be fatally confused by this non-standard behavior. Maybe she really wants to scroll the combo.
Here is the code to make it work. Put it in your app's main form, it is active for all other forms that your app shows:
public partial class Form1 : Form, IMessageFilter {
public Form1() {
InitializeComponent();
Application.AddMessageFilter(this);
this.FormClosed += (o, e) => Application.RemoveMessageFilter(this);
}
public bool PreFilterMessage(ref Message m) {
if (m.Msg == 0x20a) { // Trap WM_MOUSEWHEEL
var ctl = Control.FromHandle(m.HWnd);
if (ctl == null || !(ctl is ComboBox)) ctl = Control.FromHandle(GetParent(m.HWnd));
// Redirect when message destined for text box of a ComboBox
if (ctl != null && ctl is ComboBox && !(ctl as ComboBox).DroppedDown) {
PostMessage(ctl.Parent.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
}
return false;
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr GetParent(IntPtr hWnd);
}