Disable mouse scroll wheel in combobox VB.NET - vb.net

Does anyone know of a way to disable the mouse scroll wheel when a control such as a combobox or listbox has focus? For my purposes, combobox is all I need the answer for.
I have a combobox set to trigger a SQL query on SelectedIndexChanged, and accidentally scrolling the wheel while the combobox has focus causes about six SQL queries to fire off simultaneously.

I've found a mix response, put this code in the MouseWheel event:
Dim mwe As HandledMouseEventArgs = DirectCast(e, HandledMouseEventArgs)
mwe.Handled = True
That's all. You don't need to create a new class, if you have your project in an advanced state.

The ComboBox control doesn't let you easily override behavior of the MouseWheel event. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
Friend Class MyComboBox
Inherits ComboBox
Protected Overrides Sub OnMouseWheel(ByVal e As MouseEventArgs)
Dim mwe As HandledMouseEventArgs = DirectCast(e, HandledMouseEventArgs)
mwe.Handled = True
End Sub
End Class
Beware that this also disables the wheel in the dropdown list.

If you subclass the control it's possible (apologies for the C#)
public class NoScrollCombo : ComboBox
{
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
protected override void WndProc(ref Message m)
{
if (m.HWnd != this.Handle)
{
return;
}
if (m.Msg == 0x020A) // WM_MOUSEWHEEL
{
return;
}
base.WndProc(ref m);
}
}

One such option would be to add a handler to the comboBox, and within that comboBox, resolve the situation. I'm not sure how your code is set up, but I'm assuming if you knew when the event was happening, you could set up some kind of conditional to prevent the queries from happening
'''Insert this statement where your form loads
AddHandler comboBoxBeingWatched.MouseWheel, AddressOf buttonHandler
Private Sub buttonHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
'''Code to stop the event from happening
End Sub
In this way, you'd be able to maintain the user being able to scroll in the comboBox, but also be able to prevent the queries from happening

Combining all the answers on this thread, the best solution if you don't want to create a custom control is to handle the mousewheel event. The below will also allow the list to be scrolled if it is dropped down.
Assuming your combobox is called combobox1:
If Not ComboBox1.DroppedDown Then
Dim mwe As HandledMouseEventArgs = DirectCast(e, HandledMouseEventArgs)
mwe.Handled = True
End If

I had the exact same issue, but found that simply changing the focus of the control after the query executed to another control such as the "Query" button itself worked better than perfect. It also allowed me to still scroll the control until the SelectedIndex actually changed and was only one line of code.

Just put this in the mousewheel event or in a single handler for all the controls this applies to, maybe call it wheelsnubber.
DirectCast(e, HandledMouseEventArgs).Handled = True

Related

Block focus/select in a ReadOnly textbox

Someone knows how to block the focus/select in a read-only textbox (ReadOnly = true), without using enabled = false?
Thanks!
Controls have a GotFocus Event. You can add an event handler for this event and give another control focus, for example by calling Select() on another control or by using SelectNextControl:
Private Sub MyTextBox_GotFocus(sender as Object, e as EventArgs) _
Handles MyTextBox.GotFocus
MyTextBox.Parent.SelectNextControl(MyTextBox, True, True, True, True)
End Sub
Alternately, you can create a custom control that inherits TextBox and set ControlStyles.Selectable to False.
Public Class NonSelectableTextBox Inherits TextBox
Public Sub New()
SetStyle(ControlStyles.Selectable, false)
End Sub
End Class
Setting ControlStyles.Selectable to false will make the TextBox mimic the behavior of other controls which have this bit set to False:
Label
Panel
GroupBox
PictureBox
ProgressBar
Splitter
LinkLabel (when there is no link present in the control)
I'm not sure I understand fully why you would want that. A read only text box allows selection to allow users to copy the text in there for other purposes. What I assume from your question is that you don't want the TextBox to accept input focus when a user is tabbing through controls, which I've seen to be a more common requirement.
You can achieve this via code:
TextBox1.TabStop = False
to ensure that tab doesn't direct focus to the readonly textbox. You can also achieve this in the designer using the same property as the screenshot shows.

Enabled but unselectable menu item

