Jump to content

Generating event off windows message queue


Recommended Posts

I know there is the windows message queue API that can be downloaded, and I have this working fine and am receiving messages. But unfortunately this requires polling the message queue in my application. I'd like to handle these messages as events in an event structure, and I can do that by having a polling loop to manage the message queue, which then fires a user event when the correct message is captured from windows.

But, is there a way to do this any cleaner, similar to being able to register events based on callbacks?

Link to comment

Are you comfortable coding in C? If so, you can modify the code for the Windows message queue DLL to call PostLVUserEvent(). It's been a while since I looked at the Windows Message Queue library, but if I remember correctly, it uses an occurrence. I do not think it would be too difficult for someone with some C experience to change it to use a LabVIEW user event instead.

Link to comment

Unfortunately I'm not very comfortable, but I could still hack something together. I was hoping there was some way to make things more transparent to the programmer, so I don't have to put a polling loop in at all. Similar to callback VIs, you register and then there is nothing else you have to do, the callbacks are captured for me and I can generate user events in the callback VI to feed to my event structure. I was hoping for something similar to that or similar to a message map in MFC. This windows message happened, do this. Basically, I was trying to capture the system messages without having to add any sort of additional loops into my software to monitor the message queue, but I don't think there's an easy way to do this.

Edited by for(imstuck)
Link to comment

Not with the Windows Message Queue library as is, but the use of LVPostUserEvent() as mentioned by ned would certainly make that easy. I'll see if I can have a go at it. It would in fact simplify the DLL part enormously, since the whole queue handling in the C code can go away, as the user event will handle that internally.

I'm rooting for you! Let me know if you get it working. Sorry to Ned if I misunderstood. I thought I would still have to poll the DLL to get the user event, but I guess registering for this event in a DLL would remove that polling, as the DLL would manage the capturing of the message and posting the event in the background?

Edited by for(imstuck)
Link to comment

Edit due to miswording:

I'm rooting for you! Let me know if you get it working. Sorry to Ned if I misunderstood. I thought I would still have to poll the DLL to get the user event dll to check for Windows messages, but I guess registering for this event in a DLL would remove that polling, as the DLL would manage the capturing of the message and posting the event in the background?

Edited by for(imstuck)
Link to comment

No polling necessary. The DLL installs a hook that gets called when LabVIEW receives a Windows message. If the user registered for that message, it generates an occurrence (as currently written). What I was suggesting - and what I understand Rolf to be offering to implement - is to replace the occurrence with a user event. When the window receives a message through the Windows message queue, it will fire off a user event that will look to your LabVIEW code exactly like a user event generated by Generate User Event.

Link to comment

Not with the Windows Message Queue library as is, but the use of LVPostUserEvent() as mentioned by ned would certainly make that easy. I'll see if I can have a go at it. It would in fact simplify the DLL part enormously, since the whole queue handling in the C code can go away, as the user event will handle that internally.

Nice.

If NI got off their arse and spent time on the event structure, they could easily have included this feature as a native part of the Event structure.

Link to comment

Not with the Windows Message Queue library as is, but the use of LVPostUserEvent() as mentioned by ned would certainly make that easy. I'll see if I can have a go at it. It would in fact simplify the DLL part enormously, since the whole queue handling in the C code can go away, as the user event will handle that internally.

For some reason, it popped into my head that someone had already this and I actually thought it was you. Am I a fortune teller?

Link to comment

Nice.

If NI got off their arse and spent time on the event structure, they could easily have included this feature as a native part of the Event structure.

This along with being able to capture every message posted by windows (which is what I think you are implying anyways). Why can't I get the Window Move message? Instead I have to get mouse down on title bar through the windows API, then register for mouse move within LabVIEW, then handle the mouse move event. Then, on mouse up, I have to unregister for the mouse move event. :angry: Unless, of course, someone has a better way.

Edited by for(imstuck)
Link to comment

This along with being able to capture every message posted by windows (which is what I think you are implying anyways). Why can't I get the Window Move message? Instead I have to get mouse down on title bar through the windows API, then register for mouse move within LabVIEW, then handle the mouse move event. Then, on mouse up, I have to unregister for the mouse move event. :angry: Unless, of course, someone has a better way.

Rolf is about to give you a much better way ;)

Link to comment

Nice.

If NI got off their arse and spent time on the event structure, they could easily have included this feature as a native part of the Event structure.

The problem with this is that it needs to be working on all platforms if NI integrates it into the event structure. And that part is really not easily mapped into a generic scheme. Of course NI could implement just about all 500 Windows Message events and its 2000 variants of it in the event structure and try to find according X Windows and Mac OS events. But that would make the event structure absolutely unmanagable and it would still not cover the issue when you need to interface to software that uses windows messaging for interapplication communication. So a lot of work for little benefit, and that is a true killer argument for anything.

Link to comment

