How to measure static size beforehand? WINAPI - winapi

I am creating a widow with static text, and because of the all 96/120/180 DPI stuff, I need to create a layouting mini-engine.
The dialog is created in code, statics are created in code, fonts are created in code, everything, mostly because resources in .rc have their share of DPI related problems as well and I want a total control.
The problem with all this is that I don't know how to find the length of the text in statics. I need to calculate the initial size of the static control, and also, I need to calculate a padding between different statics in font unit sizes, but since I don't know the size of the previous static, I can't offset the next one.
The biggest problem is that static does the word wrapping, therefore I can't find a text measuring function that would calculate that and a correction for a custom font, italic, bold, oversize...
Anyone have any ideas?

The static control styles (ENDELLIPSIS,PATHELLIPSIS and LEFTNOWORDWRAP) seem to map to the DrawText flags, so calling DrawText with DT_WORDBREAK|DT_CALCRECT will probably be as close as you can get...

I can't think of any compelling reason to do this any differently then the way all other GUI class libraries do it. Just scale window sizes between the 'design' DPI setting and the target machine DPI setting. Using DPI-independent constants is pretty painful in MFC since everything is pixel based. So keep your workstation at the common 96 DPI setting, scale from there on the target machine. You do have to keep a bit of slack because of TrueType hinting.

Related

Matlab GUI Compatibility Between Mac and Windows (Display)

For some time now, I've been working on a series of GUIs. I use a Mac running OSX to write all of my code, and the problem I've encountered is that it there are deviations in appearance when the GUIs are used in windows, some of which are minor, and some of which are very significant.
1) The text in the windows version is substantially larger overall. This results in some of my button titles simply going off the button, or panel titles moving beyond the panel.
2) Axes appear to be different dimensions between Mac and Windows. i.e. An axis that appears square on my Mac will appear elongated or rectangular on windows, and vice versa.
3) Graphical displays are different. This is the real problem. Some of my GUIs use axes to display text and model chemical reaction animations. On the Mac, they look perfectly fine, but on the windows system, the sizing is completely off.
I've set all "Units" to "characters" as suggested by the Mathworks help page, and I do not specify any fonts to allow each system to use its default. I have however, specified font sizes, but apparently, 12 point font on windows appears very different from 12 point font on mac.
Are there any ways around these problems? I thought setting a specified font size and allowing for use of default fonts would fix this, but it hasn't, and I'm a little dry for ideas at this point.
Try working in 'pixels' or absolute size units instead of 'characters', and apply a scaling factor to your font sizes.
Setting 'Units' to 'characters' is probably the wrong way to go for portability, and could be the main cause of your display sizing issues. Which specific Matlab page recommended that you do so? Was it talking about cross-platform portability? The characters unit is very convenient to work with, but it is tied to the font metrics for the default system font. (See the doco for Units property at http://www.mathworks.com/help/matlab/ref/axes_props.html). That's going to differ between different operating systems. Working with 'pixels' or inches/centimeters/points, which are absolute, will probably give you more uniform results across operating systems.
And you're not wrong: OS X tends to display fonts of a given size on screen smaller than Windows does. (Generally; YMMV depending on your display DPI and system settings and other things.) For example, I run my terminals and text editors at 10 or 12 points in Windows, but 14 point or larger on Mac. So apply a scaling factor to the font sizes you set in your GUI. Figure out what looks good on Mac, and then scale it in your code to something like windows_font_size = floor(mac_font_size * 0.8) and see how it goes.
If you want to be more precise in scaling, you could grab the ScreenPixelsPerInch and ScreenSize root properties with get(0,...). You may also be able to call down in to Java code to get precise font metrics info to help with font scaling choices.
Either way, you're going to have to test your code on both systems instead of just expecting it to work portably. If you don't have ready access to a Windows development system, consider setting up a Windows VM on your Mac. With file sharing between the two sides, you'll be able to try your code out on both platforms right as you work with it.
I encountered this problem as well.
Calling this function within the FUNCTIONNAME_OpeningFcn might alleviate your issues:
function decreaseFontSizesIfReq(handles)
% make all fonts smaller on a non-mac-osx computer
persistent fontSizeDecreased
fontSizeDecreased = [];
if ~ismac()
% No MAC OSX detected; decrease font sizes
if isempty(fontSizeDecreased)
for afield = fieldnames(handles)'
afield = afield{1}; %#ok<FXSET>
try %#ok<TRYNC>
set(handles.(afield),'FontSize',get(handles.(afield),'FontSize')*0.75); % decrease font size
end
end
fontSizeDecreased=1; % do not perform this step again.
end
end

Scaling UI with DPI change of non MFC application

My application is a plug-in developed in VC++ (win32). The solutions I could find didn't work for me.
I have two options :
To disable DPI changes for my DLL plugin. That means my plug-in will not be affected with DPI changes.
To scale all the controls according to the DPI change.
Please help.
Thanks.
1. Disable DPI affect on my application UI when some one re-configures the DPI. Help required : If possible, how to do that pro-grammatically.
This is not possible. Adrian already told you that. DPI is a user setting, not an application setting. If the user wants to change their DPI, they can do so. They can also apply backwards-compatibility hacks that turn off high DPI for a particular application, but that functionality is not available to applications. As the developer, you're expected to make sure that you support high DPI environments, not disable it.
The only thing you can do as an app developer is to fail to indicate that your application is DPI-aware. This is roughly equivalent to walking around with an "IDIOT" sign taped to your forehead. You might find that people are slightly more accommodating of your shortcomings, but they won't have much respect for you and probably won't care to hang out with you very often. Windows will do much the same thing: it will hide the truth from you about the user's actual DPI settings (you can't handle the truth) and instead it will scale up your interface automatically to match. The effect is an ugly one.
Of course, you also say that you're creating a plug-in DLL, which changes things. DLLs can't alter the DPI-awareness of the entire process because that is determined by the host application. If the host application indicates that it is high DPI aware, then your DLL must also be high DPI aware. This is an all or nothing setting, just like the "IDIOT" sign.
2. Scale the UI of my application according to the DPI change. Help required : How to determine the current DPI and how to scale the UI accordingly? Is it necessary to scale every component or any other way to scale them automatically.
In order to correctly determine the current DPI settings, you need to indicate to Windows that you're not an idiot your application is high DPI aware. As discussed above, if you do not do this, Windows will assume that you cannot handle the truth and lie to you. But as we also established above, this probably does not apply to you because you're creating a DLL that runs in the context of another process that is already establishing itself as high DPI aware.
So, what you need to do is determine the DPI scale factor. You need that to scale your user interface elements accordingly when running in high DPI environments. The baseline DPI setting is taken to be 96. The following code scales a SIZE structure (that defines a width and height) relative to that baseline:
void ScaleDpi(SIZE& size)
{
// Determine the current screen DPI.
const HDC hDC = GetDC(NULL);
const int dpiX = GetDeviceCaps(hDC, LOGPIXELSX);
const int dpiY = GetDeviceCaps(hDC, LOGPIXELSY);
ReleaseDC(NULL, hDC);
// Perform the scaling.
size.cx = MulDiv(size.cx, dpiX, 96);
size.cy = MulDiv(size.cy, dpiY, 96);
}
However, if you follow good design practices, you may not need to scale every control manually. When defining windows and dialogs in a resource file (e.g., using the Visual Studio Dialog Editor), you specify the layout in logical units (known as DLUs, or dialog units). These units are independent of any particular DPI setting and are therefore preferable to using something like pixels. A simple dialog with a few controls therefore requires no special scaling effort. You'll only need to perform manual scaling if you're creating and/or laying out controls at run-time.
You'll find more tips and techniques on how to write high DPI aware applications on MSDN, in the Writing High-DPI Win32 Applications article. And I don't link this just to say RTFM—it's actually extremely helpful, and I highly recommend reading it all.
The folks who make the RealWorld Icon and Cursor editors also maintain a helpful article on their site: DPI-aware applications in Windows Vista and Windows 7.

