 |
|
 |
I tried to do it,but always failed.
Could you help me friends? thanks
|
|
|
|
 |
|
 |
I haven't investigated this much to see if it happens on regular dialogs; I have a CDialogBar that has its own share of problems and this may be one of them.
Simply, changing the Color Scheme kills the CColourPickerXP's ability to draw correctly. After I change the Color Scheme to "Olive Green" or "Silver" (something other than the current scheme), the button no longer draws although the text and color box do. To get the button to draw correctly I must restart my app.
The simple fix was to handle the WM_THEMECHANGED message. I added the following to the BEGIN_MESSAGE_MAP block:
ON_MESSAGE (WM_THEMECHANGED, OnThemeChanged)
For code, I snagged the CColourPickerXP::OnNMThemeChanged() block and changed the return value:
= 0x0501.
#ifdef _THEME_H_
m_xpButton.Open(GetSafeHwnd(), L"BUTTON");
m_xpEdit.Open(GetSafeHwnd(), L"EDIT");
m_xpCombo.Open(GetSafeHwnd(), L"COMBOBOX");
#endif
Invalidate(FALSE);
return 0;
}
I haven't seen the OnNMThemeChanged section catching any messages so I'm not certain it has a job to do. Perhaps the WM_THEMECHANGED message is more reliable?
- Stan
Old programmers never die, they just stop responding to interrupts.
|
|
|
|
 |
|
 |
Where can I find Parts and States definitions ? for example TP_BUTTON etc. ?
#ifndef
#define __ARMEN_H__
#endif
|
|
|
|
 |
|
|
 |
|
 |
In my Application I use the BS_ICON Style to display a button with an icon on it. Unfortunately, XP treats this like an Ownerdrawn button and does not automatically apply a theme to it.
What's the best way to get the functionality back (to have a simple button that displays an Icon instead of text.
(I converted the App from Ownerdrawn to BS_ICON with NT 4.0 now do I have to convert back? If yes, should I handle WS_DRAWITEM or WS_NOTIFY ?
I didn't find working examples (Native Win32 API - no MFC) on this.
Erwin
|
|
|
|
 |
|
 |
Sorry but I missed something : what is this article for ? If I want to use XP visual style in my app, I just insert a custom resource (resource type = "24"), past the code bellow in it and set the ID to "1".... what is the difference ? code to insert in custom resource : <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity processorArchitecture="x86" version="5.1.0.0" type="win32" name="YourApp.exe"/> <description>YourApp</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86"/> </dependentAssembly> </dependency> </assembly> or you can edit any "old" EXE in VStudio and insert this custom resource to make them support WinXP style
|
|
|
|
 |
|
 |
The manifest only enable Visual Themes in a Windows application. The objective of the article is to explain how to use the Visual Theme API when creating custom-drawn controls.
If you draw your own controls without Visual Themes, you use the various GDI functions to make the control appear the way you want it to, even if you're only modifying the default appearance. With Visual Themes enabled, you can call a handful of functions to allow Windows to draw the base control for you, and then modify it as you see fit.
For example, when drawing a bitmap button in XP, you can draw the button and the text using the Visual Theme API, and then use the "DrawThemeIcon" function to put the bitmap where you want it. Now that Windows XP supports icons with 32-bit color (8-bits per channel, including an alpha channel for transparancy), implementing custom controls is really quite easy.
--
Paul
"I drank... WHAT?"
|
|
|
|
 |
|
 |
OK thanks, sorry for the miss-understanding.
Due to my lack of knowledge ;o))
|
|
|
|
 |
|
 |
You're welcome! That's why we're all here -- To share the knowledge.
--
Paul
"I drank... WHAT?"
|
|
|
|
 |
|
 |
