1532 lines
42 KiB
C++
1532 lines
42 KiB
C++
/** (c) Nullsoft, Inc. C O N F I D E N T I A L
|
|
** Filename:
|
|
** Project:
|
|
** Description:
|
|
** Author:
|
|
** Created:
|
|
**/
|
|
|
|
#include "Main.h"
|
|
#include "language.h"
|
|
#include <math.h>
|
|
#include "../nu/threadname.h"
|
|
#include "resource.h"
|
|
#include <tataki/export.h>
|
|
#include "api.h"
|
|
#include "../nu/threadpool/TimerHandle.hpp"
|
|
#include "../nu/AutoWide.h"
|
|
|
|
int img_w[2] = {400, 100}, img_h[2] = {189, 34};
|
|
int about_lastpage;
|
|
HWND about_hwnd;
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
|
|
static unsigned const char sq_table[]=
|
|
{0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, 64, 65,
|
|
67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94,
|
|
96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113,
|
|
114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128,
|
|
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
|
|
142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153,
|
|
154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164,
|
|
165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175,
|
|
176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185,
|
|
185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 193, 194,
|
|
195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203,
|
|
204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212,
|
|
212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220,
|
|
221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228,
|
|
229, 229, 230, 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236,
|
|
236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 243, 243,
|
|
244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250,
|
|
251, 251, 252, 252, 253, 253, 254, 254, 255};
|
|
|
|
static __inline unsigned long isqrt(unsigned long n)
|
|
{
|
|
if (n >= 0x10000)
|
|
if (n >= 0x1000000)
|
|
if (n >= 0x10000000)
|
|
if (n >= 0x40000000) return(sq_table[n >> 24] << 8);
|
|
else return(sq_table[n >> 22] << 7);
|
|
else
|
|
if (n >= 0x4000000) return(sq_table[n >> 20] << 6);
|
|
else return(sq_table[n >> 18] << 5);
|
|
else
|
|
if (n >= 0x100000)
|
|
if (n >= 0x400000) return(sq_table[n >> 16] << 4);
|
|
else return(sq_table[n >> 14] << 3);
|
|
else
|
|
if (n >= 0x40000) return(sq_table[n >> 12] << 2);
|
|
else return(sq_table[n >> 10] << 1);
|
|
else
|
|
if (n >= 0x100)
|
|
if (n >= 0x1000)
|
|
if (n >= 0x4000) return(sq_table[n >> 8]);
|
|
else return(sq_table[n >> 6] >> 1);
|
|
else
|
|
if (n >= 0x400) return(sq_table[n >> 4] >> 2);
|
|
else return(sq_table[n >> 2] >> 3);
|
|
else
|
|
if (n >= 0x10)
|
|
if (n >= 0x40) return(sq_table[n] >> 4);
|
|
else return(sq_table[n << 2] << 5);
|
|
else
|
|
if (n >= 0x4) return(sq_table[n >> 4] << 6);
|
|
else return(sq_table[n >> 6] << 7);
|
|
}
|
|
|
|
void about_dialog(void)
|
|
{
|
|
if (about_hwnd)
|
|
{
|
|
SetForegroundWindow(about_hwnd);
|
|
return;
|
|
}
|
|
|
|
about_hwnd=(HWND)LPCreateDialogW(IDD_NEWABOUT, hMainWindow, aboutProc);
|
|
|
|
// show about window and restore last position as applicable
|
|
POINT pt = {about_rect.left, about_rect.top};
|
|
if (!windowOffScreen(about_hwnd, pt))
|
|
SetWindowPos(about_hwnd, HWND_TOP, about_rect.left, about_rect.top, 0, 0, SWP_NOSIZE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
|
else
|
|
ShowWindow(about_hwnd, SW_SHOW);
|
|
}
|
|
|
|
static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
static HWND cur_wnd;
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
int t=about_lastpage;
|
|
about_lastpage=-1;
|
|
// make sure not to show the localised page if not under a language pack
|
|
if (t==4 && config_langpack[0]) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON2, 0);
|
|
else if (t==3) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON6, 0);
|
|
else if (t==2) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON5, 0);
|
|
else if (t==1) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON4, 0);
|
|
else
|
|
{
|
|
if (t==4) t = 0;
|
|
SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON3, 0);
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
case IDOK:
|
|
DestroyWindow(hwndDlg);
|
|
return FALSE;
|
|
case IDC_BUTTON3:
|
|
case IDC_BUTTON4:
|
|
case IDC_BUTTON5:
|
|
case IDC_BUTTON6:
|
|
case IDC_BUTTON2:
|
|
{
|
|
int id=-1;
|
|
int t = 0;
|
|
void *proc = 0;
|
|
if (LOWORD(wParam)==IDC_BUTTON3) t=0;
|
|
if (LOWORD(wParam)==IDC_BUTTON4) t=1;
|
|
if (LOWORD(wParam)==IDC_BUTTON5) t=2;
|
|
if (LOWORD(wParam)==IDC_BUTTON6) t=3;
|
|
if (LOWORD(wParam)==IDC_BUTTON2) t=4;
|
|
if (t == about_lastpage) return 0;
|
|
about_lastpage=t;
|
|
switch (t)
|
|
{
|
|
case 0: id=IDD_NEWABOUT1; proc=about1Proc; break;
|
|
case 1: id=IDD_NEWABOUT2; proc=creditProc; break;
|
|
case 2: id=IDD_NEWABOUT3; proc=tipsProc; break;
|
|
case 3: id=IDD_NEWABOUT4; proc=whatsnewProc; break;
|
|
case 4: id=IDD_ABOUT_TRANSLATION; proc=translationProc; break;
|
|
}
|
|
|
|
if (IsWindow(cur_wnd))
|
|
{
|
|
DestroyWindow(cur_wnd);
|
|
cur_wnd=0;
|
|
}
|
|
|
|
if (id != -1)
|
|
{
|
|
cur_wnd = CreateDialogW(language_pack_instance, MAKEINTRESOURCEW(id), hwndDlg, (DLGPROC)proc);
|
|
// handles cases where there's no localised info page in a language pack / under en-us
|
|
if(!IsWindow(cur_wnd)) cur_wnd = LPCreateDialogW(id, hwndDlg, (DLGPROC)proc);
|
|
|
|
{
|
|
RECT r;
|
|
GetWindowRect(GetDlgItem(hwndDlg,IDC_RECT),&r);
|
|
ScreenToClient(hwndDlg,(LPPOINT)&r);
|
|
SetWindowPos(cur_wnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
|
|
}
|
|
ShowWindow(cur_wnd,SW_SHOWNA);
|
|
{
|
|
RECT r,r2;
|
|
GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON3),&r);
|
|
GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON6),&r2);
|
|
r.right=r2.right;
|
|
ScreenToClient(hwndDlg,(LPPOINT)&r);
|
|
ScreenToClient(hwndDlg,((LPPOINT)&r)+1);
|
|
InvalidateRect(hwndDlg,&r,FALSE);
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
GetWindowRect(hwndDlg, &about_rect);
|
|
if (IsWindow(cur_wnd)) DestroyWindow(cur_wnd);
|
|
cur_wnd=0;
|
|
about_hwnd=NULL;
|
|
break;
|
|
}
|
|
|
|
if (uMsg == WM_DRAWITEM)
|
|
{
|
|
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
|
|
if (di->CtlType == ODT_BUTTON)
|
|
{
|
|
wchar_t wt[123] = {0};
|
|
int sel=0;
|
|
RECT r;
|
|
GetDlgItemTextW(hwndDlg,wParam,wt,123);
|
|
|
|
if (di->CtlID==IDC_BUTTON3 && about_lastpage==0) sel=1;
|
|
else if (di->CtlID==IDC_BUTTON4 && about_lastpage==1) sel=1;
|
|
else if (di->CtlID==IDC_BUTTON5 && about_lastpage==2) sel=1;
|
|
else if (di->CtlID==IDC_BUTTON6 && about_lastpage==3) sel=1;
|
|
else if (di->CtlID==IDC_BUTTON2 && about_lastpage==4) sel=1;
|
|
|
|
if (di->CtlID != IDC_BUTTON6)
|
|
{
|
|
MoveToEx(di->hDC,di->rcItem.right-1,di->rcItem.top,NULL);
|
|
LineTo(di->hDC,di->rcItem.right-1,di->rcItem.bottom);
|
|
}
|
|
|
|
// draw text
|
|
if (!sel && (di->itemState & (ODS_SELECTED)))
|
|
SetTextColor(di->hDC,RGB(0,40,255));
|
|
r=di->rcItem;
|
|
DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);
|
|
if (sel)
|
|
{
|
|
r=di->rcItem;
|
|
r.left+=2;
|
|
SetBkMode(di->hDC,TRANSPARENT);
|
|
DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Window Proc for the 'keyboard shorcuts' tab of about screen */
|
|
static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
static HGLOBAL hResource=0;
|
|
static DWORD hResourceSize=0;
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
char *b = NULL, *p = 0, *op = 0;
|
|
DWORD size = 0;
|
|
if (!hResource)
|
|
{
|
|
hResource = langManager->LoadResourceFromFileW(language_pack_instance, hMainInstance,TEXT("TEXT"), TEXT("TIPSTEXT"),&size);
|
|
hResourceSize = size;
|
|
}
|
|
p = (char*)hResource;
|
|
if (p && (op = strstr(p, "!!End"))) // if there's "!!End" in the resource, than copy everything before it
|
|
{
|
|
b = (char*)GlobalAlloc(GPTR, op-p+1);
|
|
memcpy(b, p, op-p);
|
|
b[op-p] = 0;
|
|
} else {
|
|
b = (char*)GlobalAlloc(GPTR, hResourceSize+1);
|
|
memcpy(b, p, hResourceSize);
|
|
b[hResourceSize] = 0;
|
|
}
|
|
|
|
SetDlgItemTextA(hwndDlg, IDC_TIPS, (b ? b : p)); // send it to the text control to display
|
|
if (b) GlobalFree(b);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if(LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
DestroyWindow(about_hwnd);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (FALSE != IsDirectMouseWheelMessage(uMsg))
|
|
{
|
|
HWND textWindow;
|
|
RECT windowRect;
|
|
textWindow = GetDlgItem(hwndDlg, IDC_TIPS);
|
|
if (NULL != textWindow &&
|
|
FALSE != GetClientRect(textWindow, &windowRect))
|
|
{
|
|
POINT pt;
|
|
POINTSTOPOINT(pt, lParam);
|
|
|
|
MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1);
|
|
if (FALSE != PtInRect(&windowRect, pt))
|
|
{
|
|
SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam);
|
|
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WNDPROC whatedproc = 0;
|
|
static LRESULT CALLBACK whatseditproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(uMsg == WM_KEYDOWN)
|
|
{
|
|
if(wParam == 'F' && (GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
|
|
{
|
|
if(IsWindowEnabled(GetDlgItem(GetParent(hwndDlg), IDC_ABOUT_SEARCH)))
|
|
{
|
|
SendMessageW(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDC_ABOUT_SEARCH,0), 0);
|
|
}
|
|
}
|
|
}
|
|
return CallWindowProcW(whatedproc,hwndDlg,uMsg,wParam,lParam);
|
|
}
|
|
|
|
#define WHATSNEW_BUFFER_SIZE 262144
|
|
static wchar_t* ver_buf;
|
|
|
|
void GetWhatsNewFromFile(FILE *fp)
|
|
{
|
|
bool utf8=false, utf16=false;
|
|
unsigned char BOM[3] = {0, 0, 0};
|
|
if (fread(BOM, 3, 1, fp) == 1 && BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF)
|
|
utf8 = true;
|
|
else
|
|
{
|
|
fseek(fp, 0, SEEK_SET);
|
|
if (fread(BOM, 2, 1, fp) == 1 && BOM[0] == 0xFF && BOM[1] == 0xFE)
|
|
utf16=true;
|
|
else
|
|
fseek(fp, 0, SEEK_SET);
|
|
}
|
|
|
|
if (utf16)
|
|
{
|
|
wchar_t buffer[WHATSNEW_BUFFER_SIZE]={0}, *p=buffer;
|
|
for (;;)
|
|
{
|
|
fgetws(p,1024,fp);
|
|
if (feof(fp)) break;
|
|
if (p[wcslen(p)-1]==L'\n')
|
|
p[wcslen(p)-1]=0;
|
|
StringCchCatW(p,WHATSNEW_BUFFER_SIZE,L"\r\n");
|
|
p=p+wcslen(p);
|
|
if (p-buffer > WHATSNEW_BUFFER_SIZE) break;
|
|
}
|
|
|
|
ver_buf = wcsdup(buffer);
|
|
}
|
|
else
|
|
{
|
|
char buffer[WHATSNEW_BUFFER_SIZE]={0},*p=buffer;
|
|
for (;;)
|
|
{
|
|
fgets(p,1024,fp);
|
|
if (feof(fp)) break;
|
|
if (p[lstrlenA(p)-1]=='\n')
|
|
p[lstrlenA(p)-1]=0;
|
|
StringCchCatA(p,WHATSNEW_BUFFER_SIZE,"\r\n");
|
|
p=p+lstrlenA(p);
|
|
if (p-buffer > WHATSNEW_BUFFER_SIZE) break;
|
|
}
|
|
|
|
if (utf8)
|
|
{
|
|
ver_buf = AutoWideDup(buffer, CP_UTF8);
|
|
}
|
|
else
|
|
{
|
|
ver_buf = AutoWideDup(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
static std::map<int,wchar_t*> versions;
|
|
/* Window Proc for the 'version history' tab of about screen */
|
|
static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static UINT fm_msg;
|
|
static FINDREPLACEW find;
|
|
static wchar_t fromstring[256];
|
|
static HWND finder;
|
|
|
|
if(uMsg == fm_msg)
|
|
{
|
|
LPFINDREPLACEW lpFindReplace = (LPFINDREPLACEW) lParam;
|
|
if(lpFindReplace->Flags & FR_FINDNEXT)
|
|
{
|
|
int len = GetWindowTextLengthW(GetDlgItem(hwndDlg,IDC_TIPS))+1,
|
|
flen = lstrlenW(lpFindReplace->lpstrFindWhat), start = 0, end = 0;
|
|
wchar_t *buffer = (wchar_t*)calloc((len+1),sizeof(wchar_t)),
|
|
*search = (wchar_t*)calloc((flen+2),sizeof(wchar_t)),
|
|
*result = 0;
|
|
|
|
lstrcpynW(search,lpFindReplace->lpstrFindWhat,flen+1);
|
|
SendDlgItemMessageW(hwndDlg,IDC_TIPS,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
|
|
|
|
GetDlgItemTextW(hwndDlg,IDC_TIPS,buffer,len);
|
|
|
|
// handles the match case option
|
|
if(!(lpFindReplace->Flags & FR_MATCHCASE))
|
|
{
|
|
CharUpperBuffW(buffer, len);
|
|
CharUpperBuffW(search, flen+1);
|
|
}
|
|
|
|
if((result = wcsstr(buffer+end,search)))
|
|
{
|
|
SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SETSEL,result-buffer,(result-buffer)+flen);
|
|
SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SCROLLCARET,0,0);
|
|
}
|
|
else
|
|
{
|
|
MessageBoxW(finder,getStringW(IDS_NO_MATCHES_FOUND,NULL,0),L"Winamp",MB_ICONINFORMATION);
|
|
}
|
|
|
|
free(buffer);
|
|
free(search);
|
|
}
|
|
}
|
|
|
|
switch (uMsg) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
wchar_t fn[MAX_PATH] = {0};
|
|
FILE *fp = NULL;
|
|
int last_add = 0;
|
|
|
|
whatedproc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwndDlg,IDC_TIPS),GWLP_WNDPROC,(LONG_PTR)whatseditproc);
|
|
|
|
SendDlgItemMessage(hwndDlg, IDC_TIPS, EM_SETLIMITTEXT, 0, 0);
|
|
|
|
// attempt to pull a localised whatsnew.txt
|
|
// before reverting to the english default
|
|
if (lang_directory[0])
|
|
{
|
|
lstrcpynW(fn,lang_directory,MAX_PATH);
|
|
}
|
|
else
|
|
{
|
|
GetModuleFileNameW(NULL,fn,MAX_PATH);
|
|
PathRemoveFileSpecW(fn);
|
|
}
|
|
PathAppendW(fn, L"whatsnew.txt");
|
|
|
|
// we don't set the buffer position so that it all works on the fallback code
|
|
// and make sure there's a selection no matter what happens with other things
|
|
SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)getStringW(IDS_SHOW_ALL_HISTORY,NULL,0));
|
|
SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,0,0);
|
|
|
|
versions.clear();
|
|
fp = _wfopen(fn,L"rb");
|
|
|
|
// if there isn't a localised whatsnew.txt then revert to the old ways
|
|
if(!fp)
|
|
{
|
|
GetModuleFileNameW(NULL,fn,MAX_PATH);
|
|
PathRemoveFileSpecW(fn);
|
|
PathAppendW(fn,L"whatsnew.txt");
|
|
fp = _wfopen(fn,L"rb");
|
|
}
|
|
|
|
if (fp)
|
|
{
|
|
GetWhatsNewFromFile(fp);
|
|
fclose(fp);
|
|
wchar_t* p = ver_buf;
|
|
while(p && *p)
|
|
{
|
|
// populate the version combobox
|
|
if(!wcsncmp(p,L"Winamp 5.",9))
|
|
{
|
|
wchar_t* pp = p, ver[64] = {0};
|
|
while(pp && *pp && *pp != L'\r') pp = CharNextW(pp);
|
|
// need to make sure that we've actually found a valid part otherwise
|
|
// just skip over things and don't fill in the combobox (attempted exploit)
|
|
if(pp && *pp && *pp == L'\r'){
|
|
pp = CharNextW(pp);
|
|
// make sure that we keep within the buffer size as some people have
|
|
// tried to make a buffer overflow vulnerability with this on XP SP3
|
|
lstrcpynW(ver,p,(pp-p<64?pp-p:64));
|
|
wchar_t* v = ver, *vn = 0, *vne = 0;
|
|
while(v && *v && *v != L'\t') v = CharNextW(v);
|
|
if(v && *v == L'\t'){
|
|
vn = vne = CharNextW(v);
|
|
*v = 0;
|
|
if(vn && *vn == L'[') vn = CharNextW(vn);
|
|
while(vne && *vne && *vne != L']') vne = CharNextW(vne);
|
|
if(vne && *vne == L']') *vne = 0;
|
|
}
|
|
last_add = SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)ver);
|
|
SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETITEMDATA,last_add,(LPARAM)p);
|
|
versions[last_add] = wcsdup(vn);
|
|
}
|
|
}
|
|
p = CharNextW(p);
|
|
}
|
|
|
|
// reset the selection to the last view and force an update to that
|
|
// would be better to do it straight away on load but this ensures all synchs up
|
|
SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,_r_i("whtsnewlp",1),0);
|
|
SendMessageW(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_VER_COMBO,CBN_SELCHANGE),(LPARAM)GetDlgItem(hwndDlg,IDC_VER_COMBO));
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwndDlg,IDC_VER_COMBO),0);
|
|
EnableWindow(GetDlgItem(hwndDlg,IDC_ABOUT_SEARCH),0);
|
|
SetDlgItemTextW(hwndDlg,IDC_TIPS,getStringW(IDS_WHATSNEW_FAIL,ver_buf,WHATSNEW_BUFFER_SIZE));
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
if(LOWORD(wParam) == IDC_VER_COMBO && HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
int cur = SendMessageW((HWND)lParam,CB_GETCURSEL,0,0);
|
|
wchar_t* position = (wchar_t*)SendMessageW((HWND)lParam,CB_GETITEMDATA,cur,0);
|
|
if(cur != CB_ERR && position){
|
|
wchar_t* p = position, *out_buf = (wchar_t*)calloc(WHATSNEW_BUFFER_SIZE,sizeof(wchar_t)), *out = out_buf;
|
|
while(p && *p)
|
|
{
|
|
if(*p == L'\t')
|
|
{
|
|
if(*CharNextW(p) == L'[')
|
|
{
|
|
wchar_t* pb = p;
|
|
while(pb && *pb && *pb != L']')
|
|
{
|
|
pb = CharNextW(pb);
|
|
}
|
|
if(pb && *pb == L']') p = CharNextW(pb);
|
|
}
|
|
}
|
|
|
|
// look for 2 empty lines to indicate end of version block
|
|
if(*p == L'\r')
|
|
{
|
|
wchar_t* n = CharNextW(p);
|
|
if(n && *n == L'\n')
|
|
{
|
|
n = CharNextW(n);
|
|
if(n && *n == L'\r')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*out = *p;
|
|
p = CharNextW(p);
|
|
out = CharNextW(out);
|
|
}
|
|
*out = 0;
|
|
|
|
wchar_t released[128] = {0};
|
|
if(cur == 1 || cur > 1 && versions[cur] != 0)
|
|
StringCchPrintfW(released,128,getStringW(IDS_RELEASED,NULL,0), (cur == 1 ? AutoWide(__DATE__) : versions[cur]));
|
|
else
|
|
released[0] = 0;
|
|
SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)released);
|
|
SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)out_buf);
|
|
free(out_buf);
|
|
}
|
|
else{
|
|
SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)L"");
|
|
SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)ver_buf);
|
|
}
|
|
}
|
|
else if(LOWORD(wParam) == IDC_ABOUT_SEARCH)
|
|
{
|
|
if(!IsWindow(finder))
|
|
{
|
|
if(!fm_msg) fm_msg = RegisterWindowMessageW(FINDMSGSTRINGW);
|
|
|
|
find.lStructSize = sizeof(find);
|
|
find.hwndOwner = hwndDlg;
|
|
find.Flags = FR_DOWN|FR_HIDEWHOLEWORD|FR_HIDEUPDOWN;
|
|
find.lpstrFindWhat = fromstring;
|
|
find.wFindWhatLen = ARRAYSIZE(fromstring);
|
|
finder = FindTextW(&find);
|
|
ShowWindow(finder,SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
SetActiveWindow(finder);
|
|
}
|
|
}
|
|
|
|
else if(LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
DestroyWindow(about_hwnd);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
free(ver_buf);
|
|
ver_buf = 0;
|
|
|
|
//for (int i=0; i!=versions.size(); i++)
|
|
// free(versions[i]);
|
|
for (auto& version : versions)
|
|
{
|
|
if (version.second)
|
|
{
|
|
free(version.second);
|
|
}
|
|
}
|
|
|
|
versions.clear();
|
|
_w_i("whtsnewlp",SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_GETCURSEL,0,0));
|
|
if(IsWindow(finder)) DestroyWindow(finder);
|
|
break;
|
|
}
|
|
|
|
if (FALSE != IsDirectMouseWheelMessage(uMsg))
|
|
{
|
|
HWND textWindow;
|
|
RECT windowRect;
|
|
textWindow = GetDlgItem(hwndDlg, IDC_TIPS);
|
|
if (NULL != textWindow &&
|
|
FALSE != GetClientRect(textWindow, &windowRect))
|
|
{
|
|
POINT pt;
|
|
POINTSTOPOINT(pt, lParam);
|
|
|
|
MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1);
|
|
if (FALSE != PtInRect(&windowRect, pt))
|
|
{
|
|
SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam);
|
|
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static volatile int aboutThread_kill, aboutThread_mode;
|
|
static HPALETTE m_haboutpal;
|
|
|
|
/* This does the 'zooming' effect on the image in the 'winamp' tab of the about screen */
|
|
class AboutContext
|
|
{
|
|
public:
|
|
bool Init(HWND _hwndDlg);
|
|
bool Tick();
|
|
void Quit();
|
|
|
|
private:
|
|
int mode;
|
|
static int m_wt,m_wait;
|
|
static int a;
|
|
HDC m_hdc;
|
|
HBITMAP m_hbm,m_oldhbm;
|
|
|
|
int m_pitch,m_height;
|
|
char *m_source,*m_dib;
|
|
int m_wmul[200];
|
|
RECT r;
|
|
HBITMAP m_imgbm, m_imgoldbm;
|
|
HDC m_imgdc;
|
|
|
|
struct
|
|
{
|
|
BITMAPINFO bmi;
|
|
RGBQUAD more_bmiColors[256];
|
|
LPVOID data;
|
|
} m_bitmap;
|
|
int c,use_palette;
|
|
HWND hwndDlg;
|
|
};
|
|
|
|
int AboutContext::m_wt = 0;
|
|
int AboutContext::m_wait = 0;
|
|
int AboutContext::a = 0;
|
|
bool AboutContext::Init(HWND _hwndDlg)
|
|
{
|
|
hwndDlg = _hwndDlg;
|
|
mode=(GetAsyncKeyState(VK_SHIFT)&0x8000);
|
|
GetClientRect(GetDlgItem(hwndDlg,IDC_ABOUTIMG),&r);
|
|
HDC hdc=GetWindowDC(hwndDlg);
|
|
if (!hdc)
|
|
return false;
|
|
use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0;
|
|
m_hdc = CreateCompatibleDC(NULL);
|
|
m_imgdc = CreateCompatibleDC(NULL);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
|
|
if (!m_imgdc)
|
|
return false;
|
|
|
|
m_imgbm= (HBITMAP)LoadImage(hMainInstance,MAKEINTRESOURCE((!aboutThread_mode ? IDB_SPLASH : IDB_PLATE)),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
|
|
m_imgoldbm=(HBITMAP)SelectObject(m_imgdc,m_imgbm);
|
|
m_source=(char *)GlobalAlloc(GPTR,img_w[aboutThread_mode]*img_h[aboutThread_mode]);
|
|
|
|
if (m_imgbm && m_source)
|
|
{
|
|
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
|
m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
m_bitmap.bmi.bmiHeader.biPlanes = 1;
|
|
m_bitmap.bmi.bmiHeader.biBitCount = 8;
|
|
m_bitmap.bmi.bmiHeader.biCompression = BI_RGB;
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = 0;
|
|
m_bitmap.bmi.bmiHeader.biClrUsed = 128;
|
|
m_bitmap.bmi.bmiHeader.biClrImportant = 128;
|
|
m_bitmap.bmi.bmiHeader.biWidth = img_w[aboutThread_mode];
|
|
m_bitmap.bmi.bmiHeader.biHeight = -img_h[aboutThread_mode];
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = img_w[aboutThread_mode]*img_h[aboutThread_mode];
|
|
|
|
GetDIBits(m_imgdc,m_imgbm,0,img_h[aboutThread_mode],m_source,(BITMAPINFO *)&m_bitmap,DIB_RGB_COLORS);
|
|
GetDIBColorTable(m_imgdc,0,256,m_bitmap.bmi.bmiColors);
|
|
|
|
SelectObject(m_imgdc, m_imgoldbm);
|
|
DeleteDC(m_imgdc);
|
|
DeleteObject(m_imgbm);
|
|
}
|
|
else
|
|
{
|
|
DeleteDC(m_imgdc);
|
|
if (m_imgbm) DeleteObject(m_imgbm);
|
|
if (m_source) GlobalFree(m_source);
|
|
return false;
|
|
}
|
|
|
|
if (use_palette)
|
|
{
|
|
struct
|
|
{
|
|
LOGPALETTE logpal;
|
|
PALETTEENTRY palentries[255];
|
|
} palette;
|
|
palette.logpal.palVersion = 0x300;
|
|
palette.logpal.palNumEntries = 128;
|
|
|
|
for (c = 0; c < 128; c ++)
|
|
{
|
|
palette.logpal.palPalEntry[c].peRed = m_bitmap.bmi.bmiColors[c].rgbRed;
|
|
palette.logpal.palPalEntry[c].peGreen = m_bitmap.bmi.bmiColors[c].rgbGreen;
|
|
palette.logpal.palPalEntry[c].peBlue = m_bitmap.bmi.bmiColors[c].rgbBlue;
|
|
palette.logpal.palPalEntry[c].peFlags = 0;
|
|
}
|
|
m_haboutpal = CreatePalette((LOGPALETTE *)&palette.logpal);
|
|
}
|
|
|
|
m_pitch=((r.right-r.left+3)&~3);
|
|
m_height=r.bottom-r.top;
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = 0;
|
|
m_bitmap.bmi.bmiHeader.biClrUsed = 0;
|
|
m_bitmap.bmi.bmiHeader.biClrImportant = 0;
|
|
m_bitmap.bmi.bmiHeader.biWidth = m_pitch;
|
|
m_bitmap.bmi.bmiHeader.biHeight = -m_height;
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height;
|
|
m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, &m_bitmap.data, NULL, 0);
|
|
|
|
if (!m_hbm)
|
|
{
|
|
if (m_imgbm) DeleteObject(m_imgbm);
|
|
if (m_source) GlobalFree(m_source);
|
|
return 0;
|
|
}
|
|
m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm);
|
|
m_dib=(char*)m_bitmap.data;
|
|
{
|
|
for (int x = 0; x < img_h[aboutThread_mode]; x ++)
|
|
m_wmul[x]=x*img_w[aboutThread_mode];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool AboutContext::Tick()
|
|
{
|
|
if (aboutThread_kill)
|
|
return false;
|
|
|
|
int tab[512] = {0};
|
|
// Sleep(50);
|
|
{
|
|
int offs;
|
|
int x;
|
|
double max_d=sqrt((double)((m_pitch*m_pitch+m_height*m_height))/4.0f);
|
|
//int imax_d2=(int)(255.0/max_d*256.0);
|
|
int imax_d=(int)max_d;
|
|
double dpos;
|
|
|
|
int thiswt=m_wt;
|
|
if (thiswt > 63) thiswt = 126-thiswt;
|
|
|
|
dpos=1.0+sin(thiswt*M_PI/32.0);
|
|
|
|
if (dpos < 1.0) dpos=0.5+dpos/2.0;
|
|
if (thiswt < 32) offs=thiswt*24;
|
|
else offs=(64-thiswt)*24;
|
|
if (imax_d > 512) return false;
|
|
|
|
for (x = 0; x < imax_d; x ++)
|
|
{
|
|
tab[x]=(int) (pow(sin(x/(max_d-1)),dpos)*1.7*256.0*max_d/(x+1)) - offs;
|
|
if (tab[x]<0)tab[x]=-tab[x];
|
|
}
|
|
|
|
if (m_wt == 0)
|
|
{
|
|
if (m_wait++>=40)
|
|
{
|
|
m_wt++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_wait=0;
|
|
m_wt++;
|
|
}
|
|
m_wt&=127;
|
|
}
|
|
|
|
{
|
|
int xsc=((!aboutThread_mode ? img_w[0]*180 : img_w[1]*360))/m_pitch;
|
|
int ysc=((!aboutThread_mode ? img_h[0]*200 : img_h[1]*500))/m_height;
|
|
int w2=m_pitch/2;
|
|
int h2=m_height/2;
|
|
char *out=m_dib;
|
|
int y;
|
|
if (m_wt)
|
|
{
|
|
a=!a;
|
|
// weird interlace shit
|
|
if (a && mode)
|
|
{
|
|
out+=m_pitch;
|
|
}
|
|
for (y = -h2+(mode?a:0); y < h2; y ++)
|
|
{
|
|
int x2=w2*w2+w2+y*y+256;
|
|
int dx2=-2*w2;
|
|
int yysc=y*ysc;
|
|
int xxsc=-w2*xsc;
|
|
int x=m_pitch;
|
|
while (x--)
|
|
{
|
|
int qd=tab[isqrt(x2)];
|
|
int ow,oh;
|
|
x2+=dx2;
|
|
dx2+=2;
|
|
ow = img_w[aboutThread_mode]/2 + (qd*xxsc)/65536;
|
|
xxsc+=xsc;
|
|
oh = img_h[aboutThread_mode]/2 + (qd*yysc)/65536;
|
|
|
|
if (ow < 0) ow=0;
|
|
else if (ow >= img_w[aboutThread_mode]) ow=img_w[aboutThread_mode]-1;
|
|
if (oh < 0) oh=0;
|
|
else if (oh >= img_h[aboutThread_mode]) oh=img_h[aboutThread_mode]-1;
|
|
|
|
*out++=m_source[ow+m_wmul[oh]];
|
|
}
|
|
|
|
// weird interlace shit
|
|
if (mode)
|
|
{
|
|
y++;
|
|
out+=m_pitch;
|
|
}
|
|
}
|
|
}
|
|
else // copy, with optional rescale
|
|
{
|
|
int x;
|
|
int skipw=0;
|
|
int skiph=0;
|
|
|
|
int dxp,dyp,xp,yp;
|
|
|
|
skiph=(m_height-img_h[aboutThread_mode])/2;
|
|
skipw=(m_pitch-img_w[aboutThread_mode])/2;
|
|
|
|
if (skipw <0) skipw=0;
|
|
if (skiph <0) skiph=0;
|
|
|
|
dxp=(img_w[aboutThread_mode]<<16)/(m_pitch-skipw*2);
|
|
dyp=(img_h[aboutThread_mode]<<16)/(m_height-skiph*2);
|
|
yp=0;
|
|
for (y = 0; y < m_height; y ++)
|
|
{
|
|
if (y < skiph || y >= m_height - skiph)
|
|
{
|
|
memset(out,0,m_pitch);
|
|
out+=m_pitch;
|
|
}
|
|
else
|
|
{
|
|
char *in=m_source+(yp>>16)*img_w[aboutThread_mode];
|
|
xp=0;
|
|
for (x = 0; x < m_pitch; x ++)
|
|
{
|
|
if (x < skipw || x >=m_pitch-skipw)
|
|
{
|
|
*out++=0;
|
|
}
|
|
else
|
|
{
|
|
*out++=in[xp>>16];
|
|
xp+=dxp;
|
|
}
|
|
}
|
|
yp+=dyp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
HWND hwnd=GetDlgItem(hwndDlg,IDC_ABOUTIMG);
|
|
if (hwnd)
|
|
{
|
|
HDC h=GetDC(hwnd);
|
|
if (h)
|
|
{
|
|
if (m_haboutpal)
|
|
{
|
|
SelectPalette(h,m_haboutpal,FALSE);
|
|
RealizePalette(h);
|
|
}
|
|
BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY);
|
|
ReleaseDC(hwnd,h);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AboutContext::Quit()
|
|
{
|
|
if (m_hbm)
|
|
{
|
|
if (m_hdc) SelectObject(m_hdc, m_oldhbm);
|
|
DeleteObject(m_hbm);
|
|
m_hbm = NULL;
|
|
m_oldhbm=NULL;
|
|
}
|
|
if (m_haboutpal)
|
|
{
|
|
DeleteObject(m_haboutpal);
|
|
m_haboutpal = NULL;
|
|
}
|
|
if (m_hdc)
|
|
{
|
|
DeleteDC(m_hdc);
|
|
m_hdc=NULL;
|
|
}
|
|
if (m_source)
|
|
{
|
|
GlobalFree((HGLOBAL)m_source);
|
|
m_source=NULL;
|
|
}
|
|
}
|
|
|
|
static int AboutTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
|
|
{
|
|
AboutContext *context = (AboutContext *)user_data;
|
|
TimerHandle t(handle);
|
|
if (context->Tick())
|
|
{
|
|
t.Wait(50);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
context->Quit();
|
|
delete context;
|
|
HANDLE event = (HANDLE)id;
|
|
SetEvent(event);
|
|
WASABI_API_THREADPOOL->RemoveHandle(0, handle);
|
|
t.Close();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int AboutThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
|
|
{
|
|
AboutContext *context = new AboutContext;
|
|
if (context->Init((HWND)user_data))
|
|
{
|
|
TimerHandle t;
|
|
WASABI_API_THREADPOOL->AddHandle(0, t, AboutTickThreadPoolFunc, context, id, 0);
|
|
t.Wait(50);
|
|
}
|
|
else
|
|
{
|
|
delete context;
|
|
HANDLE event = (HANDLE)id;
|
|
SetEvent(event);
|
|
}
|
|
return 0;
|
|
}
|
|
/* Window Proc for the 'winamp' tab of the about screen */
|
|
static INT_PTR CALLBACK about1EggProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
#if 0
|
|
static char ascii[]="\n\n ______ ____ ___/\\ _/\\_ _____ dro _____ <3 ______ /\\____ _______\n\
|
|
\\_ \\/ \\/ \\_\\__/_\\ \\___ _\\ _ \\___ _\\ \\/ \\__\\ _ \\_\n\
|
|
/ / / / / \\/ |/ \\/ / / / / |/ /\n\
|
|
/ / / / / / / / / / / / ____/\n\
|
|
\\______/\\________\\____/\\____/\\_____\\____/\\_____\\____\\____/\\____/\\____/\n\
|
|
_________________________________________________________________ _________\n\
|
|
(_________________________________________________________________\\\\\\_WINAMP_)\n\n\n\
|
|
supplied by deadbeef\n\n\
|
|
cracked by rOn\n\n\
|
|
32kb cool intro by lone";
|
|
|
|
int i=0;
|
|
FILE *fh;
|
|
fh=fopen("c:\\blah.c","wt");
|
|
for(i=0;ascii[i];i++)
|
|
{
|
|
ascii[i]^=0x65;
|
|
fprintf(fh,"0x%x,",ascii[i]);
|
|
if((i&31)==31) fprintf(fh,"\n");
|
|
}
|
|
fclose(fh);
|
|
#else
|
|
static char ascii[]={
|
|
0x6f,0x6f,0x6f,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x4a,0x39,0x45,0x45,0x3a,0x4a,0x39,0x3a,0x45,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x1,0x17,0xa,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x45,0x59,0x56,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,
|
|
0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x6f,0x45,0x45,0x39,0x3a,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x39,
|
|
0x4a,0x45,0x45,0x45,0x45,0x45,0x39,0x3a,0x39,0x3a,0x3a,0x4a,0x3a,0x39,0x45,0x45,0x45,0x45,0x39,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x39,0x45,0x45,0x3a,0x45,0x39,0x3a,
|
|
0x3a,0x3a,0x45,0x45,0x3a,0x39,0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x45,0x45,0x39,0x3a,0x3a,0x39,0x45,0x45,0x3a,0x45,0x45,0x45,0x39,0x3a,0x6f,
|
|
0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,
|
|
0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x19,0x4a,0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,
|
|
0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x19,0x4a,0x45,0x45,0x45,0x45,0x4a,0x6f,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x45,
|
|
0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
|
|
0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x4a,0x6f,0x45,0x45,0x39,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,
|
|
0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,
|
|
0x3a,0x3a,0x3a,0x3a,0x4a,0x6f,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x6f,0x45,0x4d,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
|
|
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x39,0x39,0x3a,0x32,0x2c,0x2b,0x24,
|
|
0x28,0x35,0x3a,0x4c,0x6f,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
|
|
0x45,0x45,0x45,0x16,0x10,0x15,0x15,0x9,0xc,0x0,0x1,0x45,0x7,0x1c,0x45,0x1,0x0,0x4,0x1,0x7,0x0,0x0,0x3,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
|
|
0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x6,0x17,0x4,0x6,0xe,0x0,0x1,0x45,0x7,0x1c,0x45,
|
|
0x17,0x2a,0xb,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
|
|
0x56,0x57,0xe,0x7,0x45,0x6,0xa,0xa,0x9,0x45,0xc,0xb,0x11,0x17,0xa,0x45,0x7,0x1c,0x45,0x9,0xa,0xb,0x0,
|
|
};
|
|
static int dexored=0;
|
|
if(!dexored)
|
|
{
|
|
int i=0;
|
|
for(i=0;i<sizeof(ascii);i++) ascii[i]^=0x65;
|
|
dexored=1;
|
|
}
|
|
#endif
|
|
SetDlgItemTextA(hwndDlg,IDC_ASCII,ascii);
|
|
}
|
|
return 1;
|
|
case WM_LBUTTONDBLCLK:
|
|
{
|
|
EndDialog(hwndDlg,0);
|
|
ShowWindow(GetDlgItem(GetParent(hwndDlg),IDC_ABOUTIMG),SW_NORMAL);
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Window proc for the about screen (i.e. this one handles the tab changes */
|
|
static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
static HANDLE hThread;
|
|
static HWND egg_wnd;
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
if (!hThread)
|
|
{
|
|
aboutThread_kill=0;
|
|
aboutThread_mode=0;
|
|
hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0);
|
|
}
|
|
{
|
|
wchar_t buf[2048] = {0}, buf2[2048] = {0}, buf3[256] = {0},
|
|
*t1 = 0, *t2 = 0, *t3 = 0;
|
|
GetDlgItemTextW(hwndDlg,IDC_ABOUTTEXT,buf,ARRAYSIZE(buf));
|
|
StringCchPrintfW(buf2,2048,buf,(buf3[0] ? buf3 : (t1 = AutoWideDup(app_version_string))),
|
|
(t2 = AutoWideDup(APP_VERSION_PLATFORM)), (t3 = AutoWideDup(app_date)));
|
|
SetDlgItemTextW(hwndDlg, IDC_ABOUTTEXT, buf2);
|
|
link_startsubclass(hwndDlg, IDC_WINAMPLINK);
|
|
if (t1) free(t1);
|
|
if (t2) free(t2);
|
|
if (t3) free(t3);
|
|
}
|
|
return TRUE;
|
|
}
|
|
if (uMsg == WM_QUERYNEWPALETTE)
|
|
{
|
|
if (m_haboutpal)
|
|
{
|
|
HDC hdc = GetWindowDC(hwndDlg);
|
|
SelectPalette(hdc,m_haboutpal,FALSE);
|
|
RealizePalette(hdc);
|
|
InvalidateRect(hwndDlg,NULL,FALSE);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (uMsg == WM_PALETTECHANGED)
|
|
{
|
|
if (m_haboutpal)
|
|
{
|
|
HDC hdc = GetWindowDC(hwndDlg);
|
|
SelectPalette(hdc,m_haboutpal,FALSE);
|
|
RealizePalette(hdc);
|
|
UpdateColors(hdc);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (uMsg == WM_DESTROY)
|
|
{
|
|
if (hThread)
|
|
{
|
|
aboutThread_kill=1;
|
|
WaitForSingleObject(hThread,INFINITE);
|
|
CloseHandle(hThread);
|
|
hThread=NULL;
|
|
}
|
|
}
|
|
if (uMsg == WM_COMMAND)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_WINAMPLINK:
|
|
{
|
|
wchar_t homepage[1024] = {0};
|
|
if (config_langpack[0])
|
|
{
|
|
getStringW(IDS_LOCALIZED_HOMEPAGE, homepage, 1024);
|
|
}
|
|
if (homepage[0])
|
|
myOpenURL(hwndDlg, homepage);
|
|
else
|
|
myOpenURL(hwndDlg,L"http://www.winamp.com/");
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
if (uMsg == WM_LBUTTONDBLCLK)
|
|
{
|
|
if ((GetAsyncKeyState(VK_SHIFT)&0x8000) && !(GetAsyncKeyState(VK_CONTROL)&0x8000))
|
|
{
|
|
ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_HIDE);
|
|
if (!IsWindow(egg_wnd))
|
|
{
|
|
egg_wnd = LPCreateDialogW(IDD_NEWABOUT1EGG,hwndDlg,about1EggProc);
|
|
}
|
|
ShowWindow(egg_wnd, SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
|
|
{
|
|
if (hThread)
|
|
{
|
|
aboutThread_kill=1;
|
|
WaitForSingleObject(hThread,INFINITE);
|
|
CloseHandle(hThread);
|
|
hThread=NULL;
|
|
aboutThread_kill=0;
|
|
aboutThread_mode=!aboutThread_mode;
|
|
hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0);
|
|
}
|
|
}
|
|
ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_SHOW);
|
|
}
|
|
}
|
|
link_handledraw(hwndDlg,uMsg,wParam,lParam);
|
|
return 0;
|
|
}
|
|
|
|
static volatile int creditThread_kill;
|
|
static HPALETTE m_hcreditspal;
|
|
|
|
/* this thread handles the 3d credits rendering (this one does some busywork and housecleaning, actual rendering done in creditsrend.c) */
|
|
class CreditsContext
|
|
{
|
|
public:
|
|
bool Init(HWND _hwndDlg);
|
|
bool Tick(int &wait_time);
|
|
void Quit();
|
|
|
|
private:
|
|
HDC m_hdc;
|
|
HBITMAP m_hbm,m_oldhbm;
|
|
int m_pitch,m_height;
|
|
char *m_dib;
|
|
char pal[768];
|
|
struct
|
|
{
|
|
BITMAPINFO bmi;
|
|
RGBQUAD more_bmiColors[255];
|
|
} m_bitmap;
|
|
int c,use_palette;
|
|
HWND hwndDlg;
|
|
};
|
|
|
|
bool CreditsContext::Init(HWND _hwndDlg)
|
|
{
|
|
hwndDlg = _hwndDlg;
|
|
Tataki::Init(WASABI_API_SVC);
|
|
m_hcreditspal = 0;
|
|
m_hdc = 0;
|
|
m_hbm = 0;
|
|
|
|
RECT r={0,};
|
|
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
|
|
|
GetWindowRect(hwndDlg,&r);
|
|
r.right=r.right-r.left;
|
|
r.bottom=r.bottom-r.top;
|
|
HDC hdc=GetWindowDC(hwndDlg);
|
|
if (!hdc)
|
|
return false;
|
|
use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0;
|
|
m_hdc = CreateCompatibleDC(NULL);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
|
|
m_pitch=((r.right+3)&~3);
|
|
m_height=r.bottom;
|
|
if (m_pitch < 4) m_pitch=4;
|
|
if (m_height < 4) m_height=4;
|
|
// if (m_pitch > GetSystemMetrics(SM_CXSCREEN)) m_pitch=GetSystemMetrics(SM_CXSCREEN);
|
|
// if (m_height > GetSystemMetrics(SM_CYSCREEN)) m_height=GetSystemMetrics(SM_CYSCREEN);
|
|
render_init(m_pitch,m_height,pal);
|
|
|
|
{
|
|
struct
|
|
{
|
|
LOGPALETTE logpal;
|
|
PALETTEENTRY palentries[255];
|
|
} palette;
|
|
palette.logpal.palVersion = 0x300;
|
|
palette.logpal.palNumEntries = 220;
|
|
for (c = 0; c < 256; c ++)
|
|
{
|
|
palette.logpal.palPalEntry[c].peRed = pal[c*3];
|
|
palette.logpal.palPalEntry[c].peGreen = pal[c*3+1];
|
|
palette.logpal.palPalEntry[c].peBlue = pal[c*3+2];
|
|
palette.logpal.palPalEntry[c].peFlags = PC_NOCOLLAPSE;
|
|
m_bitmap.bmi.bmiColors[c].rgbRed=pal[c*3];
|
|
m_bitmap.bmi.bmiColors[c].rgbGreen=pal[c*3+1];
|
|
m_bitmap.bmi.bmiColors[c].rgbBlue=pal[c*3+2];
|
|
m_bitmap.bmi.bmiColors[c].rgbReserved=0;
|
|
}
|
|
if (use_palette)
|
|
m_hcreditspal = CreatePalette((LOGPALETTE *)&palette.logpal);
|
|
}
|
|
|
|
|
|
m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
m_bitmap.bmi.bmiHeader.biPlanes = 1;
|
|
m_bitmap.bmi.bmiHeader.biBitCount = 8;
|
|
m_bitmap.bmi.bmiHeader.biCompression = BI_RGB;
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = 0;
|
|
m_bitmap.bmi.bmiHeader.biClrImportant = 0;
|
|
m_bitmap.bmi.bmiHeader.biClrUsed = 256;
|
|
m_bitmap.bmi.bmiHeader.biWidth = m_pitch;
|
|
m_bitmap.bmi.bmiHeader.biHeight = -m_height;
|
|
m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height;
|
|
m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, (void**)&m_dib, NULL, 0);
|
|
m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm);
|
|
return (m_hbm && m_dib);
|
|
}
|
|
|
|
void CreditsContext::Quit()
|
|
{
|
|
if (m_hbm)
|
|
{
|
|
if (m_hdc) SelectObject(m_hdc, m_oldhbm);
|
|
DeleteObject(m_hbm);
|
|
m_hbm = NULL;
|
|
m_oldhbm=NULL;
|
|
}
|
|
if (m_hcreditspal)
|
|
{
|
|
DeleteObject(m_hcreditspal);
|
|
m_hcreditspal = NULL;
|
|
}
|
|
if (m_hdc)
|
|
{
|
|
DeleteDC(m_hdc);
|
|
m_hdc=NULL;
|
|
}
|
|
render_quit();
|
|
Tataki::Quit();
|
|
}
|
|
|
|
bool CreditsContext::Tick(int &wait_time)
|
|
{
|
|
if (creditThread_kill)
|
|
return false;
|
|
|
|
unsigned int thist=GetTickCount();
|
|
render_render((unsigned char*)m_dib, m_hdc);
|
|
{
|
|
HDC h=GetDC(hwndDlg);
|
|
if (h)
|
|
{
|
|
if (m_hcreditspal)
|
|
{
|
|
SelectPalette(h,m_hcreditspal,FALSE);
|
|
RealizePalette(h);
|
|
}
|
|
BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY);
|
|
ReleaseDC(hwndDlg,h);
|
|
}
|
|
}
|
|
thist=GetTickCount()-thist;
|
|
if (thist > 28) thist=28;
|
|
wait_time = 30-thist;
|
|
return true;
|
|
}
|
|
|
|
static int CreditsTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
|
|
{
|
|
CreditsContext *context = (CreditsContext *)user_data;
|
|
TimerHandle t(handle);
|
|
int wait_time=30;
|
|
if (context->Tick(wait_time))
|
|
{
|
|
t.Wait(wait_time);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
context->Quit();
|
|
delete context;
|
|
HANDLE event = (HANDLE)id;
|
|
SetEvent(event);
|
|
WASABI_API_THREADPOOL->RemoveHandle(0, handle);
|
|
t.Close();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int CreditThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
|
|
{
|
|
CreditsContext *context = new CreditsContext;
|
|
if (context->Init((HWND)user_data))
|
|
{
|
|
TimerHandle t;
|
|
WASABI_API_THREADPOOL->AddHandle(0, t, CreditsTickThreadPoolFunc, context, id, api_threadpool::FLAG_LONG_EXECUTION);
|
|
t.Wait(30);
|
|
}
|
|
else
|
|
{
|
|
delete context;
|
|
HANDLE event = (HANDLE)id;
|
|
SetEvent(event);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Window Proc for the 'credits' tab of the about screen */
|
|
static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
static int g_fullscreen=0;
|
|
static RECT rsave;
|
|
static HWND hOldParent;
|
|
static int oldstyle;
|
|
static HANDLE hThread;
|
|
if (uMsg == WM_LBUTTONDBLCLK)
|
|
{
|
|
render_togglecredits();
|
|
return 0;
|
|
}
|
|
if (uMsg == WM_KEYDOWN && g_fullscreen)
|
|
{
|
|
if (wParam == VK_ESCAPE)
|
|
{
|
|
PostMessageW(hwndDlg,WM_LBUTTONDOWN,0,0);
|
|
}
|
|
else PostMessageW(hMainWindow,uMsg,wParam,lParam);
|
|
}
|
|
if ((uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK) && g_fullscreen)
|
|
{
|
|
if (hThread)
|
|
{
|
|
creditThread_kill=1;
|
|
WaitForSingleObject(hThread,INFINITE);
|
|
CloseHandle(hThread);
|
|
hThread = 0;
|
|
if (g_fullscreen)
|
|
{
|
|
RECT r=rsave;
|
|
ScreenToClient(hOldParent,(LPPOINT)&r);
|
|
ScreenToClient(hOldParent,(LPPOINT)&r+1);
|
|
SetWindowLong(hwndDlg,GWL_STYLE,oldstyle);
|
|
SetParent(hwndDlg,hOldParent);
|
|
SetWindowPos(hwndDlg,0,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER);
|
|
}
|
|
}
|
|
g_fullscreen=0;
|
|
creditThread_kill=0;
|
|
hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
|
|
}
|
|
else if (uMsg == WM_RBUTTONDBLCLK && !g_fullscreen)
|
|
{
|
|
RECT r;
|
|
if (hThread)
|
|
{
|
|
creditThread_kill=1;
|
|
WaitForSingleObject(hThread,INFINITE);
|
|
CloseHandle(hThread);
|
|
hThread = 0;
|
|
}
|
|
g_fullscreen=1;
|
|
GetWindowRect(hwndDlg,&rsave);
|
|
oldstyle=GetWindowLongW(hwndDlg,GWL_STYLE);
|
|
hOldParent=SetParent(hwndDlg,NULL);
|
|
|
|
SetWindowLong(hwndDlg,GWL_STYLE,WS_POPUP|WS_VISIBLE);
|
|
|
|
getViewport(&r,hwndDlg,1,NULL);
|
|
|
|
SetWindowPos(hwndDlg, HWND_TOPMOST, r.left, r.top, r.right, r.bottom, SWP_DRAWFRAME);
|
|
creditThread_kill=0;
|
|
hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
|
|
// go fullscreen
|
|
}
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
if (!hThread)
|
|
{
|
|
g_fullscreen=0;
|
|
creditThread_kill=0;
|
|
hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
|
|
}
|
|
return TRUE;
|
|
}
|
|
if (uMsg == WM_QUERYNEWPALETTE)
|
|
{
|
|
if (m_hcreditspal)
|
|
{
|
|
HDC hdc = GetWindowDC(hwndDlg);
|
|
SelectPalette(hdc,m_hcreditspal,FALSE);
|
|
RealizePalette(hdc);
|
|
InvalidateRect(hwndDlg,NULL,FALSE);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (uMsg == WM_PALETTECHANGED)
|
|
{
|
|
if (m_hcreditspal)
|
|
{
|
|
HDC hdc = GetWindowDC(hwndDlg);
|
|
SelectPalette(hdc,m_hcreditspal,FALSE);
|
|
RealizePalette(hdc);
|
|
UpdateColors(hdc);
|
|
ReleaseDC(hwndDlg,hdc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (uMsg == WM_DESTROY)
|
|
{
|
|
if (hThread)
|
|
{
|
|
creditThread_kill=1;
|
|
WaitForSingleObject(hThread,INFINITE);
|
|
CloseHandle(hThread);
|
|
hThread=NULL;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
// only attempt set it to show a hand cursor if it's an ownerdraw button
|
|
if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE), GWL_STYLE) & BS_OWNERDRAW)
|
|
{
|
|
link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE);
|
|
}
|
|
if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE2), GWL_STYLE) & BS_OWNERDRAW)
|
|
{
|
|
link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE2);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if(LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
DestroyWindow(about_hwnd);
|
|
}
|
|
else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE)
|
|
{
|
|
wchar_t homepage[1024] = {0};
|
|
getStringW(IDS_AUTHOR_HOMEPAGE, homepage, 1024);
|
|
myOpenURL(hwndDlg, homepage);
|
|
}
|
|
else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE2)
|
|
{
|
|
wchar_t homepage[1024] = {0};
|
|
getStringW(IDS_AUTHOR_HOMEPAGE2, homepage, 1024);
|
|
myOpenURL(hwndDlg, homepage);
|
|
}
|
|
break;
|
|
}
|
|
link_handledraw(hwndDlg,uMsg,wParam,lParam);
|
|
return 0;
|
|
}
|