|
-
May 2nd, 2013, 06:46 PM
#1
[RESOLVED] Interesting Problem with PreFilterMessage
I have a form that prefilters some messages by implementing the IMessageFilter interface and implementing this method:
System.Windows.Forms.IMessageFilter.PreFilterMessage
This thing is beginning to annoy me, but it has generally been working. I may try to find another solution to whatever it is there for, but at the moment I am working on something else. In fact, I am working on a whole different form. The form that implements the messagefilter is created, but not shown, at the time this latest problem arises. Therefore, the form instance exists, so the prefilter is in existence, but the form is not visible or accessible.
Inside the method, I have these lines:
Code:
If Not Me.pDisplaySurface.IsDisposed Then
Dim pt As Drawing.Point = Me.pDisplaySurface.PointToClient(MousePosition)
If Me.pDisplaySurface.ClientRectangle.Contains(pt) Then
the first If statement can probably be removed, but it's a good check to have in place. the display surface is not disposed, as the form hasn't even been shown, yet. I then get a point for the mouse position, and check to see whether the panel (on a form that has not yet been shown) contains the point. The problem is: This is returning True!!!
The form hasn't been shown, but since it was created, all of the objects have also been created. So, the mouse may actually be on the thing. Therefore, I need a way to determine whether the click was even on the form, which it was not. A couple alternatives would be to position the form off the screen until it is needed, then move it back to the screen in the Shown event. There are problems with that, but not insurmountable problems. Another alternative would be to check whether the form is accessible, but that's not a great solution, because this form is shown non-modally, so other forms can be on top of it. In that scenario, it could be visible, and active, but still wouldn't be the form that the mouse was clicked on.
Is there another way to determine whether a click was on a specific form? I need some way to determine whether a form is even the one that the user was interacting with before pre-filtering the message. Since the pre-filter is just what it says, I believe that the mouse events on the form itself are all too late.
EDIT:
This is all related to this thread (which reminds me a lot of what this whole thing was about):
http://www.vbforums.com/showthread.p...g-Mouse-Events
In the final post (which is quite possibly the only one worth reading), I talk about adding and removing the message filter. I was doing that early on. I'm going to try doing that only when needed, but I will have to figure out what the problem with removing the message filter was all about.
Last edited by Shaggy Hiker; May 2nd, 2013 at 07:05 PM.
My usual boring signature: Nothing
 
-
May 3rd, 2013, 02:41 AM
#2
Re: Interesting Problem with PreFilterMessage
 Originally Posted by Shaggy Hiker
I then get a point for the mouse position, and check to see whether the panel (on a form that has not yet been shown) contains the point. The problem is: This is returning True!!!
Weather a window is shown or not, it has a location and a size. What your check is really doing is checking weather a point is inside a rectangle. That's all. Its irrelevant to those functions where the rectangle and the point came from so obviously the state of the Form and its controls are not considered.
I am curious though about why you didn't use something like MouseMove or MouseEnter for your check. You wouldn't have to worry about weather the window is shown, covered or modal.
[EDIT]
Oh never mind about that last question. If you're using IMessageFilter that means you want to capture the message before it even reaches the Form so MouseMove/MouseEnter are not appropriate.
Last edited by Niya; May 3rd, 2013 at 02:45 AM.
-
May 3rd, 2013, 03:10 AM
#3
Re: Interesting Problem with PreFilterMessage
Based on your description, I believe its something like this you actually need:-
vbnet Code:
Public Class Form2
Implements IMessageFilter
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
'Left mouse button up
Dim WM_LBUTTONUP As Integer = &H202
If Me.IsHandleCreated Then
If m.HWnd = Me.Handle AndAlso m.Msg = WM_LBUTTONUP Then
MsgBox("Click On " + Me.Name)
End If
End If
Return False
End Function
End Class
The above Form class can detect using message filters when the left mouse button has been released on its surface. There is no Win32 click message so the WM_LBUTTONUP is about as close I can come but you can use other mouse messages according to your needs.
-
May 3rd, 2013, 12:09 PM
#4
Re: Interesting Problem with PreFilterMessage
That just might work. I'm also going to pursue a different strategy. I was adding the filter in the form constructor, which is not at all necessary (but it was a good idea at the time, things just changed a bit). Instead, I'm going to add the filter as late as possible, ideally only when the form is the foreground, then remove the filter when the form loses focus. Theoretically, that should work pretty well, but in the link I provided I note that the message filter was not being removed, so RemoveFilter has some behavior issues I'll have to study a bit further. Still, I think that what you did would be a good thing to incorporate, especially this part:
If m.HWnd = Me.Handle
My usual boring signature: Nothing
 
-
May 3rd, 2013, 06:28 PM
#5
Re: Interesting Problem with PreFilterMessage
 Originally Posted by Shaggy Hiker
Instead, I'm going to add the filter as late as possible, ideally only when the form is the foreground, then remove the filter when the form loses focus.
I am assuming that adding and removing of the filter is to prevent the filter from capturing clicks that are not on the form itself. If its not, feel free to ignore what I'm about to say.
You don't need to do all that. Let the OS handle all that hassle. I think you're a little confused about how messages work. The whole reason I added the check for WM_LBUTTONUP and the form's handle is to prevent trapping messages that you don't want. I'm sure you know that every GUI application has a message loop. For message loops to work, the OS also includes a thread specific message queue. When you click on a window(any control or form) the OS resolves the thread it belongs to and posts the message only to the queue that belongs to the thread that created the window. The message loop examines this message to determine which window to send it to. This is the important bit, windows messages are window specific. That means that if your form doesn't have focus and you click on another window, the message trapped by the filter would have the handle for that window and not the your unfocused window. In other words, it has already been resolved who that message is intended for. All you have to do is ignore it if the handle doesn't match.
Last edited by Niya; May 3rd, 2013 at 06:42 PM.
-
May 4th, 2013, 02:09 PM
#6
Re: Interesting Problem with PreFilterMessage
That's pretty much true, but not really so relevant...though it is unlikely you would recognize why. One of the side effects of the message filter prompted a different, recent, thread of mine a while back. The fact that the filter is there messes up certain debugging attempts, because ALL messages go to the filter, even if they are not targeting that form. During runtime, you can certainly ignore messages that don't belong to that form, but if you are stepping through code you cannot ignore anything. What occured to me, and what I mentioned in post #4, is that I am adding the filter at the wrong time. In the original design, it was reasonable to install the filter immediately, because the form was only going to be used immediately. Now, however, the form is going to be created long before it is used (if it is ever used), so having the filter installed at form creatiion is not efficient. What occured to me is that adding the filter later will also solve the problem of stepping through the code, because the filter won't be there until it is needed. With the filter being added as I have it, stepping through ANY form, no matter what it is, runs afoul of that filter. However, if I add the filter and can't remove it, then I'll still have problems, though lesser problems.
My usual boring signature: Nothing
 
-
May 4th, 2013, 09:04 PM
#7
Re: Interesting Problem with PreFilterMessage
Ah. How dumb of me. I completely forgot to consider single stepping. Under this circumstance I completely agree. Its really very annoying when single stepping through an application to have the constant nag of procedure being stepped into when you're not concerned with it at a specific point in time.
Note however, that you can specify the DebuggerStepThrough attribute for the PreFilterMessage procedure and the debugger would not to step into the filter. This approach however would not allow you to debug the filter but you can simply comment out the attribute when you want to step into the filter to debug it. And if you want to only step into the filter when a certain message is intercepted for a certain window you can leave the attribute and have the filter call a sub when this certain message is received. This sub shouldn't have the DebuggerStepThrough attribute hence when its called, single stepping would step into it.
Last edited by Niya; May 4th, 2013 at 09:09 PM.
-
May 4th, 2013, 09:40 PM
#8
Re: Interesting Problem with PreFilterMessage
Here is an example of what I mean:-
vbnet Code:
Public Class Form2
Implements IMessageFilter
<DebuggerStepThrough()> _
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
'Left mouse button up
Dim WM_LBUTTONUP As Integer = &H202
If Me.IsHandleCreated Then
If m.HWnd = Me.Handle AndAlso m.Msg = WM_LBUTTONUP Then
Return ButtonUpFiltered(m)
End If
End If
Return False
End Function
Private Function ButtonUpFiltered(ByRef m As Message) As Boolean
MsgBox("Click On " + Me.Name)
Return False
End Function
End Class
Single stepping would completely ignore PreMessageFilter but it would step into ButtonUpFiltered if called by PreMessageFilter. That way you can debug the message filter only when certain messages are trapped and if you wish not to debug them at all you can add the DebuggerStepThrough attribute to the ButtonUpFiltered procedure too.
-
May 4th, 2013, 09:50 PM
#9
Re: Interesting Problem with PreFilterMessage
Oh and one more thing:-
 Originally Posted by Shaggy Hiker
