LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How do Confirm Popups resize?

I've developed dozens of Labwindows applications, selecting foreground/background color schemes to make panels easy to read and work with. Often needing popups, I've used the unbearably ugly CVI popup panels for decisions and notifications. I've created some popups within an app that use the color scheme, but obviously, they are app specific.

So, recently, I created a new ConfirmPopup that is general purpose. You pass it title, message and button label strings. It gathers app main panel color and the button color from the quit button. It creates the popup panel, populates it, colors it and installs it. Pretty cool. I'm going to generalize this for all types of popups, and create a function tree for them.

But... The thing I do not have yet is a way to resize the generated panel based on the length of the message text, the way the ugly CVI popups do.

Is it possible to get that snippet of source code from NI, which does the popup panel resizing? There is no Popup panel source that I can find in my 7.1 installation.

Or, has someone out there done something like this, and can give me some ideas or code?

Thanks... Gary
0 Kudos
Message 1 of 10
(4,942 Views)
Hello Gary,

There is a function and a panel attribute which will be helpful in your application.

SetPanelSize (panelHandle, height, width);
SetPanelAttribute (panelHandle, ATTR_SCALE_CONTENTS_ON_RESIZE, resize);


The function, SetPanelSize will allow you to resize a panel programmatically, based on the length of the string in your case. The ATTR_SCALE_CONTENTS_ON_RESIZE attribute will scale all the items in particular panel when the SetPanelSize function is called. I have attached an example project that demonstrates how this function and attribute can work together.

Scott Y.
NI
0 Kudos
Message 2 of 10
(4,919 Views)
Scott,

I believe that what Gary is trying to do is the exact opposite of what you are proposing.

He wants to resize the panel based on the contents, not resize the contents based on the panel.

Gary,

Unfortunately, I don't see any way to do what you want in the User Interface Library. This is low level stuff and requires a bit of Windows GDI black magic to make it happen. Essentially, you must determine the size of the bounding box for the rendered text message and then resize the panel to accomodate it. To do this, you need to know the font in use, the size the font is to be rendered in and a few other details.

I suppose you could use the height and average character width returned by the GetTextMetrics() SDK function to make a good estimate for the bounding box. You would have to figure out how many lines of text are present in the message and how many characters are in the longest line. You would then multiply the number of lines by the height and the average character width by the characters in the longest line and add an appropriate fudge factor.

Of course, this does not take into account such things as wrapping lines which requires much deeper digging into the GDI API.

It's been years since I last did anything like this so I can't be much more help than pointing you in the right direction.
Martin Fredrickson
Test Engineer

Northrop Grumman
Advanced Systems and Products
San Diego, CA 92128
0 Kudos
Message 3 of 10
(4,916 Views)
There is a function in the CVI UI Library, GetTextDisplaySize, that returns text size info, given a specific text string, and a metafont.

(A metafont is a collection of font properties. One can be created using CreateMetaFont, and then can be used to specify the font that should be used in a given control).

One would still have to deal with line wrapping issues, but for each individual line, it should only be necessary to call GetTextDisplaySize.

Luis
NI
0 Kudos
Message 4 of 10
(4,912 Views)
Hmm, I guess I missed that one while I was looking. Good to know if I ever have a need for it.
Martin Fredrickson
Test Engineer

Northrop Grumman
Advanced Systems and Products
San Diego, CA 92128
0 Kudos
Message 5 of 10
(4,906 Views)
Thanks to everyone who has contributed to these thoughts. As I've spent a little more time on this, it's clear that the only real issue is determining the height of the text message control. Given a fixed width for the created panel, the panel height is a sum of constants plus the variable text message height. So, how to determine that?

Since I'm trying to simulate the low level stuff, some things can most easily be dealt with by fixing them. Select a metafont and point size, which then gives a reletaviely fixed number of characters per line, say 45. The pixel height per line is roughly 14 for a 10 point font, so one can multiply the number of lines by 14. The issue now is determining the number of lines. strlen(message) gives number of characters, divide by 45, and we are almost there. Except that I tend to format popup messages, using \n to make things more readable. So how to count the number of \n occurances.

I was hopeful that I could generate the text message form factor before displaying it, and get the height from it.
PopupMsgCtrl = NewCtrl (panelPopup, CTRL_TEXT_MSG, message, 12, 12);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_TEXT_BOLD, 1);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_TEXT_POINT_SIZE, 10);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_TEXT_BGCOLOR, parentBGColor);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_WIDTH, textMessageWidth);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_SIZE_TO_TEXT, 1);
GetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_HEIGHT, &textMessageHeight);