After incorporating this wonderful wrapper into my project, I found this rather nasty bug that occurred only in release mode on Windows 2000. The app would crash horribly upon startup, just after it made a call to CXPTheme::Open(). After throwing out all my house furniture out through the windows in frustration, I finally figured out what was happening, and the realization left a confused smile on my face.
So what was going on? Since Windows 2000 does not support themes, the GetProc() call to "OpenThemeData" would of course fail, and a pointer to the OpenThemeDataFail() static member would be used. This would be called, and as soon as this call returned, the this pointer came back as garbage. Now there are two possibilities why this was happening:
1. My optimization setting of "Inline Any Suitable" was inlining that function, though the compiler should have detected that its address was being taken and not have inlined it in the first place.
2. The static member OpenThemeDataFail() uses a different calling convention.
Now I haven't figured out completely why, but what I did was add __stdcall to the declaration of OpenThemeDataFail() and everything worked happily! Perhaps the author might have some insight...? Check it out, this is what I did:
Original:
static HTHEME OpenThemeDataFail(HWND , LPCWSTR )
{return NULL;}
Modified:
static HTHEME __stdcall OpenThemeDataFail(HWND , LPCWSTR )
{return NULL;}
Oh, one more thing.... the 3rd constructor of CXPTheme() forgets to set the dll handle member to NULL before calling Open(), which also calls Close(). It should be defined as:
CXPTheme::CXPTheme(HWND hwnd, LPCWSTR pszClassList)
{
m_hTheme = NULL;
Open(hwnd, pszClassList);
}
Cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
Thanks for pointing out these errors. I will update the code as fast as I can.
Adding _stdcall changes the calling convention as you point out yourself. _stdcall is the standard calling convention for COM on Win32 and seeing as the theme API returns HRESULTs, there's probably som COM involved somewhere here. (If this is complete gibberish, just ignore it ).
Anyway, thanks for the input.
|
|
|
|
 |
|
 |
You're very welcome. Yes, I've done atl programming before... How does it being com affect the function pointers getting all garbled up?
Cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
Hi!
It's not really COM as such, I think, but the calling convention COM uses. I'm really on thin ice here , but as I read the documentation it has to do with who's responsible for cleaning the stack. I pulled the following table from the doc's. (_cdecl is supposedly the default calling convention)
_cdecl _stdcall _fastcall
-------------------------------------------------------------------
Arguments Pushed R to L Pushed R to L Note 3
Stack cleaned up by Caller Called Called
Naming convention Prepend "_" Note 1 Note 2<p></p>
Note 1: The _stdcall calling convention decorates each function
name by prepending an underscore character (as the _cdecl
convention does) and appending an at sign "@" and the decimal
representation of the number of bytes of stack space required.
Each argument is widened to a multiple of four bytes.<p></p>
Note 2: The _fastcall calling convention decorates each function
name by prepending an at sign "@" and appending an at sign and
the decimal representation of the number of bytes of stack space
required. Each argument is widened to a multiple of four bytes.<p></p>
Note 3: The first two function arguments that require four or
fewer bytes are placed into registers. The caller pushes the
remainder of the parameters onto the stack from right to left.
This behavior may change in future versions.
Even though I'm not able to explain any details, this tells me that a mismatch between calling conventions can result in serious trouble. I'm not sure if this makes you any wiser.
|
|
|
|
 |
|
 |
Hi Pal,
I'm trying to get theme drawing working using your wrapper. Have you actually gotten this to work? I mean I can get the background of a button to draw properly, but getting the whole thing to draw (as in the text as well) is turning out to be a real pain.
int state = PBS_NORMAL;
if(bSelected)
{
state = PBS_PRESSED;
}
// PBS_DEFAULTED, PBS_HOT
m_Theme->DrawBackground(pDC->GetSafeHdc(), BP_PUSHBUTTON, state,
&rect, NULL);
// Draw text.
{
CBarFolder* FolderTab = (CBarFolder*) arFolder.GetAt(iIdx);
DWORD textFlags = DT_CENTER | DT_END_ELLIPSIS | DT_VCENTER |
DT_SINGLELINE;
cString Name(FolderTab->cName);
//!!!
Name = "Cancel";
//!!!!!
LOGFONT TrampleMe;
LOGFONT FontInfo;
m_Theme->GetSysFont(TMT_SMALLCAPTIONFONT, &FontInfo);
/*m_Theme->GetFont(pDC->GetSafeHdc(), BP_PUSHBUTTON, state, TMT_CAPTIONFONT,
&LogFont);*/
COLORREF FontColour = m_Theme->GetSysColor(TMT_BTNTEXT);
cFont Font(FontInfo);
CGdiObject* OldFont = pDC->SelectObject(&Font);
COLORREF OldTextColour = pDC->SetTextColor(FontColour);
m_Theme->DrawText(pDC->GetSafeHdc(), BP_PUSHBUTTON, state,
Name.GetAsUnicode(), -1, textFlags, 0, &rect);
pDC->SelectObject(OldFont);
pDC->SetTextColor(OldTextColour);
}
}
As you can see, I tried using the GetFont() function, but I couldn't get this to work at all. I got the GetSysFont() function to work, but it tramples whatever is before it on the stack! Why, I don't know! Here the variable TrampleMe gets modified. Yuck And it's not your wrapper that's doing it either, I stepped through the code... It's the theme call.
Now the above snippet of code does work, except for the trampling which has been fixed in a very crude way. But of course the button font is wrong, cause I'm using TMT_SMALLCAPTIONFONT. I haven't been able to figure out which value I'm supposed to be passing here...
This is ugly Any thought?
Thanks!
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
Besides the fact, (as you probably know), that buttons are automatically handle by comctrl32.dll version 6, I must admit that I've only tested the class on "simple" problems. Right now I'm having problems with my XP installation, so I'm not able to test it out further. Sorry
|
|
|
|
 |
