Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. .NET (Core and Framework)
  4. How to override the message loop in winforms?

How to override the message loop in winforms?

Scheduled Pinned Locked Moved .NET (Core and Framework)
c++csharpwinformstutorialquestion
8 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Felix Collins
    wrote on last edited by
    #1

    Hi All, I have a situation where I need to do some custom message filtering. Unfortunately I need more functionality than provided by the IMessageFilter system or by overriding a Form's wndproc() method. What I need is to be able to run code before and after a message is processed and optionally drop selected messages. As I understand it: The IMessageFilter system only allows filtering out selected messages (can't run code after they have been processed) A Form's wndproc method only sees messages destined for that form. (I need to handle all messages for the entire application) In an unmanaged application say in visual c++ it would be a simple matter of implementing ones own getmessage/dispatchmessage loop. In the dotnet framework the actual message loop is implemented in native code and is inaccessible to the programmer. Does anyone know a solution for this? Regards, Felix

    P 1 Reply Last reply
    0
    • F Felix Collins

      Hi All, I have a situation where I need to do some custom message filtering. Unfortunately I need more functionality than provided by the IMessageFilter system or by overriding a Form's wndproc() method. What I need is to be able to run code before and after a message is processed and optionally drop selected messages. As I understand it: The IMessageFilter system only allows filtering out selected messages (can't run code after they have been processed) A Form's wndproc method only sees messages destined for that form. (I need to handle all messages for the entire application) In an unmanaged application say in visual c++ it would be a simple matter of implementing ones own getmessage/dispatchmessage loop. In the dotnet framework the actual message loop is implemented in native code and is inaccessible to the programmer. Does anyone know a solution for this? Regards, Felix

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      Unfortunately, the only thing you can do outside the form is use Application.AddMessageFilter to add your own filter, and (as you've surmised), this only works on capturing a message before it is dispatched to the window. What you could possibly do (and this would be one heck of a hack), is use a combination of AddMessageFilter and a Mediator to control what happens. What you'd do is hook into the WndProc of each form, and pass the details to the mediator to work out whether or not the message could be processed.

      "WPF has many lovers. It's a veritable porn star!" - Josh Smith

      As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

      My blog | My articles | MoXAML PowerToys | Onyx

      F 1 Reply Last reply
      0
      • P Pete OHanlon

        Unfortunately, the only thing you can do outside the form is use Application.AddMessageFilter to add your own filter, and (as you've surmised), this only works on capturing a message before it is dispatched to the window. What you could possibly do (and this would be one heck of a hack), is use a combination of AddMessageFilter and a Mediator to control what happens. What you'd do is hook into the WndProc of each form, and pass the details to the mediator to work out whether or not the message could be processed.

        "WPF has many lovers. It's a veritable porn star!" - Josh Smith

        As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

        My blog | My articles | MoXAML PowerToys | Onyx

        F Offline
        F Offline
        Felix Collins
        wrote on last edited by
        #3

        Thanks for your answer. I think I may have to add a custom BaseForm class that overrides the wndproc and which all of my Forms inherit from. That way I could insert global message processing which would be similar to writing a custom message loop.

        L 1 Reply Last reply
        0
        • F Felix Collins

          Thanks for your answer. I think I may have to add a custom BaseForm class that overrides the wndproc and which all of my Forms inherit from. That way I could insert global message processing which would be similar to writing a custom message loop.

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Keep in mind existing dialogs (OpenFileDialog, MessageBox, ...) will not inherit from your BaseForm, so while one of those is open, your special message handling will not occur automatically. :)

          Luc Pattyn [Forum Guidelines] [My Articles]


          The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


          F 1 Reply Last reply
          0
          • L Luc Pattyn

            Keep in mind existing dialogs (OpenFileDialog, MessageBox, ...) will not inherit from your BaseForm, so while one of those is open, your special message handling will not occur automatically. :)

            Luc Pattyn [Forum Guidelines] [My Articles]


            The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


            F Offline
            F Offline
            Felix Collins
            wrote on last edited by
            #5

            Yeah, it is not ideal. As there seem to be so many helpful knowledgeable people on here, I'll describe the actual problem I'm trying to solve and see if there are any other ideas. The problem I'm having is that inside one of my event handlers I'm calling some DirectShow code. Inside the DirectShow code a message loop is run to handle the COM calls. Unfortunately this inner message loop pumps my input events so if I click quickly with the mouse I can get a second event handler running nested inside the first at the point of the DirectShow call. I'm not sure what the correct term is for this behaviour so I am calling it reentrant event processing (although it is not strictly rentrancy as the event handlers are likely to be different ones). The problem arises because all the event handler code assumes that it is single threaded (which it is) and that events will be processed in order from the queue. I get unpredictable crashes of my application due to this problem. One solution I am looking at is to simply discard user input messages and timer messages while a message is being processed, hence the original topic of this thread. Another more complicated but better solution is to run a second thread with it's own message loop and invoke the COM calls on that thread. I haven't looked into the details of this too much as yet. I've got a simple project that demonstrates the problem which I can post if anyone would like to see it. Thanks for your help! regards, Felix

            D 1 Reply Last reply
            0
            • F Felix Collins

              Yeah, it is not ideal. As there seem to be so many helpful knowledgeable people on here, I'll describe the actual problem I'm trying to solve and see if there are any other ideas. The problem I'm having is that inside one of my event handlers I'm calling some DirectShow code. Inside the DirectShow code a message loop is run to handle the COM calls. Unfortunately this inner message loop pumps my input events so if I click quickly with the mouse I can get a second event handler running nested inside the first at the point of the DirectShow call. I'm not sure what the correct term is for this behaviour so I am calling it reentrant event processing (although it is not strictly rentrancy as the event handlers are likely to be different ones). The problem arises because all the event handler code assumes that it is single threaded (which it is) and that events will be processed in order from the queue. I get unpredictable crashes of my application due to this problem. One solution I am looking at is to simply discard user input messages and timer messages while a message is being processed, hence the original topic of this thread. Another more complicated but better solution is to run a second thread with it's own message loop and invoke the COM calls on that thread. I haven't looked into the details of this too much as yet. I've got a simple project that demonstrates the problem which I can post if anyone would like to see it. Thanks for your help! regards, Felix

              D Offline
              D Offline
              dybs
              wrote on last edited by
              #6

              I've had a similar issue when I try to link controls together, like a textBox and a trackBar, where updating one control should update the other. Here's how I solved it. Keep in mind this only works if it's managed code that you're trying to keep "non-reentrant". If your code is assuming a single-threaded environment, you could try setting a lock before the DirectShow code gets called, and check that lock at the beginning of the nested events, like so:

              bool lock = false;

              void SomeEvent(object sender, EventArgs e)
              {
              if(!lock){
              lock = true;
              // Some code
              DirectShowCall();
              // more code.
              lock = false;
              }
              }

              void NestedEvent(object sender, EventArgs e)
              {
              if(!lock)
              {
              // Your code here.
              }
              }

              The lock check in SomeEvent will prevent your DirectShow code from getting called in a nested fashion. This method isn't thread-safe. If you need thread-safety, you may want to look at Monitor.TryEnter.[^] Dybs

              F 1 Reply Last reply
              0
              • D dybs

                I've had a similar issue when I try to link controls together, like a textBox and a trackBar, where updating one control should update the other. Here's how I solved it. Keep in mind this only works if it's managed code that you're trying to keep "non-reentrant". If your code is assuming a single-threaded environment, you could try setting a lock before the DirectShow code gets called, and check that lock at the beginning of the nested events, like so:

                bool lock = false;

                void SomeEvent(object sender, EventArgs e)
                {
                if(!lock){
                lock = true;
                // Some code
                DirectShowCall();
                // more code.
                lock = false;
                }
                }

                void NestedEvent(object sender, EventArgs e)
                {
                if(!lock)
                {
                // Your code here.
                }
                }

                The lock check in SomeEvent will prevent your DirectShow code from getting called in a nested fashion. This method isn't thread-safe. If you need thread-safety, you may want to look at Monitor.TryEnter.[^] Dybs

                F Offline
                F Offline
                Felix Collins
                wrote on last edited by
                #7

                Hi Dybs, naturally that is a great solution if you can easily identify SomeEvent and NestedEvent, however in my case this is not so easy, there are many events that can lead to a DirectShow call and many events that could be unsafe to process nested within another call. I could search through my code and put locks in all event handlers that look likely to cause trouble but this discipline would need to be maintained in maintenance and future development, so is not ideal. The solution you propose is really a special case of my proposal to override the wndproc of all forms (by using a custom BaseForm class). The whole point of an event queue and a single gui thread is so that in programming these events one can consider them as occurring serially. Overriding message processing for the whole app will place some overhead on all activity so I'd rather avoid the wndproc solution. Another disadvantage is that by effectively discarding some messages I might see strange behaviour, for example if a user started typing while in the lock the letters entered up to the point of releasing the lock would be lost. The alternative solution I'm going to investigate is to start a second thread with its own message loop and make all DirectShow calls synchronously on that thread. Due to good architectural choices early on in the project the references to DirectShow in my application are limited to one module so it should be easy to ensure that all calls are routed through the second thread. If it works I'll post an article here to explain the solution. Regards, Felix

                F 1 Reply Last reply
                0
                • F Felix Collins

                  Hi Dybs, naturally that is a great solution if you can easily identify SomeEvent and NestedEvent, however in my case this is not so easy, there are many events that can lead to a DirectShow call and many events that could be unsafe to process nested within another call. I could search through my code and put locks in all event handlers that look likely to cause trouble but this discipline would need to be maintained in maintenance and future development, so is not ideal. The solution you propose is really a special case of my proposal to override the wndproc of all forms (by using a custom BaseForm class). The whole point of an event queue and a single gui thread is so that in programming these events one can consider them as occurring serially. Overriding message processing for the whole app will place some overhead on all activity so I'd rather avoid the wndproc solution. Another disadvantage is that by effectively discarding some messages I might see strange behaviour, for example if a user started typing while in the lock the letters entered up to the point of releasing the lock would be lost. The alternative solution I'm going to investigate is to start a second thread with its own message loop and make all DirectShow calls synchronously on that thread. Due to good architectural choices early on in the project the references to DirectShow in my application are limited to one module so it should be easy to ensure that all calls are routed through the second thread. If it works I'll post an article here to explain the solution. Regards, Felix

                  F Offline
                  F Offline
                  Felix Collins
                  wrote on last edited by
                  #8

                  Preventing Unexpected Message Pumping in Third Party Libraries - An example using DirectShow[^]

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups