From 829fe6c6bc33d53fda9c31fd45a37e1df87befff Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期五, 30 一月 2026 11:16:24 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/Servo/AccordionWnd.cpp | 787 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 787 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/Servo/AccordionWnd.cpp b/SourceCode/Bond/Servo/AccordionWnd.cpp
new file mode 100644
index 0000000..83af762
--- /dev/null
+++ b/SourceCode/Bond/Servo/AccordionWnd.cpp
@@ -0,0 +1,787 @@
+#include "stdafx.h"
+#include "AccordionWnd.h"
+
+
+#define ITEM_HEIGHT 32
+#define ITEM_SPACE 5
+#define TIMER_ID_CHECKHOVER 1
+#define EXPAND_ICON_WIDE 16
+
+#define BORDER 5
+#define SHADOWWIDE 5
+
+CAccordionWnd::CAccordionWnd()
+{
+ m_hWnd = NULL;
+ m_crFrame = GetSysColor(COLOR_WINDOWFRAME);
+ m_crBkgnd = RGB(255, 255, 255);//GetSysColor(COLOR_BTNFACE); ;
+ m_nPadding[PADDING_LEFT] = 5;
+ m_nPadding[PADDING_TOP] = 5;
+ m_nPadding[PADDING_RIGHT] = 5;
+ m_nPadding[PADDING_BOTTOM] = 5;
+ m_crItemBackground[0] = RGB(218, 218, 218);
+ m_crItemBackground[1] = RGB(34, 177, 76);
+ m_crItemFrame[0] = RGB(128, 128, 128);
+ m_crItemFrame[1] = RGB(128, 128, 128);
+ m_crItemText[0] = RGB(68, 84, 111);
+ m_crItemText[1] = RGB(0, 0, 0);
+ m_crSeparateLine = RGB(222, 222, 222);
+ m_crHoverItemBackground = RGB(244, 245, 247);
+ m_crHoverItemFrame = RGB(200, 222, 255);
+ m_hIconExpand = NULL;
+ m_hIconClose = NULL;
+ m_nHoverItem = -1;
+ m_nCheckHoverItem = -1;
+ m_bShadow = FALSE;
+ m_crShadowBkgnd = GetSysColor(COLOR_BTNFACE);
+}
+
+
+CAccordionWnd::~CAccordionWnd()
+{
+ for (size_t i = 0; i < m_vectorItems.size(); i++) {
+ delete m_vectorItems[i];
+ }
+ m_vectorItems.clear();
+}
+
+BOOL CAccordionWnd::RegisterWndClass()
+{
+ WNDCLASS wcExisting = {};
+ HINSTANCE hInstance = AfxGetInstanceHandle();
+ if (::GetClassInfo(hInstance, ACCORDIONWND_CLASS, &wcExisting) ||
+ ::GetClassInfo(NULL, ACCORDIONWND_CLASS, &wcExisting)) {
+ return TRUE;
+ }
+
+ WNDCLASS wc = {};
+ wc.lpszClassName = ACCORDIONWND_CLASS;
+ wc.hInstance = hInstance;
+ wc.lpfnWndProc = WindowProc;
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = 0;
+ wc.lpszMenuName = NULL;
+ wc.hbrBackground = NULL;
+ wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+
+ // 注册自定义类
+ if (::RegisterClass(&wc) != 0) {
+ return TRUE;
+ }
+ return (::GetLastError() == ERROR_CLASS_ALREADY_EXISTS);
+}
+
+CAccordionWnd* CAccordionWnd::FromHandle(HWND hWnd)
+{
+ CAccordionWnd* pAccordionWnd = (CAccordionWnd*)::GetProp(hWnd, ACCORDIONWND_TAG);
+ return pAccordionWnd;
+}
+
+CAccordionWnd* CAccordionWnd::Hook(HWND hWnd)
+{
+ CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
+ if (pAccordionWnd == NULL) {
+ pAccordionWnd = new CAccordionWnd();
+ pAccordionWnd->m_hWnd = hWnd;
+
+ SetProp(hWnd, ACCORDIONWND_TAG, (HANDLE)pAccordionWnd);
+ }
+
+
+ return pAccordionWnd;
+}
+
+void CAccordionWnd::LoadExpandIcon(CString strExpandFile, CString strCloseFile)
+{
+ m_hIconExpand = (HICON)::LoadImage(AfxGetInstanceHandle(), strExpandFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
+ LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+ m_hIconClose = (HICON)::LoadImage(AfxGetInstanceHandle(), strCloseFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
+ LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+}
+
+void CAccordionWnd::Setpadding(int type, unsigned int nPadding)
+{
+ if (type >= PADDING_LEFT && PADDING_LEFT <= PADDING_BOTTOM) {
+ m_nPadding[type] = nPadding;
+ }
+}
+
+void CAccordionWnd::SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemBackground[0] = crNormal;
+ m_crItemBackground[1] = crSel;
+}
+
+void CAccordionWnd::SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemFrame[0] = crNormal;
+ m_crItemFrame[1] = crSel;
+}
+
+void CAccordionWnd::SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemText[0] = crNormal;
+ m_crItemText[1] = crSel;
+}
+
+void CAccordionWnd::Init()
+{
+}
+
+void CAccordionWnd::Release()
+{
+ // delete
+ delete this;
+}
+
+/*
+ * 添加项目
+ * pszName -- 名称
+ * pWnd -- 绑定的窗口
+ * nExpandHeight -- 展开高度,如果为0则自动设置为窗口高
+ */
+void CAccordionWnd::AddItem(char* pszName, CWnd* pWnd, int nExpandHeight, BOOL bExpand/* = TRUE*/, BOOL bEnable/* = TRUE*/)
+{
+ ACCORDIONITEM* pItem = new ACCORDIONITEM;
+ memset(pItem, 0, sizeof(ACCORDIONITEM));
+ pItem->pWnd = pWnd;
+ pItem->bExpand = bExpand;
+ pItem->bEnable = bEnable;
+ strcpy_s(pItem->text, sizeof(pItem->text), pszName);
+ if (nExpandHeight == 0) {
+ RECT rect;
+ pWnd->GetWindowRect(&rect);
+ pItem->nExpandHeight = rect.bottom - rect.top;
+ }
+ else if (nExpandHeight == -1) {
+ pItem->nExpandHeight = -1;
+ }
+ else {
+ pItem->nExpandHeight = nExpandHeight;
+ }
+ m_vectorItems.push_back(pItem);
+
+
+ // 重新调整个子窗口的位置
+ ResizeItemWnd();
+}
+
+void CAccordionWnd::ResizeItemWnd()
+{
+ RECT rcClient, rcItemClient;
+ GetClientRect(m_hWnd, &rcClient);
+
+ for (size_t i = 0; i < m_vectorItems.size(); i++) {
+ ACCORDIONITEM* pItem = m_vectorItems.at(i);
+ if (pItem->pWnd != NULL) {
+ GetItemRect(rcClient, (UINT)i, &rcItemClient);
+ rcItemClient.top += ITEM_HEIGHT;
+ if (pItem->nExpandHeight == -1) {
+ rcItemClient.bottom = rcClient.bottom;
+ }
+ else {
+ rcItemClient.bottom = rcItemClient.top + pItem->nExpandHeight;
+ }
+
+ pItem->pWnd->MoveWindow(&rcItemClient);
+ pItem->pWnd->ShowWindow(pItem->bExpand ? SW_SHOW : SW_HIDE);
+ }
+ }
+}
+
+BOOL CAccordionWnd::GetItemHeaderRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
+{
+ RECT rcItem;
+ if (!GetItemRect(rcClient, nIndex, &rcItem)) {
+ return FALSE;
+ }
+
+ rcItem.bottom = rcItem.top + ITEM_HEIGHT;
+ CopyRect(lpRect, &rcItem);
+ return TRUE;
+}
+
+BOOL CAccordionWnd::GetItemRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
+{
+ if (nIndex >= m_vectorItems.size()) {
+ return FALSE;
+ }
+
+ RECT rcItemHeader;
+ rcItemHeader.left = rcClient.left + m_nPadding[PADDING_LEFT];
+ rcItemHeader.right = rcClient.right - m_nPadding[PADDING_RIGHT];
+ rcItemHeader.top = rcClient.top + m_nPadding[PADDING_TOP];
+ rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
+ for (size_t i = 0; i < m_vectorItems.size(); i++) {
+ ACCORDIONITEM* pItem = m_vectorItems.at(i);
+ if (pItem->bExpand) {
+ rcItemHeader.bottom += pItem->nExpandHeight;
+ }
+
+ if (i == nIndex) {
+ break;;
+ }
+
+ rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
+ rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
+ }
+
+
+ CopyRect(lpRect, &rcItemHeader);
+ return TRUE;
+}
+
+int CAccordionWnd::HitTest(POINT pt, int& nHitTest)
+{
+ int nRet = -1;
+ nHitTest = -1;
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ if (PtInRect(&rcClient, pt)) {
+ nRet = 1;
+ }
+
+ int nItemIndex = -1;
+ RECT rcItemHeader;
+ for (size_t i = 0; i < m_vectorItems.size(); i++) {
+ GetItemHeaderRect(rcClient, (unsigned int)i, &rcItemHeader);
+
+ if (PtInRect(&rcItemHeader, pt)) {
+ nItemIndex = (unsigned int)i;
+
+ break;
+ }
+ }
+
+ if (nItemIndex != -1) {
+ nRet = 2;
+ nHitTest = nItemIndex;
+ }
+
+ return nRet;
+}
+
+BOOL CAccordionWnd::Togle(unsigned int nIndex)
+{
+ if (nIndex >= m_vectorItems.size()) {
+ return FALSE;
+ }
+
+ ACCORDIONITEM* pItem = m_vectorItems[nIndex];
+ pItem->bExpand = !pItem->bExpand;
+
+
+ // 重新调整个子窗口的位置
+ ResizeItemWnd();
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ return TRUE;
+}
+
+void CAccordionWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
+{
+ HWND hParent;
+ hParent = GetParent(m_hWnd);
+ if (hParent != NULL) {
+ ACCORDION_NMHDR accordionWndnmhdr;
+ accordionWndnmhdr.nmhdr.hwndFrom = m_hWnd;
+ accordionWndnmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
+ accordionWndnmhdr.nmhdr.code = nCode;
+ accordionWndnmhdr.dwData = dwData;
+ accordionWndnmhdr.dwData1 = dwData1;
+ accordionWndnmhdr.dwData2 = dwData2;
+ SendMessage(hParent, WM_NOTIFY, (WPARAM)accordionWndnmhdr.nmhdr.idFrom, (LPARAM)&accordionWndnmhdr);
+ }
+}
+
+/*
+ * 拦截窗口消息函数
+ */
+LRESULT CALLBACK CAccordionWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
+ if (pAccordionWnd == NULL && uMsg != WM_NCCREATE)
+ {
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+
+
+ // 如果Hook则响应消息
+ ASSERT(hWnd);
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ return CAccordionWnd::OnNcCreate(hWnd, wParam, lParam);
+
+ case WM_DESTROY:
+ return pAccordionWnd->OnDestroy(wParam, lParam);
+
+ case WM_NCCALCSIZE:
+ return pAccordionWnd->OnNcCalcsize(wParam, lParam);
+
+ case WM_NCPAINT:
+ return pAccordionWnd->OnNcPaint(wParam, lParam);
+
+ case WM_PAINT:
+ return pAccordionWnd->OnPaint(wParam, lParam);
+
+ case WM_TIMER:
+ return pAccordionWnd->OnTimer(wParam, lParam);
+
+ case WM_MOUSEMOVE:
+ return pAccordionWnd->OnMouseMove(wParam, lParam);
+
+ case WM_LBUTTONDOWN:
+ return pAccordionWnd->OnLButtonDown(wParam, lParam);
+
+ case WM_LBUTTONUP:
+ return pAccordionWnd->OnLButtonUp(wParam, lParam);
+
+ case WM_MOUSEWHEEL:
+ return pAccordionWnd->OnMouseWheel(wParam, lParam);
+
+ case WM_SIZE:
+ return pAccordionWnd->OnSize(wParam, lParam);
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTALLKEYS;
+
+ default:
+ break;
+ }
+
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+/*
+ * WM_NCCREATE
+ * 窗口创建前的初始化工作
+ */
+LRESULT CAccordionWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+ CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
+ ASSERT(pAccordionWnd == NULL);
+
+ Hook(hWnd);
+ return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
+}
+
+/*
+ * WM_NCCALCSIZE
+ */
+LRESULT CAccordionWnd::OnNcCalcsize(WPARAM wParam, LPARAM lParam)
+{
+ if (!m_bShadow) {
+ return ::DefWindowProc(m_hWnd, WM_NCCALCSIZE, wParam, lParam);
+ }
+
+
+ LPRECT lprcWnd = (LPRECT)lParam;
+ lprcWnd->left += BORDER;
+ lprcWnd->top += BORDER;
+ lprcWnd->right -= (BORDER + SHADOWWIDE);
+ lprcWnd->bottom -= (BORDER + SHADOWWIDE);
+
+ return 0;
+}
+
+/*
+ * WM_DESTROY
+ * 窗口销毁时
+ */
+LRESULT CAccordionWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
+{
+ Release();
+ return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
+}
+
+
+/*
+ * WM_TIMER
+ */
+LRESULT CAccordionWnd::OnTimer(WPARAM wParam, LPARAM lParam)
+{
+ int nTimerId = (int)wParam;
+ if (m_nTimerId == nTimerId) {
+
+ POINT pt;
+ ::GetCursorPos(&pt);
+ ::ScreenToClient(m_hWnd, &pt);
+
+ int nRet, nHitTest;
+ nRet = HitTest(pt, nHitTest);
+ if (m_nCheckHoverItem != nHitTest) {
+ KillTimer(m_hWnd, m_nTimerId);
+ m_nHoverItem = nHitTest;
+ m_nCheckHoverItem = nHitTest;
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
+}
+
+/*
+ * WM_MOUSEMOVE
+ * 鼠标移动时,检测鼠标位置并回调给主窗口
+ */
+LRESULT CAccordionWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ pt.x = (int)LOWORD(lParam);
+ pt.y = (int)HIWORD(lParam);
+
+ int nRet, nHitTest;
+ nRet = HitTest(pt, nHitTest);
+
+ if (nRet == 2) {
+ ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
+ if (pItem != NULL && pItem->bEnable) {
+ ::SetCursor(LoadCursor(NULL, IDC_HAND));
+ }
+ }
+ else {
+ ::SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+
+ int nLastItem = m_nHoverItem;
+ if (m_nHoverItem != nHitTest) {
+ m_nHoverItem = nHitTest;
+
+ RECT rcClient, rcLastItemClient, rcCurItemClient;
+ GetClientRect(m_hWnd, &rcClient);
+ GetItemRect(rcClient, nLastItem, &rcLastItemClient);
+ ::InvalidateRect(m_hWnd, &rcLastItemClient, nHitTest < 0);
+
+ if (nHitTest >= 0) {
+ ACCORDIONITEM* pItem = m_vectorItems.at(nHitTest);
+ if (!pItem->bEnable) {
+ m_nHoverItem = -1;
+ }
+ else {
+ KillTimer(m_hWnd, m_nTimerId);
+ m_nTimerId = SetTimer(m_hWnd, TIMER_ID_CHECKHOVER, 200, NULL);
+ m_nCheckHoverItem = m_nHoverItem;
+
+ GetItemRect(rcClient, m_nHoverItem, &rcCurItemClient);
+ ::InvalidateRect(m_hWnd, &rcCurItemClient, TRUE);
+ }
+ }
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
+}
+
+/*
+ * WM_LBUTTONDOWN
+ * 鼠标左键下压
+ */
+LRESULT CAccordionWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ pt.x = (int)LOWORD(lParam);
+ pt.y = (int)HIWORD(lParam);
+
+ int nRet, nHitTest;
+ nRet = HitTest(pt, nHitTest);
+
+ if (nRet == 2) {
+ ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
+ if (pItem != NULL && pItem->bEnable) {
+ ::SetCursor(LoadCursor(NULL, IDC_HAND));
+ }
+ }
+ else {
+ ::SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
+}
+
+/*
+ * WM_LBUTTONUP
+ * 鼠标左键释放
+ */
+LRESULT CAccordionWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ pt.x = (int)LOWORD(lParam);
+ pt.y = (int)HIWORD(lParam);
+
+ int nRet, nHitTest;
+ nRet = HitTest(pt, nHitTest);
+
+ if (nRet == 2) {
+ ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
+ if (pItem != NULL && pItem->bEnable) {
+ ::SetCursor(LoadCursor(NULL, IDC_HAND));
+ Togle(nHitTest);
+ }
+ }
+ else {
+ ::SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_LBUTTONUP, wParam, lParam);
+}
+
+/*
+ * WM_MOUSEWHEEL
+ * 鼠标滚轮滚动时,缩放图像
+ */
+LRESULT CAccordionWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
+{
+ return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam);
+}
+
+/*
+ * WM_NCPAINT
+ */
+LRESULT CAccordionWnd::OnNcPaint(WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NCPAINT, wParam, lParam);
+
+
+ // 然后画边框
+ long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE);
+ if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) {
+
+ RECT rcWindow, rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
+ ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
+ GetWindowRect(m_hWnd, &rcWindow);
+ ::OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top);
+ ::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
+
+ HRGN hRgnWnd = CreateRectRgnIndirect(&rcWindow);
+ HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
+
+ HDC hDC = GetWindowDC(m_hWnd);
+ ::SelectClipRgn(hDC, hRgnWnd);
+ ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
+
+
+ // 没有阴影的边框
+ if (!m_bShadow) {
+ HBRUSH hBrushBK, hBrushFrame;
+ hBrushBK = CreateSolidBrush(m_crBkgnd);
+ ::FillRect(hDC, &rcWindow, hBrushBK);
+ DeleteObject(hBrushBK);
+
+ hBrushFrame = CreateSolidBrush(m_crFrame);
+ ::FrameRect(hDC, &rcWindow, hBrushFrame);
+ DeleteObject(hBrushFrame);
+ }
+
+ // 有阴影的边框
+ else {
+
+ RECT rcFrame0, rcFrame1;
+ rcFrame0.left = rcWindow.left + SHADOWWIDE;
+ rcFrame0.top = rcWindow.top + SHADOWWIDE;
+ rcFrame0.right = rcWindow.right;
+ rcFrame0.bottom = rcWindow.bottom;
+ rcFrame1.left = rcWindow.left;
+ rcFrame1.top = rcWindow.top;
+ rcFrame1.right = rcWindow.right - SHADOWWIDE;
+ rcFrame1.bottom = rcWindow.bottom - SHADOWWIDE;
+
+
+ // 背景框和对话框(父窗体)背景色一致
+ HBRUSH hBrushBK, hBrushFrame;
+ hBrushBK = CreateSolidBrush(m_crShadowBkgnd);
+ ::FillRect(hDC, &rcWindow, hBrushBK);
+ DeleteObject(hBrushBK);
+
+
+ // 阴影框
+ BYTE r = GetRValue(m_crShadowBkgnd);
+ BYTE g = GetGValue(m_crShadowBkgnd);
+ BYTE b = GetBValue(m_crShadowBkgnd);
+ BYTE rstep = (r - GetRValue(m_crFrame)) / SHADOWWIDE;
+ BYTE gstep = (r - GetGValue(m_crFrame)) / SHADOWWIDE;
+ BYTE bstep = (r - GetBValue(m_crFrame)) / SHADOWWIDE;
+
+ for (int i = 0; i < SHADOWWIDE; i++) {
+ hBrushBK = CreateSolidBrush(RGB(r - i * rstep, g - i * gstep, b - i * bstep));
+ ::FillRect(hDC, &rcFrame0, hBrushBK);
+ DeleteObject(hBrushBK);
+ rcFrame0.bottom -= 1;
+ rcFrame0.right -= 1;
+ }
+
+
+ // 前景框
+ hBrushBK = CreateSolidBrush(m_crBkgnd);
+ ::FillRect(hDC, &rcFrame1, hBrushBK);
+ DeleteObject(hBrushBK);
+
+ hBrushFrame = CreateSolidBrush(m_crFrame);
+ ::FrameRect(hDC, &rcFrame1, hBrushFrame);
+ DeleteObject(hBrushFrame);
+ }
+
+
+ ::DeleteObject(hRgnWnd);
+ ::DeleteObject(hRgnClient);
+ ReleaseDC(m_hWnd, hDC);
+ }
+
+ return lRet;
+}
+
+/*
+ * WM_PAINT
+ */
+LRESULT CAccordionWnd::OnPaint(WPARAM wParam, LPARAM lParam)
+{
+ HDC hDC, hMemDC;
+ HBITMAP hBitmap;
+ RECT rcClient;
+ CString strText;
+ HFONT hFont;
+ HBRUSH hBrushBK;
+
+
+ // BeginPaint
+ PAINTSTRUCT ps;
+ hDC = BeginPaint(m_hWnd, &ps);
+ GetClientRect(m_hWnd, &rcClient);
+
+ hMemDC = ::CreateCompatibleDC(hDC);
+ hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
+ rcClient.bottom - rcClient.top);
+ ::SelectObject(hMemDC, hBitmap);
+ ::SetBkMode(hMemDC, TRANSPARENT);
+
+
+ // 背景颜色
+ hBrushBK = CreateSolidBrush(m_crBkgnd);
+ ::FillRect(hMemDC, &rcClient, hBrushBK);
+ DeleteObject(hBrushBK);
+
+
+ // 绘子项列表
+ hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ ::SelectObject(hMemDC, hFont);
+
+ HPEN hPenSeparate = ::CreatePen(PS_SOLID, 1, m_crSeparateLine);
+ RECT rcItem, rcItemHeader;
+ for (size_t i = 0; i < m_vectorItems.size(); i++) {
+ ACCORDIONITEM* pItem = m_vectorItems[i];
+ GetItemRect(rcClient, (UINT)i, &rcItem);
+ GetItemHeaderRect(rcClient, (UINT)i, &rcItemHeader);
+
+
+ // 热点项的背景色和边框
+ if (m_nHoverItem == (int)i) {
+ HBRUSH hbrItemHeaderBackground = CreateSolidBrush(m_crHoverItemBackground);
+ HBRUSH hbrItemFrame = CreateSolidBrush(m_crHoverItemFrame);
+
+ HRGN hRgn = CreateRoundRectRgn(rcItemHeader.left, rcItemHeader.top, rcItemHeader.right, rcItemHeader.bottom, 2, 2);
+ ::FillRgn(hMemDC, hRgn, hbrItemHeaderBackground);
+ ::FrameRgn(hMemDC, hRgn, hbrItemFrame, 1, 1);
+ ::DeleteObject(hbrItemHeaderBackground);
+ ::DeleteObject(hbrItemFrame);
+ ::DeleteObject(hRgn);
+ }
+
+
+ // 箭头
+ BOOL bDrawIcon = DrawIconEx(hMemDC, rcItemHeader.left + (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2, rcItemHeader.top + (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2,
+ pItem->bExpand ? m_hIconExpand : m_hIconClose, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE, 0, 0, DI_NORMAL);
+
+
+ // 文本
+ ::SetTextColor(hMemDC, m_nHoverItem == (int)i ? m_crItemText[1] : m_crItemText[0]);
+ RECT rcText;
+ rcText.left = rcItemHeader.left + (bDrawIcon ? ITEM_HEIGHT : (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2);
+ rcText.top = rcItemHeader.top;
+ rcText.right = rcItemHeader.right;
+ rcText.bottom = rcItemHeader.bottom;
+ ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+
+
+ // 文本右边分隔线
+ SIZE sizeText;
+ GetTextExtentPoint32(hMemDC, pItem->text, (int)strlen(pItem->text), &sizeText);
+
+
+ HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPenSeparate);
+ MoveToEx(hMemDC, rcText.left + sizeText.cx + 10, rcItemHeader.top + (rcItemHeader.bottom - rcItemHeader.top - 1) / 2, NULL);
+ LineTo(hMemDC, rcItemHeader.right - 10, rcItemHeader.top + (rcItemHeader.bottom - rcItemHeader.top - 1) / 2);
+ ::SelectObject(hMemDC, hOldPen);
+
+
+ rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
+ rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
+ }
+ ::DeleteObject(hPenSeparate);
+
+
+ // EndPaint
+ ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
+ hMemDC, 0, 0, SRCCOPY);
+ EndPaint(m_hWnd, &ps);
+ ::DeleteObject(hBitmap);
+ ::DeleteDC(hMemDC);
+
+
+ return 1;
+}
+
+/*
+ * WM_SIZE
+ */
+LRESULT CAccordionWnd::OnSize(WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
+
+ ResizeItemWnd();
+
+ return lRet;
+}
+
+/*
+ * 设置背景色
+ * color -- 背景色
+ */
+void CAccordionWnd::SetBkgndColor(COLORREF color)
+{
+ m_crBkgnd = color;
+}
+
+
+/*
+ * 设置阴影的背景色(即父窗口的背景)
+ * color -- 背景色
+ */
+void CAccordionWnd::SetShadowBkgnd(COLORREF color)
+{
+ m_crShadowBkgnd = color;
+}
+
+/*
+ * 设置边框颜色
+ * color -- 边框颜色
+ */
+void CAccordionWnd::SetFrameColor(COLORREF color, BOOL bShadow/* = FALSE*/)
+{
+ m_crFrame = color;
+ m_bShadow = bShadow;
+ SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+}
+
--
Gitblit v1.9.3