01-24-2010 10:14 AM
Hello,
I have a requirement for an application that the window is non activatable. What that means is that when you click on the window it doesn't steal focus away from the last window you had active. This normally wouldn't be much of a problem. I use the Window API function SetWindowLongA in User32.dll and pass in WS_EX_NOACTIVATE and any other styles I wish to set at the same time. First, I tested this within a C# .NET form and all worked fine. I then ported the same function calls across to LabVIEW (Please see attached). For some reason, even though the following window styles are being applied (if you have Spy++ or WinID you can see this for yourself):
WS_VISIBLE
WS_CLIPSIBLINGS
WS_CLIPCHILDREN
WS_BORDER
WS_DLGFRAME
WS_SYSMENU
WS_THICKFRAME
WS_MINIMIZEBOX
WS_MAXIMIZEBOX
WS_CAPTION
WS_OVERLAPPEDWINDOW
WS_EX_WINDOWEDGE
WS_EX_NOACTIVATE
The WS_EX_NOACTIVATE style is not behaving as it should when applied to a LVDCHILD (VI window).
My attached VI applies the same styles to a LV generated .NET form. This behaves exactly as intended.
Clearly the code is correct, I must just be missing something due to the way LabVIEW creates its windows?
Please if anyone could advise on how to achieve the desired non activatable window in LabVIEW it would be greatly appreciated.
Steve.
Solved! Go to Solution.
01-26-2010 06:21 AM
Hi Steve,
Would it be acceptable to have it switch over and then quickly return focus? If so, the Bring to Front Invoke Node solves this problem (please see attached VI). If not, what's the C# code you are using that does this feature?
Regards,
Imtiaz Chowdhury
Project Manager
Green Running / Austin Consultants
01-26-2010 08:24 AM
alpha1 wrote:what's the C# code you are using that does this feature?
The classic example is a virtual keyboard. Windows has a virtual keyboard that works like this (see Programs>>Accessories>>Accessibility), but the problem with it is that the keys are small and very unsuitable for some apps (touch screen apps, for instance).
The key is that the window has to accept clicks without stealing the focus - when you click, the cursor has to stay where it is. I've played with this on and off over the years, but I'm by far not a Windows API expert, so I didn't find any satisfactory solution. I did manage to do something that worked by attaching the input of one thread to another and setting the focus back to the active window whenever my window got focus, but it wasn't elegant and I'm pretty sure it didn't work on LV window - when the LV window lost focus, LV forgot which control had focus before.
01-26-2010 08:45 AM
alpha1: unfortunately not. Please find attached a demo visual studio 2008 c# project. This is effectively identical to the .net code in my previously attached vi.
tst: my end application here indeed is for a touchscreen and will take user input to control other applications (including sending keys like a keyboard). the code posted by tbd here: http://forums.ni.com/ni/board/message?board.id=170&message.id=361464&requireLogin=False
along with any available solution to my problem here should give you all the tools you need to produce a virtual keyboard. I may even post a demo once I work out how to solve this window issue!
Thanks,
Steve
01-27-2010 12:13 PM
01-27-2010 12:30 PM
tst: Please find attached a c# demonstration project with the buttons a,b and c. if you run the .exe in bin\debug. Place the window side by side an instance of notepad. You will see the window style works correctly allowing notepad to be the focus window despite clicking buttons on my demo application.
Documentation about setWindowLong can be found here: http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx
But that function is generic for applying any window style. The particular style is WS_EX_NOACTIVATE
/// Windows 2000/XP: A top-level window created with this style does not become the foreground window when the user clicks it. The system does not bring this window to the foreground when the user minimizes or closes the foreground window.
/// To activate the window, use the SetActiveWindow or SetForegroundWindow function.
/// The window does not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style.
/// </summary>
WS_EX_NOACTIVATE = 0x08000000,
^^ from http://www.pinvoke.net/default.aspx/Enums/WindowStylesEx.html
I'm still unsure as to why what works in a LabVIEW generated .NET window (as per my first attachment) fails to work on a LabVIEW front panel window. Anybody able to offer an explanation?
Steve
01-27-2010 01:53 PM
If you follow the window styles link from the function documentation, you will get this:
The following styles can be specified wherever a window style is required. After the control has been created, these styles cannot be modified, except as noted
Note both my emphasis and the fact that WS_EX_NOACTIVATE is NOT on that list. I don't know if that means it can't be applied (you say it works on the C# window), but it would seem to support my recollection I mentioned earlier that you can only do this when the window is created.
As for why it would work on the .NET form, if I had to venture a guess, I would guess it was because all the windows in the LabVIEW process are connected (clicking any of them brings all of them to the front, which may even prevent this feature from working at all), but the .NET window is created out of process, but that's just a baseless guess.
01-28-2010 02:47 AM
I've just modified my original vi to accept a string control for the FindWindow function. This allows me to target a specific window to apply the style too. I tried this out on the following
"Untitled - Notepad"
"Inbox - Microsoft Outlook"
"Google - Windows Internet Explorer"
All of these applied the new style and worked as expected despite already being open.
I then tried targeting "1.vi", as expected this window did not apply the expected behaviour even though WinID and Spy++ report that the window had applied the style.
I built 1.vi into an executable and retried, again the same behaviour as the vi.
I think we're thinking along the same lines with the LV process (although this doesn't explain why the labview built exe doesnt work?). I previously tried modifying my vi to execute in the UI thread to no avail. I just tried aain with 1.vi source and .exe and nothing.
Still very unclear as to why this seems to work on everything except LabVIEW vi's/.exe's. I will continue my investigations trying this out over the weekend on as many windows built in different languages as I can think of.
Thanks for your continued interest!
Steve
01-28-2010 02:54 AM
Ok I couldn't wait.
I tried applying the style to the LabVIEW "getting started" main screen. - I believe this is made in LabVIEW (its ships as an example..). Again the window did not behave correctly.
I tried applying the style to Teststand 3.1 - I would not expect this to be made in LabVIEW. The window behaved correctly.
I then tried applying it to Measurement and Automation explorer (I believe if not the entire thing, some elements of this are made in LabVIEW - it crashed once and I saw a mess of boolean indicators and error clusters off screen). The window behaved correctly.
01-28-2010 09:21 AM
I'm pretty sure that the one-window-brings-all-to-the-front rule applies in LV EXEs too. I'm assuming this is some standard behavior which is applied to the process, but it's also possible NI wrote a specific hook to make it act that way. Remembers that the LV IDE runs on Mac and Linux as well, so it does some of the management on its own (for instance, if you look inside the window, you'll see it's not build using Windows controls. everything inside is managed by LV) and has some behaviors which may seem odd.
IF this is standard behavior, than I'm assuming there is some way to build an LV EXE and then neutralize that behavior, but you would have to dig a bit with the various spying tools to see which messages are passed around, etc., to see if you can find out how this works.
As for MAX, I'm pretty sure the MAX UI is NOT written in LV. It's possible that some of the plugins it uses are written in LV, though.
Incidentally, one thing you might consider is NOT writing the keyboard in LV. I like LV a lot, and I certainly wouldn't mind being able to build such a keyboard, but if I had to and couldn't get LV to do it, I would probably just build it in another langauge.