What is the correct way to autosize a Static control?

I want to adjust a Static control's size to its content size, so I need to calculate the size of its text content first. I found a way to use GetTextExtentPoint32 to calculate the size, but I need to set the DC's font to the same as the control's font first. Is there a better way to do this? I've set the Static control's font once, I think maybe I don't need to set the DC's font the second time.
What is the best way to calculate the size of a Static control's text content? And is there a better way to autosize the Static control?
It sounds to me like you've already figured out the correct way to do it. Call GetTextExtentPoint32 to figure out the ideal size of the control given the text that it contains, and then resizing the control to the calculated size.
It's a lot of work, but that's what happens when you're working with the raw Win32 API. You don't have a handy wrapper library that abstracts all this for you in a Control.AutoSize() function. You could easily write your own function and re-use it, but the Win32 standard controls do not expose an "auto-size" API.
As far as the font, you will definitely need to make sure that the device context is using the same font as the control, otherwise you'll calculate the wrong size. But you don't have to create a new device context, request a handle the static control's font, and select that into your new DC. Instead, you can just use the static control's DC using the GetDC function and passing in the handle to your static control window. Make sure that if you call GetDC, you always follow up with a call to ReleaseDC when you're finished!
However, do note some caveats of the GetTextExtentPoint32 function that may interfere with the accuracy of the size you calculate:
It ignores clipping.
It does not take into account new lines (\n) or carriage returns (\r\n) when computing the height.
It does not take into account prefix characters (those preceded in the string with ampersand) and used to denote keyboard mnemonics if your static control does not have the SS_NOPREFIX style.
It may not return an accurate result in light of the kerning that may be implemented automatically by some devices.
(This is all mentioned in the linked documentation, but does anyone actually read that?)
Perhaps an easier alternative is to draw the text the same way that the static control is already doing. Unless you have the SS_SIMPLE style set (which uses TextOut or ExtTextOut to draw text as an optimization), static controls draw their text by calling the DrawText function with the appropriate parameters, given the other control styles that are set (reference).
You can do exactly the same thing, and add the DT_CALCRECT flag in your call to the DrawText function, which causes it to determine the width and height of the rectangle required to draw the specified text without actually drawing the text.
Most windows using static text controls are dialogs, where the static control's size is expressed in dialog units (DLU), which account roughly for the size of the font. In this way, dialog controls tend to have sensible sizes.
If you are not using dialogs, you can attempt to fake dialog behavior using MapDialogRect.
Otherwise yes you must use GetTextExtentPoint32.
There is no autosize for static control as far as I know. You are doing it correct.
Use GetWinDowText to get the text of static window
Use GetDC to get the dc for the window
Use WM_GETFONT to get the font for the window and select the font into the dc
Use one of the text size calculation function to calculate the text size
Restore the the original dc font
Release dc
You will always have to select the proper font into the dc to get accurate result. Also I personally prefer DrawText with DT_CALCRECT to calculate the size of a text. Refer http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498%28v=vs.85%29.aspx
With DrawText, you dont have to supply the character count if the text is NULL terminated. Plus you can combine various formatting option to adjust the calculation. For example, an Ampersand(&) character in a static control text underlines the next character. With Drawtext you will be able to calculate the size properly but in GetTextExtentPoint32 there is no provision to specify this.

