Skip to content

Commit 07ee8c4

Browse files
committed
Added dark mode and solved small bugs
1 parent a3ecb47 commit 07ee8c4

28 files changed

+552
-138
lines changed

ChildFrm.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWndExt)
2525
ON_MESSAGE(WMU_POSTINIT, &CChildFrame::OnPostInit)
2626
ON_MESSAGE(WMU_ISPOPULATEMODE, &CChildFrame::OnIsPopulateMode)
2727
ON_MESSAGE(WMU_SETWORDWRAP, &CChildFrame::OnSetWordWrap)
28+
ON_MESSAGE(WMU_DARKMODE, &CChildFrame::OnDarkMode)
2829
END_MESSAGE_MAP()
2930

3031
// CChildFrame construction/destruction
@@ -80,15 +81,15 @@ int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
8081

8182
CString sTitle(_T("Queries"));
8283

83-
if (! m_pQueryPane->Create(sTitle, this, CSize(240, 240), TRUE, PANEQUERYID,
84+
if (! m_pQueryPane->Create(sTitle, this, CSize(300, 200), TRUE, PANEQUERYID,
8485
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI,
8586
AFX_CBRS_REGULAR_TABS, AFX_NON_CLOSE_DOCKING_PANE_STYLE))
8687
{
8788
TRACE(_T("Failed to create Query window\n"));
8889
return FALSE; // failed to create
8990
}
9091
sTitle.Format(_T("Messages"));
91-
if (! m_pMessagePane->Create(sTitle, this, CSize(240, 240), TRUE, PANEMESSAGEID,
92+
if (! m_pMessagePane->Create(sTitle, this, CSize(700, 200), TRUE, PANEMESSAGEID,
9293
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI,
9394
AFX_CBRS_REGULAR_TABS, AFX_NON_CLOSE_DOCKING_PANE_STYLE))
9495
{
@@ -97,7 +98,7 @@ int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
9798
}
9899

99100
sTitle.Format(_T("Databases"));
100-
if (! m_pDatabasePane->Create(sTitle, this, CSize(200, 240), TRUE, PANEDATABASEID,
101+
if (! m_pDatabasePane->Create(sTitle, this, CSize(250, 250), TRUE, PANEDATABASEID,
101102
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI,
102103
AFX_CBRS_REGULAR_TABS, AFX_NON_CLOSE_DOCKING_PANE_STYLE))
103104
{
@@ -204,7 +205,9 @@ LRESULT CChildFrame::OnPostInit(WPARAM wParam, LPARAM lParam)
204205
GetActiveDocument()->UpdateAllViews(nullptr, CDatabaseExplorerApp::UH_INITDATABASE);
205206

206207
if (DoListTable == static_cast<int>(wParam))
207-
GetActiveDocument()->UpdateAllViews(nullptr, CDatabaseExplorerApp::UH_LISTTABLE, reinterpret_cast<CObject*>(&m_pDatabasePane->GetSelection()));
208+
GetActiveDocument()->UpdateAllViews(nullptr,
209+
CDatabaseExplorerApp::UH_LISTTABLE,
210+
reinterpret_cast<CObject*>(&m_pDatabasePane->GetSelection()));
208211

209212
return 1;
210213
}
@@ -218,3 +221,12 @@ LRESULT CChildFrame::OnSetWordWrap(WPARAM wParam, LPARAM lParam)
218221
{
219222
return m_pQueryPane->GetRichEditCtrl()->SetTargetDevice(nullptr, static_cast<long>(wParam));
220223
}
224+
225+
LRESULT CChildFrame::OnDarkMode(WPARAM wParam, LPARAM lParam)
226+
{
227+
m_pQueryPane->SetDarkMode(static_cast<BOOL>(wParam));
228+
m_pMessagePane->SetDarkMode(static_cast<BOOL>(wParam));
229+
m_pDatabasePane->SetDarkMode(static_cast<BOOL>(wParam));
230+
231+
return 1;
232+
}

ChildFrm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ constexpr int PANEQUERYID = 22;
1212
constexpr int PANEMESSAGEID = 32;
1313
constexpr int PANEDATABASEID = 33;
1414
constexpr int DoInitDatabase = 1;
15-
constexpr int DoListTable = 2;
15+
constexpr WPARAM DoListTable = 2;
1616
constexpr int UpdateFrameText = 3;
1717

1818
enum class Color
@@ -73,6 +73,7 @@ class CChildFrame : public CMDIChildWndExt
7373
afx_msg LRESULT OnPostInit(WPARAM wParam, LPARAM lParam);
7474
afx_msg LRESULT OnIsPopulateMode(WPARAM wParam, LPARAM lParam);
7575
afx_msg LRESULT OnSetWordWrap(WPARAM wParam, LPARAM lParam);
76+
afx_msg LRESULT OnDarkMode(WPARAM wParam, LPARAM lParam);
7677
//}}AFX_MSG
7778
DECLARE_MESSAGE_MAP()
7879
};

ColorHeaderCtrl.cpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// ColorHeaderCtrl.cpp : implementation file
2+
//
3+
4+
#include "pch.h"
5+
#include "ColorHeaderCtrl.h"
6+
7+
#ifdef _DEBUG
8+
#define new DEBUG_NEW
9+
#undef THIS_FILE
10+
static char THIS_FILE[] = __FILE__;
11+
#endif
12+
13+
// CColorHeaderCtrl
14+
15+
IMPLEMENT_DYNAMIC(CColorHeaderCtrl, CHeaderCtrl)
16+
17+
CColorHeaderCtrl::CColorHeaderCtrl()
18+
: m_bPrint(FALSE)
19+
, m_bTheme(FALSE)
20+
, m_bCustomDraw(FALSE)
21+
, m_crText(GetSysColor(COLOR_WINDOWTEXT))
22+
, m_crBackground(GetSysColor(COLOR_WINDOW))
23+
{
24+
m_crBackgroundHot = m_crBackgroundPressed = m_crBackground;
25+
m_crBackgroundHotTheme = m_crBackgroundPressedTheme = m_crBackgroundTheme = m_crBackground;
26+
}
27+
28+
BEGIN_MESSAGE_MAP(CColorHeaderCtrl, CHeaderCtrl)
29+
//{{AFX_MSG_MAP(CColorHeaderCtrl)
30+
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CColorHeaderCtrl::OnNMCustomdraw)
31+
//}}AFX_MSG_MAP
32+
END_MESSAGE_MAP()
33+
34+
// CColorHeaderCtrl message handlers
35+
36+
void CColorHeaderCtrl::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
37+
{
38+
if (!m_bCustomDraw)
39+
return;
40+
41+
LPNMLVCUSTOMDRAW pNMCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
42+
// TODO: Add your control notification handler code here
43+
44+
*pResult = CDRF_DODEFAULT;
45+
46+
switch (pNMCD->nmcd.dwDrawStage)
47+
{
48+
case CDDS_PREPAINT:
49+
*pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
50+
break;
51+
case CDDS_ITEMPREPAINT:
52+
{
53+
static HFONT hNewFont = NULL;
54+
if (!hNewFont)
55+
{
56+
LOGFONT lf;
57+
GetFont()->GetLogFont(&lf);
58+
lf.lfQuality = NONANTIALIASED_QUALITY;
59+
hNewFont = ::CreateFontIndirect(&lf);
60+
}
61+
SetTextColor(pNMCD->nmcd.hdc, m_crText);
62+
SelectObject(pNMCD->nmcd.hdc, hNewFont);
63+
*pResult = CDRF_NEWFONT;
64+
}
65+
break;
66+
case CDDS_POSTPAINT:
67+
CRect rect;
68+
GetClientRect(&rect);
69+
70+
CDC MemDC;
71+
CBitmap bitmap;
72+
CDC* pDC = CDC::FromHandle(pNMCD->nmcd.hdc);
73+
MemDC.CreateCompatibleDC(pDC);
74+
if (bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()))
75+
{
76+
CBitmap* pOldBitmap = static_cast<CBitmap*>(MemDC.SelectObject(&bitmap));
77+
if (!m_bPrint)
78+
{
79+
m_bPrint = TRUE;
80+
::SendMessage(pNMCD->nmcd.hdr.hwndFrom, WM_PRINTCLIENT, (WPARAM)MemDC.GetSafeHdc(), PRF_CLIENT);
81+
CBrush brush;
82+
brush.CreateSolidBrush(m_crBackground);
83+
CBrush* pOldBrush = static_cast<CBrush*>(pDC->SelectObject(&brush));
84+
pDC->FillRect(&rect, &brush);
85+
pDC->SelectObject(pOldBrush);
86+
DeleteObject(&brush);
87+
88+
if (!m_bTheme)
89+
{
90+
const HTHEME hTheme = OpenThemeData(pNMCD->nmcd.hdr.hwndFrom, L"HEADER");
91+
if (hTheme)
92+
{
93+
CDC TestDC;
94+
TestDC.CreateCompatibleDC(pDC);
95+
CBitmap bitmapTest;
96+
bitmapTest.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
97+
CBitmap* pOldBitmapTest = static_cast<CBitmap*>(TestDC.SelectObject(&bitmapTest));
98+
DrawThemeBackground(hTheme, TestDC.GetSafeHdc(), HP_HEADERITEM, HIS_NORMAL, &rect, NULL);
99+
m_crBackgroundTheme = TestDC.GetPixel(1, 1);
100+
DrawThemeBackground(hTheme, TestDC.GetSafeHdc(), HP_HEADERITEM, HIS_HOT, &rect, NULL);
101+
m_crBackgroundHotTheme = TestDC.GetPixel(1, 1);
102+
DrawThemeBackground(hTheme, TestDC.GetSafeHdc(), HP_HEADERITEM, HIS_PRESSED, &rect, NULL);
103+
m_crBackgroundPressedTheme = TestDC.GetPixel(1, 1);
104+
TestDC.SelectObject(pOldBitmapTest);
105+
DeleteObject(bitmapTest);
106+
DeleteDC(TestDC);
107+
CloseThemeData(hTheme);
108+
109+
m_bTheme = TRUE;
110+
}
111+
}
112+
113+
CDC HotDC, PressedDC;
114+
HotDC.CreateCompatibleDC(pDC);
115+
PressedDC.CreateCompatibleDC(pDC);
116+
CBitmap bitmapHot, bitmapPressed;
117+
bitmapHot.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
118+
CBitmap* pOldBitmapHot = static_cast<CBitmap*>(HotDC.SelectObject(&bitmapHot));
119+
bitmapPressed.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
120+
CBitmap* pOldBitmapPressed = static_cast<CBitmap*>(PressedDC.SelectObject(&bitmapPressed));
121+
// default color => custom
122+
pDC->TransparentBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, rect.Width(), rect.Height(), m_crBackgroundTheme);
123+
// Copy pDC to 2 temporary DC
124+
HotDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
125+
PressedDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
126+
// hot brush in PressedDC
127+
CBrush brushHot;
128+
brushHot.CreateSolidBrush(m_crBackgroundHot);
129+
CBrush* pOldBrushHot = static_cast<CBrush*>(PressedDC.SelectObject(&brushHot));
130+
PressedDC.FillRect(&rect, &brushHot);
131+
PressedDC.SelectObject(pOldBrushHot);
132+
DeleteObject(brushHot);
133+
// Hot color (Light Blue) => Pressed
134+
PressedDC.TransparentBlt(0, 0, rect.Width(), rect.Height(), &HotDC, 0, 0, rect.Width(), rect.Height(), m_crBackgroundHotTheme);
135+
// Pressed brush in pDC
136+
CBrush brushPressed;
137+
brushPressed.CreateSolidBrush(m_crBackgroundPressed);
138+
CBrush* pOldBrushPressed = static_cast<CBrush*>(pDC->SelectObject(&brushPressed));
139+
pDC->FillRect(&rect, &brushPressed);
140+
pDC->SelectObject(pOldBrushPressed);
141+
DeleteObject(brushPressed);
142+
// Hot => Pressed
143+
pDC->TransparentBlt(0, 0, rect.Width(), rect.Height(), &PressedDC, 0, 0, rect.Width(), rect.Height(), m_crBackgroundPressedTheme);
144+
145+
HotDC.SelectObject(pOldBitmapHot);
146+
DeleteObject(bitmapHot);
147+
DeleteDC(HotDC);
148+
149+
PressedDC.SelectObject(pOldBitmapPressed);
150+
DeleteObject(bitmapPressed);
151+
DeleteDC(PressedDC);
152+
}
153+
else
154+
{
155+
m_bPrint = FALSE;
156+
}
157+
MemDC.SelectObject(pOldBitmap);
158+
DeleteObject(bitmap);
159+
}
160+
DeleteDC(MemDC);
161+
break;
162+
}
163+
}
164+
165+
void CColorHeaderCtrl::UpdateCustomDrawFlag()
166+
{
167+
if (GetSysColor(COLOR_WINDOW) != m_crBackground ||
168+
GetSysColor(COLOR_WINDOWTEXT) != m_crText)
169+
m_bCustomDraw = TRUE;
170+
else
171+
m_bCustomDraw = FALSE;
172+
}

ColorHeaderCtrl.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
3+
// CColorHeaderCtrl
4+
5+
class CColorHeaderCtrl : public CHeaderCtrl
6+
{
7+
DECLARE_DYNAMIC(CColorHeaderCtrl)
8+
9+
public:
10+
CColorHeaderCtrl();
11+
~CColorHeaderCtrl() override = default;
12+
13+
public:
14+
void UpdateCustomDrawFlag();
15+
BOOL IsCustomDraw() const { return m_bCustomDraw; }
16+
COLORREF GetTextColorEx() const { return m_crText; }
17+
COLORREF GetBackgroundColor() const { return m_crBackground; }
18+
COLORREF GetBackgroundColorHot() const { return m_crBackgroundHot; }
19+
COLORREF GetBackgroundColorPressed() const { return m_crBackgroundPressed; }
20+
void SetTextColorEx(const COLORREF cr)
21+
{
22+
m_crText = cr;
23+
UpdateCustomDrawFlag();
24+
}
25+
void SetBackgroundColor(const COLORREF cr)
26+
{
27+
m_crBackground = cr;
28+
UpdateCustomDrawFlag();
29+
}
30+
void SetBackgroundColorHot(const COLORREF cr) { m_crBackgroundHot = cr; }
31+
void SetBackgroundColorPressed(const COLORREF cr) { m_crBackgroundPressed = cr; }
32+
33+
protected:
34+
COLORREF m_crText;
35+
COLORREF m_crBackground;
36+
COLORREF m_crBackgroundHot;
37+
COLORREF m_crBackgroundPressed;
38+
COLORREF m_crBackgroundTheme;
39+
COLORREF m_crBackgroundHotTheme;
40+
COLORREF m_crBackgroundPressedTheme;
41+
BOOL m_bCustomDraw{ FALSE };
42+
BOOL m_bPrint; // To avoid infinite loop with WM_PRINTCLIENT
43+
BOOL m_bTheme; // TRUE when m_crBackgroundTheme was read from GetWindowTheme
44+
45+
protected:
46+
//{{AFX_MSG(CHeaderCtrlEx)
47+
afx_msg void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
48+
//}}AFX_MSG
49+
DECLARE_MESSAGE_MAP()
50+
};

ColorListView.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// ColorListView.cpp : implementation file
2+
//
3+
4+
#include "pch.h"
5+
#include "ColorListView.h"
6+
7+
#ifdef _DEBUG
8+
#define new DEBUG_NEW
9+
#undef THIS_FILE
10+
static char THIS_FILE[] = __FILE__;
11+
#endif
12+
13+
// CColorListView
14+
15+
IMPLEMENT_DYNCREATE(CColorListView, CListView)
16+
17+
BEGIN_MESSAGE_MAP(CColorListView, CListView)
18+
END_MESSAGE_MAP()
19+
20+
// CColorListView diagnostics
21+
22+
#ifdef _DEBUG
23+
void CColorListView::AssertValid() const
24+
{
25+
CListView::AssertValid();
26+
}
27+
28+
#ifndef _WIN32_WCE
29+
void CColorListView::Dump(CDumpContext& dc) const
30+
{
31+
CListView::Dump(dc);
32+
}
33+
#endif
34+
#endif //_DEBUG
35+
36+
// CColorListView message handlers
37+
38+
void CColorListView::OnInitialUpdate()
39+
{
40+
CListView::OnInitialUpdate();
41+
42+
// TODO: Add your specialized code here and/or call the base class
43+
44+
if (!m_pHeaderCtrl->GetSafeHwnd())
45+
{
46+
HWND hWnd = reinterpret_cast<HWND>(::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0));
47+
m_pHeaderCtrl->SubclassWindow(hWnd);
48+
m_clrDefText = GetListCtrl().GetTextColor();
49+
m_clrDefBack = GetListCtrl().GetTextBkColor();
50+
}
51+
}
52+
53+
BOOL CColorListView::SetTextColor(const COLORREF cr)
54+
{
55+
m_clrDefText = cr;
56+
return GetListCtrl().SetTextColor(cr);
57+
}
58+
59+
BOOL CColorListView::SetTextBkColor(const COLORREF cr)
60+
{
61+
m_clrDefBack = cr;
62+
return GetListCtrl().SetTextBkColor(cr);
63+
}

0 commit comments

Comments
 (0)