The problem with this is that it needs to be working on all platforms if NI integrates it into the event structure. And that part is really not easily mapped into a generic scheme. Of course NI could implement just about all 500 Windows Message events and its 2000 variants of it in the event structure and try to find according X Windows and Mac OS events. But that would make the event structure absolutely unmanagable and it would still not cover the issue when you need to interface to software that uses windows messaging for interapplication communication. So a lot of work for little benefit, and that is a true killer argument for anything.

Nope. I don't buy it.

Lots of features work on one platform but not another (because it doesn't exist) but that is beside the point.

You don't have to implement the "500 Windows Message events and its 2000 variants", just expose the message hook (which they must already be using for the Event Structure on all platforms) and let the labview user filter what messages he/she wants with Gcode.

Edited by ShaunR
Link to comment

Nope. I don't buy it.

Lots of features work on one platform but not another (because it doesn't exist) but that is beside the point.

You don't have to implement the "500 Windows Message events and its 2000 variants", just expose the message hook (which they must already be using for the Event Structure on all platforms) and let the labview user filter what messages he/she wants with Gcode.

And here you are wrong. There is no message hook in LabVIEW or any application necessary. It's the event loop at the core of the application with GetMessage() that receives these events and then distributes it. And messing at that level with events is for sure going to open up a myriad of possibilities to lock up your application from the diagram completely.

And a Mac application has yet another rather different type of event loop. And if they change that to work with Cocoa instead of Carbon, which is a prerequist to make LabVIEW work as 64 Bit application on the Mac, since Apple dropped the Carbon support for 64 Bit completely for anything UI related, then that is again a VERY different event paradigma. Not even starting to talk about X Windows events, which are very powerful, and at the same time VERY easy to break completely with different windows managers.

There simply is no way at all to provide an interface to a message hook like functionality that is working on all platforms in the same way, does work uniformly on various platform versions, and supports the full power of message hooking of the platform. The best there is would be to extend the event loop to give more access to certain low level events like mouse move, common system management events like power saving events and such things but in a true platform independent manner like other LabVIEW features.

Integrating native platform events into the event structure is simply a no go in my opinion. Such a core object like the event structure should not make an application break on non Windows platforms when being loaded.

And message hooking is tricky at best and can easily create dangerous situations where you can lock up your application in very interesting ways that are almost impossible to debug without C source level debuggers.

Link to comment

And here you are wrong. There is no message hook in LabVIEW or any application necessary. It's the event loop at the core of the application with GetMessage() that receives these events and then distributes it. And messing at that level with events is for sure going to open up a myriad of possibilities to lock up your application from the diagram completely.

<snip>

And message hooking is tricky at best and can easily create dangerous situations where you can lock up your application in very interesting ways that are almost impossible to debug without C source level debuggers.

Nope. Still not convinced!. If they can spend oodles on POOP and trivial eye candy, then they can spend a fraction of that on standard OS event methods for the rest of us. It's not rocket science.

GetMessage() in a while loop is windows only and a pretty poor way of doing it. If that is the method used, then it really does need a revamp. Although the currentEvent on the Mac could be an analogue, there is no equivalent in Linux (x11) as that is purely asynchronous. The bottom line is, NI have to "hook" into the OS message system (either by polling or by registering) to be able to get messages at all. They just don't publish all the messages to us. Whilst it would be nice to have a few more "generic" frames in the event structure that are available across all OSs (after all, there are a lot of similarities), that doesn't mean to say they cannot provide the raw messages in a frame so we can write platform specific software (like we do with activeX and .NET). Especially if they can't be bothered to wrap some of the common ones up for us ........and don't get me started with VISA events! :P

I'm also not buying the "lock-up" and "dangerous situations" argument. All these methods are standard event messaging that applications must use to interact with the OSs and have well defined wrappers in most other languages. There are lots of code snippets around and they are all pretty much identical since they just call OS api functions (or X11/Xorg in Linux). Hooking events is very straight forward (as you are about to demonstrate :) ).

If the argument boils down to "it's hard" (which I refute since they are already doing it for "some" events - for all the OSs) then that isn't really an excuse for a $4,000 piece of software from a multinational corporation that is quite prepared to come up with a whole new paradigm.

  • Like 1
Link to comment

Forgive my ignorance, but how could you lock up an OS just by monitoring messages? If you wanted to start filtering them, it might start getting hairy, but I would expect that a listen-only approach would be quite safe.

Windows message hooks don't just "monitor" the message queue, they hook it. This means if anything in the hook does not respond properly, depending on the type of hook, the application in question can get completely locked up. Even in modern day multithreading and multitasking Windows, anything UI oriented goes through that message queue (and a lot of other things like OLE data marshalling, which is used by most ActiveX components too).

Link to comment

As I'm working on the sidelines on this I run into a difficulty. Windows handles are really opaque pointers and as such they are surprisingly 32 bits on Windows 32 Bit and 64 Bits on Windows 64 Bit. This is a bit of a problem as the original Windwos Message Queue library contains a Windows handle in its data structure, as it completely mirrors the MSG structure used in the WinAPI. There seems to be only one datatype in LabVIEW that truely mimicks this behaviour and that is the so called user refnum. That is a refnum that is defined by object description files in the LabVIEW resource directory and as such not documented at all.

So the question is now, does anyone know of another LabVIEW datatype that is sure to be truely pointer sized when embedded in a cluster or alternatingly is there any objection to not include the Windows handle in the message structure?

Link to comment

So the question is now, does anyone know of another LabVIEW datatype that is sure to be truely pointer sized when embedded in a cluster or alternatingly is there any objection to not include the Windows handle in the message structure?

You're referring to the hWnd handle, right? A happy compromise might be to use whatever type works correctly internally and then have a VI for exposing it which will output it to one of two terminals, a U32 or a U64, based on the platform via a Conditional disable structure.

Link to comment

As I'm working on the sidelines on this I run into a difficulty. Windows handles are really opaque pointers and as such they are surprisingly 32 bits on Windows 32 Bit and 64 Bits on Windows 64 Bit. This is a bit of a problem as the original Windwos Message Queue library contains a Windows handle in its data structure, as it completely mirrors the MSG structure used in the WinAPI. There seems to be only one datatype in LabVIEW that truely mimicks this behaviour and that is the so called user refnum. That is a refnum that is defined by object description files in the LabVIEW resource directory and as such not documented at all.

So the question is now, does anyone know of another LabVIEW datatype that is sure to be truely pointer sized when embedded in a cluster or alternatingly is there any objection to not include the Windows handle in the message structure?

The easy way would probably just expose it as a 32 bit value and if the user "must" have it, then make him deference with a moveblock (move the issue downstream).

However, I'm not sure what you are asking here. If the DLL is 32 bit bit, then it can only be loaded in LV x32 (and therefore can only handle 32 bit pointers anyway). If it is a 64 bit, then that cannot be used by LV32 bit. So if the cluster uses a U64 it will be able to represent both even if it creates a "red dot" when passed to another API/DLL call which is set to pointer sized.

Link to comment

The easy way would probably just expose it as a 32 bit value and if the user "must" have it, then make him deference with a moveblock (move the issue downstream).

However, I'm not sure what you are asking here. If the DLL is 32 bit bit, then it can only be loaded in LV x32 (and therefore can only handle 32 bit pointers anyway). If it is a 64 bit, then that cannot be used by LV32 bit. So if the cluster uses a U64 it will be able to represent both even if it creates a "red dot" when passed to another API/DLL call which is set to pointer sized.

I was thinking about creating both a 32 bit and 64 bit DLL but would like to keep one VI interface only. A fixed always 64 Bit integer would probably work except that it is not a normal integer but really a distinct datatype that should not be connected to anything else. The enum inside a datalog refnum abuse is a nice trick to ensure this, yet most refnums in LabVIEW (except the user refnum) are always 32 Bit entities so that would be not an option. I also need to pass out some kind of refnum to manage the message hook throughout the program. In practice this is the HWND of the hooked window too, but since this refnum is only supposed to be used with functions from that library there are several ways to deal with this in a transparent way as the user does not need to be concerned about what the refnum really is. However in the message structure I do not have that luxury. The only reason for it to exist in there, is to allow a possible user of the library to use it to do something on Windows API level with it and I have no intentions on providing any wrappers for any Windows API calls to work with a private version of this refnum.

It may be a always 64 Bit sort of hack really that will be done similar to what LabVIEW does when dealing with pointer sized variables.

Link to comment
I was thinking about creating both a 32 bit and 64 bit DLL but would like to keep one VI interface only. A fixed always 64 Bit integer would probably work except that it is not a normal integer but really a distinct datatype that should not be connected to anything else. The enum inside a datalog refnum abuse is a nice trick to ensure this, yet most refnums in LabVIEW (except the user refnum) are always 32 Bit entities so that would be not an option. I also need to pass out some kind of refnum to manage the message hook throughout the program. In practice this is the HWND of the hooked window too, but since this refnum is only supposed to be used with functions from that library there are several ways to deal with this in a transparent way as the user does not need to be concerned about what the refnum really is. However in the message structure I do not have that luxury. The only reason for it to exist in there, is to allow a possible user of the library to use it to do something on Windows API level with it and I have no intentions on providing any wrappers for any Windows API calls to work with a private version of this refnum. It may be a always 64 Bit sort of hack really that will be done similar to what LabVIEW does when dealing with pointer sized variables.

Yup. It is a nice trick (refnum) because of the polymorphism that can be performed and it is "the right way". However. I have found that this is true only within LabVIEW and when dealing with interactions with external code, it is better (IMHO) to leave things in the native form for things like this since you only end up type casting it back to an integer to pump it into another call. I had the same sort of thoughts with the SQLite APIs SQL ref but left it as an integer in the end since every VI ended up with a type cast in and out.

Edited by ShaunR
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.