WP7 XNA: How to change size or style of SpriteFont fonts dynamically in code?

There seems no way to change font size or style in code, right?? It seems the only way is to duplicate the font files and load them all when program starts??
Thanks
SpriteFonts convert a font, with style, size, and other parameters, to a pixel-based format for use as a texture within XNA. Those pixels are static, so yes, there is no way to change them, short of looping through per pixel.
However there is scaling (though it won't look so great scaling larger) to help with size adjustments needed, plus you could, like you said, create multiple SpriteFont files from the same base font for different styles, and dynamically choose one of those sprite font "textures" within your code.
Beyond that, for true fully dynamic runtime usage, you'd need to essentially create these sprite font textures on the fly, in memory. This means you'd have to do what the SpriteFont Content Pipeline project does but at runtime instead. This is possible in WinForms, but as far as I know not really an option for WP7 as you apparently are using.

How can I resize my vb6 program so that it automatically fits in any screen resolution?

How can I have a vb6 program which opens correctly in 1280*1024 but when switched to other resolutions say 640*480 i can only see half of the screen. how to re-size my vb6 program so that it automatically fits in any screen resolution?
You need to use the Screen object, this will always give you the current resolution in pixels:
Dim screenwidth,screenheight As Single
screenwidth = Screen.Width \ Screen.TwipsPerPixelX
screenheight = Screen.Height \ Screen.TwipsPerPixelY
Usually a Form amenable to resizing has controls that lend themselves to a "flow" layout. Often this is something like a TextBox, grid control, etc. that supports scrollbars. You shrink/grow such controls as required after allocating positions for (i.e. moving) the fixed-size elements like buttons and such.
For a busy Form with lots of fixed size controls that isn't "document oriented" there is no set answer. Sometimes creating a scrollable Form makes sense but usually it doesn't.
Some people try to resize "fixed" elements, change fonts sizes, etc. This can produce results of mixed quality though, sometimes good and sometimes not.
Considerations about the Form size are best made up front as part of the design process. For some applications it might be better to decide on a minimum supported Form size. In other cases you may have to break things up with dialog Forms or tab controls.
There's no easy way to do this in VB6, like there is in .Net. You have to manually resize everything in the form's Resized event handler based on the new form's client size. It's a pain, and a huge mess, but it's the only way to do it.
Correction: There's never only one way to do things, but I've been programming VB6 for several years, and usually just writing it into the Resize handler is straightforward enough, and I haven't found any good way to do it other than that.
Have you tried any 3rd party tools for doing this? Here's (a free) one that seems to work :-
ActiveResize Control Lite - I created a quick project to try it and it does what it says on the tin!
The lite version has some limitions such as number of forms in project, number of controls on form etc. You can also buy a Standard or Professional version if you need more functionality.
I know we've spent countless hours trying to implement our own resizing code only to remove it all and fix the location of most controls, move a few to make it look better and limit the min/max functionality of the form - none of which give a nice user experience. If we needed to do it again I probably use this control (or a similar one) just for the time savings.
I use ComponentOne SizerOne
The C1Elastic control allow from resizing and maintain the aspect ratio, resizing the inside controls on the setting you defined.
It's not free, but it payed itself with all the time I saved.
Form1.Height = Screen.Height
Form1.Width = Screen.Width
This code sets form size according to screen resolution.
"ActiveResize Control Lite" ActiveX tool is limited to 20 controls per form.
Once we know the screen resolution, there are a number of things you can do.
• The easiest solution would be do design different form to accommodate the four most popular monitor resolutions – 640 x 480, 800 x 600, 1024 x 768, and 1600 x 1200.
• Alternatively, we could write code that dynamically resizes and relocates every control on the form, based on the screen resolution – not an easy undertaking!
• Third party controls that resize the controls based on the screen resolution are quite effective. On the whole, though, it's better to just avoid this kind of problem, if you can. For example, see Creating Flexible Forms in Visual Basic (Flexi-Forms) at codeguru.com
To auto fit screen resolution you need to download an active x, drag it on your conform.
Search for "veg gold vb6.0 screen Resize".

Resources