so having the filter installed at form creatiion is not efficient.
Unless your filter is doing something extra with all the messages, the only overhead you incur is that of an extra function on the call stack. The call stack for every single message in the app is already quite long, one extra function in the chain of calls the message passes through is really not gonna make any measurable difference.
-
May 5th, 2013, 09:08 AM
#10
Re: Interesting Problem with PreFilterMessage
Typing two iis in creation isn't efficient, either.
I didn't know about the DebuggerStepThrough attribute, though, which could be useful for this.
As it turns out, it does appear to be working...sort of, by moving the addition of the filter from the constructor to Shown, then removing it. In the other thread linked to early on, I found that the filter wasn't being removed even with RemoveFilter. Whatever that was about appears to have gone away, but I'm also thinking that the prefilter may not have fully solved the issues that prompted that earlier thread, as there appears to still be a scenario where the mouse gets lost, but I'm a ways away from getting back to working on those forms, so that will wait.
My usual boring signature: Nothing
 
-
May 6th, 2013, 07:13 AM
#11
Re: Interesting Problem with PreFilterMessage
 Originally Posted by Shaggy Hiker
...as there appears to still be a scenario where the mouse gets lost, but I'm a ways away from getting back to working on those forms, so that will wait.
You have to return False for the messages to be processed by the window for which it was originally intended. If you have any condition that returns True then any message sent under that condition would be lost. That is one possible cause of this problem, but I'm speculating on this one as I'm not really certain what you mean by losing the mouse. I'm assuming clicks/mouse moves etc don't go through or something.
-
May 6th, 2013, 10:40 AM
#12
Re: [RESOLVED] Interesting Problem with PreFilterMessage
I'd be spectulating, as well. I notice that the earlier thread, which is what prompted me to get into filtering the messages, was written about two years back. By now, it could have been written by a different person. The problem I had was that the PreFilterMessage implementation was still being called even after I had called RemoveFilter, which should have unhooked the message filter entirely. That appears to no longer be the case, but there also appears to be something going wrong with the drag-copy that started the original thread. Eventually, perhaps in a few days, I'll get back to that code and figure out whether or not it works. At least one of the forms that filter is found in is in a transitional state from one design to another, so it may not be working for any number of reasons. Neither of the forms that have the message filter work the way they did when I wrote that original thread, so there is plenty of work left to do.
My usual boring signature: Nothing
 
-
Jul 18th, 2013, 12:34 PM
#13
Re: [RESOLVED] Interesting Problem with PreFilterMessage
I just found the problem with this line:
If m.HWnd = Me.Handle
m.HWnd is an interesting value. It will almost never be Me.Handle in real use, since Me.Handle is the HWnd for the form, but m.HWnd will be the handle for whatever control is relevant, which in the case of mouse up, will be the handle of the control on which the mouse was pressed.
This is just a note, not a solution or a question. I just felt that the thread left something unreported.
My usual boring signature: Nothing
 
