Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

Windowless controls problem...

Hello

I'm using Measurement Studio (8.1.11.337) in a Visual Studio 2003 (Standard Edition). Program itself is written in C++, and uses MFC. We have used (for years) UI controls without problems in Windowed mode. Recently, we decided that switching to windowless mode will allow for both better performance (we have configurations consisting of thousands of controls) and appearance (transparency and non-rectangular shapes).

At the very beginning, NI::CNiKnob::SetWindowless( true ) did nothing for us. We create all controls dynamically, like this:

class AWindowClass : public CWnd {
// some stuff
    NI::CNiKnob knob;
}

AWindowClass::OnCreate( LPCREATESTRUCT )
{
    gauge.Create( "", WS_VISIBLE, CRect( CPoint( 0, 0 ),
            CSize( configuration->getWindow( )->getWidth( ), configuration->getWindow( )->getHeight( ) ) ),
            this, 0, 0, FALSE, lic
    );
    gauge.SetWindowless( true );   // nothing happens, still windowed
}

Of course, lic is valid license string, configuration holds configuration, etc. Control starts in windowed mode, and insight into MFC sources shows clearly, that it has no intent to go windowless...Then, after some experiments with ActiveX Control Test Container (provided by Microsoft with Visual Studio), I found out that Windowless property needs to be set on control's startup, and then it works fine. Well...I guess that I have to live with that, so I did as follows:
1) For first NI::CNiKnob ever created, I create it in special window _and_ in windowed mode
2) Then, I set it's Windowless property to true, and
3) Serialized whole thing using it's IPersistentStreamInit COM interface to COleStreamFile initialized by CreateMemoryStream function call. I think this is better way than using static files on disk (say that I upgrade libraries and file format changes?)
4) Destroyed (by means of DestroyWindow) NI::CNiKnob just serialized
5) And finally, created apropriate, final control by following call
knob.CreateControl( "{4D79497E-BCBB-4477-9E5C-CBD7284EE8AC}", "WindowlessKnob", WS_VISIBLE,
            rect, parent, 1, & knobProperties, FALSE, license );
(knobProperties being CFile just created, of course after flushing and resetting its read pointer)

This time behavior is different. Breakpoints set in MFC show clearly that there is windowless activation in progress. But, alas, before I can see and enjoy my new windowless control on screen, I get assertion failure. Namely, CWnd::SubclassDlgItem(UINT nID, CWnd* pParent), defined in wincore.cpp (from line 4912 on) fires following assert on line 4929:
ASSERT(pSite->m_hWnd != NULL);
Quick check in MFC documentation, and it seems that m_hWnd _should_ be NULL for Windowless controls (it says "NULL if the control is windowless"). So control's CreateControl code should not call SubclassDlgItem at all.

So the question is: how to get this to work? Am I doing something wrong?

Any help appreciated.
Michal

0 Kudos
Message 1 of 12
(11,491 Views)

From the readme file:

In Visual C++, the Measurement Studio 8.1.1 implementation of windowless controls is not compatible with the MFC ActiveX control container. Measurement Studio controls do not paint correctly when you set the Windowless property to true. You can work around this issue using a helper class to implement the appropriate dialog, SDI, or MDI function. For more information, refer to National Instruments KnowledgeBase Article 2ZFF2AXL.

Please try the workaround and let us know if you have any problems.

David Rohacek
National Instruments

0 Kudos
Message 2 of 12
(11,467 Views)
I'm aware of the issue. But my problem is different. It's not that I have paint problems for windowless control. I have trouble creating one! As described above, I get assertion failures inside of NI::CNiKnob::CreateControl call. So, my questions are rather as follows:
1) Am I right that one can only _create_ windowless control by giving it persistent properties already set to Windowless? Or perhaps there's way to switch already created control to windowless mode?
2) If my way is correct, then, how does one prevents control from trying to subclass not existing window, which (AFAIK) _must_ cause assertion failures.
3) Or maybe someone has working code snippet for dynamic creation of windowless controls from MFC C++ code?

Any help will be appreciated
Michal
0 Kudos
Message 3 of 12
(11,463 Views)
Michal,

The assertion failure could be happening because you're trying to change the property of the control to Windowless.  As David mentioned, it is not possible to make a windowless control using C++ MFC; in the edit-time environment, we even coerce the "Windowless" property to be false (even when a user attempts to change that property to true) so I imagine that errors are to be expected if you try and change this property programmatically.

Do you still get the assertion failure when you eliminate the portion of code that attempts to change this property? 
Derrick S.
Product Manager
NI DIAdem
National Instruments
0 Kudos
Message 4 of 12
(11,433 Views)
Dear Derrick

"The assertion failure could be happening because you're trying to change the property of the control to Windowless"

Hmm, I doubt that. First, it does not occur when I call SetWindowless. Second, I did simple test: modified program, so that it serializes control properties with Windowless set to true (to file on disk) and then exits. On the second run, control is created from serialized persistent state, i.e. without using SetWindowless at all. Yet I get same assertion failure...

"
As David mentioned, it is not possible to make a windowless control using C++ MFC"

Did I missed something? Yeah, English is not my primary language, that's the problem...:-(. Yet, I cannot find _where_ exactly did David mention, that "it is not possible to make windowless controle using C++ MFC". I actually see (quite the opposite), that he mentions knowledge base article which states (indirectly) that it can be done - simply because it describes workaround for controls not painting correctly. And you have to succesfully create control in order to expect it to paint at all. So KB Article convinces me that one can create windowless control in C++ MFC...or perhaps we assign different meaning to terms "paint" and "create"? But they're fairly standard...

Moreover, this thread suggests that it is possible to use windowless NI controls, provided one have (and I do have it) version 7 of MFC libraries.

