#include "main.h" #include ".\cddbui.h" #include ".\cddb.h" #include "api__in_cdda.h" #include ".\resource.h" #include "..\winamp\wa_ipc.h" #include #include #include #include #include "cddbcontrolwinamp.tlh" #define PROP_PRGDLG L"PRGDLG" #define TIMER_PROGRESS_DESTROY_ID 1978 #define TIMER_PROGRESS_DESTROY_ELAPSE 250 #define TIMER_PROGRESS_ANIMATE_ID 1980 #define TIMER_PROGRESS_ANIMATE_ELAPSE 65 #define MODAL_EXIT 0 #define MODAL_ACTIVE 1 #define MODAL_DESTROY 2 #define ICON_OFFSET_X 12 #define ICON_OFFSET_Y 12 #define DIALOG_HEIGHT_NORMAL 66 #define DIALOG_HEIGHT_EXTENDED 160 #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif //IDC_HAND typedef struct _PROGRESSICON { HINSTANCE hInstance; LONG resId; RECT rc; LONG frames; LONG step; HBITMAP hbmp; } PROGRESSICON; typedef struct _PROGRESSDLG { PROGRESSICON icon; UINT uState; DWORD dwAutoClose; CDDBDLG_ONBTNCLICK OnAbort; CDDBDLG_ONBTNCLICK OnButton1; BSTR Btn1Data; BSTR AbortData; WORD Modal; HRESULT rCode; HANDLE user; } PROGRESSDLG; static HFONT hFont = NULL; static LONG fontRef = 0; static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static void CALLBACK ProgressDlg_OnTimer(HWND hwnd, UINT uMsg, UINT_PTR evntId, DWORD dwTime); static void InvalidateLogo(HWND hwnd, PROGRESSICON *pIcon); static BOOL EndProgressDialog(HWND hwnd); #define GET_DATA(__hwnd) ((PROGRESSDLG*)GetPropW((__hwnd), PROP_PRGDLG)) static wchar_t szText1[256]; static wchar_t szText2[256]; #define GET_SAFE_LANGSTRING(__str, __buff, __cch) ((__str) ? (IS_INTRESOURCE(__str) ? WASABI_API_LNGSTRINGW_BUF((UINT)(UINT_PTR)(__str), (__buff), (__cch)) : (__str)) : L"") #define GET_SAFE_LANGSTRING1(__str) GET_SAFE_LANGSTRING((__str), (szText1), (sizeof(szText1)/sizeof(wchar_t))) #define GET_SAFE_LANGSTRING2(__str) GET_SAFE_LANGSTRING((__str), (szText2), (sizeof(szText2)/sizeof(wchar_t))) typedef struct _ENUMWND_DATAPACK { HWND host; HWND *list; INT index; INT count; UINT flags; BOOL found; } ENUMWND_DATAPACK; HWND CddbProgressDlg_Create(HWND hwndParent, INT nCmdShow) { HWND hdlg = WASABI_API_CREATEDIALOGPARAMW(IDD_CDDB_PROGRESS, NULL, DialogProc, 0L); if (hdlg && SW_HIDE != nCmdShow) ShowWindow(hdlg, SW_HIDE); return hdlg; } BOOL CddbProgressDlg_Initialize(HWND hwnd, LPCWSTR pszCaption, CDDBDLG_ONBTNCLICK fnOnAbort, BSTR bstrAbortUser) { HWND hwndCtrl; PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; KillTimer(hwnd, TIMER_PROGRESS_ANIMATE_ID); pDlg->OnAbort = (fnOnAbort) ? fnOnAbort : NULL; if (pDlg->AbortData) SysFreeString(pDlg->AbortData); pDlg->AbortData = (bstrAbortUser) ? SysAllocString(bstrAbortUser) : NULL; SetDlgItemTextW(hwnd, IDC_LBL_CAPTION, GET_SAFE_LANGSTRING1(pszCaption)); SetDlgItemTextW(hwnd, IDC_LBL_STATUS, L""); if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_LBL_REASON))) { ShowWindow(hwndCtrl, SW_HIDE); SetWindowTextW(hwndCtrl, L""); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_PRG_STATUS))) { ShowWindow(hwndCtrl, SW_HIDE); SendMessageW(hwndCtrl, PBM_SETPOS, (WPARAM)0, (LPARAM)0L); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDCANCEL))) { SetWindowTextW(hwndCtrl, GET_SAFE_LANGSTRING1(MAKEINTRESOURCEW((fnOnAbort) ? IDS_ABORT : IDS_CLOSE))); EnableWindow(hwndCtrl, (NULL != fnOnAbort)); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_LV_EXT))) { SendMessageW(hwndCtrl, LVM_DELETEALLITEMS, 0, 0L); } pDlg->icon.step = 0; InvalidateLogo(hwnd, &pDlg->icon); SetTimer(hwnd, TIMER_PROGRESS_ANIMATE_ID, TIMER_PROGRESS_ANIMATE_ELAPSE, ProgressDlg_OnTimer); pDlg->uState = STATE_ACTIVE; return TRUE; } BOOL CddbProgressDlg_Completed(HWND hwnd, LPCWSTR pszResult, LPCWSTR pszReason, DWORD nAutoCloseDelay, HRESULT rCode) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; KillTimer(hwnd, TIMER_PROGRESS_ANIMATE_ID); pDlg->uState = STATE_COMPLETED; pDlg->rCode = rCode; if (AUTOCLOSE_NOW == nAutoCloseDelay) { EndProgressDialog(hwnd); } else { HWND hwndCtrl; SetDlgItemTextW(hwnd, IDC_LBL_STATUS, GET_SAFE_LANGSTRING1(pszResult)); if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_PRG_STATUS))) { ShowWindow(hwndCtrl, SW_HIDE); SendMessageW(hwndCtrl, PBM_SETPOS, (WPARAM)0, (LPARAM)0L); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_LBL_REASON))) { SetWindowTextW(hwndCtrl, GET_SAFE_LANGSTRING1(pszReason)); ShowWindow(hwndCtrl, SW_SHOWNORMAL); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDCANCEL))) { if (AUTOCLOSE_NEVER != nAutoCloseDelay) { INT time = nAutoCloseDelay/1000 + (((nAutoCloseDelay%1000)>500) ? 1 : 0); if (time) { wchar_t szText[128] = {0}; StringCchPrintfW(szText, sizeof(szText)/sizeof(wchar_t), L"%s (%d)", GET_SAFE_LANGSTRING1(MAKEINTRESOURCEW(IDS_CLOSE)),time); SetDlgItemTextW(hwnd, IDCANCEL, szText); } else SetWindowText(hwndCtrl, GET_SAFE_LANGSTRING1(MAKEINTRESOURCEW(IDS_CLOSE))); } else SetWindowText(hwndCtrl, GET_SAFE_LANGSTRING1(MAKEINTRESOURCEW(IDS_CLOSE))); EnableWindow(hwndCtrl, TRUE); } pDlg->icon.step = pDlg->icon.frames - 1; InvalidateLogo(hwnd, &pDlg->icon); if (AUTOCLOSE_NEVER != nAutoCloseDelay) { pDlg->dwAutoClose = GetTickCount() + nAutoCloseDelay; return (0 != SetTimer(hwnd, TIMER_PROGRESS_DESTROY_ID, TIMER_PROGRESS_DESTROY_ELAPSE, ProgressDlg_OnTimer)); } } return TRUE; } BOOL CddbProgressDlg_SetStatus(HWND hwnd, LPCWSTR pszStatus, INT nPercentCompleted) { BOOL br(TRUE); HWND hwndCtrl; if (!hwnd || !IsWindow(hwnd)) return FALSE; if (pszStatus && !SetDlgItemTextW(hwnd, IDC_LBL_STATUS, GET_SAFE_LANGSTRING1(pszStatus))) br = FALSE; hwndCtrl = GetDlgItem(hwnd, IDC_PRG_STATUS); if (hwndCtrl) { if (nPercentCompleted > 100) nPercentCompleted = 100; if (nPercentCompleted < 0) ShowWindow(hwndCtrl, SW_HIDE); else { SendMessageW(hwndCtrl, PBM_SETPOS, (WPARAM)nPercentCompleted, (LPARAM)0L); ShowWindow(hwndCtrl, SW_SHOWNA); } } return br; } UINT CddbProgressDlg_GetState(HWND hwnd) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return STATE_INACTIVE; pDlg = GET_DATA(hwnd); return (pDlg) ? pDlg->uState : STATE_INACTIVE; } BOOL CddbProgressDlg_EnableAbortButton(HWND hwnd, BOOL bEnable) { HWND hwndBtn; if(!hwnd || !IsWindow(hwnd)) return FALSE; if (NULL == (hwndBtn = GetDlgItem(hwnd, IDCANCEL))) return FALSE; return EnableWindow(hwndBtn, bEnable); } BOOL CddbProgressDlg_ShowButton1(HWND hwnd, LPCWSTR pszCaption, CDDBDLG_ONBTNCLICK fnOnButton1, BSTR bstrUser) { PROGRESSDLG *pDlg; HWND hwndBtn; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; if (NULL == (hwndBtn = GetDlgItem(hwnd, IDC_BUTTON1))) return FALSE; if (pDlg->Btn1Data) SysFreeString(pDlg->Btn1Data); if(pszCaption && fnOnButton1) { SetWindowTextW(hwndBtn, GET_SAFE_LANGSTRING1(pszCaption)); ShowWindow(hwndBtn, SW_SHOWNORMAL); pDlg->OnButton1 = fnOnButton1; pDlg->Btn1Data = (bstrUser) ? SysAllocString(bstrUser) : NULL; SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)TRUE, (LPARAM)hwndBtn); } else { ShowWindow(hwndBtn, SW_HIDE); pDlg->OnButton1 = NULL; pDlg->Btn1Data = NULL; } return TRUE; } BOOL CddbProgressDlg_ShowInTaskbar(HWND hwnd, BOOL bShow) { HRESULT hr; ITaskbarList *pTaskbar; if(!hwnd || !IsWindow(hwnd)) return FALSE; hr = CoCreateInstance(CLSID_TaskbarList,0, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (void**)&pTaskbar); if(SUCCEEDED(hr)) { hr = pTaskbar->HrInit(); if (SUCCEEDED(hr)) { if (bShow) { hr = pTaskbar->AddTab(hwnd); pTaskbar->ActivateTab(hwnd); } else pTaskbar->DeleteTab(hwnd); } pTaskbar->Release(); } return (S_OK == hr); } BOOL CddbProgressDlg_SetExtendedMode(HWND hwnd, BOOL bEnable) { RECT rc; HWND hwndCtrl; INT height; if(!hwnd || !IsWindow(hwnd)) return FALSE; GetWindowRect(hwnd, &rc); RECT rw; GetClientRect(hwnd, &rw); height = (rc.bottom - rc.top) - (rw.bottom - rw.top); SetRect(&rw, 0, 0, 1, (bEnable) ? DIALOG_HEIGHT_EXTENDED : DIALOG_HEIGHT_NORMAL); MapDialogRect(hwnd, &rw); height += rw.bottom; if (height == rc.bottom - rc.top) return TRUE; if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_BUTTON1))) { GetWindowRect(hwndCtrl, &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); SetWindowPos(hwndCtrl, NULL, rw.left, rw.top + (height - (rc.bottom - rc.top)), 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDCANCEL))) { GetWindowRect(hwndCtrl, &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); SetWindowPos(hwndCtrl, NULL, rw.left, rw.top + (height - (rc.bottom - rc.top)), 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_LV_EXT))) { PROGRESSDLG *pDlg; INT listBottom; GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 1); listBottom = rw.top - MulDiv(4, HIWORD(GetDialogBaseUnits()), 8); pDlg = GET_DATA(hwnd); if (pDlg) { GetWindowRect(hwndCtrl, &rw); MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); INT listTop = ICON_OFFSET_Y * 2 + (pDlg->icon.rc.bottom - pDlg->icon.rc.top); SetWindowPos(hwndCtrl, NULL, ICON_OFFSET_X, listTop, rc.right - rc.left - ICON_OFFSET_X*2, listBottom - listTop, SWP_NOACTIVATE | SWP_NOZORDER); ShowWindow(hwndCtrl, (bEnable) ? SW_SHOW : SW_HIDE); } } SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); return TRUE; } BOOL CddbProgressDlg_AddRecord(HWND hwnd, LPCWSTR pszArtist, LPCWSTR pszTitle, LPCWSTR pszLanguage) { HWND hwndList; LVITEMW item; INT index; if(!hwnd || !IsWindow(hwnd)) return FALSE; hwndList = GetDlgItem(hwnd, IDC_LV_EXT); if (!hwndList) return FALSE; item.mask = LVIF_TEXT; item.iItem = 0xFFFF; item.iSubItem = 0; item.pszText = GET_SAFE_LANGSTRING1(pszArtist); index = (INT)SendMessageW(hwndList, LVM_INSERTITEMW, 0, (LPARAM)&item); if (-1 == index) return FALSE; if (0 == index) { item.state = LVIS_FOCUSED | LVIS_SELECTED; item.stateMask = item.state; SendMessageW(hwndList, LVM_SETITEMSTATE, (WPARAM)index, (LPARAM)&item); } item.iItem = index; item.mask = LVIF_TEXT; item.iSubItem = 1; item.pszText = GET_SAFE_LANGSTRING1(pszTitle);; SendMessageW(hwndList, LVM_SETITEMW, 0, (LPARAM)&item); item.iItem = index; item.mask = LVIF_TEXT; item.iSubItem = 2; item.pszText = GET_SAFE_LANGSTRING1(pszLanguage);; SendMessageW(hwndList, LVM_SETITEMW, 0, (LPARAM)&item); return TRUE; } #define HOOK_MAX_DATA 12 typedef struct _HOOKDATA { HHOOK handle; int ref; HWND modalList[HOOK_MAX_DATA]; } HOOKDATA; static HOOKDATA g_hook = { NULL, 0}; static LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam) { MOUSEHOOKSTRUCT *pMouse = (MOUSEHOOKSTRUCT*)lParam; switch(wParam) { case WM_NCLBUTTONDOWN: case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDOWN: case WM_NCRBUTTONDBLCLK: case WM_NCMBUTTONDOWN: case WM_NCMBUTTONDBLCLK: if (FALSE == IsWindowEnabled(pMouse->hwnd)) { for(int i = g_hook.ref - 1; i > -1 ; i--) { HWND hwndOwner = GetWindow(g_hook.modalList[i], GW_OWNER); if (hwndOwner == pMouse->hwnd || hwndOwner == GetWindow(pMouse->hwnd, GW_OWNER)) { DWORD style = GetWindowLongPtrW(g_hook.modalList[i], GWL_STYLE); if (0 != (WS_VISIBLE & style) && 0 == (WS_DISABLED & style)) { HWND hwndTest = GetForegroundWindow(); if (hwndTest == g_hook.modalList[i]) { FLASHWINFO flash; flash.hwnd = g_hook.modalList[i]; flash.cbSize = sizeof(FLASHWINFO); flash.dwFlags = FLASHW_CAPTION; flash.uCount = 2; flash.dwTimeout = 100; FlashWindowEx(&flash); MessageBeep(MB_OK); } else SetForegroundWindow(g_hook.modalList[i]); return CallNextHookEx(g_hook.handle, code, wParam, lParam); } } } } break; } return CallNextHookEx(g_hook.handle, code, wParam, lParam); } static void AddModalHook(HWND hdlg) { if (!hdlg) return; if (!g_hook.handle) { ZeroMemory(&g_hook, sizeof(HOOKDATA)); g_hook.handle = SetWindowsHookEx(WH_MOUSE, HookProc, line.hDllInstance, NULL); if (!g_hook.handle) return; } if (HOOK_MAX_DATA == (g_hook.ref - 1)) return; g_hook.modalList[g_hook.ref] = hdlg; g_hook.ref++; return; } static void ReleaseModalHook(HWND hdlg) { if (!hdlg) return; for (int i = 0; i < g_hook.ref; i++) { if (g_hook.modalList[i] == hdlg) { if (i != g_hook.ref -1) MoveMemory(&g_hook.modalList[i], &g_hook.modalList[i + 1], (g_hook.ref - i -1)*sizeof(HWND)); g_hook.ref--; if (!g_hook.ref) { UnhookWindowsHookEx(g_hook.handle); ZeroMemory(&g_hook, sizeof(HOOKDATA)); } return; } } return ; } HRESULT CddbProgressDlg_DoModal(HWND hwnd, RECT *prc) { MSG msg; HWND hwndOwner; PROGRESSDLG *pDlg; HRESULT rCode; HWND disabledList[32] = {0}; if(!hwnd || !IsWindow(hwnd)) return E_INVALIDARG; pDlg = GET_DATA(hwnd); if (!pDlg || MODAL_ACTIVE == pDlg->Modal) return E_POINTER; pDlg->Modal = MODAL_ACTIVE; hwndOwner = GetParent(hwnd); if (hwndOwner == GetDesktopWindow()) hwndOwner = NULL; if (hwndOwner != line.hMainWindow && hwndOwner == (HWND)SendMessageW(line.hMainWindow, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT)) { hwndOwner = line.hMainWindow; } DWORD mineTID, parentTID; mineTID = GetWindowThreadProcessId(hwnd, NULL); parentTID = (hwndOwner) ? GetWindowThreadProcessId(hwndOwner, NULL) : mineTID; if (hwndOwner) { HWND *p; if (mineTID != parentTID) AttachThreadInput(parentTID, mineTID, TRUE); p = disabledList; if (IsWindowEnabled(hwndOwner)) { *p = hwndOwner; p++; } FindAllOwnedWindows(hwndOwner, p, sizeof(disabledList)/sizeof(HWND) - (INT)(p - disabledList), FINDWND_ONLY_ENABLED); for (p = disabledList; *p != NULL; p++) { if (hwnd != *p) EnableWindow(*p, FALSE); } } AddModalHook(hwnd); msg.message = WM_NULL; while(MODAL_ACTIVE == pDlg->Modal) { if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; else if (!CallMsgFilter(&msg, MSGF_DIALOGBOX) && !IsDialogMessage(hwnd, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else if (MODAL_ACTIVE == pDlg->Modal) WaitMessage(); } ReleaseModalHook(hwnd); rCode = pDlg->rCode; if (msg.message == WM_QUIT) PostQuitMessage((int)msg.wParam); if (hwndOwner) { if (mineTID != parentTID) AttachThreadInput(parentTID, mineTID, FALSE); for (HWND *p = disabledList; *p != NULL; p++) { if (hwnd != *p) EnableWindow(*p, TRUE); } SetActiveWindow(hwndOwner); } if (prc && !GetWindowRect(hwnd, prc)) SetRect(prc, 0, 0, 0,0); if(MODAL_EXIT != pDlg->Modal) DestroyWindow(hwnd); return rCode; } BOOL CddbProgressDlg_ExitModal(HWND hwnd, HRESULT rCode, BOOL bDesroy) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; if (MODAL_ACTIVE == pDlg->Modal) { pDlg->Modal = (bDesroy) ? MODAL_DESTROY : MODAL_EXIT; pDlg->rCode = rCode; PostMessageW(hwnd, WM_NULL, 0, 0); } return TRUE; } BOOL CddbProgressDlg_IsModal(HWND hwnd) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); return (pDlg && (MODAL_ACTIVE == pDlg->Modal)); } INT CddbProgressDlg_GetSelRecordIndex(HWND hwnd) { HWND hwndList; if(!hwnd || !IsWindow(hwnd)) return -1; hwndList = GetDlgItem(hwnd, IDC_LV_EXT); if (!hwndList) return -1; return (INT)(INT_PTR)SendMessageW(hwndList, LVM_GETNEXTITEM, -1, (LPARAM)(LVNI_SELECTED | LVNI_FOCUSED)); } BOOL CddbProgressDlg_SetUserData(HWND hwnd, HANDLE user) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return FALSE; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; pDlg->user = user; return TRUE; } HANDLE CddbProgressDlg_GetUserData(HWND hwnd) { PROGRESSDLG *pDlg; if(!hwnd || !IsWindow(hwnd)) return NULL; pDlg = GET_DATA(hwnd); return (pDlg) ? pDlg->user : NULL; } static void InvalidateLogo(HWND hwnd, PROGRESSICON *pIcon) { RECT rc; SetRect(&rc, ICON_OFFSET_X, ICON_OFFSET_Y, ICON_OFFSET_X + (pIcon->rc.right - pIcon->rc.left), ICON_OFFSET_Y + (pIcon->rc.bottom - pIcon->rc.top)); InvalidateRect(hwnd, &rc, TRUE); } static BOOL EnableWindowTheme(HWND hwnd, BOOL bEnable) { static HMODULE hModule = NULL; static BOOL firstTime = TRUE; static HRESULT (WINAPI *__setwintheme)(HWND, LPCWSTR, LPCWSTR) = NULL; if (!hModule) { if (!firstTime) return FALSE; firstTime = FALSE; hModule = LoadLibraryW(L"UxTheme.dll"); if (!hModule) return FALSE; __setwintheme = (HRESULT (WINAPI *)(HWND, LPCWSTR, LPCWSTR))GetProcAddress(hModule, "SetWindowTheme"); if (!__setwintheme) { FreeLibrary(hModule); hModule = NULL; return FALSE; } } return (S_OK == __setwintheme(hwnd, NULL, ((bEnable) ? NULL : L""))); } static HRESULT InitializeProgressIcon(PROGRESSICON *pIcon) { HRESULT hr; LONG/*_PTR*/ lVal; // benski> windows 64 isn't supported by gracenote ICddbUIOptions *pUIOptions; if (!pIcon) return E_INVALIDARG; ZeroMemory(pIcon, sizeof(PROGRESSICON)); hr = Cddb_GetIUIOptions((void**)&pUIOptions); if (FAILED(hr)) return hr; hr = pUIOptions->GetCurrent(UI_DISP_PROGRESS); if (SUCCEEDED(hr)) { if (SUCCEEDED(pUIOptions->get_ResourceHINSTANCE(&lVal))) pIcon->hInstance = (HINSTANCE)lVal; if (SUCCEEDED(pUIOptions->get_Left(&lVal))) pIcon->rc.left = (LONG)lVal; if (SUCCEEDED(pUIOptions->get_Top(&lVal))) pIcon->rc.top = (LONG)lVal; if (SUCCEEDED(pUIOptions->get_Right(&lVal))) pIcon->rc.right = (LONG)lVal; if (SUCCEEDED(pUIOptions->get_Bottom(&lVal))) pIcon->rc.bottom = (LONG)lVal; pUIOptions->get_ProgressResourceID(&pIcon->resId); pUIOptions->get_Frames(&pIcon->frames); } pUIOptions->Release(); return hr; } static BOOL AnimateProgressIcon(HDC hdc, INT x, INT y, PROGRESSICON *pIcon) { INT w, h; HDC hdcDst; HBITMAP bmpOld; if (!hdc || !pIcon) return FALSE; if (!pIcon->hbmp) { if (pIcon->hInstance && pIcon->resId) { pIcon->hbmp = (HBITMAP)LoadImageW(pIcon->hInstance, MAKEINTRESOURCEW(pIcon->resId), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE); } if (!pIcon->hbmp) return FALSE; } hdcDst = CreateCompatibleDC(hdc); bmpOld = (HBITMAP)SelectObject(hdcDst, pIcon->hbmp); w = pIcon->rc.right - pIcon->rc.left; h = pIcon->rc.bottom - pIcon->rc.top; BitBlt(hdc, x, y, w, h, hdcDst, pIcon->rc.left + (pIcon->step * w), pIcon->rc.top, SRCCOPY); SelectObject(hdcDst, bmpOld); DeleteDC(hdcDst); return TRUE; } static void CALLBACK ProgressDlg_OnTimer(HWND hwnd, UINT uMsg, UINT_PTR evntId, DWORD dwTime) { PROGRESSDLG *pDlg; pDlg = GET_DATA(hwnd); if (!pDlg) return; DWORD tclose; switch(evntId) { case TIMER_PROGRESS_ANIMATE_ID: InvalidateLogo(hwnd, &pDlg->icon); if (++pDlg->icon.step >= pDlg->icon.frames) { KillTimer(hwnd, evntId); pDlg->icon.step = pDlg->icon.frames - 1; } break; case TIMER_PROGRESS_DESTROY_ID: tclose = pDlg->dwAutoClose; if (dwTime >= tclose) { KillTimer(hwnd, evntId); EndProgressDialog(hwnd); } else { wchar_t szText[128] = {0}; tclose = (tclose - dwTime)/1000 + ((((tclose - dwTime)%1000) > 500) ? 1 : 0); StringCchPrintfW(szText, sizeof(szText)/sizeof(wchar_t), L"%s (%d)", GET_SAFE_LANGSTRING1(MAKEINTRESOURCEW(IDS_CLOSE)), tclose); SetDlgItemTextW(hwnd, IDCANCEL, szText); } break; } } static BOOL EndProgressDialog(HWND hwnd) { PROGRESSDLG *pDlg; pDlg = GET_DATA(hwnd); if (!pDlg) return FALSE; if (MODAL_ACTIVE == pDlg->Modal) { pDlg->Modal = MODAL_DESTROY; PostMessageW(hwnd, WM_NULL, 0, 0); } else { DestroyWindow(hwnd); } return TRUE; } static INT_PTR ProgressDlg_OnDialogInit(HWND hwnd, HWND hwndFocus, LPARAM lParam) { HWND hwndCtrl; PROGRESSDLG *pDlg(NULL); pDlg = (PROGRESSDLG*)calloc(1, sizeof(PROGRESSDLG)); if (pDlg) { pDlg->uState = STATE_INACTIVE; if ((FAILED(InitializeProgressIcon(&pDlg->icon)) || !SetPropW(hwnd, PROP_PRGDLG, pDlg))) { free(pDlg); pDlg = NULL; DestroyWindow(hwnd); return TRUE; } } hwndCtrl = GetDlgItem(hwnd, IDC_PRG_STATUS); if (hwndCtrl) { RECT rc; EnableWindowTheme(hwndCtrl, FALSE); SetWindowLongPtrW(hwndCtrl, GWL_EXSTYLE, GetWindowLongPtrW(hwndCtrl, GWL_EXSTYLE) & ~WS_EX_STATICEDGE); GetWindowRect(hwndCtrl, &rc); SetWindowPos(hwndCtrl, NULL, 0, 0, rc.right - rc.left, 3, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); SendMessageW(hwndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); SendMessageW(hwndCtrl, PBM_SETPOS, 0, 0L); SendMessageW(hwndCtrl, PBM_SETSTEP, 1, 0L); SendMessageW(hwndCtrl, PBM_SETBARCOLOR, 0, (LPARAM)GetSysColor(COLOR_WINDOW)); SendMessageW(hwndCtrl, PBM_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT)); } hwndCtrl = GetDlgItem(hwnd, IDC_LBL_STATUS); if(hwndCtrl) { if (!hFont) { HFONT hf; LOGFONT lf; hf = (HFONT)SendMessageW(hwndCtrl, WM_GETFONT, 0, 0L); if (hf) hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT); if (hf && GetObject(hf, sizeof(LOGFONT), &lf)) { HDC hdc = GetDC(hwndCtrl); lf.lfHeight = (hdc) ? -MulDiv(7, GetDeviceCaps(hdc, LOGPIXELSY), 72) : -9; lf.lfWeight = FW_THIN; lf.lfQuality = PROOF_QUALITY; StringCchCopy(lf.lfFaceName, sizeof(lf.lfFaceName)/sizeof(*lf.lfFaceName), L"Arial"); hFont = CreateFontIndirect(&lf); if (hdc) ReleaseDC(hwnd, hdc); } } if (hFont) { SendMessageW(hwndCtrl, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE); SendDlgItemMessageW(hwnd, IDC_LBL_REASON, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE); fontRef++; } } if (NULL != (hwndCtrl = GetDlgItem(hwnd, IDC_LV_EXT))) { DWORD exstyle = LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP; SendMessageW(hwndCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, exstyle, exstyle); LVCOLUMNW column; column.mask = LVCF_WIDTH | LVCF_TEXT; column.cx = 120; column.pszText = L"Artist"; SendMessageW(hwndCtrl, LVM_INSERTCOLUMNW, (WPARAM)0xEFFF, (LPARAM)&column); column.cx = 160; column.pszText = L"Album"; SendMessageW(hwndCtrl, LVM_INSERTCOLUMNW, (WPARAM)0xEFFF, (LPARAM)&column); column.cx = 40; column.pszText = L"Language"; SendMessageW(hwndCtrl, LVM_INSERTCOLUMNW, (WPARAM)0xEFFF, (LPARAM)&column); } return TRUE; } static void ProgressDlg_OnDestroy(HWND hwnd) { PROGRESSDLG *pDlg; pDlg = GET_DATA(hwnd); if (pDlg) { RemovePropW(hwnd, PROP_PRGDLG); if (pDlg->icon.hbmp) DeleteObject(pDlg->icon.hbmp); if (pDlg->Btn1Data) SysFreeString(pDlg->Btn1Data); if (pDlg->AbortData) SysFreeString(pDlg->AbortData); free(pDlg); pDlg = NULL; } if (fontRef && 0 == --fontRef) { DeleteObject(hFont); hFont = NULL; } } static void ProgressDlg_OnCommand(HWND hwnd, WORD ctrlId, WORD evntId, HWND hwndCtrl) { PROGRESSDLG *pDlg; pDlg = GET_DATA(hwnd); if (!pDlg) return; switch(ctrlId) { case IDCANCEL: pDlg->rCode = S_FALSE; switch(pDlg->uState) { case STATE_ACTIVE: if (!pDlg->OnAbort) return; SetWindowTextW(hwndCtrl, WASABI_API_LNGSTRINGW(IDS_ABORTING)); EnableWindow(hwndCtrl, FALSE); pDlg->uState = STATE_ABORTING; pDlg->OnAbort(hwnd, pDlg->AbortData); return; case STATE_ABORTING: return; // don't do anything } ; EndProgressDialog(hwnd); break; case IDC_BUTTON1: if (BN_CLICKED == evntId) { if (pDlg->OnButton1) pDlg->OnButton1(hwnd, pDlg->Btn1Data); } break; } } static void ProgressDlg_OnErase(HWND hwnd, HDC hdc) { PROGRESSDLG *pDlg; if (NULL != (pDlg = GET_DATA(hwnd))) { RECT rc; SetRect(&rc, ICON_OFFSET_X, ICON_OFFSET_Y, ICON_OFFSET_X + (pDlg->icon.rc.right - pDlg->icon.rc.left), ICON_OFFSET_Y + (pDlg->icon.rc.bottom - pDlg->icon.rc.top)); if (RectVisible(hdc, &rc)) { if (AnimateProgressIcon(hdc, ICON_OFFSET_X, ICON_OFFSET_Y, &pDlg->icon)) ExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); } } } static void ProgressDlg_OnLButtonDown(HWND hwnd, DWORD wKey, POINTS pts) { PROGRESSDLG *pDlg = GET_DATA(hwnd); if (pDlg) { POINT pt; RECT rc; POINTSTOPOINT(pt, pts); SetRect(&rc, ICON_OFFSET_X, ICON_OFFSET_Y, ICON_OFFSET_X + (pDlg->icon.rc.right - pDlg->icon.rc.left), ICON_OFFSET_Y + (pDlg->icon.rc.bottom - pDlg->icon.rc.top)); if (PtInRect(&rc, pt)) SendMessageW(line.hMainWindow, WM_WA_IPC, (WPARAM)L"http://www.cddb.com/", IPC_OPEN_URL); } } static INT_PTR ProgressDlg_OnSetCursor(HWND hwnd, HWND hwndCursor, WORD htCode, WORD msgId) { PROGRESSDLG *pDlg = GET_DATA(hwnd); if (pDlg) { RECT rc; POINT pt; GetCursorPos(&pt); MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); SetRect(&rc, ICON_OFFSET_X, ICON_OFFSET_Y, ICON_OFFSET_X + (pDlg->icon.rc.right - pDlg->icon.rc.left), ICON_OFFSET_Y + (pDlg->icon.rc.bottom - pDlg->icon.rc.top)); if (PtInRect(&rc, pt)) return (NULL != SetCursor(LoadCursor(NULL, IDC_HAND))); } return FALSE; } static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: return ProgressDlg_OnDialogInit(hwndDlg, (HWND)wParam, lParam); case WM_DESTROY: ProgressDlg_OnDestroy(hwndDlg); break; case WM_COMMAND: ProgressDlg_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; case WM_ERASEBKGND: ProgressDlg_OnErase(hwndDlg, (HDC)wParam); break; case WM_LBUTTONDOWN: ProgressDlg_OnLButtonDown(hwndDlg, (DWORD)wParam, MAKEPOINTS(lParam)); break; case WM_SETCURSOR: return ProgressDlg_OnSetCursor(hwndDlg, (HWND)wParam, LOWORD(lParam), HIWORD(lParam)); } return 0; } static BOOL CALLBACK EnumWnd_OnNextWindow(HWND hwnd, LPARAM lParam) { ENUMWND_DATAPACK *pData = (ENUMWND_DATAPACK*)lParam; if (!pData) return FALSE; if (!pData->found) { if (pData->host == hwnd) pData->found = TRUE; // return TRUE; } ULONG_PTR style = GetWindowLongPtrW(hwnd, GWL_STYLE); if (0 == (WS_CHILD & style) && (0 == (FINDWND_ONLY_VISIBLE & pData->flags) || (WS_VISIBLE & style)) && (0 == (FINDWND_ONLY_ENABLED & pData->flags) || 0 == (WS_DISABLED & style))) { HWND hwndOwner = GetWindow(hwnd, GW_OWNER); if (pData->host == hwndOwner) { if (pData->index == pData->count) return FALSE; /// pData->list[pData->index] = hwnd; pData->index++; } } return TRUE; } BOOL FindAllOwnedWindows(HWND hwndHost, HWND *hwndList, INT cList, UINT flags) { BOOL br; ENUMWND_DATAPACK data; ZeroMemory(&data, sizeof(ENUMWND_DATAPACK)); if (!hwndHost || !hwndList) return FALSE; data.host = hwndHost; data.list = hwndList; data.count = cList; data.flags = flags; data.list[0] = NULL; br = EnumWindows(EnumWnd_OnNextWindow, (LPARAM)&data); data.list[data.index] = NULL; return br; }