-
Jul 18th, 2013, 06:36 PM
#14
Re: [RESOLVED] Interesting Problem with PreFilterMessage
You seemed surprised by that. Every single message that the message pump deals with will pass through there. There will be messages with many different handles passing through.
-
Jul 18th, 2013, 09:32 PM
#15
Re: [RESOLVED] Interesting Problem with PreFilterMessage
I was a bit surprised at some of the things I found. This has been a VERY fragmented approach, as I've glanced at the code, then gone off and worked on other things for a month or more, then come back to it. This thread was started in May, it's now mid-July and I finally spent some time looking at this. I had cavalierly dealt with HWnd, without bothering to see whether or not it worked, or why. I forget what it was that I was working on at the time I created this thread, but it wasn't really this. In fact, I suspect that it was a form that I ended up taking in a TOTALLY different direction where none of this applied. Whatever the reason was, I didn't spend any time looking at it or looking at the form that I used this in.
However, when I came back to it, I read the original thread that got me into prefiltering messages. That had been working, and now it wasn't. What suprised me was that the HWnd of the message that had the mouseUP message was the same that had the MouseDown. That makes plenty of sense, but it makes the original thread (which was YEARS back, rather than months, and I have only a vague memory of what I had tried out). I note that in that thread, what got me into this was that when the mouse was over disabled controls when the mouse button was released, there was no Mouse Up event. There should have been, because the MouseUp event should have been raised by the control that got the Mouse Up message, which was the control that had the Mouse Down. So, why wasn't I seeing those events years back? Maybe I solved the wrong problem today. Now that I think about it, I just realized that I may have performed the wrong test. The control could become disabled while the mouse is down. Will the Mouse Up still happen if that occurs? I can't look now, so that'll have to wait.
My usual boring signature: Nothing
 
-
Jul 18th, 2013, 09:44 PM
#16
Re: [RESOLVED] Interesting Problem with PreFilterMessage
 Originally Posted by Shaggy Hiker
The control could become disabled while the mouse is down. Will the Mouse Up still happen if that
occurs? I can't look now, so that'll have to wait.
If a Button is disabled on MouseDown, it only receives an additional paint message. No MouseUp.
-
Jul 18th, 2013, 09:51 PM
#17
Re: [RESOLVED] Interesting Problem with PreFilterMessage
In this case, the mouse will be enabled on MouseDown, but can become disabled before the MouseUp. No MouseUp event will be emitted, but will the filter see a MouseUp message? I'll have to take a look.
My usual boring signature: Nothing
 
-
Jul 19th, 2013, 02:32 AM
#18
Re: [RESOLVED] Interesting Problem with PreFilterMessage
Well what I'm saying is that there will be no messages if its disables on MouseDown so I would expect that if its disabled anytime after MouseDown but before MouseUp then there will be no messages.
-
Jul 19th, 2013, 11:13 AM
#19
Re: [RESOLVED] Interesting Problem with PreFilterMessage
Yeah, the MouseUp is going to be a problem. I need to get that, but the hWnd of the message is going to be a bit harder to figure out in some circumstances. I can't work on it today, but I'll give it a look tomorrow.
My usual boring signature: Nothing
 
-
Jul 20th, 2013, 06:08 PM
#20
Re: [RESOLVED] Interesting Problem with PreFilterMessage
This turned out to be trivial. The MouseUp message is sent, it just isn't sent with the hWnd of the control that emitted the MouseDown message. Normally, the MouseUp message will have the same hWnd as the control that raised the MouseDown, but if the control in question becomes disabled, the MouseUp has a different hWnd. I didn't bother figuring out which window handle that was, though I assume it was the parent, or the form, or something like that. The key is that the control won't raise the MouseUp event, because it doesn't get the MouseUp message if it has been disabled.
The other half that I was going to look at turned out to be a memory issue. To be more specific, I had forgotten the logic behind what I had written, and was using the control incorrectly. This may be an issue, because people may not like the way I have it working. Still, that's a useability concern, not a programming concern.
My usual boring signature: Nothing
 
-
Jul 21st, 2013, 06:42 AM
#21
Re: [RESOLVED] Interesting Problem with PreFilterMessage
Its better to stick to common conventions so you don't have to actually remember how to correctly use certain components. For example, not closing streams or resetting their pointer when you write methods to take and process stream parameters or never cloning clonable objects when you pass them into methods no matter what benefit you get from breaking these conventions. It saves you from having to willfully remember you did weird things here and there. It can be a little tedious to do in practice but it helps.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|