Jump to content

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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.

Link to post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites

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 post
Share on other sites
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 post
Share on other sites

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.

  • Similar Content

    • By torekp
      DLL functions or shared variables?  Or something else?
      I have a Labview 2014-64 executable (or I can build a DLL) that runs one piece of equipment, the X-ray.  The other engineer has a large CVI Labwindows 2015 + MS Visual Studio 2012 (C++) executable that runs everything else.  I want the Labview code to be a slave of the CVI code, accepting commands to turn X-ray On or Off, reporting failures, and the like.  Translating the X-ray code into C++ would be possible in principle, but not fun.
      Shared variables look easy, but I'm kinda scared of them.  I would define all the shared variables in my LV code, since I'm more familiar with LV, then use them in both.  There's a thread in here called "Shared Variable Woes" so maybe I should be scared.  In the alternative, I tried building a proof-of-concept DLL in Labview, and calling its functions in CVI/C++, and it works, but it's kinda clunky.  (I'm attaching it below in case you want to play, or advise.)
      Your advice would be appreciated.
      XrayDLL.zip
    • By Gan Uesli Starling
      We have a gage supplied by a company that shipped it with a *.exe application targeted for LVRTE 2009. I need to retarget it for 2017, but don't have the source code. The supplier had said they'd gladly supply me with a copy of the *.LV source, but they have looked and cannot find their own copy in-house.
      History of Need: Our global corporate mother ship's IT department, in their infinite wisdom, is mandating an upgrade from Win7 to Win10. That with yet even further constraints. They enforce a list of "approved versions" of "approved applications". And for LVRTE, they are insisting upon 2017, with 2009 being a red light.
      So, then, my query. Is converting an app without the source for a higher LVRTE doable at all? File is attached.
      If it is doable, instructions on how?
      Concentricity-Gage.exe
    • By Dawid
      I'm trying to execute LPR.exe command to print some labels on a printer. However as its normal, problems occur. I could not find answer on any topic conneced with "sytem exec". I already tried all described methods (I think so). That's why I'm asking very kindly for any help.
      When trying to execute or call the LPR.exe from System exec VI, I'm receiving error:
      "'C:\Windows\System32\lpr.exe' is not recognized as an internal or external command, operable program or batch file."
      Generally I would like to call function: "lpr -S 192.168.1.5 -P lp C:\test\do_druku.txt" which works from command window without any problem.
       

      print.vi

    • By jhoehner
      Hello All,
      First time LAVA poster here with my first question. Why do some LabVIEW programmers insist on wiring the error cluster to the bottom of their VI as opposed to the sides as shown in most NI documentation. Is there any benefit to it? Is it 100% a preference thing? Is there a way to make LabVIEW connect error wires like this automatically?
      I've only seen it in advanced LabVIEW code from experienced programmers and some parts of the Actor Framework.
      Your insight and experience is appreciated! 

    • By the_mitten
      The introduction of parallel, read-only access for DVRs in LabVIEW 2017 adds a great deal of flexibility to using DVRs to monitor values in parallel executions of code. Fo\The downside of this, of course, is the necessity of using the In Place Element (IPE) throughout your code simply to read the value. Having IPEs throughout your code just to read a value both takes up block diagram real estate and also takes more clicks than desirable to insert.
      Similarly, though less frequently, there are times when you only need to update the value within a DVR without actually performing any logic inside of the IPE.  This situation is less frequent, at least for me, as I am usually using arrays or classes with DVRs such that I actually need to modify the existing data rather than simply replacing it.
      A more preferable solution to the above situations would be to have Read/Get and Write/Set VIs for the DVRs to simplify the process of working with them. This way, and IPE on the block diagram would only be needed when you were actually modifying the existing data within the DVR, rather than simply overwriting or returning the current value.
      Thanks to the power of malleable VIs and the type specialization structure that is now officially released in LabVIEW 2018, a better solution is now available. I’ve created two malleable VIs, Read  DVR Value (Parallel) and Write DVR Value that allow you to perform a write and a parallel read on any DVR data type.
       Now, you can use a single VI that you can insert via Quick Drop to read or to write DVR values.  
      Download the attached ZIP file to access the two malleable VIs and example code, and please let me know your thoughts in the comments!
       


      DVR Read and Write VIs 1.0.0.zip
×
×
  • Create New...

Important Information

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