|
 |
Ok I have another question. I've been banging my head against the wall for hours because of this one. I have figured out how to draw a minimize button, using the WP_MINBUTTON part id and Theme->DrawBackground(). Now this only draws the button as it should look when the app is in focus, but what about when the app is not in focus? I haven't been able to find any way to do this anywhere in the docs. Any ideas?
Here's my code:
Theme = new cTheme(GetSafeHwnd(), L"WINDOW");
....
int stateId = MINBS_NORMAL;
if(IsPressed())
{
stateId = MINBS_PUSHED;
}
else if(IsHot())
{
stateId = MINBS_HOT;
}
else
{
stateId = MINBS_NORMAL;
}
if(Theme)
{
Theme->DrawBackground(Dc.m_hDC, WP_MINBUTTON, stateId, &ClientRect,
NULL);
}
else
{
// Original painting.
}
Thanks again!
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
Sorry, I don't know. Maybe you should try the forums and see if anybody can help you there? Actually if you get an answer I would really like to know. Then maybe you could post it here.
|
|
|
|
 |
|
 |
Actually, this should work...
Manually specify the stateId instea of using IsPressed() etc. maybe the problem is coming from there.
That's exactly what I used and it works.
|
|
|
|
 |
|
 |
Thanks for the quick responses, and of course the AWESOME article. I've gotten it all to work. However, I'm wondering if there is any way to say, enable all controls on a dialog to use themes automatically --- or do we have to do it the hard way, and draw each and every control (or subclass them all)? It seems ridiculous to think that you would have to do this, but I see no other way...
Please help!
Thanks,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
|
 |
|
 |
Great article! Though I'm a little confused... Does this code work on all versions of windows or not? You state the following in your article:
> To make your application working under all windows versions, you should do > something like this:
>
>
> #ifdef _XPTHEME_H_
> if (CXPTheme::IsAppThemed())
> {
> CXPTheme theme(GetSafeHwnd(), L"TOOLBAR");
> theme.DrawBackground(pDC->GetSafeHdc(), TP_BUTTON, TS_CHECKED, &rc, 0);
> }else
> {
> #endif
> pDC->DrawEdge(....);
> #ifdef _XPTHEME_H_
> }
> #endif
So if I compile this code with the _XPTHEME_H_ header included, will it run on Windows 98 for example? (Sorry if the answer is obvious).
Cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
This is the intention! I have not tried it on Windows 98, but there is no reason why it shouldn't. To test it out though, the same code should be run on both 98 and XP. I mean, there is no visual clue showing the code is working by just running it on win98.
The test would be successful if visual styles appeared on XP, while the application avoided a crash on win98 (but still looked like a win98 app).
|
|
|
|
 |
|
 |
Yes of course . But why the need for the #ifdef ?
Anyways, I will test it on Windows98 to see what happens.
Cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
 |
|
 |
No need really other than to turn off using theming completly through a compiler switch. You can very well do without them.
|
|
|
|
 |
|
 |
Does this article talk about making controls look like XP style under all Windows platforms other than Windows XP? If it does, I am interested in your posting a demo project.
Are you going to add a demo project for download?
Thanks
|
|
|
|
 |