In WinForms application I need some "caption" in dynamically created ContextMenuStrip.
That caption is changable text composed in ContextMenuStrip_Opening event handler.
For that purpose I'm trying to use ToolStripControlHost with label in it, like this:
Dim labelItem As ToolStripControlHost = New ToolStripControlHost(New Label)
...
labelItem.BackColor = Color.Transparent
labelItem.ForeColor = Color.FromKnownColor(KnownColor.HotTrack)
labelItem.ToolTipText = "mytooltiptext"
mycontextmenu.Items.Add(labelItem)
That work almost OK, but...
I try to disable that "labelItem" to avoid clicks and keypresses and then it becomes gray automatically what is unwanted and also then tooltiptext is not showed.
If "labelItem" is enabled then color is OK, item cannot be selected with keys but can be with mouse and on mouse click it takes focus to itself. That is also unwanted but shows tooltiptext.
Is here a way in described situation to get "labelItem" to be enabled and able to show tooltiptext but be unselectable? In short... How to make an item like is described which would be in color (enabled) but would not accept mouse clicks and take a focus?
Don't disable the item. Set the disabled state image and then in the click event handler, just ignore the case for the item you don't want to be active.
Enabled and Disabled are predetermined definitions for for the appearance and behavior of a control. Disabled will always mean the control can't be clicked.
If you need alternate behavior, you'll need to write it yourself. I would suggest tracking two global variables in your form: whether or not your item should be active in a boolean and which object currently has focus in an object. Then use these to write your click event behavior. For example:
Public Class Form1
Public RunEvent As Boolean
Public HasFocus As Object
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If RunEvent Then
'Do something
Else
HasFocus.Focus()
End If
End Sub
End Class

How to have an invisible start up form?

I have an application that is a part of a solution of projects. In this project I would like for it to start up form to be invisible, but still have a notification icon in the tray visible for this form.
I know that adding me.hide into the form_load doesn't work. I tried adding a module that instantiates the startup form and I set it as the startup object. Although that didn't work either. I am running out of ideas to have this form invisible. Could anyone help out? I am using VB.NET.
Paste this in your form code:
Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
If Not Me.IsHandleCreated Then
Me.CreateHandle()
value = False
End If
MyBase.SetVisibleCore(value)
End Sub
The way that works is that the very first request to show the form, done by the Application class, this code overrides the Visible property back to False. The form will behave as normal after this, you can call Show() to make it visible and Close() to close it, even when it was never visible. Note that the Load event doesn't fire until you show it so be sure to move any code in your event handler for it, if any, to the constructor or this override.
Put this in the form's Shown event
Me.Visible = False
The easiest way is to set the opacity of the form to 0%. When you want it to appear, set it back to 100%
Here is another way that I've found to do this.
Set the form properties with
ShowInTaskbar = False
Then in the form's constructor add
WindowState = FormWindowState.Minimized
This is very easy to implement and works with no flicker. In my case I also use a NotifyIcon to access the program from the notification tray and just set
WindowState = FormWindowState.Normal
Show()
BringToFront()
In the Notify_MouseClick event handler.
To hide the form again after displaying it, just minimizing again doesn't quite do the job. In my case I use the Form_Closing event and just hide the form.
Hide()
Use Me.Opacity = 0 to hide the form on load event.
Then use the following code in the form.Shown event
Me.Hide()
Me.Opacity = 100
Just to throw out a completely different approach, have you considered not using the overload of Application.Run() that takes (and automatically shows) a Form? If you use the one that passes in an ApplicationContext (or more tyoically, your own subclass of ApplicationContext) then you can choose what your behavior is. See here for more details:
http://msdn.microsoft.com/en-us/library/ms157901
Try this:
Sub New()
MyBase.SetVisibleCore(False)
End Sub

Visually remove/disable close button from title bar .NET