"
imagine that errors are to be expected if you try and change this property programmatically.
Do you still get the assertion failure when you eliminate the portion of code that attempts to change this property? "

Alas :-(. Well, I guess I can make my way around this, provided I'll get working example of using windowless NI control in MFC. Can you provide such example? I'll be very grateful.
Perhaps I forgot to set some additional property (apart from Windowless) which, when set, prevents NI control from trying to subclass not-existing window, and thereby assertion failure?

Best regards
Michal

0 Kudos
Message 5 of 12
(11,423 Views)
Hi Michal,

I talked with David and Derrick and we believe that we might have goofed up on our readme at some point. We are not sure if this is out of date or what, but we are going to investigate the issue and I will then confirm what the expected behavior of our controls are to regards to windowless activation.

Have a great holiday!

Best Regards,
Jonathan N.
National Instruments
0 Kudos
Message 6 of 12
(11,415 Views)
Hi Jonathan

Thanks for your time. I'm really looking forward to solving this issue. I hope I can work my problems out, provided that I get _any_ working example of dynamically created windowless NI controls in MFC. Or official confirmation that it's not going to work, for that matter, but I really hope this is not the case.

Best regards
Michal
0 Kudos
Message 7 of 12
(11,311 Views)
Hey Michal,

We're still looking into the issue and either Jonathan, David or I will provide you with an update as soon as we have one.  Until then, we really appreciate your continued patience!
Derrick S.
Product Manager
NI DIAdem
National Instruments
0 Kudos
Message 8 of 12
(11,291 Views)

Hi Michal,

Thanks for your patience as I've finally figured out after digging through old and new source code what our official stance is on supporting windowless activation. 

Alright so as far a windowless activation goes, in Measurement Studio 7.0 we were able to set that property to true.  However, when we did, the control did not paint correctly
as a result of us not determining if the control site supported windowless activation So we fixed that problem in Measurement Studio 8.0 by coercing the Windowless property to false if the dialog did not support windowless activation

So your next question might be, how does Windowless activation take place and how can you be sure that we are doing the right checking? Well the way that windowless activation takes place is that the windowless control queries the client site for the
IOleInPlaceSiteWindowless interface.  If this interface is supported and CanWindowlessActivate returns S_OK, the control activates itself as windowless, otherwise the control creates a window. 

Microsoft provides methods of querying interfaces and control sites to determine if they support windowless or not.  You can do this on your end if you want to double-check our thoughts as here is the basic code we use to determine this.  So basically you need to call the GetClientSite() method to retrieve a pointer to the control's current client site in its container.  If that pointer was called pClientSite, you could then say:

IOleInPlaceSiteWindowless *pI=NULL;
if((pClientSite && SUCCEEDED(pClientSite->QueryInterface(&pI)) &&  pI->CanWindowlessActivate() == S_OK))
    windowlessSupport =  TRUE;
else
    windowlessSupport = FALSE;

Visual Basic 6.0 and other NI IDEs support the above interface and hence the controls can be made windowless.

Now the MFC dialog does NOT support this (i.e. as the query
CanWindowlessActivate fails for this) and hence the controls are not being able to be made windowless.  We tested both Measurement Studio ActiveX controls as well as custom ActiveX controls that we created in the MFC Dialog, and both were rendered windowed as the above query was failing. So the only way of getting controls to be windowless is by implementing a custom client site that supports windowless controls. If you are curious, the following article could be of some help which is called MFCClientSite

Now, the thread you mentioned talks about the MFC 7.0 container which shipped with Visual Studio .NET 2002. 
At the time of the release of Visual Studio .NET 2002, Microsoft stated that support for Windowless controls was added to MFC. That means that it should be present for later versions also. Also, MFC supports creation of windowless ActiveX controls using the ActiveX wizards so they must b supporting windowless activation for their containers (but how? who knows).  But what I can say is that the VC++ dialog does not defaultly support Windowless controls.  A custom site implementation must be provided for a container to support Windowless controls. 

So all in all, if you are using the default VC++ dialog, then our controls don't support Windowless.  So your best bet is to not mess with that Windowless property unless you are implementing your own custom control site. 

Best Regards and I hope this clears things up,

Jonathan N.
National Instruments
0 Kudos
Message 9 of 12
(11,068 Views)
Hi Jonathan

Thanks for providing the answer and sorry for the delay - notification email somehow got chewed by anti-spam filter, and it is by accident that I've noticed it. To sum things up,  just to make sure I got that well:
 - NI controls _do_ support windowless activation, but...
 - ...Microsoft is incorrect in their claim that MFC version in question supports windowless activation. Because it does not.
In fact, I can get a proof of windowless activation via ActiveX control test container. If I create control here, set windowless to true, store control to a disk file, re-run control container and then load file - I get fully windowless control.
Moreover, I have suspected that it is MFC which screws things up. I even managed to find example code that contains support for windowless activation on MFC. So that my container _does seem_ to support windowless activation, and when I put breakpoints here and there, I see that this is indeed windowless activation in progress. But, as I described before, something gets wrong along the process and assertion failures kill me. I guess that this custom code which supports windowless activation for MFC has to be expanded/corrected. I'll look after this, try to fix that personally, because windowless activation is really important for our product.

What would help me, thought, is having _any_ working example of windowless activation in MFC, modified or not. You don't happen to have such code around, have you? (Rhetoric question, I know, but I had to ask 😉 ).

Thanks for the help so far, I really appreciate this. Being developer myself, I know that you have plenty other things to do, and that looking after particular (quite rare, it seems) case in particular environment can be really tough and boring job at the same time.

Best regards
Michal
0 Kudos
Message 10 of 12
(10,792 Views)