spage_assoc.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. #define APSTUDIO_READONLY_SYMBOLS
  2. #include "main.h"
  3. #include "api.h"
  4. #include "./spage_assoc.h"
  5. #include "./setup_resource.h"
  6. #include "../nu/ns_wc.h"
  7. #include "../nu/AutoWide.h"
  8. #include "./langutil.h"
  9. #include "./setupcommon.h"
  10. #include "../playlist/svc_playlisthandler.h"
  11. #include <api/service/waservicefactorybase.h>
  12. #include "../Agave/URIHandler/svc_urihandler.h"
  13. #include <api/service/waservicefactory.h>
  14. #include <commctrl.h>
  15. #define MF_SELECTED 0x0001
  16. #define MF_TYPE_MASK 0xFF00
  17. #define MF_TYPE_REREAD 0xFF
  18. #define MF_TYPE_UNKNOWN 0x00
  19. #define MF_TYPE_AUDIO 0x01
  20. #define MF_TYPE_VIDEO 0x02
  21. #define MF_TYPE_PLAYLIST 0x03
  22. #define MF_TYPE_AUXILIARY 0x04
  23. #define ID_REGISTERCD ((TYPE_CATEGORIES_NUM) + 1)
  24. #define ID_REGISTERAGENT ((TYPE_CATEGORIES_NUM) + 2)
  25. #define SET_TYPE(_val, _type) ((_val) = ((_val) & ~MF_TYPE_MASK) | ((_type) << 8))
  26. #define GET_TYPE(_val) ((_val) >> 8)
  27. #define IS_NEEDREREAD(_val) GET_TYPE((_val), MF_TYPE_REREAD)
  28. #define IS_SELECTED(_val) (MF_SELECTED & (_val))
  29. #define INITMETA( _type, _selected) ((WORD)(((_type) << 8) | ((_selected) ? MF_SELECTED : 0x0000)))
  30. static wchar_t szAuxExt[] = L"wsz\0wal\0wlz\0";
  31. static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  32. static BOOL IsAgentScheduled(void)
  33. {
  34. HKEY hKey = NULL;
  35. BOOL bActive(FALSE);
  36. WCHAR szAgent[MAX_PATH*2] = {0};
  37. DWORD cb = sizeof(szAgent);
  38. if (ERROR_SUCCESS != RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey))
  39. return FALSE;
  40. if (ERROR_SUCCESS != RegQueryValueExW(hKey, L"WinampAgent", NULL, NULL, (BYTE*)szAgent, &cb))
  41. szAgent[0] = 0x00;
  42. RegCloseKey(hKey);
  43. if (*szAgent)
  44. {
  45. WCHAR szPath[MAX_PATH*2] = {0};
  46. GetModuleFileNameW(NULL, szPath, sizeof(szPath)/sizeof(wchar_t));
  47. PathUnquoteSpacesW(szAgent);
  48. PathRemoveFileSpecW(szAgent);
  49. PathRemoveFileSpecW(szPath);
  50. DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  51. bActive = (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, szPath, -1, szAgent, -1));
  52. }
  53. return bActive;
  54. }
  55. static BOOL IsAgentExist(void)
  56. {
  57. wchar_t szAgent[MAX_PATH] = {0};
  58. if (0 == GetModuleFileNameW(hMainInstance, szAgent, sizeof(szAgent)/sizeof(wchar_t)))
  59. return FALSE;
  60. PathRemoveFileSpecW(szAgent);
  61. if (NULL == PathCombineW(szAgent, szAgent, L"winampa.exe"))
  62. return FALSE;
  63. return (FALSE != PathFileExistsW(szAgent));
  64. }
  65. static BOOL RefreshIcons(void)
  66. {
  67. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, NULL, NULL);
  68. return TRUE;
  69. }
  70. static void RegisterProtocols()
  71. {
  72. if (config_no_registry)
  73. return;
  74. wchar_t winampexe[MAX_PATH] = {0};
  75. GetModuleFileNameW(hMainInstance, winampexe, MAX_PATH);
  76. WCHAR szApplication[256] = {0};
  77. INT r = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, NULL, 0);
  78. if (r > ARRAYSIZE(szApplication) || 0 == r)
  79. return;
  80. if (0 == MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, szApplication, ARRAYSIZE(szApplication)))
  81. return;
  82. if (NULL != WASABI_API_SVC)
  83. {
  84. for(size_t i =0;;i++)
  85. {
  86. waServiceFactory *sf = WASABI_API_SVC->service_enumService(svc_urihandler::getServiceType(), i);
  87. if (NULL == sf) break;
  88. svc_urihandler *handler = (svc_urihandler *)sf->getInterface();
  89. if (NULL != handler)
  90. {
  91. WCHAR szName[128] = {0}, szDesc[256] = {0};
  92. for (size_t k = 0; ;k++)
  93. {
  94. INT ret = handler->EnumProtocols(k, szName, ARRAYSIZE(szName), szDesc, ARRAYSIZE(szDesc));
  95. if (0 != ret)
  96. break;
  97. if (0 == handler->RegisterProtocol(szName, winampexe))
  98. {
  99. IFileTypeRegistrar *registrar = 0;
  100. if (GetRegistrar(&registrar, true) == 0 && registrar)
  101. {
  102. registrar->RegisterMediaPlayerProtocol(szName, szApplication);
  103. registrar->Release();
  104. }
  105. }
  106. }
  107. sf->releaseInterface(handler);
  108. }
  109. }
  110. }
  111. }
  112. setup_page_assoc::setup_page_assoc() : ref(1), hwnd(NULL), pszTypes(NULL), pMeta(NULL), bRegCD(FALSE), bAgent(FALSE), bExplorerMenu(TRUE)
  113. {
  114. ZeroMemory(expanded, sizeof(expanded));
  115. ZeroMemory(szTopExt, sizeof(szTopExt));
  116. ZeroMemory(szCaretExt, sizeof(szCaretExt));
  117. }
  118. setup_page_assoc::~setup_page_assoc()
  119. {
  120. if (pszTypes)
  121. {
  122. free(pszTypes);
  123. pszTypes = NULL;
  124. }
  125. if (pMeta)
  126. {
  127. free(pMeta);
  128. pMeta = NULL;
  129. }
  130. }
  131. size_t setup_page_assoc::AddRef()
  132. {
  133. return ++ref;
  134. }
  135. size_t setup_page_assoc::Release()
  136. {
  137. if (1 == ref)
  138. {
  139. delete(this);
  140. return 0;
  141. }
  142. return --ref;
  143. }
  144. HRESULT setup_page_assoc::GetName(bool bShort, const wchar_t **pszName)
  145. {
  146. if (bShort)
  147. {
  148. static wchar_t szShortName[32] = {0};
  149. *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_ASSOCIATIONS, szShortName, sizeof(szShortName)/sizeof(wchar_t));
  150. }
  151. else
  152. {
  153. static wchar_t szLongName[64] = {0};
  154. *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_ASSOCIATIONS_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t));
  155. }
  156. return S_OK;
  157. }
  158. HRESULT setup_page_assoc::Save(HWND hwndText)
  159. {
  160. HRESULT hr(S_OK);
  161. WORD *pm;
  162. wchar_t ext_list[16384] = {0}, *p = 0, *pe = ext_list;
  163. BOOL bFirst(TRUE);
  164. size_t len = ARRAYSIZE(ext_list);
  165. // make sure that we honour the agent setting even if no settings changed
  166. // this allows the agent to be restarted correctly after a normal upgrade
  167. if (bAgent && IsAgentExist())
  168. config_agent_add();
  169. else
  170. config_agent_remove();
  171. // temporary: always enumerate and register protocols
  172. RegisterProtocols();
  173. if (S_FALSE == IsDirty()) return S_OK;
  174. if (!pszTypes) return S_FALSE;
  175. config_setup_filetypes(0);
  176. for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++)
  177. {
  178. config_register_capability(p, 0);
  179. config_register(p, IS_SELECTED(*pm));
  180. if (IS_SELECTED(*pm) && (S_OK == hr) && GET_TYPE(*pm) != MF_TYPE_AUXILIARY)
  181. {
  182. if (!len) { hr = S_FALSE; continue; }
  183. if (!bFirst)
  184. {
  185. pe[0] = L':';
  186. pe++;
  187. len--;
  188. }
  189. else bFirst = FALSE;
  190. if (S_OK != StringCchCopyExW(pe, len, p, &pe, &len, STRSAFE_IGNORE_NULLS)) hr = S_FALSE;
  191. }
  192. }
  193. if (S_OK == hr) _w_sW("config_extlist", ext_list);
  194. config_regcdplayer(bRegCD, 0);
  195. (bExplorerMenu) ? config_adddircontext(0) : config_removedircontext(0);
  196. config_registermediaplayer(1);
  197. WritePrivateProfileStringW(L"Jump To File Extra", L"newIconLib", L"refresh", INI_FILE);
  198. RefreshIcons();
  199. return hr;
  200. }
  201. static BOOL IsFirstSetup()
  202. {
  203. wchar_t szVer[512] = {0};
  204. if (0 == GetPrivateProfileIntW(L"WinampReg", L"IsFirstInst", 1, INI_FILE)) return FALSE;
  205. GetPrivateProfileStringW(L"Winamp", L"config_extlist", L"", szVer, 512, INI_FILE);
  206. if (*szVer) return FALSE;
  207. GetPrivateProfileStringW(L"WinampReg", L"WAVer", L"", szVer, 512, INI_FILE);
  208. return (!*szVer || CSTR_EQUAL != CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  209. NORM_IGNORECASE, szVer, -1, AutoWide(APP_VERSION), -1));
  210. }
  211. static wchar_t *BuildExtensionString(WORD **ppMeta, BOOL bFirstSetup)
  212. {
  213. INT cWA(0), cPL(0), cAux(0), lWA(0), lPL(0), lAux(0);
  214. wchar_t *pszType, *pWAExt = in_getextlistW(), *pPLExt, *p;
  215. if (pWAExt)
  216. {
  217. for(p = pWAExt; *p != 0; cWA++, p += lstrlenW(p) + 1);
  218. lWA = (INT)(p - pWAExt);
  219. }
  220. if (playlistManager)
  221. {
  222. size_t playlistEnum = 0;
  223. const wchar_t *playlistExt=0;
  224. while (NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++))) { lPL += (lstrlenW(playlistExt) + 1); cPL++; }
  225. lPL += 2;
  226. }
  227. for(p = szAuxExt; *p != 0; cAux++, p += lstrlenW(p) + 1);
  228. lAux = (INT)(p - szAuxExt);
  229. pszType = (wchar_t*)calloc((lWA + lPL + lAux + 1), sizeof(wchar_t));
  230. if (ppMeta)
  231. {
  232. *ppMeta = (WORD*)calloc((cWA + cPL + cAux), sizeof(WORD));
  233. }
  234. if (pszType)
  235. {
  236. if (pWAExt) CopyMemory(pszType, pWAExt, lWA*sizeof(wchar_t));
  237. pPLExt = pszType + lWA;
  238. p = pPLExt;
  239. if (playlistManager)
  240. {
  241. size_t playlistEnum=0;
  242. const wchar_t *playlistExt=0;
  243. while (lPL > 0 && NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++)))
  244. {
  245. int c = lstrlenW(playlistExt) + 1;
  246. lstrcpynW(p, playlistExt, c);
  247. if (c)
  248. {
  249. p += c;
  250. lPL -= c;
  251. }
  252. }
  253. if (lPL > 1) *p = 0x00;
  254. }
  255. CopyMemory(p, szAuxExt, lAux*sizeof(wchar_t));
  256. *(p+lAux)=0;
  257. }
  258. if(ppMeta && *ppMeta)
  259. {
  260. int i;
  261. WORD *pm = *ppMeta;
  262. p = pszType;
  263. for (i = 0; i < cWA; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_REREAD, ((!bFirstSetup) ? config_isregistered(p) : 1));
  264. for (i = 0; i < cPL; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_PLAYLIST, ((!bFirstSetup) ? config_isregistered(p) : 1));
  265. for (i = 0; i < cAux; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_AUXILIARY, ((!bFirstSetup) ? config_isregistered(p) : 1));
  266. }
  267. if (pWAExt) GlobalFree(pWAExt);
  268. return pszType;
  269. }
  270. static BOOL GetPLExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest)
  271. {
  272. BOOL result(FALSE);
  273. int n(0);
  274. waServiceFactory *sf = 0;
  275. LPCWSTR ext;
  276. DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  277. while (NULL != (sf = WASABI_API_SVC->service_enumService(WaSvc::PLAYLISTHANDLER, n++)))
  278. {
  279. svc_playlisthandler * handler = static_cast<svc_playlisthandler *>(sf->getInterface());
  280. if (handler)
  281. {
  282. int k(0);
  283. while (NULL != (ext = handler->EnumerateExtensions(k++)))
  284. {
  285. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, ext, -1))
  286. {
  287. result = (S_OK == StringCchCopyW(pszDest, cchDest, handler->GetName()));
  288. if (result && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"M3U8", -1)) // ugly...
  289. result = (S_OK == StringCchCatW(pszDest, cchDest, L" (Unicode)"));
  290. break;
  291. }
  292. }
  293. sf->releaseInterface(handler);
  294. }
  295. }
  296. return result;
  297. }
  298. static BOOL GetAuxExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest)
  299. {
  300. BOOL result(FALSE);
  301. DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  302. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wal", -1))
  303. result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_MODERN, NULL, 0)));
  304. else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wsz", -1))
  305. result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_CLASSIC, NULL, 0)));
  306. else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wlz", -1))
  307. result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_LANG_PACK, NULL, 0)));
  308. return result;
  309. }
  310. static BOOL GetExtensionName(LPCWSTR pszFile, INT type, LPWSTR pszDest, INT cchDest)
  311. {
  312. switch(type)
  313. {
  314. case MF_TYPE_AUDIO:
  315. case MF_TYPE_VIDEO:
  316. return in_get_extended_fileinfoW(pszFile, L"family", pszDest, cchDest);
  317. case MF_TYPE_PLAYLIST:
  318. {
  319. const wchar_t *pszExt = PathFindExtensionW(pszFile);
  320. return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetPLExtensionName(pszExt, pszDest, cchDest) : FALSE;
  321. }
  322. case MF_TYPE_AUXILIARY:
  323. {
  324. const wchar_t *pszExt = PathFindExtensionW(pszFile);
  325. return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetAuxExtensionName(pszExt, pszDest, cchDest) : FALSE;
  326. }
  327. }
  328. return FALSE;
  329. }
  330. HRESULT setup_page_assoc::Revert(void)
  331. {
  332. HRESULT hr(S_OK);
  333. if (pszTypes)
  334. {
  335. free(pszTypes);
  336. pszTypes = NULL;
  337. }
  338. if (pMeta)
  339. {
  340. free(pMeta);
  341. pMeta = NULL;
  342. }
  343. BOOL firstSetup = IsFirstSetup();
  344. pszTypes = BuildExtensionString(&pMeta, firstSetup);
  345. ZeroMemory(expanded, sizeof(expanded));
  346. ZeroMemory(szTopExt, sizeof(szTopExt));
  347. ZeroMemory(szCaretExt, sizeof(szCaretExt));
  348. bRegCD = (firstSetup) ? TRUE : config_iscdplayer();
  349. bAgent = (FALSE != IsAgentExist()) ? ((firstSetup) ? FALSE : IsAgentScheduled()) : FALSE;
  350. bExplorerMenu = (firstSetup) ? TRUE : config_isdircontext();
  351. if (hwnd) UpdateUI();
  352. return hr;
  353. }
  354. HRESULT setup_page_assoc::IsDirty(void)
  355. {
  356. if (IsFirstSetup()) return S_OK;
  357. HRESULT hr(S_FALSE);
  358. DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  359. wchar_t *pszOrigTypes = BuildExtensionString(NULL, TRUE), *p;
  360. if ((!pszOrigTypes && pszTypes) || (pszOrigTypes && !pszTypes))
  361. {
  362. if (pszOrigTypes) free(pszOrigTypes);
  363. return S_OK;
  364. }
  365. else if (!pszOrigTypes && !pszTypes) return S_FALSE;
  366. INT cr = CompareStringW(lcid, NORM_IGNORECASE, pszTypes, -1, pszOrigTypes, -1);
  367. if (0 == cr) hr = E_UNEXPECTED;
  368. else if (CSTR_EQUAL == cr)
  369. {
  370. WORD *pm;
  371. for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++)
  372. {
  373. if ((MF_SELECTED & *pm) != (BYTE)config_isregistered(p)) { hr = S_OK; break; }
  374. }
  375. }
  376. else hr = S_OK;
  377. if (pszOrigTypes) free(pszOrigTypes);
  378. if (S_FALSE == hr && bRegCD != config_iscdplayer()) hr = S_OK;
  379. if (S_FALSE == hr && bAgent != (IsAgentExist() && IsAgentScheduled())) hr = S_OK;
  380. if (S_FALSE == hr && bExplorerMenu != config_isdircontext()) hr = S_OK;
  381. return hr;
  382. }
  383. HRESULT setup_page_assoc::Validate(void)
  384. {
  385. return S_OK;
  386. }
  387. HRESULT setup_page_assoc::CreateView(HWND hwndParent, HWND *phwnd)
  388. {
  389. *phwnd = WACreateDialogParam(MAKEINTRESOURCEW((!IsWin8() ? IDD_SETUP_PAGE_ASSOC : IDD_SETUP_PAGE_ASSOC_WIN8)), hwndParent, ::DialogProc, (LPARAM)this);
  390. return S_OK;
  391. }
  392. void setup_page_assoc::UpdateUI(void)
  393. {
  394. TVINSERTSTRUCTW is = {0};
  395. WORD *pm;
  396. HTREEITEM hBranch[TYPE_CATEGORIES_NUM], hFirst(NULL), hCaret(NULL), hItem;
  397. INT sBranch[TYPE_CATEGORIES_NUM] = {0};
  398. INT ids[TYPE_CATEGORIES_NUM] = {IDS_FILETYPE_UNKNOWN, IDS_FILETYPE_AUDIO, IDS_FILETYPE_VIDEO, IDS_FILETYPE_PLAYLIST, IDS_FILETYPE_AUXILIARY};
  399. INT i;
  400. wchar_t szText[MAX_PATH] = {0}, buf[MAX_PATH] = {0}, buf2[MAX_PATH] = {0}, *p, *test;
  401. if (!hwnd || !IsWindow(hwnd)) return;
  402. DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  403. HWND hwndTree = GetDlgItem(hwnd,IDC_TREE_TYPES);
  404. SendMessageW(hwndTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
  405. if (!pszTypes) return;
  406. for (i = 0; i < ARRAYSIZE(hBranch); i++)
  407. {
  408. hBranch[i] = NULL;
  409. sBranch[i] = -1;
  410. }
  411. INT len = ARRAYSIZE(buf);
  412. StringCchCopyW(buf, len, L"test.");
  413. test = buf + lstrlenW(buf);
  414. len -= (INT)(test - buf);
  415. SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L);
  416. is.hInsertAfter = TVI_LAST;
  417. is.item.mask = TVIF_STATE | TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM;
  418. is.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED;
  419. for(i = 0, pm = pMeta, p = pszTypes; *p != 0 && *(p+1) != 0; pm++, p += lstrlenW(p) + 1, i++)
  420. {
  421. StringCchCopyW(test, len, p);
  422. OutputDebugStringW(test);
  423. OutputDebugStringW(L"\r\n");
  424. if (MF_TYPE_REREAD == GET_TYPE(*pm))
  425. {
  426. if (!in_get_extended_fileinfoW(buf, L"type", buf2, MAX_PATH))
  427. ZeroMemory(buf2, sizeof(buf2));
  428. *pm = *pm & 0x00FF;
  429. switch(buf2[0])
  430. {
  431. case L'0': SET_TYPE(*pm, MF_TYPE_AUDIO); break;
  432. case L'1': SET_TYPE(*pm, MF_TYPE_VIDEO); break;
  433. }
  434. }
  435. INT index = GET_TYPE(*pm);
  436. if (!hBranch[index])
  437. {
  438. is.hInsertAfter = TVI_SORT;
  439. is.hParent = TVI_ROOT;
  440. is.item.cChildren = 1;
  441. is.item.state = INDEXTOSTATEIMAGEMASK(1) | ((expanded[index]) ? TVIS_EXPANDED : 0);
  442. is.item.pszText = getStringW(ids[index], NULL, 0);
  443. is.item.lParam = -(index + 1);
  444. hBranch[index] = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
  445. is.item.cChildren = 0;
  446. is.hInsertAfter = TVI_LAST;
  447. wchar_t t[32] = {0};
  448. StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", index + 1);
  449. if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hBranch[index];
  450. if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hBranch[index];
  451. }
  452. is.hParent = hBranch[index];
  453. if (MF_SELECTED & *pm)
  454. {
  455. if (-1 == sBranch[index]) sBranch[index] = 1;
  456. else if (0 == sBranch[index]) sBranch[index] = 2;
  457. }
  458. else
  459. {
  460. if (-1 == sBranch[index]) sBranch[index] = 0;
  461. else if (1 == sBranch[index]) sBranch[index] = 2;
  462. }
  463. lstrcpynW(szText, p, MAX_PATH);
  464. INT count = lstrlenW(szText);
  465. CharUpperW(szText);
  466. wchar_t szName[MAX_PATH] = {0};
  467. if (GetExtensionName(buf, GET_TYPE(*pm), szName, MAX_PATH))
  468. {
  469. if (count) StringCchCatW(szText, MAX_PATH, L"\t");
  470. StringCchCatW(szText, MAX_PATH, szName);
  471. }
  472. is.item.pszText = szText;
  473. is.item.lParam = (LPARAM)i;
  474. is.item.state = INDEXTOSTATEIMAGEMASK((MF_SELECTED & *pm)?2:1);
  475. hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
  476. if (hItem)
  477. {
  478. if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szTopExt, -1)) hFirst = hItem;
  479. if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szCaretExt, -1)) hCaret = hItem;
  480. }
  481. }
  482. // insert cd
  483. is.hParent = TVI_ROOT;
  484. is.item.state = INDEXTOSTATEIMAGEMASK(bRegCD + 1);
  485. is.item.pszText = getStringW(IDS_REGISTER_CDPLAYER, NULL, 0);
  486. is.item.lParam = -ID_REGISTERCD;
  487. hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
  488. if (!hFirst || !hCaret)
  489. {
  490. wchar_t t[32] = {0};
  491. StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", ID_REGISTERCD);
  492. if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hItem;
  493. if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hItem;
  494. }
  495. // agent
  496. BOOL bAgentExist = IsAgentExist();
  497. HWND hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT);
  498. if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist);
  499. hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC);
  500. if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist);
  501. CheckDlgButton(hwnd, IDC_CHK_AGENT, (bAgent && bAgentExist) ? BST_CHECKED : BST_UNCHECKED);
  502. CheckDlgButton(hwnd, IDC_CHK_CD, (bRegCD) ? BST_CHECKED : BST_UNCHECKED);
  503. CheckDlgButton(hwnd, IDC_CHK_EXPLORER_MENU, (bExplorerMenu) ? BST_CHECKED : BST_UNCHECKED);
  504. is.item.mask = TVIF_STATE;
  505. is.item.stateMask = TVIS_STATEIMAGEMASK;
  506. for (int i = 0; i < sizeof(hBranch)/sizeof(HTREEITEM); i++)
  507. {
  508. if (!hBranch[i]) continue;
  509. is.item.hItem = hBranch[i];
  510. is.item.state = INDEXTOSTATEIMAGEMASK(sBranch[i] + 1);
  511. SendMessageW(hwndTree, TVM_SETITEM, 0, (LPARAM)&is.item);
  512. SendMessageW(hwndTree, TVM_SORTCHILDREN, FALSE, (LPARAM)hBranch[i]);
  513. }
  514. if (hCaret) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hCaret);
  515. if (hFirst) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hFirst);
  516. SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L);
  517. }
  518. INT setup_page_assoc::TreeView_OnCustomDraw(NMTVCUSTOMDRAW *ptvcd)
  519. {
  520. switch(ptvcd->nmcd.dwDrawStage)
  521. {
  522. case CDDS_PREPAINT:
  523. return CDRF_DODEFAULT | CDRF_NOTIFYITEMDRAW;
  524. case CDDS_ITEMPREPAINT:
  525. return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT;
  526. case CDDS_ITEMPOSTPAINT:
  527. {
  528. RECT rt;
  529. WCHAR szText[256] = {0};
  530. TVITEMW item = {0};
  531. item.hItem = (HTREEITEM)ptvcd->nmcd.dwItemSpec;
  532. item.mask = TVIF_TEXT | TVIF_STATE;
  533. item.stateMask = TVIS_SELECTED;
  534. item.pszText = szText;
  535. item.cchTextMax = 256;
  536. SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMW, 0, (LPARAM)&item);
  537. *(DWORD_PTR*)&rt = ptvcd->nmcd.dwItemSpec;
  538. SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rt);
  539. SetTextColor(ptvcd->nmcd.hdc, ptvcd->clrText);
  540. SetBkColor(ptvcd->nmcd.hdc, ptvcd->clrTextBk);
  541. DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT);
  542. rt.right += 8;
  543. rt.top = ptvcd->nmcd.rc.top;
  544. rt.bottom = ptvcd->nmcd.rc.bottom;
  545. ExtTextOutW(ptvcd->nmcd.hdc, 0, 0, ETO_OPAQUE, &rt, L"", 0, NULL);
  546. rt.left += 4;
  547. DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
  548. if ((TVIS_SELECTED & item.state) && ptvcd->nmcd.hdr.hwndFrom == GetFocus())
  549. {
  550. if (0 == (0x01/*UISF_HIDEFOCUS*/ & SendMessageW(ptvcd->nmcd.hdr.hwndFrom, 0x0129/*WM_QUERYUISTATE*/, 0, 0L)))
  551. {
  552. rt.left -= 4;
  553. SetTextColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT));
  554. SetBkColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOW));
  555. DrawFocusRect(ptvcd->nmcd.hdc, &rt);
  556. }
  557. }
  558. }
  559. break;
  560. }
  561. return CDRF_DODEFAULT;
  562. }
  563. BOOL setup_page_assoc::TreeView_OnClick(NMHDR *pnmh)
  564. {
  565. TVHITTESTINFO ht;
  566. GetCursorPos(&ht.pt);
  567. MapWindowPoints(HWND_DESKTOP, pnmh->hwndFrom, &ht.pt, 1);
  568. if(NULL != SendMessageW(pnmh->hwndFrom, TVM_HITTEST, 0, (LPARAM)&ht))
  569. {
  570. if ((TVHT_ONITEM | TVHT_ONITEMRIGHT) & ht.flags)
  571. {
  572. TreeView_OnItemStateClick(pnmh->hwndFrom, ht.hItem);
  573. if (TVHT_ONITEMSTATEICON & ht.flags) return TRUE;
  574. }
  575. }
  576. return FALSE;
  577. }
  578. BOOL setup_page_assoc::TreeView_OnKeyDown(NMTVKEYDOWN *ptvkd)
  579. {
  580. switch(ptvkd->wVKey)
  581. {
  582. case VK_SPACE:
  583. {
  584. HTREEITEM hItem = (HTREEITEM)(HTREEITEM)SendMessageW(ptvkd->hdr.hwndFrom, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L);
  585. if (hItem) TreeView_OnItemStateClick(ptvkd->hdr.hwndFrom, hItem);
  586. return TRUE;
  587. }
  588. }
  589. return FALSE;
  590. }
  591. void setup_page_assoc::TreeView_OnItemStateClick(HWND hwndTree, HTREEITEM hItem)
  592. {
  593. HTREEITEM hParent = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)hItem);
  594. HTREEITEM hChild = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem);
  595. TVITEMW item = {0};
  596. item.hItem = hItem;
  597. item.mask = TVIF_STATE | TVIF_PARAM;
  598. item.stateMask = TVIS_STATEIMAGEMASK;
  599. if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) return;
  600. INT state = ((item.state>>12) - 1);
  601. INT param = (INT)item.lParam;
  602. SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L);
  603. state = (2 == state) ? 1 : !state;
  604. item.mask = TVIF_STATE;
  605. item.state = INDEXTOSTATEIMAGEMASK(state + 1);
  606. SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
  607. if (!hChild)
  608. {
  609. INT count = 1, selcount = state;
  610. item.hItem = hItem;
  611. while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PREVIOUS, (LPARAM)item.hItem)))
  612. {
  613. count++;
  614. if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue;
  615. if (2 == (item.state>>12)) selcount++;
  616. }
  617. item.hItem = hItem;
  618. while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem)))
  619. {
  620. count++;
  621. if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue;
  622. if (2 == (item.state>>12)) selcount++;
  623. }
  624. item.hItem = hParent;
  625. item.state = INDEXTOSTATEIMAGEMASK(((!selcount) ? 1 : ((selcount == count) ? 2 :3)));
  626. SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
  627. if (param >= 0) pMeta[param] = (pMeta[param] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0);
  628. else
  629. {
  630. switch(-param)
  631. {
  632. case ID_REGISTERCD: bRegCD = state; break;
  633. }
  634. }
  635. }
  636. else
  637. {
  638. item.hItem = hChild;
  639. while(item.hItem)
  640. {
  641. item.mask = TVIF_PARAM;
  642. if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item) && item.lParam >= 0) pMeta[item.lParam] = (pMeta[item.lParam] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0);
  643. item.mask = TVIF_STATE;
  644. item.state = INDEXTOSTATEIMAGEMASK(state + 1);
  645. SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
  646. item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem);
  647. }
  648. }
  649. UpdateWindow(hwnd);
  650. SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
  651. SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L);
  652. SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
  653. InvalidateRect(hwndTree, NULL, FALSE);
  654. }
  655. INT_PTR setup_page_assoc::OnInitDialog(HWND hwndFocus, LPARAM lParam)
  656. {
  657. HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES);
  658. if (hwndTree)
  659. {
  660. HIMAGELIST himl = ImageList_LoadImage(hMainInstance, MAKEINTRESOURCE(IDB_CHECKBOX), 16, 1, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_LOADTRANSPARENT);
  661. if (himl) himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)himl);
  662. if (himl) ImageList_Destroy(himl);
  663. WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)TreeViewProc);
  664. if (fnOldProc) SetPropW(hwndTree, L"TVPROC", fnOldProc);
  665. }
  666. UpdateUI();
  667. return 0;
  668. }
  669. void setup_page_assoc::OnDestroy(void)
  670. {
  671. HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES);
  672. if (hwndTree)
  673. {
  674. TVITEMW item = {0};
  675. HIMAGELIST himl;
  676. INT index1(-1), index2(-1);
  677. wchar_t *p;
  678. ZeroMemory(expanded, sizeof(expanded));
  679. ZeroMemory(szTopExt, sizeof(szTopExt));
  680. ZeroMemory(szCaretExt, sizeof(szCaretExt));
  681. item.mask = TVIF_PARAM | TVIF_STATE;
  682. item.stateMask = TVIS_EXPANDED;
  683. item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, 0L);
  684. while(item.hItem)
  685. {
  686. if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item))
  687. {
  688. INT param = (INT)-item.lParam;
  689. if (param < TYPE_CATEGORIES_NUM) expanded[param] = (BYTE)(TVIS_EXPANDED & item.state);
  690. }
  691. item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem);
  692. }
  693. item.mask = TVIF_PARAM;
  694. item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_FIRSTVISIBLE, 0L);
  695. if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index1 = (INT)item.lParam;
  696. item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L);
  697. if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index2 = (INT)item.lParam;
  698. if (index1 < 0) StringCchPrintfW(szTopExt, ARRAYSIZE(szTopExt), L"#%d", -index1);
  699. if (index2 < 0) StringCchPrintfW(szCaretExt, ARRAYSIZE(szCaretExt), L"#%d", -index2);
  700. if (index1 >= 0 || index2 >= 0)
  701. {
  702. INT i;
  703. for(i = 0, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, i++)
  704. {
  705. if (index1 == i)
  706. {
  707. StringCchCopyW(szTopExt, ARRAYSIZE(szTopExt), p);
  708. if (index2 < 0) break;
  709. index1 = -1;
  710. }
  711. if (index2 == i)
  712. {
  713. StringCchCopyW(szCaretExt, ARRAYSIZE(szCaretExt), p);
  714. if (index1 < 0) break;
  715. index2 = -1;
  716. }
  717. }
  718. }
  719. himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)NULL);
  720. if (himl) ImageList_Destroy(himl);
  721. }
  722. }
  723. void setup_page_assoc::OnSize(UINT nType, INT cx, INT cy)
  724. {
  725. RECT rw;
  726. INT h, r;
  727. h = cy;
  728. r = cx;
  729. HWND hwndCtrl = GetDlgItem(hwnd, IDC_LBL_HEADER);
  730. if (hwndCtrl)
  731. {
  732. GetWindowRect(hwndCtrl, &rw);
  733. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
  734. SetWindowPos(hwndCtrl, NULL, 0, 0, cx - rw.left*2, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
  735. }
  736. if (IsWin8())
  737. {
  738. // hide the treeview (as needed to process things nicely but needs to be hidden on Windows 8 and higher as they work differently)
  739. hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES);
  740. if (hwndCtrl)
  741. {
  742. SetWindowPos(hwndCtrl, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW);
  743. }
  744. return;
  745. }
  746. hwndCtrl = GetDlgItem(hwnd, IDC_CHK_EXPLORER_MENU);
  747. if (hwndCtrl)
  748. {
  749. GetWindowRect(hwndCtrl, &rw);
  750. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
  751. h = cy - (((rw.bottom - rw.top)*3) + 6);
  752. r = max(0, (cx - (rw.right - rw.left))/2) + (rw.right - rw.left);
  753. SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
  754. h, rw.right - rw.left + 26,
  755. rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
  756. }
  757. hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT);
  758. if (hwndCtrl)
  759. {
  760. GetWindowRect(hwndCtrl, &rw);
  761. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
  762. SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
  763. h + (rw.bottom - rw.top) + 2,
  764. rw.right - rw.left + 26,
  765. rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
  766. }
  767. hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC);
  768. if (hwndCtrl)
  769. {
  770. GetWindowRect(hwndCtrl, &rw);
  771. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
  772. SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
  773. h + (rw.bottom - rw.top)*2 + 2,
  774. rw.right - rw.left + 26,
  775. rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
  776. }
  777. hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES);
  778. if (hwndCtrl)
  779. {
  780. GetWindowRect(hwndCtrl, &rw);
  781. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
  782. SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
  783. rw.top, rw.right - rw.left + 26,
  784. h - rw.top - 4, SWP_NOACTIVATE | SWP_NOZORDER);
  785. }
  786. }
  787. void setup_page_assoc::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
  788. {
  789. switch(nCtrlID)
  790. {
  791. case IDC_CHK_EXPLORER_MENU:
  792. {
  793. switch (nEvntID)
  794. {
  795. case BN_CLICKED:
  796. bExplorerMenu = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
  797. break;
  798. }
  799. break;
  800. }
  801. case IDC_CHK_AGENT:
  802. {
  803. switch (nEvntID)
  804. {
  805. case BN_CLICKED:
  806. bAgent = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
  807. break;
  808. }
  809. break;
  810. }
  811. case IDC_CHK_CD:
  812. {
  813. switch (nEvntID)
  814. {
  815. case BN_CLICKED:
  816. bRegCD = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
  817. break;
  818. }
  819. break;
  820. }
  821. }
  822. }
  823. BOOL setup_page_assoc::OnNotify(INT nCtrlID, NMHDR *pnmh, LRESULT *pResult)
  824. {
  825. switch(nCtrlID)
  826. {
  827. case IDC_TREE_TYPES:
  828. switch(pnmh->code)
  829. {
  830. case NM_CUSTOMDRAW: *pResult = TreeView_OnCustomDraw((NMTVCUSTOMDRAW*)pnmh); return TRUE;
  831. case NM_CLICK: *pResult = TreeView_OnClick(pnmh); return TRUE;
  832. case TVN_KEYDOWN: *pResult = TreeView_OnKeyDown((NMTVKEYDOWN*)pnmh); return TRUE;
  833. }
  834. }
  835. return FALSE;
  836. }
  837. INT_PTR setup_page_assoc::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  838. {
  839. switch(uMsg)
  840. {
  841. case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
  842. case WM_DESTROY: OnDestroy(); break;
  843. case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break;
  844. case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
  845. case WM_NOTIFY:
  846. {
  847. LRESULT result = 0;
  848. if (OnNotify((INT)wParam, (NMHDR*)lParam, &result))
  849. {
  850. SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)(LONG_PTR)result);
  851. return TRUE;
  852. }
  853. }
  854. break;
  855. }
  856. return 0;
  857. }
  858. static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  859. {
  860. setup_page_assoc *pInst = (setup_page_assoc*)GetPropW(hwnd, L"SETUPPAGE");
  861. switch(uMsg)
  862. {
  863. case WM_INITDIALOG:
  864. pInst = (setup_page_assoc*)lParam;
  865. if (pInst)
  866. {
  867. pInst->hwnd = hwnd;
  868. SetPropW(hwnd, L"SETUPPAGE", pInst);
  869. }
  870. break;
  871. case WM_DESTROY:
  872. if (pInst)
  873. {
  874. pInst->PageDlgProc(uMsg, wParam, lParam);
  875. RemovePropW(hwnd, L"SETUPPAGE");
  876. pInst = NULL;
  877. }
  878. break;
  879. }
  880. return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
  881. }
  882. static void TreeViewCheckItems(HWND hwnd, TVITEMW *pItem)
  883. {
  884. while (pItem->hItem)
  885. {
  886. SendMessageW(hwnd, TVM_SETITEMW, 0, (LPARAM)pItem);
  887. HTREEITEM hChild = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)pItem->hItem);
  888. if (hChild)
  889. {
  890. HTREEITEM hTemp = pItem->hItem;
  891. pItem->hItem = hChild;
  892. TreeViewCheckItems(hwnd, pItem);
  893. pItem->hItem = hTemp;
  894. }
  895. pItem->hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_NEXT, (LPARAM)pItem->hItem);
  896. }
  897. }
  898. static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  899. {
  900. WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"TVPROC");
  901. if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam);
  902. switch(uMsg)
  903. {
  904. case WM_DESTROY:
  905. RemovePropW(hwnd, L"TVPROC");
  906. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)fnOldProc);
  907. break;
  908. case WM_CHAR:
  909. if (0x01/*(CTRL_A)*/ == wParam)
  910. {
  911. TVITEMW item = {0};
  912. item.mask = TVIF_HANDLE | TVIF_STATE;
  913. item.stateMask = TVIS_STATEIMAGEMASK;
  914. item.state = INDEXTOSTATEIMAGEMASK(2);
  915. item.hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_ROOT, 0L);
  916. SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
  917. TreeViewCheckItems(hwnd, &item);
  918. SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
  919. return 0;
  920. }
  921. break;
  922. }
  923. return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam);
  924. }
  925. #ifdef CBCLASS
  926. #undef CBCLASS
  927. #endif
  928. #define CBCLASS setup_page_assoc
  929. START_DISPATCH
  930. CB(ADDREF, AddRef)
  931. CB(RELEASE, Release)
  932. CB(API_SETUPPAGE_GET_NAME, GetName)
  933. CB(API_SETUPPAGE_CREATEVIEW, CreateView)
  934. CB(API_SETUPPAGE_SAVE, Save)
  935. CB(API_SETUPPAGE_REVERT, Revert)
  936. CB(API_SETUPPAGE_ISDIRTY, IsDirty)
  937. CB(API_SETUPPAGE_VALIDATE, Validate)
  938. END_DISPATCH
  939. #undef CBCLASS