One of my colleagues asked me recently how to implement "Ctrl-A" functionality in a string control, where pressing Ctrl-A selects all the text in the string. Unfortunately, this functionality is not natively supported in LabVIEW (vote here if you think it should be).
To demonstrate how to implement this functionality, I wrote the simple example VI you can download here. But then my colleague asked me how this code could be implemented in a reusable fashion, where the Ctrl-A functionality could be added to an arbitrary number of VIs and an arbitrary number of strings, without the need to rewrite the code each time.
I realized that this expanded task could be easily accomplished with a DQMH module. This module is somewhat different from a standard DQMH module in multiple ways:
1. There is only a single "public API" method, which is the VI added to the caller to enable Ctrl-A support.
2. I didn't add any MHL cases to the module.
3. All the management of requests is handled in the EHL of the module, since the module is responding to events other than its own requests.
So this demo probably isn't a good place to start if you're trying to learn the basics of DQMH, but it is a handy illustration of how a DQMH can be used as a "brat" VI (i.e. a VI that controls its parent) with a few modifications.
The attached project is saved in LabVIEW 2015. You can open and run the two 'Test' VIs in the project to see the module in action. I plan on taking this approach for future "brat"-like reusable features I may need to write.
Thanks for the idea and method. I had to do a similar thing in a past project to capture the escape key, as a software estop of sorts. So whenever a new VI panel opened (dialogs etc) I had to register the panel etc. My method was not nearly this clean and this makes sense to me.
Your colleague sounds like the one who's the real brat...
Seriously though, thanks for the tips and this help with this. For purpose of discussion, I tried the same concept but without DQMH. My goal was to make this as lightweight as possible, and since a one-VI solution wasn't possible I did it in 2. Other than my one poor design choice (using named queues to pass reference data) how is the DQMH solution better than my 2-VI solution? Any thoughts on how to replace the named queue and make the data more secure, without adding additional files to the hierarchy?
(Main files are in LabVIEW 2016, revised 2013 version also attached)
<Edit: Tested 2013, found that it failed for two reasons: 1) Clear error doesn't have the error number input so I had to add my own custom "ClearSpecificError" VI and 2) in 2013 the string control processes the "a" key even though ctrl is held down causing it to overwrite the text so I had to use the "Key Down?" event instead.>
I am still out of the office and I will look at the code when I get back next week.
I would like to understand more why "adding additional files to the hierarchy" is seen as a reason to not use one approach over the other.
A DQMH module might seem heavy handed, however a DQMH module out of the box does three things right: start when asked to start, gracefully stops when it needs to stop and handles errors. Whenever I need to ensure that I have those three things working, I use a DQMH module. I don't have to worry about those three things, because the DQMH module just works. If the DQMH module stops doing any of those three things, is because the developer added code that broke those features.
I think for most real-world applications, number of files isn't a problem (but I have heard horror stories of building EXEs with thousands of VIs, but that's beside the point). However it's much easier to share examples or re-use VIs if it's single file.
Now, I know your next response is most likely something like "sharing of reuse code should be done with packages, so number of files doesn't matter". But when sharing a simple example with a customer/client/colleague, it is SO much easier to just attach a single file and say "hey try this", instead of "Hey, here's a package with 52 files, install it and go find the one called blahblahMain.vi and run it".
For the record, my feelings here are not DQMH specific, it's all LVOOP architectures. I think there's a definite need for these extensible, integrated, bullet-proof architectures, but simple reusable code doesn't necessarily need it. Having something that takes 52 files to accomplish something that could be 1 makes life simpler. And I'm just a simple guy :-)
Your example requires unzipping multiple files and telling somebody which VI to use. My example requires unzipping multiple files and telling somebody which VI to use. You don't need to know anything about the underlying code of either approach to drop that single VI and be successful. Since the situations are the same from the end user's perspective, I'd rather know the underlying design of that single VI, whatever it may be, has been signed off by the community.
...but simple reusable code doesn't necessarily need it.
Are you talking about simple examples, to illustrate techniques, or reliable reuse code to actually use in a real-world application? Because they aren’t the same thing.
I think there's a definite need for these extensible, integrated, bullet-proof architectures, but simple reusable code doesn't necessarily need it. Having something that takes 52 files to accomplish something that could be 1 makes life simpler. And I'm just a simple guy :-)
I can come at it from two directions:
1) I don’t use DQMH; I use a difference architecture called “Messenger Library”. Thus Darren’s demo isn’t much use to me. Using an architecture in an example limits your audience to those using that architecture already (which is a small number).
2) It takes a lot of work to get reliable reuse code that you can just drop in without worry. Your two-VI solution, viewed as reuse code, has significant issues, things that take long-term effort to identify and fix. It memory-leaks a named-queue reference if called again in a loop (such as if it is used in a dialog VI); it can only be used in one place, but (I think) would silently fail if called in a second place; and the “Run VI” method is blockable by Root Loop (such as if the User has a menu open). These issues may not matter much in the intended use case (single use, for UI code only), but they could matter if this design was used for some other purpose.
One of the lesser understood advantages of “bullet proof” is that it reduces the number of things to worry about (or waste time debugging). If I were creating something in Messenger Library to handle Ctrl-A, I would be spending no time worrying about starting and stopping my Async “thing”, or about “Root Loop”, or cleaning up references. I worked that all out years ago.
Using an architecture in an example limits your audience to those using that architecture already (which is a small number).
While I couldn't quite verbalize my thoughts as I wanted, I think you nailed it with this comment. Anyone who knows a little bit of LabVIEW can easily understand the "two-VI" solution. A solution written in DQMH, Messenger Library, Actor Framework, or any other solid framework might be technically 'better" but would take an average user without knowledge of the framework quite a bit of time to understand it enough to debug or modify it. Now if this were part of an existing large application that used the DQMH framework already, and all of the developers on the project understood DQMH, adding yet another module with the same framework would likely be the better solution.
Your example requires unzipping multiple files and telling somebody which VI to use.
Yes, this is why I was hoping for a single-VI solution, but as we discussed it's likely not possible. However, two VIs is way easier to navigate on disk than 52.
It's obvious my solution has holes, but the good news it was just an educational experiment and not something I'll be using in a mission critical application. I'll think on ways to improve it given your feedback of reference leaks and UI thread blocks etc.