#include "./setupPage.h" #include "./setupListbox.h" #include "./setupGroupList.h" #include "./setupImage.h" #include "../common.h" #include "../resource.h" #include "../api__ml_online.h" #include "../../nu/windowsTheme.h" #include //#include static ATOM SERVICELIST_PROP = 0; #define SLF_UNICODE 0x0001 #define SLF_DRAGMOVE 0x0002 typedef BOOL (SetupListboxItem::*ITEMMOUSEPROC)(SetupListbox*, const RECT*, UINT, POINT); class Listbox : public SetupListbox { protected: Listbox(HWND hListbox, SetupGroupList *groupList); ~Listbox(); public: static HRESULT AttachToWindow(HWND hwndListbox, SetupGroupList *groupList, SetupListbox **pInstance); public: HWND GetHwnd() { return hwnd; } HFONT GetFont() { return (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0L); } LRESULT CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL MeasureItem(INT itemId, UINT *cx, UINT *cy); BOOL DrawItem(HDC hdc, const RECT *itemRect, INT itemId, UINT itemState, UINT itemAction); INT_PTR KeyToItem(INT vKey, INT caretPos); INT_PTR CharToItem(INT vKey, INT caretPos); BOOL DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect); BOOL GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize); INT GetCheckboxThemeState(BOOL checked, UINT state); INT HitTest(POINT pt, RECT *prcItem); void SetCapture(SetupListboxItem *item); SetupListboxItem *GetCapture(); void ReleaseCapture(); BOOL InvalidateRect(const RECT *prcInvalidate, BOOL fErase); BOOL InvalidateItem(INT itemId, BOOL fErase); void UpdateCount(); BOOL DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg); BOOL GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize); INT GetPageCount(); INT GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut); INT GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut); SetupListboxItem *GetSelection(); BOOL SetSelection(SetupListboxItem *item); BOOL GetIndex(SetupListboxItem *item, INT *iItem); BOOL DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt); HMENU GetContextMenu(UINT menuId); protected: friend static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam); void OnDestroy(); void GetItemRect(INT itemId, RECT *prcItem); SetupImage *GetExpandboxImage(HDC hdc, BOOL fExpanded); void OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc); void OnMouseLeave(); void OnEraseBkGround(HDC hdc); void OnCaptureChanged(HWND hwndGained); void NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain); void OnCommand(INT commandId, INT eventId, HWND hControl); protected: HWND hwnd; UINT flags; WNDPROC originalProc; UXTHEME buttonTheme; SetupGroupList *groups; INT mouseoverId; INT capturedId; SetupImage *expandedImage; SetupImage *collapsedImage; }; #define GetList(__hwnd) ((Listbox*)GetPropW((__hwnd), MAKEINTATOM(SERVICELIST_PROP))) HRESULT SetupListbox::CreateInstance(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance) { return Listbox::AttachToWindow(hListbox, groupList, pInstance); } SetupListbox *SetupListbox::GetInstance(HWND hListbox) { return GetList(hListbox); } Listbox::Listbox(HWND hListbox, SetupGroupList *groupList) : hwnd(hListbox), flags(0), originalProc(NULL), buttonTheme(NULL), groups(groupList), mouseoverId(LB_ERR), capturedId(LB_ERR), expandedImage(NULL), collapsedImage(NULL) { if (IsWindowUnicode(hwnd)) flags |= SLF_UNICODE; buttonTheme = (UxIsAppThemed()) ? UxOpenThemeData(hwnd, L"Button") : NULL; groups->AddRef(); UpdateCount(); } Listbox::~Listbox() { if (NULL != hwnd) { RemoveProp(hwnd, MAKEINTATOM(SERVICELIST_PROP)); if (NULL != originalProc) { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)originalProc); CallPrevProc(WM_DESTROY, 0, 0L); } } if (NULL != groups) groups->Release(); if (NULL != buttonTheme) UxCloseThemeData(buttonTheme); if (NULL != expandedImage) expandedImage->Release(); if (NULL != collapsedImage) collapsedImage->Release(); } HRESULT Listbox::AttachToWindow(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance) { if (0 == SERVICELIST_PROP) { SERVICELIST_PROP = GlobalAddAtom(TEXT("omSetupListbox")); if (0 == SERVICELIST_PROP) return E_UNEXPECTED; } if(NULL == hListbox || !IsWindow(hListbox) || NULL == groupList) return E_INVALIDARG; Listbox *list = new Listbox(hListbox, groupList); if (NULL == list) return E_OUTOFMEMORY; list->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hListbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)Listbox_WindowProc); if (NULL == list->originalProc || !SetProp(hListbox, MAKEINTATOM(SERVICELIST_PROP), list)) { if (NULL != list->originalProc) SetWindowLongPtr(hListbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)list->originalProc); delete(list); return E_FAIL; } if (NULL != pInstance) *pInstance = list; return S_OK; } LRESULT Listbox::CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { return (0 != (SLF_UNICODE & flags)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); } LRESULT Listbox::CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { return (0 != (SLF_UNICODE & flags)) ? CallWindowProcW(originalProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(originalProc, hwnd, uMsg, wParam, lParam); } void Listbox::UpdateCount() { SendMessage(hwnd, WM_SETREDRAW, FALSE, 0L); INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L); size_t recordCount = (NULL != groups) ? groups->GetListboxCount() : 0; SendMessage(hwnd, LB_SETCOUNT, (WPARAM)recordCount, 0L); SetupListboxItem *item; UINT cy, maxCY = 0; for (size_t i = 0; i < recordCount; i++) { if (SUCCEEDED(groups->FindListboxItem(i, &item)) && item->MeasureItem(this, NULL, &cy) && cy > maxCY) { maxCY = cy; } } SendMessage(hwnd, LB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)maxCY); if (recordCount > 0) { if (iSelected < 0) iSelected = 0; if ((size_t)iSelected >= recordCount) iSelected = (INT)(recordCount - 1); SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iSelected, TRUE); SendMessage(hwnd, LB_SETANCHORINDEX, (WPARAM)iSelected, 0L); SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iSelected, 0L); } SendMessage(hwnd, WM_SETREDRAW, TRUE, 0L); } BOOL Listbox::MeasureItem(INT itemId, UINT *cx, UINT *cy) { SetupListboxItem *item; HRESULT hr = groups->FindListboxItem(itemId, &item); return (SUCCEEDED(hr)) ? item->MeasureItem(this, cx, cy) : FALSE; } BOOL Listbox::DrawItem(HDC hdc, const RECT *prcItem, INT itemId, UINT itemState, UINT itemAction) { SetupListboxItem *item; HRESULT hr = groups->FindListboxItem(itemId, &item); if (FAILED(hr)) return FALSE; if (0 != (ODS_SELECTED & itemState) && GetFocus() != hwnd) itemState |= ODS_INACTIVE; if (item->IsDisabled()) itemState |= ODS_DISABLED; return item->DrawItem(this, hdc, prcItem, itemState); } INT Listbox::GetPageCount() { RECT clientRect; if (NULL == hwnd || !GetClientRect(hwnd, &clientRect)) return 0; INT itemHeight = (INT)SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0L); return (clientRect.bottom - clientRect.top) / itemHeight; } INT Listbox::GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut) { INT iLast = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L); if (iLast >= 0) iLast--; SetupListboxItem *testItem; while(iItem++ < iLast) { if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem))) { if (FALSE == testItem->IsDisabled()) break; } } if (NULL != itemOut) { *itemOut = (iItem <= iLast) ? testItem : NULL; } return (iItem <= iLast) ? iItem : LB_ERR; } INT Listbox::GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut) { SetupListboxItem *testItem; while(iItem-- > 0) { if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem))) { if (FALSE == testItem->IsDisabled()) break; } } if (NULL != itemOut) { *itemOut = (iItem >= 0) ? testItem : NULL; } return (iItem >= 0) ? iItem : LB_ERR; } SetupListboxItem *Listbox::GetSelection() { INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L); if (LB_ERR == iSelected) return NULL; SetupListboxItem *item; return (SUCCEEDED(groups->FindListboxItem(iSelected, &item))) ? item : NULL; } BOOL Listbox::SetSelection(SetupListboxItem *item) { INT iItem = LB_ERR; if (NULL != item) { iItem = groups->GetListboxItem(item); if (LB_ERR == iItem) return FALSE; } BOOL resultOk = (LB_ERR != SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iItem, 0L)); if (LB_ERR == iItem) resultOk = TRUE; if (LB_ERR != iItem) { HWND hParent = GetParent(hwnd); if (NULL != hParent) SendMessage(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SELCHANGE), (LPARAM)hwnd); } return resultOk; } BOOL Listbox::GetIndex(SetupListboxItem *item, INT *iItem) { if (NULL == iItem) return FALSE; *iItem = (NULL != item && NULL != groups) ? groups->GetListboxItem(item) : LB_ERR; return (LB_ERR != *iItem); } INT_PTR Listbox::KeyToItem(INT vKey, INT iCaret) { SetupListboxItem *item; HRESULT hr = groups->FindListboxItem(iCaret, &item); if (FAILED(hr)) return -1; RECT itemRect; GetItemRect(iCaret, &itemRect); INT_PTR result = item->KeyToItem(this, &itemRect, vKey); if (-1 != result) return result; INT iTarget, iCount; switch(vKey) { case VK_UP: case VK_LEFT: iTarget = GetPrevEnabledItem(iCaret, NULL); if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L); SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE); return -2; case VK_DOWN: case VK_RIGHT: iTarget = GetNextEnabledItem(iCaret, NULL); if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)iCaret, 0L); return -2; case VK_HOME: if (iCaret > 0) { SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L); iTarget = GetNextEnabledItem(-1, NULL); if (iTarget >= iCaret) iTarget = LB_ERR; if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE); } return -2; case VK_PRIOR: if (iCaret > 0) { INT iTop = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L); if (iTop == iCaret) { INT iPage = iCaret - GetPageCount() + 1; iTop = (iPage <= 0) ? 0 : (iPage - 1); } iTarget = GetPrevEnabledItem(iTop + 1, NULL); if (LB_ERR == iTarget) { SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L); iTarget = GetNextEnabledItem(iTop, NULL); if (iTarget > iCaret) iTarget = LB_ERR; } if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE); } return -2; case VK_END: iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L); if (iCount > 0 && iCaret != (iCount - 1)) { SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L); iTarget = GetPrevEnabledItem(iCount, NULL); if (iTarget <= iCaret) iTarget = LB_ERR; if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE); } return -2; case VK_NEXT: iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L); if (iCount > 0 && iCaret != (iCount - 1)) { INT iPage = GetPageCount(); INT iBottom = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L) + iPage - 1; if (iBottom == iCaret) { iBottom += iPage; if (iBottom >= iCount) iBottom = iCount -1; } iTarget = GetNextEnabledItem(iBottom - 1, NULL); if (LB_ERR == iTarget) { SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L); iTarget = GetPrevEnabledItem(iBottom, NULL); if (iTarget < iCaret) iTarget = LB_ERR; } if (LB_ERR != iTarget) return iTarget; SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE); } return -2; } return result; } INT_PTR Listbox::CharToItem(INT vKey, INT caretPos) { return -2; //SetupListboxItem *item; //HRESULT hr = groups->FindListboxItem(caretPos, &item); //return (SUCCEEDED(hr)) ? item->CharToItem(this, vKey) : -1; } INT Listbox::GetCheckboxThemeState(BOOL checked, UINT state) { if (FALSE != checked) { if (0 != (ODS_DISABLED & state)) return CBS_CHECKEDDISABLED; if (0 != (ODS_HOTLIGHT & state)) return CBS_CHECKEDHOT; if (0 != (ODS_SELECTED & state)) return CBS_CHECKEDPRESSED; return CBS_CHECKEDNORMAL; } if (0 != (ODS_DISABLED & state)) return CBS_UNCHECKEDDISABLED; if (0 != (ODS_HOTLIGHT & state)) return CBS_UNCHECKEDHOT; if (0 != (ODS_SELECTED & state)) return CBS_UNCHECKEDPRESSED; return CBS_UNCHECKEDNORMAL; } BOOL Listbox::DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect) { if (NULL != buttonTheme) { INT stateId = GetCheckboxThemeState(checked, state); if (SUCCEEDED(UxDrawThemeBackground(buttonTheme, hdc, BP_CHECKBOX, stateId, pRect, pClipRect))) return TRUE; } UINT stateId = DFCS_BUTTONCHECK; if (FALSE != checked) stateId |= DFCS_CHECKED; if (0 != (ODS_DISABLED & state)) stateId |= DFCS_INACTIVE; if (0 != (ODS_HOTLIGHT & state)) stateId |= DFCS_HOT; if (0 != (ODS_SELECTED & state)) stateId |= DFCS_PUSHED; return DrawFrameControl(hdc, (LPRECT)pRect,DFC_BUTTON, stateId); } BOOL Listbox::GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize) { if (NULL != buttonTheme) { HDC hdcMine = NULL; if (NULL == hdc) { hdcMine = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); hdc = hdcMine; } INT stateId = GetCheckboxThemeState(checked, state); HRESULT hr = UxGetThemePartSize(buttonTheme, hdc, BP_CHECKBOX, stateId, NULL, TS_DRAW, pSize); if (NULL != hdcMine) ReleaseDC(hwnd, hdcMine); if (SUCCEEDED(hr)) return TRUE; } pSize->cx = 13; pSize->cy = 13; return TRUE; } void Listbox::OnDestroy() { delete(this); } INT Listbox::HitTest(POINT pt, RECT *prcItem) { RECT itemRect; INT itemId = (INT)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELONG(pt.x, pt.y)); if (LB_ERR == itemId || LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect) || FALSE == PtInRect(&itemRect, pt)) { return LB_ERR; } if (NULL != prcItem) CopyRect(prcItem, &itemRect); return itemId; } void Listbox::GetItemRect(INT itemId, RECT *prcItem) { if (LB_ERR == ::SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)prcItem)) SetRectEmpty(prcItem); } BOOL Listbox::DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt) { if (WM_MOUSEMOVE == mouseEvent && 0 != ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) & mouseFlags)) { flags |= SLF_DRAGMOVE; } else { flags &= ~SLF_DRAGMOVE; } return (0 != (SLF_DRAGMOVE & flags)); } void Listbox::OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc) { POINT pt; POINTSTOPOINT(pt, pts); SetupListboxItem *item; RECT itemRect; if (LB_ERR != capturedId) { if (SUCCEEDED(groups->FindListboxItem(capturedId, &item))) { GetItemRect(capturedId, &itemRect); if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt))) { CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts)); } return; } capturedId = LB_ERR; } if (DoDragAndDrop(mouseEvent, mouseFlags, pt)) return; INT itemId = HitTest(pt, &itemRect); if (mouseoverId != itemId) { if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item))) { RECT leaveRect; GetItemRect(mouseoverId, &leaveRect); item->MouseLeave(this, &leaveRect); } mouseoverId = itemId; TRACKMOUSEEVENT tm; tm.cbSize = sizeof(TRACKMOUSEEVENT); tm.hwndTrack = hwnd; tm.dwFlags = TME_LEAVE; if (LB_ERR == mouseoverId) tm.dwFlags |= TME_CANCEL; TrackMouseEvent(&tm); } if (LB_ERR != mouseoverId) { if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item))) { BOOL callListbox = FALSE; if (FALSE != item->IsDisabled()) { switch(mouseEvent) { case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case 0x020C /*WM_XBUTTONUP*/: callListbox = TRUE; break; } } else { if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt))) { callListbox = TRUE; } } if (FALSE != callListbox) { CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts)); } return; } } if (FALSE != fDefaultHandler) { CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts)); } } void Listbox::OnMouseLeave() { if (LB_ERR != mouseoverId) { SetupListboxItem *item; INT itemId = mouseoverId; mouseoverId = LB_ERR; if (SUCCEEDED(groups->FindListboxItem(itemId, &item))) { RECT itemRect; GetItemRect(itemId, &itemRect); if (item->MouseLeave(this, &itemRect)) return; } } CallPrevProc(WM_MOUSELEAVE, 0, 0L); } void Listbox::SetCapture(SetupListboxItem *item) { INT prevCapturedId = capturedId; capturedId = (NULL != item) ? groups->GetListboxItem(item) : LB_ERR; NotifyReleaseCapture(prevCapturedId, item); if (LB_ERR != capturedId && ::GetCapture() != hwnd) ::SetCapture(hwnd); } SetupListboxItem *Listbox::GetCapture() { SetupListboxItem *capturedItem; if (LB_ERR == capturedId || FAILED(groups->FindListboxItem(capturedId, &capturedItem))) capturedItem = NULL; return capturedItem; } void Listbox::ReleaseCapture() { if (LB_ERR != capturedId) { INT prevCapturedId = capturedId; capturedId = LB_ERR; NotifyReleaseCapture(prevCapturedId, NULL); if (::GetCapture() == hwnd) ::ReleaseCapture(); } } void Listbox::NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain) { if (LB_ERR == itemId) return; SetupListboxItem *item; if (SUCCEEDED(groups->FindListboxItem(itemId, &item))) { RECT itemRect; GetItemRect(itemId, &itemRect); item->CaptureChanged(this, &itemRect, itemGain); } } void Listbox::OnCaptureChanged(HWND hwndGained) { if (hwnd != hwndGained && LB_ERR != capturedId) { INT prevCapturedId = capturedId; capturedId = LB_ERR; NotifyReleaseCapture(prevCapturedId, NULL); } } BOOL Listbox::InvalidateRect(const RECT *prcInvalidate, BOOL fErase) { return ::InvalidateRect(hwnd, prcInvalidate, fErase); } BOOL Listbox::InvalidateItem(INT itemId, BOOL fErase) { if (itemId < 0) return FALSE; RECT itemRect; if (LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect)) return FALSE; return ::InvalidateRect(hwnd, &itemRect, fErase); } void Listbox::OnEraseBkGround(HDC hdc) { INT iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L); RECT clientRect, itemRect; GetClientRect(hwnd, &clientRect); if (iCount > 0 && LB_ERR != SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)(iCount - 1), (LPARAM)&itemRect)) { clientRect.top = itemRect.top; } if (clientRect.top < clientRect.bottom) { HBRUSH hb = NULL; HWND hParent = GetParent(hwnd); if (NULL != hParent) { hb = (HBRUSH)SendMessage(hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc, (LPARAM)hwnd); } if (NULL == hb) { hb = GetSysColorBrush(COLOR_WINDOW); } FillRect(hdc, &clientRect, hb); } } void Listbox::OnCommand(INT commandId, INT eventId, HWND hControl) { if (NULL == hControl) { SetupListboxItem *item = GetSelection(); if (NULL != item) { item->Command(this, commandId, eventId); } } } SetupImage *Listbox::GetExpandboxImage(HDC hdc, BOOL fExpanded) { if (fExpanded) { if (NULL == expandedImage) expandedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(137), 3); return expandedImage; } if (NULL == collapsedImage) collapsedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(135), 3); return collapsedImage; } BOOL Listbox::DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg) { SetupImage *image = GetExpandboxImage(hdc, fExpanded); return (NULL != image) ? image->DrawImage(hdc, pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom- pRect->top, 0, 0, rgbBk, rgbFg) : FALSE; } BOOL Listbox::GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize) { SetupImage *image = GetExpandboxImage(hdc, fExpanded); return (NULL != image) ? image->GetSize(pSize) : FALSE; } HMENU Listbox::GetContextMenu(UINT menuId) { HMENU baseMenu = WASABI_API_LOADMENUW(IDR_SETUPMENU); if (NULL == baseMenu) return NULL; switch(menuId) { case menuGroupContext: return GetSubMenu(baseMenu, 0); } return NULL; } LRESULT Listbox::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_DESTROY: OnDestroy(); return 0; case WM_MOUSEMOVE: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::MouseMove); return 0; case WM_LBUTTONDOWN: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDown); return 0; case WM_LBUTTONUP: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::LButtonUp); return 0; case WM_LBUTTONDBLCLK: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDblClk); return 0; case WM_RBUTTONDOWN: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::RButtonDown); return 0; case WM_RBUTTONUP: OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::RButtonUp); return 0; case WM_MOUSELEAVE: OnMouseLeave(); return 0; case WM_CAPTURECHANGED: OnCaptureChanged((HWND)lParam); break; case WM_ERASEBKGND: OnEraseBkGround((HDC)wParam); return TRUE; case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return 0; } return CallPrevProc(uMsg, wParam, lParam); } static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { Listbox *list = GetList(hwnd); if (NULL != list) return list->WindowProc(uMsg, wParam, lParam); return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); }