XP Style
-
kann mir denn wirklich keiner helfen?
hier noch ein wenig mehr Code. Vieleicht hilft das ja:
CRect rect; GetClientRect( &rect ); m_myb.Create(_T(""), WS_CHILD | WS_VISIBLE , rect, this, ID_BUTTON2); m_myb.SetIcon(m_icon); CDC *pDc = GetDC(); CXPTheme theme(GetSafeHwnd(), L"BUTTON"); theme.DrawBackground(pDc->GetSafeHdc(), BS_PUSHBUTTON, PBS_HOT, &rect,0); ReleaseDC(pDc);
....
-
Hi,
dein code gibt leider nicht viele Hinweise, was du genau machst...
Aber es ist eigentlich nicht so schwer.
1. Erstelle eine Dialogbasierende Anwendung
2. füge die 5 Dateien von codeproject in dein projekt verzeichniss
3. im solution explorer die dateien dem projekt hinzufügen
4. im rc editor den ok button einen membervariable zufügen
5. den ok button den stil 'ownerdraw' zuweisen (ganz wichtig!)
6. erstelle eine klasse z.b. CXPButton abgeleitet von CButton mit dem Klassenassistent
7. s. code unten
8. in der dialog klasse die variable des button auf CXPButton ändern
9. starten -> voila
CXPButton code:
// CXPButton class CXPButton : public CButton { DECLARE_DYNAMIC(CXPButton) public: CXPButton(); virtual ~CXPButton(); private: CXPTheme m_theme; protected: DECLARE_MESSAGE_MAP() public: virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/); afx_msg BOOL OnEraseBkgnd(CDC* pDC); };
CXPButton implementierung:
// CXPButton IMPLEMENT_DYNAMIC(CXPButton, CButton) CXPButton::CXPButton() : m_theme(GetSafeHwnd(), L"BUTTON") { } CXPButton::~CXPButton() { } BEGIN_MESSAGE_MAP(CXPButton, CButton) ON_WM_ERASEBKGND() END_MESSAGE_MAP() // CXPButton message handlers void CXPButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // wird aufegrufen vom Framework wegen ownerdraw-style CDC dc; dc.Attach(lpDrawItemStruct->hDC); CString strCaption; GetWindowText(strCaption); m_theme.DrawBackground(lpDrawItemStruct->hDC, TP_BUTTON, TS_CHECKED, &lpDrawItemStruct->rcItem, 0); int nOldBkgnMode = dc.SetBkMode(TRANSPARENT); dc.DrawText(strCaption, &lpDrawItemStruct->rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER); dc.SetBkMode(nOldBkgnMode); dc.Detach(); } BOOL CXPButton::OnEraseBkgnd(CDC* pDC) { // wir zeichnen nichts, weil wir das fenster mit den button // komplett in DrawItem zeichnen // ausserdem verhindern wir dadurch flickern da der standard hintergrund // weiss gezeichnet wird return TRUE; }
Viel spass beim experimentieren der Styles
Gruss
EB (0x0000)
-
danke dir für den quellcode... Hab da aber mal noch ne frage... es scheint eigentlich zu gehen... eigentlich hem... ich sehe nämlich nichts vom Button außer der schrift "OK" habe eigentlich alles so gemacht wie Du es beschrieben hast... Ich schicke mal ein wenig Quellcode
// XPBUTTON.cpp : implementation file // #include "stdafx.h" #include "XPStyle.h" #include "XPBUTTON.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON IMPLEMENT_DYNAMIC(CXPBUTTON, CButton) CXPBUTTON::CXPBUTTON(): m_theme(GetSafeHwnd(), L"BUTTON") { } CXPBUTTON::~CXPBUTTON() { } BEGIN_MESSAGE_MAP(CXPBUTTON, CButton) //{{AFX_MSG_MAP(CXPBUTTON) ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON message handlers void CXPBUTTON::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // wird aufegrufen vom Framework wegen ownerdraw-style CDC dc; dc.Attach(lpDrawItemStruct->hDC); CString strCaption; GetWindowText(strCaption); m_theme.DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, PBS_HOT, &lpDrawItemStruct->rcItem, 0); int nOldBkgnMode = dc.SetBkMode(TRANSPARENT); dc.DrawText(strCaption, &lpDrawItemStruct->rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER); dc.SetBkMode(nOldBkgnMode); dc.Detach(); } BOOL CXPBUTTON::OnEraseBkgnd(CDC* pDC) { // wir zeichnen nichts, weil wir das fenster mit den button // komplett in DrawItem zeichnen // ausserdem verhindern wir dadurch flickern da der standard hintergrund // weiss gezeichnet wird return TRUE; }
#if !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_) #define AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // XPBUTTON.h : header file // ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON window class CXPBUTTON : public CButton { DECLARE_DYNAMIC(CXPBUTTON) // Construction public: CXPBUTTON(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CXPBUTTON) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); //}}AFX_VIRTUAL // Implementation public: virtual ~CXPBUTTON(); private: CXPTheme m_theme; // Generated message map functions protected: //{{AFX_MSG(CXPBUTTON) afx_msg BOOL OnEraseBkgnd(CDC* pDC); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_)
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__8277A099_2BD2_4DC9_ADFA_572AF7763D2F__INCLUDED_) #define AFX_STDAFX_H__8277A099_2BD2_4DC9_ADFA_572AF7763D2F__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #define _WIN32_WINNT 0x0501 #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxdisp.h> // MFC Automation classes #include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT #include "XPTheme.h" //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__8277A099_2BD2_4DC9_ADFA_572AF7763D2F__INCLUDED_)
// XPStyleDlg.cpp : implementation file // #include "stdafx.h" #include "XPStyle.h" #include "XPStyleDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "XPBUTTON.h" ///////////////////////////////////////////////////////////////////////////// // CXPStyleDlg dialog CXPStyleDlg::CXPStyleDlg(CWnd* pParent /*=NULL*/) : CDialog(CXPStyleDlg::IDD, pParent) { //{{AFX_DATA_INIT(CXPStyleDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CXPStyleDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXPStyleDlg) DDX_Control(pDX, IDOK, m_MyXPButton); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CXPStyleDlg, CDialog) //{{AFX_MSG_MAP(CXPStyleDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXPStyleDlg message handlers BOOL CXPStyleDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CXPStyleDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CXPStyleDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; }
// XPStyleDlg.h : header file // #if !defined(AFX_XPSTYLEDLG_H__016FCC2C_E80E_4781_B6BE_52B12609424C__INCLUDED_) #define AFX_XPSTYLEDLG_H__016FCC2C_E80E_4781_B6BE_52B12609424C__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "XPBUTTON.h" ///////////////////////////////////////////////////////////////////////////// // CXPStyleDlg dialog class CXPStyleDlg : public CDialog { // Construction public: CXPStyleDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CXPStyleDlg) enum { IDD = IDD_XPSTYLE_DIALOG }; CXPBUTTON m_MyXPButton; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CXPStyleDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(CXPStyleDlg) virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_XPSTYLEDLG_H__016FCC2C_E80E_4781_B6BE_52B12609424C__INCLUDED_)
So das war es denke ich mal... also eigentlich so wie Du es mir geschrieben hattest... Aber wie schon geschrieben bekomme ich keinen Button gezeigt sondern nur den Text. Der Button funktioniert aber wenn ich in den bereich klicke... Seltsam
...
-
Hi,
der code funktioniert bei mir so wie er soll. Hast Du vielleicht den Designdienst
unter XP abgeschaltet?
Debugge mal die Funktion DrawItem. Was liefert DrawBackground zurück?
Der Rückgabewert muss S_OK sein, sonst ist da was nicht in Ordnung.Gruss
EB
-
bei:
m_theme.DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, PBS_DEFAULTED, &lpDrawItemStruct->rcItem, 0);kommt ein wert von -2147024890 glaube nicht das der richtig ist, also das da irgendetwas falsch läuft... ausgeschaltet dürfte er aber nicht sein, weil der ThemenExplorer con codeguro auch funktioniert... muss ich vieleicht noch wm_themenchange behandeln?
-
bei:
m_theme.DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, PBS_DEFAULTED, &lpDrawItemStruct->rcItem, 0);kommt ein wert von -2147024890 glaube nicht das der richtig ist, also das da irgendetwas falsch läuft... ausgeschaltet dürfte er aber nicht sein, weil der ThemenExplorer con codeguro auch funktioniert... muss ich vieleicht noch wm_themenchange behandeln?
-
sorry mein explorer hat grad gesponnen... Deshalb sind die einträge jetzt doppelt!!!
-
habe es nochmal debugt und habe außer das :
m_theme.DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, PBS_DEFAULTED, &lpDrawItemStruct->rcItem, 0);
einen komischen wert zurückliefert noch festgestellt, das m_hTheme selber NULL :
- m_theme {...}
m_hTheme 0x00000000 -> warum null oder ist das so?
+ m_hThemeDll 0x5b0f0000
m_bLoaded 1
m_pOpenThemeData 0x5b0f7cb8
m_pCloseThemeData 0x5b0f4940
m_pDrawThemeBackground 0x00000000
m_pDrawThemeText 0x00000000
m_pGetThemeBackgroundContentRect 0x00000000
m_pGetThemeBackgroundExtent 0x00000000
m_pGetThemePartSize 0x00000000
m_pGetThemeTextExtent 0x00000000
m_pGetThemeTextMetrics 0x00000000
m_pGetThemeBackgroundRegion 0x00000000
m_pHitTestThemeBackground 0x00000000
m_pDrawThemeEdge 0x00000000
m_pDrawThemeIcon 0x00000000
m_pIsThemePartDefined 0x00000000
m_pIsThemeBackgroundPartiallyTransparent 0x00000000
m_pGetThemeColor 0x00000000
m_pGetThemeMetric 0x00000000
m_pGetThemeString 0x00000000
m_pGetThemeBool 0x00000000
m_pGetThemeInt 0x00000000
m_pGetThemeEnumValue 0x00000000
m_pGetThemePosition 0x00000000
m_pGetThemeFont 0x00000000
m_pGetThemeRect 0x00000000
m_pGetThemeMargins 0x00000000
m_pGetThemeIntList 0x00000000
m_pGetThemePropertyOrigin 0x00000000
m_pSetWindowTheme 0x00000000
m_pGetThemeFilename 0x00000000
m_pGetThemeSysColor 0x00000000
m_pGetThemeSysColorBrush 0x00000000
m_pGetThemeSysBool 0x00000000
m_pGetThemeSysSize 0x00000000
m_pGetThemeSysFont 0x00000000
m_pGetThemeSysString 0x00000000
m_pGetThemeSysInt 0x00000000
m_pIsThemeActive 0x00000000
m_pIsAppThemed 0x00000000
m_pGetWindowTheme 0x00000000
m_pEnableThemeDialogTexture 0x00000000
m_pIsThemeDialogTextureEnabled 0x00000000
m_pGetThemeAppProperties 0x00000000
m_pSetThemeAppProperties 0x00000000
m_pGetCurrentThemeName 0x00000000
m_pGetThemeDocumentationProperty 0x00000000
m_pDrawThemeParentBackground 0x00000000
m_pEnableTheming 0x00000000
-
also m_theme darf nicht null sein. bei initialisierung von :
IMPLEMENT_DYNAMIC(CXPBUTTON, CButton) CXPBUTTON::CXPBUTTON(): m_theme(GetSafeHwnd(), L"BUTTON") { }
bekommt m_theme NULL, da GetSafeHwnd() null zurückliefert, da der Button bzw. die Dialogbox noch nicht existiert irgendwie :
+ m_theme {...}
+ this 0x0012fe90 {CXPBUTTON hWnd=0x00000000}
CButton::CButton returned <void>
CWnd::GetSafeHwnd returned 0x00000000
CXPTheme::CXPTheme returned <void>Hem.... Habe nun in DrawItem die Zeile:
CXPTheme m_theme(GetSafeHwnd(), L"BUTTON");
eingefügt. und es funktioniert... Warum das ganze so ist verstehe ich schon... aber wozu schreibe ich denn dann das ganze so:
IMPLEMENT_DYNAMIC(CXPBUTTON, CButton) CXPBUTTON::CXPBUTTON(): m_theme(GetSafeHwnd(), L"BUTTON") { }
-
Hi,
ich habe den code auch mal debugt. GetSafeHwnd liefert natürlich NULL weil
es im Konstruktor aufgerufen wird und das Fenster dann noch nicht existiert.Trotzdem wird bei mir ein gültiges themehandle gesetzt (zumindest im Debug-Mode)
warum auch immer da ein Unterschied bei dir ist, liegt wohl tiefer im
Betriebssystem (XP Professionell SP2), aber du hast recht das es so nicht
richtig ist.Da DrawItem im laufe des Programms sehr oft aufgerufen wird, ist es ziemlicher
Overkill jedesmal ein Objekt vom Typ CXPTheme zu erzeugen, auch wenn das
auf modernen schnellen Rechnern nicht so auffält.Um es dennoch mit der Membervariable zu machen, bleibt dann wohl nichts anderes
übrig als diese zu Laufzeit dynamisch zu erzeugen.Bei einem abgeleiteten Button am besten in PreSubclassWindow
IMPLEMENT_DYNAMIC(CXPButton, CButton) CXPButton::CXPButton() : m_pTheme(NULL) { } CXPButton::~CXPButton() { delete m_pTheme; } void CXPButton::PreSubclassWindow() { m_pTheme = new CXPTheme(GetSafeHwnd(), L"BUTTON"); CButton::PreSubclassWindow(); }
Gruss
EB
-
habe es geändert. weil mit dem Overkill hast Du schon recht... Jetzt steht bei m_theme auch etwas drin, also ist nicht mehr NULL. nur leider geht es dann auch nicht. wie gesagt: nur wenn ich die zeile:
CXPTheme m_theme(GetSafeHwnd(), L"BUTTON");
in die DrawItem function schreibe... ist ganz schön seltsam...
-
habe jetzt in der Function PreSubClassWindow() folgendes geändert:
void CXPBUTTON::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class m_pTheme = CXPTheme(GetSafeHwnd(), L"BUTTON"); CButton::PreSubclassWindow(); }
und das:
delete m_pTheme;
habe ich gelöscht... Danach ging es auf einmal...
Noch mal nur so ne andere Frage...
um den Status des Buttons muss ich mich jetzt selbst kümmern oder gibt es da vieleicht noch ne einfachere Methode? ich wollte es mit wm_mousemove in verbindung mit der drawitem Methode machen und so abfragen ob sich die mause über dem button befindet, um dann das aussehen auf BPS_HOT zu stellen...?
-
darkangel76 schrieb:
habe jetzt in der Function PreSubClassWindow() folgendes geändert:
void CXPBUTTON::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class m_pTheme = CXPTheme(GetSafeHwnd(), L"BUTTON"); CButton::PreSubclassWindow(); }
und das:
delete m_pTheme;
Du hast in der Header datei aus CXPTheme m_theme wohl keinen Zeiger
gemacht!
Das hatte ich eigentlich als Grundwissen vorausgesetzt...
Es muss im Heáder folgendes stehen:private: CXPTheme* m_pTheme;
Danach klappt die Speicherzuweisung mit new und das freigeben mit delete.
darkangel76 schrieb:
um den Status des Buttons muss ich mich jetzt selbst kümmern oder gibt es da vieleicht noch ne einfachere Methode? ich wollte es mit wm_mousemove in verbindung mit der drawitem Methode machen und so abfragen ob sich die mause über dem button befindet, um dann das aussehen auf BPS_HOT zu stellen...?
Stimmmt, das gehört jetzt alles Dir
und wird alles in DrawItem
gemacht. Sieh dir dazu die MSDN an was alles in der Struktur lpDrawItemStruct
drinsteckt, dann kannst Du entscheiden wie und was Du zeichnest in DrawItem.Gruss
EB
-
Hab jetzt soweit alles fertig. auch das der Button auf Mouseleave reagiert u. so... hat nur noch einen kleinen Grafik fehler... der button sieht ein wenig nach mehrmaliegen rüberfahren mit der maus oder beim durchlaufen mit der Tastatur wie ein eingestampf aus - falls du weist was ich meine... wenn ich das fenster minimiere und dann wieder groß mache ist er wieder normal... Na mal schauen ob ich das noch wegbekomme
Danke Dir aber janz dolle...
-
Ich stelle mal meinen Quellcode von meinem CXPButton rein... Vieleicht kann mir ja jemand sagen warum mein Button nachdem ich mit meiner Maus ein paar mal rüber gefahren bin irgendwie so aussieht als ob er tiefergesetzt wurde... Ist schon merkwürdig... man könnte zwar im Hauptprogramm dann über nen wm_mousemove abfragen wo sich der zeiger befindet und dann den kompletten Dialog neu zeichnen, aber ich wollte eigentlich alles in meiner CXPButton Klasse unterbringen. So das man sich beim einbinden keinen Kopf mehr machen muss... erst recht wenn es am ende dann vieleicht 10 Button und noch anderer kram ist... kann man das ganze vieleicht mit nem Sendmessage ans Dialogfenster in "onMouseLeave" erreichen? und wenn ja wie?
// XPBUTTON.cpp : implementation file // #include "stdafx.h" #include "XPStyle.h" #include "XPBUTTON.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define ODS_NOFOCUSRECT 0x0200 ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON IMPLEMENT_DYNAMIC(CXPBUTTON, CButton) CXPBUTTON::CXPBUTTON(): m_pTheme(NULL) { bMouseOverButton = false; } CXPBUTTON::~CXPBUTTON() { } BEGIN_MESSAGE_MAP(CXPBUTTON, CButton) //{{AFX_MSG_MAP(CXPBUTTON) ON_WM_ERASEBKGND() ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON message handlers void CXPBUTTON::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // wird aufegrufen vom Framework wegen ownerdraw-style CDC dc; dc.Attach(lpDrawItemStruct->hDC); CString strCaption; GetWindowText(strCaption); if (m_pTheme.IsAppThemed()) { // button state BOOL bIsPressed = (lpDrawItemStruct->itemState & ODS_SELECTED); BOOL bIsFocused = (lpDrawItemStruct->itemState & ODS_FOCUS); BOOL bIsDisabled = (lpDrawItemStruct->itemState & ODS_DISABLED); BOOL bDrawFocusRect = !(lpDrawItemStruct->itemState & ODS_NOFOCUSRECT); // Prepare draw... paint button background DWORD state = (bIsPressed)?PBS_PRESSED:PBS_NORMAL; if(state == PBS_NORMAL) { if(bIsFocused) state = PBS_DEFAULTED; if(bMouseOverButton) state = PBS_HOT; } m_pTheme.DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, state, &lpDrawItemStruct->rcItem, 0); int nOldBkgnMode = dc.SetBkMode(TRANSPARENT); dc.DrawText(strCaption, &lpDrawItemStruct->rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER); dc.SetBkMode(nOldBkgnMode); if (bIsFocused && bDrawFocusRect) { RECT focusRect =lpDrawItemStruct->rcItem; InflateRect(&focusRect, -3, -3); DrawFocusRect(dc, &focusRect); } } dc.Detach(); } BOOL CXPBUTTON::OnEraseBkgnd(CDC* pDC) { // wir zeichnen nichts, weil wir das fenster mit den button // komplett in DrawItem zeichnen // ausserdem verhindern wir dadurch flickern da der standard hintergrund // weiss gezeichnet wird return TRUE; } void CXPBUTTON::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class m_pTheme = CXPTheme(GetSafeHwnd(), L"BUTTON"); CButton::PreSubclassWindow(); } void CXPBUTTON::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(!bMouseOverButton) { bMouseOverButton = TRUE; TRACKMOUSEEVENT trackmouseevent; trackmouseevent.cbSize = sizeof(trackmouseevent); trackmouseevent.dwFlags = TME_LEAVE; trackmouseevent.hwndTrack = GetSafeHwnd(); trackmouseevent.dwHoverTime = 0; _TrackMouseEvent(&trackmouseevent); InvalidateRect(NULL, FALSE); } CButton::OnMouseMove(nFlags, point); } LONG CXPBUTTON::OnMouseLeave(WPARAM wParam, LPARAM lParam) { bMouseOverButton = false; InvalidateRect(NULL, FALSE); return 0; }
#if !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_) #define AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // XPBUTTON.h : header file // ///////////////////////////////////////////////////////////////////////////// // CXPBUTTON window class CXPBUTTON : public CButton { DECLARE_DYNAMIC(CXPBUTTON) // Construction public: CXPBUTTON(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CXPBUTTON) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL // Implementation public: virtual ~CXPBUTTON(); private: CXPTheme m_pTheme; BOOL ScreenPointInButtonRect(CPoint point); bool bMouseOverButton; // Generated message map functions protected: //{{AFX_MSG(CXPBUTTON) afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnMouseMove(UINT nFlags, CPoint point); //}}AFX_MSG LONG OnMouseLeave(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_)
ist bestimmt nur kinderkram für die meisten von euch, aber für mich die halbe c++ welt...