When looking at the MouseMove problem, I wandered over to the first argument passed to MouseMove, MouseDown, etc.
sender as System.Object (sometimes referred to as eventSender as System.Object).
What was the point of this this? We never used it in our code, so why was it being passed?
From this article - http://www.informit.com/articles/article.aspx?p=102148&seqNum=3 I realized that you can use that argument to figure out the who called the function. For example, if you have the MouseDown handle the call from 10 buttons, you can use the sender object to figure which button called the MouseDown routine. What you need to do is convert (cast) it to an Control or a Button, and then you can get the Button's text.
Another use I found for this is if you manually call MouseDown, or manually call MouseMove. In that past if we called a MouseMove event from the MouseDown routine, we just passed the sender from MouseDown to MouseMove. Sample code below:
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
Form1_MouseMove(sender, e)
End Sub
At first I thought in MouseMove, we could use the sender object to see if the routine was called by code or by the Form. But in MouseMove, when you look at the sender object, you cannot tell. So one way to tell is do something like this:
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
Form1_MouseMove("FromMouseDown", e)
End Sub
Then in MouseMove, you can do the following:
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
If TypeOf sender Is String Then
'Do Something, you can even test what the string value is
Dim aString as String = DirectCast(sender, String)
If aString = "FromMouseDown" Then
MsgBox("FromMouseDown")
End If
End If
End Sub
Thursday, December 27, 2007
MouseMove put to rest
Ok, the problem initially seemed to be because of my trackball mouse. After putting a workaround where i saved the position of the mouse in mousedown and in mousemove checked to see if the position was different, I just cleaned my trackball, and lo and behold the problem went away. It seems that because my trackball was dirty, the mousemove event kept getting called, even though the position wasn't changing.
Wednesday, December 26, 2007
MouseMove oddity
So far the previous problem only occurs on my machine. I have a trackball mouse, and this only occurs on my machine. On a machine with a regular mouse, this does not occur. Now it just might be my trackball mouse.
MouseMove event is always fired
I've always coded with the idea that the MouseMove event in VB.NET occurs when the mouse actually moves. However, maybe its my machine, but I created a new project. Added a MouseMove event to the form, with a Debug Statement. This debug statement is always called, even when my mouse is not moving. Odd. I'm using .NET 2003. The problems this causes are many if you assume the mousemove event should only be called when the mouse is actually moving.
Wednesday, December 19, 2007
Textbox ignores the first character if you set the CharacterCasing property in the KeyPress event
I had this situation where I had a Textbox on a Form, and in the KeyPress event, I set the CharacterCasing to either Upper or Lower depending on the field I was working on. The problem I had was that the first character was getting ignored. It turned out that the problem was that for some reason setting the CharacterCasing in the KeyPress event causes you to lose the first character. The solution was to move the CharacterCasing block to the TextBox.Enter event.
To recreate this error, open a form, add a textbox to the form. Create a Keypress Event, and set the TextBox's CharacterCasing to True. If you run the program and click in the textbox, and enter a value, the first value will be ignored.
The solution was to move it to the TextBox.Enter subroutine.
To recreate this error, open a form, add a textbox to the form. Create a Keypress Event, and set the TextBox's CharacterCasing to True. If you run the program and click in the textbox, and enter a value, the first value will be ignored.
The solution was to move it to the TextBox.Enter subroutine.
Tuesday, December 18, 2007
Avoid Memory Leaks with FromHBitmap and GetHbitmap - Continued
Ok, earlier I mentioned how to avoid memory leaks with FromHBitmap and GetHbitmap. In the example I had a bitmap supplied by reference. A key thing to realize (which I didn't at the time) is that the approach I presented can lead to broken pointers. Example is below:
'Just say you have the following Picture box (FImage)
'If you do the following, abmp will point to the Image of FImage (you don't make a copy)
Dim abmp as Bitmap = FImage.Image
'If you then supply abmp to the function I mentioned in the earlier post.
'Then all of a sudden FImage.Image does not have any data and you get an error when you try to use it.
So be careful when using the code below.
'Just say you have the following Picture box (FImage)
'If you do the following, abmp will point to the Image of FImage (you don't make a copy)
Dim abmp as Bitmap = FImage.Image
'If you then supply abmp to the function I mentioned in the earlier post.
'Then all of a sudden FImage.Image does not have any data and you get an error when you try to use it.
So be careful when using the code below.
Stop stickykey hell
This is from my manager:
I don't know if you ever accidentally get into Windows "Filterkeys" mode, but if you press both shift keys at once, or one shift key for 8 seconds, you go into an accessibility mode in text is selected.
If like me, you never ever ever want this to happen, go into Control Panel>Accessibility options>Keyboard>Filterkeys settings button>Uncheck "keyboard shortcut"
I turn off the rest of them too – I have absent-mindedly tapped the shift key a few times and gone into "StickyKey" hell.
Task Manager doesn't have Menu Bar or Tabs
Ok, not programmer related, but all of a sudden my Task Manager didn't have the Menu Bar or Tabs. After a quick google search, it turns out that it is running in "Tiny Footprint Mode" and the solution is to double-click the border area again. The enable it again, double-click the border around the tabs.
Monday, December 17, 2007
Avoid Memory Leaks with FromHBitmap and GetHbitmap
In VB6 we called .Handle to get a handle to an image, which I then passed to a C routine. In order to get a handle to an image in VB.NET, I had to call GetHbitmap.ToInt32 to get a handle. Then in order to get the image back from that call, I would call FromHBitmap. Below is an example:
Public Function DoSomething(ByRef hbmp As Bitmap) As Integer
Dim returnVal As Integer
Dim hbmp1 As IntPtr
If Not hbmp Is Nothing Then
hbmp1 = hbmp.GetHbitmap 'Get a handle to the image
returnVal = DoSomethingInC(hbmp1.ToInt32) 'get an Integer Pointer to the Image which is passed to the C routine
hbmp = Bitmap.FromHbitmap(hbmp1)
Return returnVal
Else
Return MiscError
End If
End Function
Now when I did this, I had a memory leak with GetHBitmap and FromHBitmap. You solve that by calling .Dispose and DeleteObject. Highlighted below.
Public Function DoSomething(ByRef hbmp As Bitmap) As Integer
Dim returnVal As Integer
Dim hbmp1 As IntPtr
If Not hbmp Is Nothing Then
hbmp1 = hbmp.GetHbitmap 'Get a handle to the image
returnVal = DoSomethingInC(hbmp1.ToInt32) 'get an Integer Pointer to the Image which is passed to the C routine
If Not hbmp Is Nothing Then hbmp.Dispose()
hbmp = Nothing
hbmp = Bitmap.FromHbitmap(hbmp1)
DeleteObject(hbmp1)
Return returnVal
Else
Return MiscError
End If
End Function
A couple of thoughts:
1. Doing this slows down performance, as the calls to GetHbitmap and FromHBitmap is a lot slower than just calling Image.Handle (in VB6). I still haven't figured out how to solve the performance hit.
2. I still have issues with 8 bit images, as in VB.NET we do everything in 32 bit, and previously my C routines were working with 8 bits. I still haven't figured out a workaround to this.
Public Function DoSomething(ByRef hbmp As Bitmap) As Integer
Dim returnVal As Integer
Dim hbmp1 As IntPtr
If Not hbmp Is Nothing Then
hbmp1 = hbmp.GetHbitmap 'Get a handle to the image
returnVal = DoSomethingInC(hbmp1.ToInt32) 'get an Integer Pointer to the Image which is passed to the C routine
hbmp = Bitmap.FromHbitmap(hbmp1)
Return returnVal
Else
Return MiscError
End If
End Function
Now when I did this, I had a memory leak with GetHBitmap and FromHBitmap. You solve that by calling .Dispose and DeleteObject. Highlighted below.
Public Function DoSomething(ByRef hbmp As Bitmap) As Integer
Dim returnVal As Integer
Dim hbmp1 As IntPtr
If Not hbmp Is Nothing Then
hbmp1 = hbmp.GetHbitmap 'Get a handle to the image
returnVal = DoSomethingInC(hbmp1.ToInt32) 'get an Integer Pointer to the Image which is passed to the C routine
If Not hbmp Is Nothing Then hbmp.Dispose()
hbmp = Nothing
hbmp = Bitmap.FromHbitmap(hbmp1)
DeleteObject(hbmp1)
Return returnVal
Else
Return MiscError
End If
End Function
A couple of thoughts:
1. Doing this slows down performance, as the calls to GetHbitmap and FromHBitmap is a lot slower than just calling Image.Handle (in VB6). I still haven't figured out how to solve the performance hit.
2. I still have issues with 8 bit images, as in VB.NET we do everything in 32 bit, and previously my C routines were working with 8 bits. I still haven't figured out a workaround to this.
Avoid Memory Leaks with PictureBox
I had a situation where I had a memory leak with a PictureBox, I did something like this:
Dim bm_out As New Bitmap(Width, Height)
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
gr_out.DrawImage(...)
FullImage.Image = bm_out
Now everytime this block of code was called, when the New Bitmap was created we created a new block of memory. When I left this function, I was constantly losing memory. The reason for this is that FullImage.Image was pointing to a block of memory, and when I called FullImage.Image = bm_out, I pointed it to a new block of memory, and lost the pointer to the previous block of memory. But that previous block of memory was still allocated. So I had a memory leak. The solution was this one line, before FullImage.Image = bm_out
FullImage.Image.Dispose()
So the code like this did not have the memory leak.
Dim bm_out As New Bitmap(Width, Height)
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
gr_out.DrawImage(...)
FullImage.Image.Dispose()
FullImage.Image = bm_out
Dim bm_out As New Bitmap(Width, Height)
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
gr_out.DrawImage(...)
FullImage.Image = bm_out
Now everytime this block of code was called, when the New Bitmap was created we created a new block of memory. When I left this function, I was constantly losing memory. The reason for this is that FullImage.Image was pointing to a block of memory, and when I called FullImage.Image = bm_out, I pointed it to a new block of memory, and lost the pointer to the previous block of memory. But that previous block of memory was still allocated. So I had a memory leak. The solution was this one line, before FullImage.Image = bm_out
FullImage.Image.Dispose()
So the code like this did not have the memory leak.
Dim bm_out As New Bitmap(Width, Height)
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
gr_out.DrawImage(...)
FullImage.Image.Dispose()
FullImage.Image = bm_out
Subscribe to:
Posts (Atom)