The above does not work. textMessageWidth=300. Trying to set the ATTR_SIZE_TO_TEXT does not force the text message to change it's height to match the number of 300 pixel lines that can be displayed. The call to GetCtrlAttribute (... ATTR_HEIGHT...) returns a small number. There may be an order in which to do these things, that will result in the correct answer. Stay tuned....
0 Kudos
Message 6 of 10
(4,899 Views)
I would suggest using the functions Luis mentioned above.

The algorithm you would need is pretty straightforward:

1. Call CreateMetaFont with the appropriate font and size specified.
2. Call GetTextDisplay Size with the metafont and string you want to display.
3. Use the value returned to set the height of the panel and the height of the text control.

Seems simple enough to me.
Martin Fredrickson
Test Engineer

Northrop Grumman
Advanced Systems and Products
San Diego, CA 92128
0 Kudos
Message 7 of 10
(4,894 Views)
But, the Text control entry on the GetDisplayTextSize FP says:
Note This function does not support multiline text strings. The function assumes that any special characters embedded in the string, such as tabs and line-feeds, appear as characters, subject to the character set used in the font.

And everything I'm trying to do is multi-line. Not sure this function would be of any help.


Can one of the NI experts explain why
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_SIZE_TO_TEXT, 1);
does absolutely nothing with regard to a text message control? Whether I try to do something passively or actively with this call, it does nothing. By passive, I mean set the text message control before writing a long string to it -- by actively, I mean calling it after I sent the long string to the control.

With message = about 300 chars,

PopupMsgCtrl = NewCtrl (panelPopup, CTRL_TEXT_MSG, "123456789012345678901234567890123456789012345", 12, 12);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_WIDTH, textMessageWidth);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_SIZE_TO_TEXT, 1);
SetCtrlVal (panelPopup, PopupMsgCtrl, message);
GetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_HEIGHT, &textMessageHeight);

textMessageHeight ends up about 41, instead of about 196

In this case,
PopupMsgCtrl = NewCtrl (panelPopup, CTRL_TEXT_MSG, "123456789012345678901234567890123456789012345", 12, 12);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_WIDTH, textMessageWidth);
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_SIZE_TO_TEXT, 1);
SetCtrlVal (panelPopup, PopupMsgCtrl, message);
GetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_HEIGHT, &textMessageHeight);

textMessageHeight ends up about 14, instead of about 196
0 Kudos
Message 8 of 10
(4,883 Views)
A followup on
SetCtrlAttribute (panelPopup, PopupMsgCtrl, ATTR_SIZE_TO_TEXT, 1);

After experimenting with this call, it appears to erase all height and width settings. It puts the contents into a single line, unless it encounters a newline. For each newline it encounters, it wraps the string and increases the height accordingly. What this means is that if you have set the text message control with a long string, say 580 chars, with no newlines, when you make the above call, the text message is resixed to 14 pixels high by many hundreds of pixels wide.

NI, can you fix this? Why can't text message controls wrap and resize similar to text boxes? How about an ATTR_AUTO_RESIZE, or ATTR_AUTO_WRAP attribute? This ATTR_SIZE_TO_TEXT attribute is pretty much useless.
0 Kudos
Message 9 of 10
(4,860 Views)
Gary,

You're correct in your interpretation of ATTR_SIZE_TO_TEXT. It is intended to allow you to clip text to a certain width-height box, which you can do when you set that attribute to 0 (the default is 1, which is why initially you did not see a change in behavior). You can do some quick experiments with a text message control in the UI editor, and by turning on the "text raised" option, you can see the effect of the "size to text" option with different text strings, with or without line feeds (to enter a line feed in the Edit Text Message dialog, press ).

The text message is intended as a very simple control for displaying text, which is why it does not offer attributes such as justification and wrapping. If you need automatic wrapping, I recommend that you use a text box control. From you previous emails, I get the impression that you want to set the control to a fixed width, and then allow the control to vary its height based on the content of the message (which will have not embedded line feeds). If that is the case, I recommend the following code, which should do what you need:

SetCtrlAttribute (panel, textBox, ATTR_CTRL_MODE, VAL_INDICATOR);
SetCtrlAttribute (panel, textBox, ATTR_WIDTH, width);
SetCtrlAttribute (panel, textBox, ATTR_WRAP_MODE, VAL_WORD_WRAP);
SetCtrlVal (panel, textBox, message);
GetCtrlAttribute (panel, textBox, ATTR_TOTAL_LINES, &totalLines);
SetCtrlAttribute (panel, textBox, ATTR_VISIBLE_LINES, totalLines);

Luis
NI
0 Kudos
Message 10 of 10
(4,848 Views)