OSDN Git Service

Add TortoiseProc
[tortoisegit/TortoiseGitJp.git] / Utils / MiscUI / XPImageButton.cpp
1 #include "stdafx.h"\r
2 #include "XPTheme.h"\r
3 #include "XPImageButton.h"\r
4 \r
5 \r
6 IMPLEMENT_DYNAMIC(CXPImageButton, CButton)\r
7 CXPImageButton::CXPImageButton()\r
8 {\r
9 }\r
10 \r
11 CXPImageButton::~CXPImageButton()\r
12 {\r
13 }\r
14 \r
15 BEGIN_MESSAGE_MAP(CXPImageButton, CButton)\r
16         ON_NOTIFY_REFLECT (NM_CUSTOMDRAW, OnNotifyCustomDraw)\r
17 END_MESSAGE_MAP()\r
18 \r
19 void CXPImageButton::OnNotifyCustomDraw(NMHDR * pNotifyStruct, LRESULT* result)\r
20 {\r
21         LPNMCUSTOMDRAW pCustomDraw = (LPNMCUSTOMDRAW)pNotifyStruct;\r
22         ASSERT(pCustomDraw->hdr.hwndFrom == m_hWnd);\r
23 \r
24         DWORD style = GetStyle();\r
25         if ((style & (BS_BITMAP | BS_ICON)) == 0 || !m_xpButton.IsAppThemed() || !m_xpButton.IsActive())\r
26         {\r
27                 // not an icon or bitmap. So just let windows handle its drawing.\r
28                 *result = CDRF_DODEFAULT;\r
29                 return;\r
30         }\r
31 \r
32         if (pCustomDraw->dwDrawStage == CDDS_PREERASE)\r
33         {\r
34                 m_xpButton.DrawParentBackground(m_hWnd, pCustomDraw->hdc, &pCustomDraw->rc);\r
35         }\r
36 \r
37         if (pCustomDraw->dwDrawStage == CDDS_PREERASE || pCustomDraw->dwDrawStage == CDDS_PREPAINT)\r
38         {\r
39                 m_xpButton.Open(m_hWnd, L"BUTTON");\r
40                 if (!m_xpButton.IsAppThemed() || !m_xpButton.IsActive())\r
41                 {\r
42                         *result = CDRF_DODEFAULT;\r
43                         return;\r
44                 }\r
45 \r
46                 // find the state for DrawThemeBackground()\r
47                 int state_id = PBS_NORMAL;\r
48                 if (style & WS_DISABLED)\r
49                         state_id = PBS_DISABLED;\r
50                 else if (pCustomDraw->uItemState & CDIS_SELECTED)\r
51                         state_id = PBS_PRESSED;\r
52                 else if (pCustomDraw->uItemState & CDIS_HOT)\r
53                         state_id = PBS_HOT;\r
54                 else if (style & BS_DEFPUSHBUTTON)\r
55                         state_id = PBS_DEFAULTED;\r
56 \r
57                 // draw themed button background according to the button state\r
58                 m_xpButton.DrawBackground(pCustomDraw->hdc, BP_PUSHBUTTON, state_id, &pCustomDraw->rc, NULL);\r
59 \r
60                 CRect content_rect (pCustomDraw->rc); \r
61                 m_xpButton.GetBackgroundContentRect(pCustomDraw->hdc, BP_PUSHBUTTON, state_id, &pCustomDraw->rc, &content_rect);\r
62                 m_xpButton.Close();\r
63 \r
64                 // draw the image\r
65                 if (style & BS_BITMAP)\r
66                 {\r
67                         DrawBitmap(pCustomDraw->hdc, &content_rect, style);\r
68                 }\r
69                 else\r
70                 {\r
71                         ASSERT (style & BS_ICON);\r
72                         DrawIcon(pCustomDraw->hdc, &content_rect, style);\r
73                 }\r
74 \r
75                 // draw the focus rectangle if needed\r
76                 if (pCustomDraw->uItemState & CDIS_FOCUS)\r
77                 {\r
78                         // draw focus rectangle\r
79                         DrawFocusRect(pCustomDraw->hdc, &content_rect);\r
80                 }\r
81 \r
82                 *result = CDRF_SKIPDEFAULT;\r
83                 return;\r
84         }\r
85 \r
86         ASSERT (false);\r
87         *result = CDRF_DODEFAULT;\r
88 }\r
89 \r
90 void CXPImageButton::DrawBitmap(HDC hDC, const CRect& Rect, DWORD style)\r
91 {\r
92         HBITMAP hBitmap = GetBitmap();\r
93         if (hBitmap == NULL)\r
94                 return;\r
95 \r
96         // determine the size of the bitmap image\r
97         BITMAPINFO bmi;\r
98         memset (&bmi, 0, sizeof(BITMAPINFO));\r
99         bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
100         GetDIBits(hDC, hBitmap, 0, 0, NULL, &bmi, DIB_RGB_COLORS);\r
101 \r
102         // determine position of top-left corner of bitmap\r
103         int x = ImageLeft(bmi.bmiHeader.biWidth, Rect, style);\r
104         int y = ImageTop(bmi.bmiHeader.biHeight, Rect, style);\r
105 \r
106         // Draw the bitmap\r
107         DrawState(hDC, NULL, NULL, (LPARAM) hBitmap, 0, x, y, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight,\r
108                         (style & WS_DISABLED) != 0 ? (DST_BITMAP | DSS_DISABLED) : (DST_BITMAP | DSS_NORMAL));\r
109 }\r
110 \r
111 void CXPImageButton::DrawIcon(HDC hDC, const CRect& Rect, DWORD style)\r
112 {\r
113         HICON hIcon = GetIcon();\r
114         if (hIcon == NULL)\r
115                 return;\r
116 \r
117         // determine the size of the icon\r
118         ICONINFO ii;\r
119         GetIconInfo(hIcon, &ii);\r
120         BITMAPINFO bmi;\r
121         memset(&bmi, 0, sizeof(BITMAPINFO));\r
122         bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
123         int cx = 0;\r
124         int cy = 0;\r
125         if (ii.hbmColor != NULL)\r
126         {\r
127                 GetDIBits(hDC, ii.hbmColor, 0, 0, NULL, &bmi, DIB_RGB_COLORS);\r
128                 cx = bmi.bmiHeader.biWidth;\r
129                 cy = bmi.bmiHeader.biHeight;\r
130         }\r
131         else\r
132         {\r
133                 GetDIBits(hDC, ii.hbmMask, 0, 0, NULL, &bmi, DIB_RGB_COLORS);\r
134                 cx = bmi.bmiHeader.biWidth;\r
135                 cy = bmi.bmiHeader.biHeight/2;\r
136         }\r
137 \r
138         // determine the position of the top-left corner of the icon\r
139         int x = ImageLeft (cx, Rect, style);\r
140         int y = ImageTop (cy, Rect, style);\r
141 \r
142         // Draw the icon\r
143         DrawState(hDC, NULL, NULL, (LPARAM) hIcon, 0, x, y, cx, cy,\r
144                 (style & WS_DISABLED) != 0 ? (DST_ICON | DSS_DISABLED) : (DST_ICON | DSS_NORMAL));\r
145         if (ii.hbmColor) \r
146                 DeleteObject(ii.hbmColor);\r
147         if (ii.hbmMask) \r
148                 DeleteObject(ii.hbmMask);\r
149 }\r
150 \r
151 int CXPImageButton::ImageLeft(int cx, const CRect& Rect, DWORD style) const\r
152 {\r
153         // calculate the left position of the image so it is drawn on left, right or centered (the default)\r
154         // as set by the style settings.\r
155         int x = Rect.left;\r
156         if (cx > Rect.Width())\r
157                 cx = Rect.Width();\r
158         else if ((style & BS_CENTER) == BS_LEFT)\r
159                 x = Rect.left;\r
160         else if ((style & BS_CENTER) == BS_RIGHT)\r
161                 x = Rect.right - cx;\r
162         else\r
163                 x = Rect.left + (Rect.Width() - cx)/2;\r
164         return x;\r
165 }\r
166 \r
167 int CXPImageButton::ImageTop(int cy, const CRect& Rect, DWORD style) const\r
168 {\r
169         // calculate the top position of the image so it is drawn on top, bottom or vertically centered (the default)\r
170         // as set by the style settings.\r
171         int y = Rect.top;\r
172         if (cy > Rect.Height())\r
173                 cy = Rect.Height();\r
174         if ((style & BS_VCENTER) == BS_TOP)\r
175                 y = Rect.top;\r
176         else if ((style & BS_VCENTER) == BS_BOTTOM)\r
177                 y = Rect.bottom - cy;\r
178         else\r
179                 y = Rect.top + (Rect.Height() - cy)/2;\r
180         return y;\r
181 }\r