Programming In C + Win API: How To Get Windows 7 L

2019-01-08 11:27发布

问题:

I am programming strictly in C and WinAPI, no C++ or C#. I am a beginner and just learning to draw controls etc. The thing is that when I create Windows or other controls like Command Buttons, they have Windows Native look. Take a look at this:

But in Windows 7, the command buttons look like this:

Now, how do I get command buttons in my program to look like that. Is it even possible? I am following this tutorial, for reference: http://zetcode.com/gui/winapi/

Thanks.

回答1:

You enable visual styles for your app by providing an XML manifest, either as a separate file or as an embedded resource. See Enabling Visual Styles for details.



回答2:

That's how the controls looked back in the 1990s, before themes (visual styles) were invented. As you've noticed, modern buttons are now painted all fancy-pants with gradients and throbbing and all that. But for backwards-compatibility reasons, you have to specifically request that your controls get that treatment, or they'll fall back to the legacy style.

You do that by specifying a manifest. You can either add one in plain text format to your application's root directory, or you can have Visual Studio (2005 and later) automatically embed one in your EXE.

The second route is the way I'd go. Add the following code to your stdafx.h file to inform the compiler that you want it to add the manifest automatically upon building your project:

#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif

This MSDN article has more information on visual styles than you could ever want.


And if you really want your application to look native, you need to change the background brush used for the main window. By default, it's set to use the same color as a textbox's background (white).

You want to use the color used to paint 3D controls, instead. Modify the hbrBackground member of your WNDCLASS (or WNDCLASSEX) structure as shown here:

wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

Why do you have to add 1? For backwards-compatibility reasons, again. The details are boring. :-)



回答3:

You probably remember when Windows XP arrived with that fresh new look, and you could revert it back to Windows 95/2000 classic appearance, or you could change the color theme. That was called visual styles, which brought to Windows a better theming support.

Visual styles remained as a feature since then. Windows Vista and 7 introduced Aero, but they still allowed using the classic theme. Windows 8 has removed both Aero and the classic theme, and added the Metro theme. High-contrast themes are now part of visual styles and do not have the classic appearance anymore.

Thus, a classic themed application in Windows 7 when it was expected an Aero style, is an issue with the visual style of the application. I'm not sure why but Microsoft did not leave the old classic theme optional while migrating the API to the new look.

So, how do I apply the modern style?

Either way this MSDN article explains how to enable visual styles for your application. I have seen people saying that enabling Unicode (defining UNICODE) would make it, but it is not required. Basically, you just need to write a manifest file specifying version 6 of the common controls DLL as requirement, then embed it as a resource or place under appname.exe.manifest in the executable's directory. A sample manifest would look like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0" processorArchitecture="*"
        name="CompanyName.ProductName.YourApplication" type="win32"/>
    <description>Your application description here.</description>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0" type="win32" processorArchitecture="*"
                publicKeyToken="6595b64144ccf1df" language="*"/>
        </dependentAssembly>
    </dependency>
</assembly>

If you go for the embed option, don't forget to have winuser.h included in your resource file. You may also want to initialize the common controls DLL in your WinMain, according to this MinGW guide:

I’ve seen this step missed in some examples, and it can cause some odd behaviors under certain operating system versions and certain conditions, such as buttons being invisible, or dialogs failing to be created.

INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);