I have been asked to remove or disable the close button from our VB .NET 2005 MDI application. There are no native properties on a form that allow you to grey out the close button so the user cannot close it, and I do not remember seeing anything in the form class that will allow me to do this.
Is there perhaps an API call or some magical property to set or function to call in .NET 2005 or later to do this?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More information:
I need to maintain the minimize/maximize functionality
I need to maintain the original title bar because the form's drawing methods are already very complex.
Based on the latest information you added to your question, skip to the end of my answer.
This is what you need to set to false: Form.ControlBox Property
BUT, you will lose the minimize and maximize buttons as well as the application menu (top left).
As an alternative, override OnClose and set Cancel to true (C# example):
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason != CloseReason.WindowsShutDown && e.CloseReason != CloseReason.ApplicationExitCall)
{
e.Cancel = true;
}
base.OnFormClosing(e);
}
If neither of these solutions are acceptable, and you must disable just the close button, you can go the pinvoke/createparams route:
How to disable close button from window form using .NET application
This is the VB version of jdm's code:
Private Const CP_NOCLOSE_BUTTON As Integer = &H200
Protected Overloads Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim myCp As CreateParams = MyBase.CreateParams
myCp.ClassStyle = myCp.ClassStyle Or CP_NOCLOSE_BUTTON
Return myCp
End Get
End Property
You can disable the close button and the close menu item in the system menu by changing the "class style" of the window. Add the following code to your form:
const int CS_NOCLOSE = 0x200;
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_NOCLOSE;
return cp;
}
}
This will not just stop the window from getting closed, but it will actually grey out the button. It is C# but I think it should be easy to translate it to VB.
Here is a simple way to remove the close button:
1. Select the Form
2. Now go to Properties.
3. Find ControlBox and change the value to False.
This will remove all the Control Buttons (e.g. Minimize, Maximize, Exit) and also the icon also that is in the to left corner before the title.
You should be able to override the OnClose event of the form. This is common when an application minimizes to the System Tray when "closed".
When you press the X box on the form.
The Form1_Closing is done first, then the Form1_Closed is done.
The e.Cancel = True in the Form1_Closing - prevents Form1_Closed from being called therefore, leaving your form still active.
Prevent to close the form, but hide it:
Private Sub Form1_Closing(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
Me.WindowState = FormWindowState.Minimized
Me.Visible=false
e.Cancel = True
End Sub
You can set the ControlBox property to False, but the whole title bar will be gone but the title itself...
What jmweb said here is OK as well. The X close button won't go if you cancel the event on form closing. But doing so, you need to release the processes the form needs and then closing the form.
Me.Dispose()
Me.Close()
This worked for me using Menu Strip.
Select (or click) the form itself
Click on events in the property window (the little lightning bolt icon).
Look for Form.Closing and double click it.
Then type: e.cancel=true
Making a Form without a Titlebar in Visual Basic.
Go to Form Properties and set both ControlBox and ShowIcon to false.
Then, clear all the text from the form's text property.
go to properties and select from bored style as none
Just select the required form and in the properties section, set controlBox = false
That just worked for me :)
Private Sub Form1_Closing(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
Beep()
e.Cancel = True
End Sub

Populating a DataGridView on-the-fly (VB.NET)

I have a DataGridView which reads data from a custom (CSLA) list object. The dataset might have 100,000 records, and obviously I don't want to show them all at once because, for one, it would take ages to load.
I think it would be nice if I could read the first (for instance) 20 records, and make it so upon scrolling to the end of the list, it reads the next 20 and adds them to the DataGridView.
I have experimented with various ways of doing this, mostly using a custom class inheriting from DataGridView to capture scroll events and raising an event which adds new records. I will include the code below:
Public Class TestDGV
Inherits DataGridView
Public Sub New()
AddHandler Me.VerticalScrollBar.ValueChanged, AddressOf vsScrollEvent
AddHandler Me.RowsAdded, AddressOf vsRowsAddedEvent
End Sub
Private Sub vsScrollEvent(ByVal sender As Object, _
ByVal e As EventArgs)
With DirectCast(sender, ScrollBar)
If .Value >= (.Maximum - .LargeChange) Then
RaiseEvent ScrollToEnd()
End If
End With
End Sub
Private Sub vsRowsAddedEvent(ByVal sender As Object, ByVal e As EventArgs)
ScrollbarOn()
End Sub
Public Event ScrollToEnd()
Public Sub ScrollbarOff()
Me.VerticalScrollBar.Enabled = False
End Sub
Public Sub ScrollbarOn()
Me.VerticalScrollBar.Enabled = True
End Sub
End Class
Though this (sort of) works, it can be buggy. The biggest problem was that if you used the mouse to scroll the DataGrid, it would get stuck in a loop as it process the scrollbar's ValueChanged event after the data was added. That's why I added ScrollbarOff and ScrollbarOn - I call them before and after getting new records, which disables the scrollbar temporarily.
The problem with that is that after the scrollbar is re-enabled, it doesn't keep track of the current mouse state, so if you hold down the 'Down' button with the mouse (or click on part of the scrollbar) it stops scrolling after it has added the new records, and you have to click it again.
Also, it doesn't seem a particularly elegant way of doing things.
Has anyone ever done this before, and how did you achieve it?
Cheers.
Perhaps you could reduce your result set and use the << and >> kind of paging controls. Nerd Dinner demo introduced an elegant solution using LINQ:
//
// GET: /Dinners/
// /Dinners/Page/2
public ActionResult Index(int? page)
{
const int pageSize = 20;
var upcomingDinners = dinnerRepository.FindUpcomingDinners();
var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize)
.Take(pageSize)
.ToList();
return View(paginatedDinners);
}
What about using the virtualproperty of the DataGridView?
See Implementing Virtual Mode with Just-In-Time Data Loading in the Windows Forms DataGridView Control for an example.