#define APSTUDIO_READONLY_SYMBOLS #include "main.h" #include "./setup.h" #include "./setup_resource.h" #include "./loadimage.h" #include "./langutil.h" #include "../nu/AutoWide.h" #include "api.h" #define HEADER_FONT_NAME "Arial"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS" #define HEADER_FONT_SIZE 13 //11 #define HEADER_FONT_ITALIC FALSE #define HEADER_FONT_WEIGHT FW_MEDIUM #define HEADER_TEXT_COLOR RGB(255,255,255)//RGB(16, 72, 148)//RGB(7, 30, 140) #define HEADER_BORDER_COLOR RGB(236, 233, 216) #define HEADER_PAGENUM_FONT_NAME "Lucida Sans Unicode"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS" #define HEADER_PAGENUM_FONT_SIZE 10 #define HEADER_PAGENUM_FONT_ITALIC FALSE #define HEADER_PAGENUM_FONT_WEIGHT FW_SEMIBOLD//FW_MEDIUM #define HEADER_PAGENUM_TEXT_COLOR RGB(210,120,42) #define NAVIGATION_FONT_NAME "Arial" #define NAVIGATION_FONT_SIZE 9 #define NAVIGATION_FONT_ITALIC FALSE #define NAVIGATION_FONT_WEIGHT FW_MEDIUM #define NAVIGATION_SEL_FONT_NAME "Arial" #define NAVIGATION_SEL_FONT_SIZE 10 #define NAVIGATION_SEL_FONT_ITALIC FALSE #define NAVIGATION_SEL_FONT_WEIGHT FW_MEDIUM//FW_SEMIBOLD #define NAVIGATION_SEL_TEXT_COLOR RGB(252, 252, 255) #define NAVIGATION_TEXT_COLOR RGB(222, 225, 234) #define NAVIGATION_BACK_COLOR RGB(137,145,156)//RGB(150,156,163) #define NAVIGATION_PADDING_LEFT 0 #define NAVIGATION_PADDING_RIGHT 0 #define PAGE_BACK_COLOR RGB(236, 234, 232) typedef struct _UI { ULONG ref; HBRUSH hbPage; HBRUSH hbHeader; HBRUSH hbNavItemSel; HBRUSH hbNavBack; HFONT hfHeader; HFONT hfNavItem; HFONT hfNavItemSel; HFONT hfHeaderPageNum; INT nHdrTxtHeight; INT nHdrPageTxtHeight; INT nNavTxtHeight; INT nNavTxtSelHeight; INT nHdrHeight; INT nNavItemHeight; COLORREF rgbPageBk; } UI; typedef struct _SPTHEME { WNDPROC fnOldProc; UI *pui; BOOL bUnicode; } SPTHEME; static WASetup *g_pAttachInstance = NULL; static BOOL bUseMarquee = -1; static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static INT ConvertFontHeight(HWND hwnd, INT ptHeight); static DWORD GetHighestFontQuality(void); static BOOL InitializeUI(UI *pui, HWND hwndCtrl); static BOOL ReleaseUI(UI *pui); static const wchar_t *GetUnknownStr(void); static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static BOOL JobStatus_Advance(HWND hwndStatus); WASetup::WASetup(void) : ref((size_t)1), hwnd(NULL), hwndActive(NULL), nPageActive((size_t)-1), pui(NULL), hWinamp(NULL) { } WASetup::~WASetup(void) { if (hwnd && IsWindow(hwnd)) DestroyWindow(hwnd); size_t index; index = pageList.size(); while(index--) { pageList[index]->Release(); } index = jobList.size(); while(index--) { jobList[index]->Release(); } } svc_setup *WASetup::CreateInstance() { WASetup *instance = new WASetup(); return (svc_setup*)instance; } int WASetup::AddRef(void) { return ++ref; } int WASetup::Release(void) { if (1 == ref) { delete(this); return 0; } return --ref; } HRESULT WASetup::InsertPage(ifc_setuppage *pPage, int* pIndex) { size_t index; if (!pIndex || !pPage) return E_INVALIDARG; index = *pIndex; if (index >= pageList.size()) { index = pageList.size(); pageList.push_back(pPage); } else { //pageList.insertBefore(*pIndex, pPage); pageList.insert(pageList.begin() + index, pPage); } *pIndex = (int)index; pPage->AddRef(); return S_OK; } HRESULT WASetup::RemovePage(size_t index) { if (index >= pageList.size()) return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); pageList[index]->Release(); pageList.erase(pageList.begin() + index); return S_OK; } HRESULT WASetup::GetPageCount(int *pCount) { if (!pCount) return E_INVALIDARG; *pCount = (int)pageList.size(); return S_OK; } HRESULT WASetup::GetPage(size_t index, ifc_setuppage **pPage) { if (index >= pageList.size()) return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); *pPage = pageList[index]; return S_OK; } HRESULT WASetup::AddJob(ifc_setupjob *pJob) { for (size_t i = 0; i < jobList.size(); i++) { if (jobList[i] == pJob) return S_OK; } jobList.push_back(pJob); pJob->AddRef(); return S_OK; } HRESULT WASetup::RemoveJob(ifc_setupjob *pJob) { for (size_t i = 0; i < jobList.size(); i++) { if (jobList[i] == pJob) { jobList[i]->Release(); jobList.erase(jobList.begin() + i); return S_OK; } } return E_INVALIDARG; } HRESULT WASetup::GetActiveIndex(int* pIndex) { if (!pIndex) return E_INVALIDARG; *pIndex = (int)nPageActive; return S_OK; } HRESULT WASetup::CreateStatusWnd(HWND *phwndStatus) { HWND hwndStatus; if (!phwndStatus) return S_FALSE; *phwndStatus = NULL; if (-1 == bUseMarquee) { OSVERSIONINFO vi; vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); bUseMarquee = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0))); } hwndStatus = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUPSTATUS), NULL, JobStatusDialog); if (!hwndStatus) return S_FALSE; if (rcUI.right != rcUI.left) { RECT rw; GetWindowRect(hwndStatus, &rw); SetWindowPos(hwndStatus, NULL, rcUI.left + ((rcUI.right - rcUI.left) - (rw.right - rw.left))/2, rcUI.top + ((rcUI.bottom - rcUI.top) - (rw.bottom - rw.top))/2, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); } HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS); if (hwndCtrl) { if (bUseMarquee) { SetWindowLongPtrW(hwndCtrl, GWL_STYLE, GetWindowLongPtrW(hwndCtrl, GWL_STYLE) | 0x08/*PBS_MARQUEE*/); SendMessageW(hwndCtrl, (WM_USER + 10)/*PBM_SETMARQUEE*/, TRUE, (LPARAM)200); } else { SendMessageW(hwndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 1 + (INT)(pageList.size() + jobList.size()))); SendMessageW(hwndCtrl, PBM_SETPOS, 0, 0L); SendMessageW(hwndCtrl, PBM_SETSTEP, 1, 0L); } } *phwndStatus = hwndStatus; return S_OK; } static BOOL WaSetup_MessageLoop(HWND hMainWnd, HACCEL hAccel) { MSG msg; for (;;) { DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); if (WAIT_OBJECT_0 == status) { while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { //if (!CallMsgFilter(&msg, MSGF_DIALOGBOX)) { if (msg.message == WM_QUIT) return (BOOL)msg.wParam; if (!TranslateAcceleratorW(hMainWnd, hAccel, &msg) && !IsDialogMessageW(hMainWnd, &msg)) { TranslateMessage(&msg); DispatchMessageW(&msg); } } } } } } HRESULT WASetup::Start(HWND hwndWinamp) { INT_PTR r(IDOK); SetRectEmpty(&rcUI); hWinamp = hwndWinamp; if (pageList.size()) { HACCEL hAccel; static UI ui = {0, }; for (size_t i = 0; i < pageList.size(); i++) pageList[i]->Revert(); g_pAttachInstance = this; InitializeUI(&ui, hwnd); pui = &ui; hwnd = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP), NULL, ::DialogProc); if (!hwnd) return E_UNEXPECTED; HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance; hAccel = LoadAcceleratorsW(hInst, MAKEINTRESOURCEW(IDR_ACCEL_SETUP)); r = WaSetup_MessageLoop(hwnd, hAccel); g_pAttachInstance = NULL; ReleaseUI(&ui); } return (IDOK == r) ? S_OK : S_FALSE; } HRESULT WASetup::Save(HWND hwndStatus) { HRESULT hr(S_OK); HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS); for (size_t i = 0; i < pageList.size(); i++) { if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_SAVING, NULL, 0)); if (S_OK != pageList[i]->Save(hwndText)) hr = S_FALSE; JobStatus_Advance(hwndStatus); } WritePrivateProfileStringW(L"WinampReg", L"WAVer", AutoWide(APP_VERSION), INI_FILE); return hr; } HRESULT WASetup::ExecJobs(HWND hwndStatus) { HRESULT hr(S_OK); HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS); HWND hwndBtn = GetDlgItem(hwndStatus, IDC_BTN_SKIP); for (size_t i = 0; i < jobList.size(); i++) { if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_JOBS, NULL, 0)); if (hwndBtn && S_OK == jobList[i]->IsCancelSupported() && SetPropW(hwndStatus, L"JOB", (HANDLE)jobList[i])) { EnableWindow(hwndBtn, TRUE); } if (S_OK != jobList[i]->Execute(hwndText)) hr = S_FALSE; if (hwndBtn) EnableWindow(hwndBtn, FALSE); JobStatus_Advance(hwndStatus); } return hr; } HRESULT WASetup::GetWinampWnd(HWND *phwndWinamp) { if (NULL == phwndWinamp) return E_INVALIDARG; *phwndWinamp = hWinamp; return (NULL == hWinamp) ? E_UNEXPECTED : S_OK; } static INT_PTR CALLBACK tmpProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { return 0; } INT_PTR WASetup::OnInitDialog(HWND hwndFocused, LPARAM lParam) { HWND hwndLB, hwndFrame, hwndHeader; RECT rw, rc; HICON hIcon = LoadIconW(hMainInstance, MAKEINTRESOURCE(ICON_XP)); // make other people's dialogs show the winamp icon HWND h = CreateDialogW(hMainInstance, MAKEINTRESOURCE(IDD_OPENLOC), NULL, tmpProc); SetClassLongPtrW(h, GCLP_HICON, (LONG_PTR)hIcon); DestroyWindow(h); SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDC_BTN_NEXT), TRUE); wchar_t buf[256] = {0}; StringCchPrintfW(buf,256, getStringW(IDS_SETUP_WND_TITLE,NULL,0), AutoWideDup(app_version_string)); SetWindowTextW(hwnd, buf); // adjust dialog rw.left = GetPrivateProfileIntW(L"SETUP", L"left", 0, INI_FILE); rw.top = GetPrivateProfileIntW(L"SETUP", L"top", 0, INI_FILE); rw.right = GetPrivateProfileIntW(L"SETUP", L"right", 0, INI_FILE); rw.bottom = GetPrivateProfileIntW(L"SETUP", L"bottom", 0, INI_FILE); if (rw.left != rw.right && rw.top != rw.bottom) { INT x, y; GetWindowRect(hwnd, &rc); x = (rw.right) ? (rw.left + ((rw.right - rw.left) - (rc.right - rc.left))/2) : rw.left; y = (rw.bottom) ? (rw.top + ((rw.bottom - rw.top) - (rc.bottom - rc.top))/2) : rw.top; SetWindowPos(hwnd, NULL, x, y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); } hwndFrame = GetDlgItem(hwnd, IDC_FRAME); // TODO if this is needed again then remove // deletes the 'Tools' menu as it's not used DeleteMenu(GetMenu(hwnd), 2, MF_BYPOSITION); DrawMenuBar(hwnd); WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndFrame, GWLP_WNDPROC, (LONG_PTR)FrameWndProc); if (fnOldProc) SetPropW(hwndFrame, L"SKINFRAME", fnOldProc); SetWindowLongPtrW(hwndFrame, GWL_STYLE, GetWindowLongPtrW(hwndFrame, GWL_STYLE) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); if (!IsWinXPTheme()) SetWindowLongPtrW(hwndFrame, GWL_EXSTYLE, (GetWindowLongPtrW(hwndFrame, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE) | WS_EX_STATICEDGE); SetWindowPos(hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOOWNERZORDER); GetClientRect(hwndFrame, &rc); MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2); hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); if (hwndLB) { GetWindowRect(hwndLB, &rw); SetWindowPos(hwndLB, GetDlgItem(hwnd, IDC_BTN_BACK), rc.left, rc.top, rw.right - rw.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER); SendMessageW(hwndLB, WM_SETFONT, (WPARAM)pui->hfNavItem, FALSE); } hwndHeader = GetDlgItem(hwnd, IDC_HEADER); if (hwndHeader) { SendMessageW(hwndHeader, WM_SETFONT, (WPARAM)pui->hfHeader, FALSE); GetWindowRect(hwndLB, &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); SetWindowPos(hwndHeader, NULL, rw.right, rc.top, rc.right - rw.right, pui->nHdrHeight, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); } if (hwndLB) { for (size_t i = 0; i < pageList.size(); i++) SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)i); SendMessageW(hwndLB, LB_SETCURSEL, 0, 0L); PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); } ShowWindow(hwnd, SW_SHOWNORMAL); DWORD ourThreadID, foregroundThreadID; foregroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), NULL); ourThreadID = GetCurrentThreadId(); if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, TRUE); SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); SetForegroundWindow(hwnd); SetFocus(hwnd); if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, FALSE); return 0; } void WASetup::OnDestroy(void) { GetWindowRect(hwnd, &rcUI); } void WASetup::OnCancel(void) { BOOL bNeedSave = FALSE; WCHAR szTitle[128] = {0}; for (size_t i = 0; i < pageList.size() && !bNeedSave; i++) { bNeedSave = (S_FALSE != pageList[i]->IsDirty()); } GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR)); if (bNeedSave) { INT nr = MessageBoxW(hwnd, getStringW(IDS_SAVE_CHANGES_BEFORE_EXIT, NULL, 0), szTitle, MB_YESNOCANCEL | MB_ICONWARNING); switch(nr) { case IDYES: SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDM_FILE_SAVECHANGES, 0), 0L); break; case IDCANCEL: return; } } else if (IDNO == MessageBoxW(hwnd, getStringW(IDS_QUIT_OK, NULL, 0), szTitle, MB_YESNO | MB_ICONWARNING)) return; DestroyWindow(hwnd); PostQuitMessage(IDCANCEL); } void WASetup::OnNext_Clicked(HWND hwndCtrl) { HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) + 1; if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L); PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); } void WASetup::OnBack_Clicked(HWND hwndCtrl) { HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) -1; if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L); PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); } void WASetup::OnNavigation_SelChange(HWND hwndCtrl) { HWND hwndFrame; HMENU hMenu; MENUITEMINFO mii; INT idList[] = { IDC_BTN_BACK, IDC_BTN_NEXT}; INT count = (INT)SendMessageW(hwndCtrl, LB_GETCOUNT, 0, 0L); INT index = (INT)SendMessageW(hwndCtrl, LB_GETCURSEL, 0, 0L); if (nPageActive == (size_t)index) return; if (-1 != nPageActive && S_FALSE == pageList[nPageActive]->Validate()) { SendMessageW(hwndCtrl, LB_SETCURSEL, nPageActive, 0L); return; } hwndFrame = GetDlgItem(hwnd, IDC_FRAME); hMenu = GetMenu(hwnd); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE; for(int i = sizeof(idList)/sizeof(int) - 1; i >= 0 ; i--) { HWND hwndBtn = GetDlgItem(hwnd, idList[i]); BOOL bEnable = (IDC_BTN_NEXT == idList[i]) ? ((count - index) > 1) : (0 != index); if (hwndBtn) { if (bEnable != IsWindowEnabled(hwndBtn)) { if (IDC_BTN_NEXT == idList[i]) SendMessageW(hwnd, DM_SETDEFID, (WPARAM)((bEnable) ? IDC_BTN_NEXT : IDOK), 0L); EnableWindow(hwndBtn, bEnable); } if (hMenu) { mii.fState = (bEnable) ? MFS_ENABLED : MFS_DISABLED; SetMenuItemInfoW(hMenu, (IDC_BTN_NEXT == idList[i]) ? IDM_NAVIGATE_NEXT : IDM_NAVIGATE_BACK, FALSE, &mii); } } } if (hwndActive) { DestroyWindow(hwndActive); hwndActive = NULL; nPageActive = (size_t)-1; } if (S_OK != pageList[index]->CreateView(hwnd, &hwndActive)) hwndActive = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP_PAGE_ERROR), hwnd, ErrorPageDialog); HWND hwndHeader; RECT rc; GetClientRect(hwndFrame, &rc); MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2); hwndHeader = GetDlgItem(hwnd, IDC_HEADER); if (hwndHeader && (WS_VISIBLE & GetWindowLongPtrW(hwndHeader, GWL_STYLE))) { RECT rw; GetWindowRect(hwndHeader, &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); rc.top = rw.bottom; rc.left = rw.left; } SetWindowPos(hwndActive, GetDlgItem(hwnd, IDC_LB_NAVIGATION), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE); if(IsWinXPTheme()) WAEnableThemeDialogTexture(hwndActive, ETDT_ENABLETAB); else { SPTHEME *pTheme = (SPTHEME*)malloc(sizeof(SPTHEME)); pTheme->bUnicode = IsWindowUnicode(hwndActive); pTheme->pui = pui; pTheme->fnOldProc = (WNDPROC)SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)PageWndProc); if (!pTheme->fnOldProc || !SetPropW(hwndActive, L"SPTHEME", pTheme)) { if (pTheme->fnOldProc) SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)pTheme->fnOldProc); free(pTheme); } } ShowWindow(hwndActive, SW_SHOW); nPageActive = index; if (hwndHeader) InvalidateRect(hwndHeader, NULL, FALSE); HWND hwndTest = GetNextDlgTabItem(hwnd, GetWindow(hwndActive, GW_HWNDPREV), FALSE); if (hwndTest) SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndTest, TRUE); } void WASetup::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) { switch(nCtrlID) { case IDOK: if (BN_CLICKED == nEvntID) { if (-1 != nPageActive && S_FALSE != pageList[nPageActive]->Validate()) { DestroyWindow(hwnd); PostQuitMessage(IDOK); } } break; case IDCANCEL: if (BN_CLICKED == nEvntID) OnCancel(); break; case IDC_BTN_NEXT: if (BN_CLICKED == nEvntID) OnNext_Clicked(hwndCtrl); break; case IDC_BTN_BACK: if (BN_CLICKED == nEvntID) OnBack_Clicked(hwndCtrl); break; case IDC_LB_NAVIGATION: switch(nEvntID) { case LBN_SELCHANGE: OnNavigation_SelChange(hwndCtrl); break; } break; case IDM_HELP_ABOUT: WADialogBox(MAKEINTRESOURCEW(IDD_ABOUT), hwnd, AboutDialogProc); break; case IDM_NAVIGATE_BACK: SendMessageW(GetDlgItem(hwnd, IDC_BTN_BACK), BM_CLICK, 0, 0L); break; case IDM_NAVIGATE_NEXT: SendMessageW(GetDlgItem(hwnd, IDC_BTN_NEXT), BM_CLICK, 0, 0L); break; case IDM_FILE_EXIT: OnCancel(); break; case IDM_FILE_SAVECHANGES: if (S_OK != Save(NULL)) { WCHAR szTitle[128] = {0}, szText[256] = {0}; GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR)); MessageBoxW(hwnd, getStringW(IDS_CHANGES_NOT_SAVED, szText, sizeof(szText)/sizeof(wchar_t)), szTitle, MB_OK | MB_ICONERROR); } break; } } void WASetup::OnDrawHeader(DRAWITEMSTRUCT *pdis) { const wchar_t *pszName; RECT ri, re; INT top; CopyRect(&ri, &pdis->rcItem); CopyRect(&re, &ri); re.right = ri.left + 1; FillRect(pdis->hDC, &re, (HBRUSH)GetStockObject(WHITE_BRUSH)); ri.left = re.right; SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL); FillRect(pdis->hDC, &ri, pui->hbHeader); if (nPageActive >= pageList.size() || S_OK != pageList[nPageActive]->GetName(FALSE, &pszName) || !*pszName) pszName = GetUnknownStr(); SetBkMode(pdis->hDC, TRANSPARENT); InflateRect(&ri, -4, -2); top = ri.top + (ri.bottom - ri.top - pui->nHdrTxtHeight)/2 - 1; if (top > ri.top) ri.top = top; if (ri.left < ri.right) { RECT rn; wchar_t szPageInfo[64] = {0}; CopyRect(&rn, &ri); SetTextColor(pdis->hDC, HEADER_PAGENUM_TEXT_COLOR); UINT oldMode = SetTextAlign(pdis->hDC, TA_RIGHT); HFONT hfOld = (pui->hfHeaderPageNum) ? (HFONT)SelectObject(pdis->hDC, pui->hfHeaderPageNum) : NULL; top = ri.top + pui->nHdrTxtHeight - pui->nHdrPageTxtHeight; if (top > rn.top) rn.top = top; rn.right -= 8; rn.left = rn.right - 42; StringCchPrintfW(szPageInfo, sizeof(szPageInfo)/sizeof(wchar_t), L"%d/%d", nPageActive + 1, pageList.size()); ExtTextOutW(pdis->hDC, rn.right, rn.top, ETO_CLIPPED, &rn, szPageInfo, lstrlenW(szPageInfo), NULL); SetTextAlign(pdis->hDC, oldMode); if (hfOld) SelectObject(pdis->hDC, hfOld); ri.right = rn.left -= 4; } if (ri.left < ri.right) { SetTextColor(pdis->hDC, HEADER_TEXT_COLOR); SetTextAlign(pdis->hDC, TA_LEFT); ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, pszName, lstrlenW(pszName), NULL); } } void WASetup::OnDrawNavigationItem(DRAWITEMSTRUCT *pdis) { const wchar_t *pszName; RECT ri; HFONT hfOld; wchar_t szTitle[128] = {0}; COLORREF rgbText; if (pdis->itemID == -1) return; CopyRect(&ri, &pdis->rcItem); ri.left += NAVIGATION_PADDING_LEFT; ri.right -= NAVIGATION_PADDING_RIGHT; if (ODA_FOCUS == pdis->itemAction) { if (0 == (0x0200/*ODS_NOFOCUSRECT*/ & pdis->itemState)) { InflateRect(&ri, -1, -1); DrawFocusRect(pdis->hDC, &ri); } return; } if (ODS_SELECTED & pdis->itemState) { HBRUSH hbActive; if (pui->hbNavItemSel) { SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL); hbActive = pui->hbNavItemSel; } else { SetBrushOrgEx(pdis->hDC, 0, 0, NULL); hbActive = pui->hbNavBack; } FillRect(pdis->hDC, &ri, hbActive); rgbText = SetTextColor(pdis->hDC, NAVIGATION_SEL_TEXT_COLOR); hfOld = (HFONT)SelectObject(pdis->hDC, pui->hfNavItemSel); } else { if (ODA_SELECT == pdis->itemAction) { SetBrushOrgEx(pdis->hDC, 0, 0, NULL); FillRect(pdis->hDC, &ri, pui->hbNavBack); } rgbText = 0; hfOld = NULL; } if (pdis->itemData >= pageList.size() || S_OK != pageList[pdis->itemData]->GetName(TRUE, &pszName) || !*pszName) pszName = GetUnknownStr(); SetBkMode(pdis->hDC, TRANSPARENT); InflateRect(&ri, -4, -2); INT top = ri.top + (ri.bottom - ri.top - pui->nNavTxtHeight)/2 - 1; if (top > ri.top) ri.top = top; StringCchPrintfW(szTitle, sizeof(szTitle)/sizeof(wchar_t), L"%d. %s", pdis->itemData + 1, pszName); ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, szTitle, lstrlenW(szTitle), NULL); if (ODS_SELECTED & pdis->itemState) { SetTextColor(pdis->hDC, rgbText); if (hfOld) SelectObject(pdis->hDC, hfOld); } } INT_PTR WASetup::OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis) { switch(nCtrlID) { case IDC_HEADER: OnDrawHeader(pdis); return TRUE; case IDC_LB_NAVIGATION: OnDrawNavigationItem(pdis); return TRUE; } return 0; } INT_PTR WASetup::OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis) { switch(nCtrlID) { case IDC_LB_NAVIGATION: pmis->itemHeight = (pui) ? pui->nNavItemHeight : 0; return TRUE; } return FALSE; } INT_PTR WASetup::OnColorListBox(HDC hdc, HWND hwndCtrl) { if (hwndCtrl == GetDlgItem(hwnd, IDC_LB_NAVIGATION)) { SetTextColor(hdc, NAVIGATION_TEXT_COLOR); SetBkColor(hdc, NAVIGATION_BACK_COLOR); return (INT_PTR)pui->hbNavBack; } return NULL; } INT_PTR WASetup::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR result = 0; switch(uMsg) { case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); case WM_DESTROY: OnDestroy(); break; case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; case WM_DRAWITEM: result = OnDrawItem((INT)wParam, (DRAWITEMSTRUCT*)lParam); break; case WM_MEASUREITEM: result = OnMeasureItem((INT)wParam, (MEASUREITEMSTRUCT*)lParam); break; case WM_CTLCOLORLISTBOX: return OnColorListBox((HDC)wParam, (HWND)lParam); case WM_CHAR: if (0x30 == wParam) { OutputDebugStringA("test\n"); return 0; } } if (result) { SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONG_PTR)result); return TRUE; } return 0; } static INT_PTR WINAPI DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { WASetup *pInst = (WASetup*)GetPropW(hwndDlg, L"SETUPDLG"); if (!pInst && g_pAttachInstance) { pInst = g_pAttachInstance; pInst->hwnd = hwndDlg; SetPropW(hwndDlg, L"SETUPDLG", pInst); g_pAttachInstance = NULL; } switch(uMsg) { case WM_DESTROY: if (pInst) { pInst->DialogProc(uMsg, wParam, lParam); RemovePropW(hwndDlg, L"SETUPDLG"); pInst = NULL; } break; } return (pInst) ? pInst->DialogProc(uMsg, wParam, lParam) : 0; } static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_ABOUT), FALSE)); wchar_t buf[2048] = {0}, buf2[2048] = {0}; GetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf,ARRAYSIZE(buf)); StringCchPrintfW(buf2,2048,(buf[0] ? buf : L"v%s %s - %s"),AutoWideDup(app_version_string),AutoWideDup(APP_VERSION_PLATFORM),AutoWideDup(app_date)); SetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf2); } break; case WM_DESTROY: { DeleteObject((HBITMAP)SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_GETIMAGE, IMAGE_BITMAP, 0L)); } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hwndDlg, 0); break; } } return 0; } static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BTN_SKIP: if (BN_CLICKED == HIWORD(wParam)) { ifc_setupjob *pj = (ifc_setupjob*)GetPropW(hwndDlg, L"JOB"); if (pj) { HWND hwndStatus = GetDlgItem(hwndDlg, IDC_LBL_STATUS); EnableWindow((HWND)lParam, FALSE); if (hwndStatus) SetWindowTextW(hwndStatus, getStringW(IDS_HTTP_ABORT, NULL, 0)); pj->Cancel(hwndStatus); } } break; } case WM_DESTROY: RemovePropW(hwndDlg, L"JOB"); } return 0; } static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_WINDOWPOSCHANGED: if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & ((WINDOWPOS*)lParam)->flags)) { HWND messageWindow; messageWindow = GetDlgItem(hwndDlg, IDC_LBL_MESSAGE); if (NULL != messageWindow) { RECT rect; long top; GetWindowRect(messageWindow, &rect); MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT*)&rect, 1); top = rect.top; GetClientRect(hwndDlg, &rect); rect.top = top; SetWindowPos(messageWindow, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); } } break; } return 0; } static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { SPTHEME *pTheme = (SPTHEME*)GetPropW(hwnd, L"SPTHEME"); if (!pTheme || !pTheme->fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam); switch(uMsg) { case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: SetBkColor((HDC)wParam, PAGE_BACK_COLOR); SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); return (LRESULT)pTheme->pui->hbPage; case WM_DESTROY: { WNDPROC fnOldProc = pTheme->fnOldProc; RemovePropA(hwnd, "SPTHEME"); free(pTheme); SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam); } } return (pTheme->bUnicode) ? CallWindowProcW(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam); } static DWORD GetHighestFontQuality(void) { DWORD fdwQuality; BOOL bSmoothing; if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &bSmoothing, 0) && bSmoothing) { OSVERSIONINFO vi = { sizeof(OSVERSIONINFO), }; fdwQuality = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0))) ? 5/*CLEARTYPE_QUALITY*/ : ANTIALIASED_QUALITY; } else fdwQuality = DEFAULT_QUALITY; return fdwQuality; } static BOOL InitializeUI(UI *pui, HWND hwndCtrl) { if (!pui) return FALSE; if (!pui->ref) { HBITMAP hbmp; BITMAP bi; HDC hdc; INT logPx; TEXTMETRIC tm; hdc = GetWindowDC(hwndCtrl); logPx = GetDeviceCaps(hdc, LOGPIXELSY); pui->hbPage = CreateSolidBrush(PAGE_BACK_COLOR); hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVIGATION_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if (hbmp) { pui->hbNavBack = CreatePatternBrush(hbmp); DeleteObject(hbmp); } else pui->hbNavBack = CreateSolidBrush(NAVIGATION_BACK_COLOR); pui->hfNavItem = CreateFontA(-MulDiv(NAVIGATION_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_FONT_WEIGHT, NAVIGATION_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_FONT_NAME); pui->hfNavItemSel = CreateFontA(-MulDiv(NAVIGATION_SEL_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_SEL_FONT_WEIGHT, NAVIGATION_SEL_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_SEL_FONT_NAME); pui->hfHeader = CreateFontA(-MulDiv(HEADER_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_FONT_WEIGHT, HEADER_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetHighestFontQuality(), FF_DONTCARE, HEADER_FONT_NAME); pui->hfHeaderPageNum = CreateFontA(-MulDiv(HEADER_PAGENUM_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_PAGENUM_FONT_WEIGHT, HEADER_PAGENUM_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetHighestFontQuality(), FF_DONTCARE, HEADER_PAGENUM_FONT_NAME); pui->nHdrHeight = 36; hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_HEADER_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if (hbmp) { if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nHdrHeight = bi.bmHeight; pui->hbHeader = CreatePatternBrush(hbmp); DeleteObject(hbmp); } pui->nNavItemHeight = 32; // hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVITEM_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); // if (hbmp) // { // if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nNavItemHeight = bi.bmHeight; // pui->hbNavItemSel = CreatePatternBrush(hbmp); // DeleteObject(hbmp); // } HFONT hfOld = (HFONT)SelectObject(hdc, pui->hfHeader); GetTextMetrics(hdc, &tm); pui->nHdrTxtHeight = tm.tmAscent; SelectObject(hdc, pui->hfHeaderPageNum); GetTextMetrics(hdc, &tm); pui->nHdrPageTxtHeight = tm.tmAscent; SelectObject(hdc, pui->hfNavItem); GetTextMetrics(hdc, &tm); pui->nNavTxtHeight = tm.tmAscent; SelectObject(hdc, pui->hfNavItemSel); GetTextMetrics(hdc, &tm); pui->nNavTxtSelHeight = tm.tmAscent; SelectObject(hdc, hfOld); ReleaseDC(hwndCtrl, hdc); } pui->ref++; return TRUE; } static BOOL ReleaseUI(UI *pui) { if (!pui) return FALSE; if (0 == pui->ref) { return TRUE; } if (1 == pui->ref) { if (pui->hbPage) DeleteObject(pui->hbPage); if (pui->hbNavBack) DeleteObject(pui->hbNavBack); if (pui->hbHeader) DeleteObject(pui->hbHeader); if (pui->hbNavItemSel) DeleteObject(pui->hbNavItemSel); if (pui->hfNavItem) DeleteObject(pui->hfNavItem); if (pui->hfNavItemSel) DeleteObject(pui->hfNavItemSel); if (pui->hfHeader) DeleteObject(pui->hfHeader); if (pui->hfHeaderPageNum) DeleteObject(pui->hfHeaderPageNum); ZeroMemory(pui, sizeof(UI)); return TRUE; } pui->ref--; return TRUE; } static const wchar_t *GetUnknownStr(void) { static wchar_t unknown[64] = {0,}; return (unknown) ? unknown : getStringW(IDS_UNKNOWN, unknown, sizeof(unknown)/sizeof(wchar_t)); } static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"SKINFRAME"); if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam); switch(uMsg) { case WM_DESTROY: RemovePropW(hwnd, L"SKINFRAME"); SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); break; case WM_PAINT: ValidateRect(hwnd, NULL); return 0; case WM_ERASEBKGND: return 1; } return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam); } static BOOL JobStatus_Advance(HWND hwndStatus) { if (bUseMarquee > 0 ) return TRUE; if (!hwndStatus) return FALSE; HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS); if (!hwndCtrl) return FALSE; SendMessageW(hwndCtrl, PBM_STEPIT, 0, 0L); return TRUE; } #ifdef CBCLASS #undef CBCLASS #endif #define CBCLASS WASetup START_DISPATCH CB(ADDREF, AddRef) CB(RELEASE, Release) CB(API_SETUP_INSERT_PAGE, InsertPage) CB(API_SETUP_REMOVE_PAGE, RemovePage) CB(API_SETUP_GET_PAGE_COUNT, GetPageCount) CB(API_SETUP_GET_PAGE, GetPage) CB(API_SETUP_GET_ACTIVE_INDEX, GetActiveIndex) CB(API_SETUP_START, Start) CB(API_SETUP_ADD_JOB, AddJob) CB(API_SETUP_REMOVE_JOB, RemoveJob) CB(API_SETUP_CREATE_STATUSWND, CreateStatusWnd) CB(API_SETUP_SAVE, Save) CB(API_SETUP_EXECJOBS, ExecJobs) CB(API_SETUP_GETWINAMPWND, GetWinampWnd) END_DISPATCH #undef CBCLASS