激战2直伤死灵:XButtonXP
来源:百度文库 编辑:中财网 时间:2024/04/28 08:56:52
Introduction
Looking around for a theme-aware toggle button that could display text and an icon, I could not find one, so XButtonXP is the result: a pushbutton that can also be a toggle button, and can display icon and/or text.What's New in v1.3
In this version I have corrected (I believe) all the outstanding bugs that have been reported (see list), and added several new features:
- Grayscale icons - in previous version, icon on disabled button looked like this:
In this version they look like:
- Transparent background for toolbar style - the parent's background is shown when mouse is not hovering: No hover
Hover - Multi-line text buttons - buttons with multiple lines of text are now supported using standard style
BS_MULTILINE
: - Custom text and background colors - custom colors may now be used for button text and background colors:
XButtonXP in Action
Here is what XButtonXP looks like with themes: Icon on LeftIcon on Right
No Icon
No Text
Toggled
Disabled
And here is what XButtonXP looks like without themes:
Icon on LeftIcon on Right
No Icon
No Text
Toggled
Disabled
XButtonXP can also be drawn using toolbar style:
No HoverHover
CXButtonXP Implementation Notes
Theme Support
Normally, when you add manifest file to exe, all controls used by exe will be displayed as themed. However, this is not true of ownerdraw controls - the XP theming engine just ignores them. Since I needed an ownerdraw button, it meant that XButtonXP had to handle the XP theming support. I created theCXThemeHelper
class to handle loading UXTHEME.DLL and getting theme function pointers via GetProcAddress()
. To make CXThemeHelper
lightweight and easy to reuse, I designed it as singleton class, so that there is only one copy of DLL's module handle and function pointers per process. The first time that CXButtonXP::DrawItem()
is called, the theme is opened for Button
class:
if (ThemeHelper.IsThemeLibAvailable()) { m_hTheme = ThemeHelper.OpenThemeData(m_hWnd, _T("Button")); }
Aside from using theme functions for drawing the controls, one other thing CXButtonXP
must do is handle WM_THEMECHANGED
message, which is broadcast to every window following a theme change event:
case WM_THEMECHANGED:{ if (IsThemed()) { if (m_hTheme) { // when user changes themes, close current theme and re-open ThemeHelper.CloseThemeData(m_hTheme); m_hTheme = NULL; m_bFirstTime = TRUE; } }}
CXThemeHelper API
TheCXThemeHelper
API includes: - BOOL IsAppThemed()
- BOOL IsThemeActive()
- BOOL IsThemeLibAvailable()
- BOOL CloseThemeData(HTHEME hTheme)
- BOOL DrawThemeBackground()
- BOOL DrawThemeParentBackground()
- BOOL DrawThemeText()
- BOOL GetThemeBackgroundContentRect()
- HTHEME OpenThemeData()
Controlling XButtonXP Theming
CXButtonXP
will use themes to draw button in the following circumstances: - The app is running on XP
- Themes are enabled on system, and app has not been set to "Disable visual themes" via Properties dialog:
- Themes have not been disabled via
CXButtonXP::EnableTheming()
function.
CXButtonXP Starting Point
I used Ewan Ward's article Native Win32 Theme aware Owner-draw Controls without MFC as starting point for XButtonXP. First, I adapted his code for MFC, and then usedCXThemeHelper
to enable theme support. The next step was to fix default button problem. Default Button Problem
This problem plagues all ownerdraw buttons. Left uncorrected, it can give the visual appearance that there are multiple default buttons on dialog, and improperly handles ENTER key. Fortunately, Paolo Messina describes this problem in detail, and has written very nice class to transparently fix this problem for any ownerdraw button.Keyboard Input
The final task was to ensure that SPACE and ENTER keys worked properly. On standard pushbutton, these keys produce button-click event. In order for XButtonXP to handle them in same way, I had to intercept WM_GETDLGCODE message, and ask for all keys. At the same time, I did not want to interfere with TAB key processing. The WM_GETDLGCODE message provides mechanism to do this, by returning appropriate code. Then, I added handlers forWM_KEYDOWN
and WM_KEYUP
, to catch ENTER and SPACE key presses. I converted these to WM_LBUTTONDOWN
and WM_LBUTTONUP
messages, to emulate mouse click. CXButtonXP Functions
Here are functions in CXButtonXP
:
How to use
To integrate CXButtonXP
into your app, you first need to add following files to your project:
- XButtonXP.cpp
- XButtonXP.h
- XThemeHelper.cpp
- XThemeHelper.h
- OddButton.cpp
- OddButton.h
- CreateGrayscaleIcon.h
Next, include header file XButtonXP.h in appropriate project files (typically the dialog header file). Now you are ready to start using CXButtonXP
.
The demo app shows how to call XButtonXP:
Collapse | Copy Codem_XButtonXP.SetIcon(IDI_MFC, CXButtonXP::LEFT);
You can combine XButtonXP function calls like this:
Collapse | Copy Codem_XButtonXP.SetIcon(IDI_MFC, CXButtonXP::LEFT) .SetToggle(FALSE) .EnableTheming(TRUE) .SetDrawToolbar(FALSE);
Tips & Tricks
- The button must not have
BS_OWNERDRAW
property in dialog template. - When you include XButtonXP in your app, you might get error message about the symbol
DFCS_HOT
, even though you have installed Platform SDK. To fix this, you need to put this line in stdafx.h, before any includes: Collapse | Copy Code#define WINVER 0x0500
- The compiler error message fatal error C1083: Cannot open include file: 'uxtheme.h': No such file or directory means that compiler cannot find uxtheme.h, which is in Microsoft Platform SDK. This is free download from Microsoft site. I would give url here, but Microsoft keeps changing download page for Platform SDK, so best thing is to google for it.
- When custom colors are used for text or background, theming is automatically switched off.
Acknowledgments
- XButtonXP code is based partially on Ewan Ward's article Native Win32 Theme aware Owner-draw Controls without MFC.
- Thanks to Paolo Messina for his COddButton class.