view_pmp_queue.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. /* almost the same as view_pmp_devices, but only one device*/
  2. #include "main.h"
  3. #include <windows.h>
  4. #include <windowsx.h>
  5. #include <stdio.h>
  6. #include <shlobj.h>
  7. #include "..\..\General\gen_ml/ml.h"
  8. #include "..\..\General\gen_ml/itemlist.h"
  9. #include "../nu/listview.h"
  10. #include "..\..\General\gen_ml/childwnd.h"
  11. #include "../winamp/wa_ipc.h"
  12. #include "../winamp/wa_dlg.h"
  13. #include "resource1.h"
  14. #include "SkinnedListView.h"
  15. #include "DeviceView.h"
  16. #include "api__ml_pmp.h"
  17. #include "./graphics.h"
  18. #include <strsafe.h>
  19. #include "../nu/AutoWide.h"
  20. static HRGN g_rgnUpdate = NULL;
  21. static int offsetX, offsetY, customAllowed;
  22. static DeviceView *device;
  23. static SkinnedListView * listTransfers=NULL;
  24. std::map<DeviceView *, bool> device_update_map;
  25. typedef struct TransferView
  26. {
  27. HFONT font;
  28. SIZE unitSize;
  29. HRGN updateRegion;
  30. POINT updateOffset;
  31. } TransferView;
  32. #define TRANSFERVIEW(_hwnd) ((TransferView*)GetViewData(_hwnd))
  33. #define TRANSFERVIEW_RET_VOID(_self, _hwnd) { (_self) = TRANSFERVIEW((_hwnd)); if (NULL == (_self)) return; }
  34. #define TRANSFERVIEW_RET_VAL(_self, _hwnd, _error) { (_self) = TRANSFERVIEW((_hwnd)); if (NULL == (_self)) return (_error); }
  35. #define TRANSFERVIEW_DLU_TO_HORZ_PX(_self, _dlu) MulDiv((_dlu), (_self)->unitSize.cx, 4)
  36. #define TRANSFERVIEW_DLU_TO_VERT_PX(_self, _dlu) MulDiv((_dlu), (_self)->unitSize.cy, 8)
  37. void handleContextMenuResult(int r, C_ItemList * items=NULL, DeviceView * dev=NULL);
  38. int showContextMenu(int context,HWND hwndDlg, Device * dev, POINT pt);
  39. class TransferItemShadowShort
  40. {
  41. public:
  42. CopyInst * c;
  43. wchar_t * status, * type, * track, * sourceDevice, * destDevice, * lastChanged, * sourceFile, * clientType;
  44. bool changed;
  45. TransferItemShadowShort(CopyInst * c)
  46. {
  47. changed = false;
  48. this->c = c;
  49. status = _wcsdup(c->statusCaption);
  50. type = _wcsdup(c->typeCaption);
  51. track = _wcsdup(c->trackCaption);
  52. lastChanged = _wcsdup(c->lastChanged);
  53. sourceDevice = _wcsdup(c->sourceDevice);
  54. destDevice = _wcsdup(c->destDevice);
  55. sourceFile = _wcsdup(c->sourceFile);
  56. clientType = AutoWideDup(c->dev->GetConnection());
  57. }
  58. ~TransferItemShadowShort()
  59. {
  60. if (status) free(status);
  61. if (type) free(type);
  62. if (track) free(track);
  63. if (lastChanged) free(lastChanged);
  64. if (sourceDevice) free(sourceDevice);
  65. if (destDevice) free(destDevice);
  66. if (sourceFile) free(sourceFile);
  67. if (clientType) free(clientType);
  68. }
  69. bool Equals(TransferItemShadowShort * a)
  70. {
  71. if (!a) return false;
  72. return (c == a->c) && !wcscmp(track,a->track) && !wcscmp(status,a->status) && !wcscmp(type,a->type);
  73. }
  74. };
  75. LinkedQueue *getTransferQueue(DeviceView *deviceView)
  76. {
  77. if (deviceView)
  78. {
  79. return (deviceView->isCloudDevice ? &cloudTransferQueue : &deviceView->transferQueue);
  80. }
  81. else if (device)
  82. {
  83. return (device->isCloudDevice ? &cloudTransferQueue : &device->transferQueue);
  84. }
  85. return NULL;
  86. }
  87. LinkedQueue *getFinishedTransferQueue(DeviceView *deviceView)
  88. {
  89. if (deviceView)
  90. {
  91. return (deviceView->isCloudDevice ? &cloudFinishedTransfers : &deviceView->finishedTransfers);
  92. }
  93. else if (device)
  94. {
  95. return (device->isCloudDevice ? &cloudFinishedTransfers : &device->finishedTransfers);
  96. }
  97. return NULL;
  98. }
  99. int getTransferProgress(DeviceView *deviceView)
  100. {
  101. if(deviceView)
  102. {
  103. return (deviceView->isCloudDevice ? cloudTransferProgress : deviceView->currentTransferProgress);
  104. }
  105. else if(device)
  106. {
  107. return (device->isCloudDevice ? cloudTransferProgress : device->currentTransferProgress);
  108. }
  109. return 0;
  110. }
  111. // TODO hook up to a config (would need to work after a reset to be 100% safe...?)
  112. int sharedQueue = 1;
  113. static C_ItemList *getTransferListShadow()
  114. {
  115. C_ItemList * list = new C_ItemList;
  116. if (!sharedQueue)
  117. {
  118. LinkedQueue * txQueue = getTransferQueue();
  119. if (txQueue)
  120. {
  121. txQueue->lock();
  122. for (int j = 0; j < txQueue->GetSize(); j++)
  123. list->Add(new TransferItemShadowShort((CopyInst*)txQueue->Get(j)));
  124. txQueue->unlock();
  125. }
  126. LinkedQueue * finishedTX = getFinishedTransferQueue();
  127. if (finishedTX)
  128. {
  129. finishedTX->lock();
  130. for (int j = 0; j < finishedTX->GetSize(); j++)
  131. list->Add(new TransferItemShadowShort((CopyInst*)finishedTX->Get(j)));
  132. finishedTX->unlock();
  133. }
  134. }
  135. else
  136. {
  137. // TODO should probably review this when we're more intelligent on multi-handling
  138. // we do the cloud transfer queue specifically so as not to duplicate by devices
  139. LinkedQueue * txQueue = &cloudTransferQueue;
  140. if (txQueue)
  141. {
  142. txQueue->lock();
  143. for (int j = 0; j < txQueue->GetSize(); j++)
  144. list->Add(new TransferItemShadowShort((CopyInst*)txQueue->Get(j)));
  145. txQueue->unlock();
  146. }
  147. LinkedQueue * finishedTX = &cloudFinishedTransfers;
  148. if (finishedTX)
  149. {
  150. finishedTX->lock();
  151. for (int j = 0; j < finishedTX->GetSize(); j++)
  152. list->Add(new TransferItemShadowShort((CopyInst*)finishedTX->Get(j)));
  153. finishedTX->unlock();
  154. }
  155. for (int i = 0; i < devices.GetSize(); i++)
  156. {
  157. DeviceView * d = (DeviceView *)devices.Get(i);
  158. if (!d || d->isCloudDevice) continue;
  159. LinkedQueue * txQueue = getTransferQueue(d);
  160. if (txQueue)
  161. {
  162. txQueue->lock();
  163. for (int j = 0; j < txQueue->GetSize(); j++)
  164. list->Add(new TransferItemShadowShort((CopyInst*)txQueue->Get(j)));
  165. txQueue->unlock();
  166. }
  167. LinkedQueue * finishedTX = getFinishedTransferQueue(d);
  168. if (finishedTX)
  169. {
  170. finishedTX->lock();
  171. for (int j = 0; j < finishedTX->GetSize(); j++)
  172. list->Add(new TransferItemShadowShort((CopyInst*)finishedTX->Get(j)));
  173. finishedTX->unlock();
  174. }
  175. }
  176. }
  177. return list;
  178. }
  179. class TransferContents : public ListContents
  180. {
  181. public:
  182. TransferContents()
  183. {
  184. oldSize = 0;
  185. listShadow = 0;
  186. InitializeCriticalSection(&cs);
  187. }
  188. void Init()
  189. {
  190. lock();
  191. if (!listShadow)
  192. listShadow = getTransferListShadow();
  193. unlock();
  194. }
  195. virtual ~TransferContents()
  196. {
  197. DeleteCriticalSection(&cs);
  198. delete listShadow;
  199. }
  200. virtual int GetNumColumns()
  201. {
  202. // TODO check the number of columns are ok, etc
  203. return 7;//(device->isCloudDevice ? 7 : 3);
  204. }
  205. virtual int GetNumRows()
  206. {
  207. return (listShadow ? listShadow->GetSize() : 0);
  208. }
  209. virtual wchar_t * GetColumnTitle(int num)
  210. {
  211. // TODO need to clean this up as needed
  212. switch (num + 1)
  213. {
  214. case 0: return WASABI_API_LNGSTRINGW(IDS_TYPE);
  215. case 1: return WASABI_API_LNGSTRINGW(IDS_TRACK);
  216. case 2: return WASABI_API_LNGSTRINGW(IDS_STATUS);
  217. case 3: return WASABI_API_LNGSTRINGW(IDS_LAST_CHANGED);
  218. case 4: return WASABI_API_LNGSTRINGW(IDS_SOURCE);
  219. case 5: return WASABI_API_LNGSTRINGW(IDS_DESTINATION);
  220. case 6: return WASABI_API_LNGSTRINGW(IDS_SOURCE_FILE);
  221. case 7: return WASABI_API_LNGSTRINGW(IDS_CLIENT_TYPE);
  222. }
  223. return L"";
  224. }
  225. virtual int GetColumnWidth(int num)
  226. {
  227. switch (num)
  228. {
  229. case 0: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col0_width" : L"cloud_col0_width"), 300);
  230. case 1: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col1_width" : L"cloud_col1_width"), 150);
  231. case 2: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col2_width" : L"cloud_col2_width"), 100);
  232. case 3: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col3_width" : L"cloud_col3_width"), 100);
  233. case 4: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col4_width" : L"cloud_col4_width"), 100);
  234. case 5: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col5_width" : L"cloud_col5_width"), 100);
  235. case 6: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col6_width" : L"cloud_col6_width"), 300);
  236. case 7: return global_config->ReadInt((!device->isCloudDevice ? L"transfers_col7_width" : L"cloud_col7_width"), 100);
  237. default: return 0;
  238. }
  239. }
  240. virtual void ColumnResize(int col, int newWidth)
  241. {
  242. if (NULL != global_config &&
  243. col >= 0 &&
  244. col < GetNumColumns())
  245. {
  246. wchar_t buffer[64] = {0};
  247. if (FAILED(StringCchPrintf(buffer, ARRAYSIZE(buffer), (!device->isCloudDevice ? L"transfers_col%d_width" : L"cloud_col%d_width"), col)))
  248. return;
  249. global_config->WriteInt(buffer, newWidth);
  250. }
  251. }
  252. void lock()
  253. {
  254. EnterCriticalSection(&cs);
  255. }
  256. void unlock()
  257. {
  258. LeaveCriticalSection(&cs);
  259. }
  260. virtual void GetCellText(int row, int col, wchar_t * buf, int buflen)
  261. {
  262. if (NULL == buf)
  263. return;
  264. buf[0] = L'\0';
  265. lock();
  266. if (row < listShadow->GetSize())
  267. {
  268. TransferItemShadowShort * t = (TransferItemShadowShort *)listShadow->Get(row);
  269. if (NULL != t)
  270. {
  271. // TODO need to clean this up as needed
  272. switch (col + 1)
  273. {
  274. case 0: /*StringCchCopy(buf, buflen, t->type);*/ break;
  275. case 1: StringCchCopy(buf, buflen, t->track); break;
  276. case 2: StringCchCopy(buf, buflen, t->status); break;
  277. case 3: StringCchCopy(buf, buflen, t->lastChanged); break;
  278. case 4: StringCchCopy(buf, buflen, t->sourceDevice); break;
  279. case 5: StringCchCopy(buf, buflen, t->destDevice); break;
  280. case 6: StringCchCopy(buf, buflen, t->sourceFile); break;
  281. case 7: StringCchCopy(buf, buflen, t->clientType); break;
  282. }
  283. }
  284. }
  285. unlock();
  286. }
  287. void PushPopItem(CopyInst *c)
  288. {
  289. lock();
  290. int size = listShadow->GetSize();
  291. for (int i=0; i<size; i++)
  292. {
  293. TransferItemShadowShort * t = (TransferItemShadowShort *)listShadow->Get(i);
  294. if (c == t->c)
  295. {
  296. t->changed=true;
  297. listShadow->Del(i);
  298. listShadow->Add(t);
  299. if (listTransfers)
  300. {
  301. HWND hwnd = listTransfers->listview.getwnd();
  302. PostMessage(hwnd, LVM_REDRAWITEMS, i, size);
  303. }
  304. unlock();
  305. return;
  306. }
  307. }
  308. unlock();
  309. }
  310. void ItemUpdate(CopyInst * c)
  311. {
  312. lock();
  313. int size = listShadow->GetSize();
  314. for (int i=0; i<size; i++)
  315. {
  316. TransferItemShadowShort * t = (TransferItemShadowShort *)listShadow->Get(i);
  317. if (c == t->c)
  318. {
  319. TransferItemShadowShort * n = new TransferItemShadowShort(c);
  320. n->changed=true;
  321. listShadow->Set(i,n);
  322. delete t;
  323. if (listTransfers)
  324. {
  325. HWND hwnd = listTransfers->listview.getwnd();
  326. PostMessage(hwnd,LVM_REDRAWITEMS,i,i);
  327. }
  328. unlock();
  329. return;
  330. }
  331. }
  332. unlock();
  333. }
  334. void FullUpdate()
  335. {
  336. C_ItemList * newListShadow = getTransferListShadow();
  337. if (newListShadow)
  338. {
  339. int newSize = newListShadow->GetSize();
  340. lock();
  341. oldSize = listShadow->GetSize();
  342. for (int i = 0; i < newSize; i++)
  343. {
  344. TransferItemShadowShort * newt = (TransferItemShadowShort *)newListShadow->Get(i);
  345. TransferItemShadowShort * oldt = i < oldSize ? (TransferItemShadowShort *)listShadow->Get(i) : NULL;
  346. newt->changed = !newt->Equals(oldt);
  347. }
  348. C_ItemList * oldListShadow = listShadow;
  349. listShadow = newListShadow;
  350. for (int i = 0; i < oldListShadow->GetSize(); i++) delete(TransferItemShadowShort *)oldListShadow->Get(i);
  351. delete oldListShadow;
  352. if (listTransfers)
  353. {
  354. HWND hwnd = listTransfers->listview.getwnd();
  355. if (newSize != oldSize) PostMessage(hwnd,LVM_SETITEMCOUNT,newSize, 0);
  356. for (int i=0; i<newSize; i++)
  357. {
  358. TransferItemShadowShort * t = (TransferItemShadowShort *)listShadow->Get(i);
  359. if (t->changed) PostMessage(hwnd,LVM_REDRAWITEMS,i,i);
  360. }
  361. }
  362. unlock();
  363. }
  364. }
  365. virtual songid_t GetTrack(int pos) { return 0; }
  366. private:
  367. CRITICAL_SECTION cs;
  368. C_ItemList * listShadow;
  369. int oldSize;
  370. };
  371. static TransferContents transferListContents;
  372. static void updateStatus(HWND hwnd)
  373. {
  374. HWND statusWindow = GetDlgItem(hwnd, IDC_STATUS);
  375. if (NULL == statusWindow)
  376. return;
  377. int txProgress = getTransferProgress(device);
  378. LinkedQueue * txQueue = getTransferQueue(device);
  379. LinkedQueue * finishedTX = getFinishedTransferQueue(device);
  380. int size = (txQueue ? txQueue->GetSize() : 0);
  381. if (size > 0)
  382. {
  383. wchar_t buffer[256] = {0}, format[256] = {0};
  384. int pcnum, time, pc, total;
  385. pcnum = (size * 100) - txProgress;
  386. total = size * 100;
  387. total += 100 * (finishedTX ? finishedTX->GetSize() : 0);
  388. time = (int)(device->transferRate * (((double)pcnum)/100.0));
  389. pc = ((total-pcnum)*100)/total;
  390. WASABI_API_LNGSTRINGW_BUF((time > 0 ? IDS_TRANFERS_PERCENT_REMAINING : IDS_TRANFERS_PERCENT_REMAINING_NOT_TIME), format, ARRAYSIZE(format));
  391. if (SUCCEEDED(StringCchPrintf(buffer, ARRAYSIZE(buffer), format, size, pc, time/60, time%60)))
  392. {
  393. if (0 == SendMessage(statusWindow, WM_GETTEXT, (WPARAM)ARRAYSIZE(format), (LPARAM)format) ||
  394. CSTR_EQUAL != CompareString(LOCALE_USER_DEFAULT, 0, format, -1, buffer, -1))
  395. {
  396. SendMessage(statusWindow, WM_SETTEXT, 0, (LPARAM)buffer);
  397. }
  398. }
  399. }
  400. else
  401. {
  402. int length = (int)SendMessage(statusWindow, WM_GETTEXTLENGTH, 0, 0L);
  403. if (0 != length)
  404. SendMessage(statusWindow, WM_SETTEXT, 0, 0L);
  405. }
  406. }
  407. void TransfersListUpdateItem(CopyInst * item, DeviceView *view)
  408. {
  409. if (view == device)
  410. transferListContents.ItemUpdate(item);
  411. }
  412. void TransfersListPushPopItem(CopyInst * item, DeviceView *view)
  413. {
  414. if (view == device)
  415. transferListContents.PushPopItem(item);
  416. }
  417. static bool AddSelectedItems(C_ItemList *items, W_ListView *listview, LinkedQueue *transfer_queue, int &row, DeviceView *&dev)
  418. {
  419. transfer_queue->lock();
  420. int l = transfer_queue->GetSize();
  421. for (int j=0; j<l; j++)
  422. {
  423. if (listview->GetSelected(row++))
  424. {
  425. CopyInst * c = (CopyInst *)transfer_queue->Get(j);
  426. if (c->songid)
  427. {
  428. if (!dev && c->dev)
  429. dev = c->dev;
  430. if (dev)
  431. {
  432. if (c->dev != dev)
  433. {
  434. transfer_queue->unlock();
  435. return false;
  436. }
  437. else
  438. items->Add((void*)c->songid);
  439. }
  440. }
  441. }
  442. }
  443. transfer_queue->unlock();
  444. return true;
  445. }
  446. static void RemoveSelectedItems(DeviceView *device, W_ListView *listview, LinkedQueue *transfer_queue, int &row, bool finished_queue)
  447. {
  448. transfer_queue->lock();
  449. int j = transfer_queue->GetSize();
  450. while (j-- > 0)
  451. {
  452. if (listview->GetSelected(--row))
  453. {
  454. if (j == 0 && !finished_queue)
  455. {
  456. CopyInst * d = (CopyInst *)transfer_queue->Get(j);
  457. if (d && (d->status == STATUS_WAITING || d->status == STATUS_CANCELLED) && device->transferContext.IsPaused())
  458. {
  459. transfer_queue->Del(j);
  460. d->Cancelled();
  461. delete d;
  462. } // otherwise don't bother
  463. }
  464. else
  465. {
  466. CopyInst * d = (CopyInst*)transfer_queue->Del(j);
  467. if (d)
  468. {
  469. if ((d->status == STATUS_WAITING || d->status == STATUS_CANCELLED) && !finished_queue)
  470. d->Cancelled();
  471. delete d;
  472. }
  473. }
  474. }
  475. }
  476. transfer_queue->unlock();
  477. }
  478. static void CancelSelectedItems(DeviceView *device, W_ListView *listview, LinkedQueue *transfer_queue, int &row)
  479. {
  480. transfer_queue->lock();
  481. int j = transfer_queue->GetSize();
  482. int sel = listview->GetSelectedCount();
  483. for (int i = 0, q = 0; i <= j; i++)
  484. {
  485. if (listview->GetSelected(i) || !sel)
  486. {
  487. CopyInst * d = (CopyInst *)transfer_queue->Get(q);
  488. if (d && d->status == STATUS_WAITING)
  489. {
  490. transfer_queue->Del(q);
  491. d->Cancelled();
  492. delete d;
  493. }
  494. else if (d && d->status == STATUS_TRANSFERRING)
  495. {
  496. d->Cancelled();
  497. }
  498. else
  499. {
  500. q++;
  501. }
  502. }
  503. }
  504. transfer_queue->unlock();
  505. }
  506. static void RetrySelectedItems(DeviceView *device, W_ListView *listview, LinkedQueue *transfer_queue, LinkedQueue *finished_transfer_queue, int &row)
  507. {
  508. transfer_queue->lock();
  509. finished_transfer_queue->lock();
  510. int j = finished_transfer_queue->GetSize();
  511. int sel = listview->GetSelectedCount();
  512. LinkedQueue retryTransferQueue;
  513. int i = 0;
  514. for (int q = 0; i <= j; i++)
  515. {
  516. if (listview->GetSelected(i) || !sel)
  517. {
  518. CopyInst * d = (CopyInst *)finished_transfer_queue->Get(q);
  519. if (d && (d->status == STATUS_DONE || d->status == STATUS_CANCELLED || d->status == STATUS_ERROR))
  520. {
  521. // due to STATUS_DONE being applied in most cases, have to look at the
  522. // status message and use as the basis on how to proceed with the item
  523. if (lstrcmpi(d->statusCaption, WASABI_API_LNGSTRINGW(IDS_UPLOADED)))
  524. {
  525. retryTransferQueue.Offer(d);
  526. finished_transfer_queue->Del(q);
  527. }
  528. else
  529. {
  530. q++;
  531. }
  532. }
  533. else
  534. {
  535. q++;
  536. }
  537. }
  538. }
  539. i = 0;
  540. for (; i <= retryTransferQueue.GetSize(); i++)
  541. {
  542. CopyInst * d = (CopyInst *)retryTransferQueue.Get(i);
  543. if (d)
  544. {
  545. WASABI_API_LNGSTRINGW_BUF(IDS_WAITING, d->statusCaption, sizeof(d->statusCaption)/sizeof(wchar_t));
  546. SYSTEMTIME system_time;
  547. GetLocalTime(&system_time);
  548. GetTimeFormat(LOCALE_INVARIANT, NULL, &system_time, NULL, d->lastChanged, sizeof(d->lastChanged)/sizeof(wchar_t));
  549. d->dev->AddTrackToTransferQueue(d);
  550. }
  551. }
  552. transfer_queue->unlock();
  553. finished_transfer_queue->unlock();
  554. }
  555. typedef struct _LAYOUT
  556. {
  557. INT id;
  558. HWND hwnd;
  559. INT x;
  560. INT y;
  561. INT cx;
  562. INT cy;
  563. DWORD flags;
  564. HRGN rgn;
  565. }
  566. LAYOUT, PLAYOUT;
  567. #define SETLAYOUTPOS(_layout, _x, _y, _cx, _cy) { _layout->x=_x; _layout->y=_y;_layout->cx=_cx;_layout->cy=_cy;_layout->rgn=NULL; }
  568. #define SETLAYOUTFLAGS(_layout, _r) \
  569. { \
  570. BOOL fVis; \
  571. fVis = (WS_VISIBLE & (LONG)GetWindowLongPtr(_layout->hwnd, GWL_STYLE)); \
  572. if (_layout->x == _r.left && _layout->y == _r.top) _layout->flags |= SWP_NOMOVE; \
  573. if (_layout->cx == (_r.right - _r.left) && _layout->cy == (_r.bottom - _r.top)) _layout->flags |= SWP_NOSIZE; \
  574. if ((SWP_HIDEWINDOW & _layout->flags) && !fVis) _layout->flags &= ~SWP_HIDEWINDOW; \
  575. if ((SWP_SHOWWINDOW & _layout->flags) && fVis) _layout->flags &= ~SWP_SHOWWINDOW; \
  576. }
  577. #define LAYOUTNEEEDUPDATE(_layout) ((SWP_NOMOVE | SWP_NOSIZE) != ((SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_SHOWWINDOW) & _layout->flags))
  578. #define GROUP_MIN 0x1
  579. #define GROUP_MAX 0x2
  580. #define GROUP_STATUSBAR 0x1
  581. #define GROUP_MAIN 0x2
  582. /*
  583. IDC_BUTTON_PAUSETRANSFERS,
  584. IDC_BUTTONCANCELSELECTED,
  585. IDC_BUTTON_CLEARFINISHED,
  586. IDC_BUTTON_REMOVESELECTED,
  587. IDC_BUTTON_RETRYSELECTED,
  588. IDC_STATUS,
  589. IDC_LIST_TRANSFERS,
  590. */
  591. static void TransferView_UpdateLayout(HWND hwnd, BOOL fRedraw, BOOL fUpdateAll = FALSE)
  592. {
  593. static INT controls[] =
  594. {
  595. GROUP_STATUSBAR, IDC_BUTTON_PAUSETRANSFERS, IDC_BUTTON_CLEARFINISHED, IDC_BUTTON_REMOVESELECTED, IDC_BUTTON_RETRYSELECTED, IDC_STATUS,
  596. GROUP_MAIN, IDC_LIST_TRANSFERS
  597. };
  598. INT index;
  599. RECT rc, rg, ri;
  600. LAYOUT layout[sizeof(controls)/sizeof(controls[0])], *pl;
  601. BOOL skipgroup;
  602. HRGN rgn = NULL;
  603. GetClientRect(hwnd, &rc);
  604. if (rc.bottom == rc.top || rc.right == rc.left) return;
  605. SetRect(&rg, rc.left, rc.top, rc.right, rc.bottom);
  606. pl = layout;
  607. skipgroup = FALSE;
  608. InvalidateRect(hwnd, NULL, TRUE);
  609. for (index = 0; index < sizeof(controls) / sizeof(*controls); index++)
  610. {
  611. if (controls[index] >= GROUP_MIN && controls[index] <= GROUP_MAX) // group id
  612. {
  613. skipgroup = FALSE;
  614. switch (controls[index])
  615. {
  616. case GROUP_STATUSBAR:
  617. {
  618. wchar_t buffer[128] = {0};
  619. HWND ctrl = GetDlgItem(hwnd, IDC_BUTTON_PAUSETRANSFERS);
  620. GetWindowTextW(ctrl, buffer, ARRAYSIZE(buffer));
  621. LRESULT idealSize = MLSkinnedButton_GetIdealSize(ctrl, buffer);
  622. SetRect(&rg, rc.left + WASABI_API_APP->getScaleX(1),
  623. rc.bottom - WASABI_API_APP->getScaleY(HIWORD(idealSize)),
  624. rc.right, rc.bottom);
  625. rc.bottom = rg.top - WASABI_API_APP->getScaleY(3);
  626. }
  627. break;
  628. case GROUP_MAIN:
  629. SetRect(&rg, rc.left + WASABI_API_APP->getScaleX(1), rc.top, rc.right, rc.bottom);
  630. break;
  631. }
  632. continue;
  633. }
  634. if (skipgroup) continue;
  635. pl->id = controls[index];
  636. pl->hwnd = GetDlgItem(hwnd, pl->id);
  637. if (!pl->hwnd) continue;
  638. GetWindowRect(pl->hwnd, &ri);
  639. MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&ri, 2);
  640. pl->flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS;
  641. switch (pl->id)
  642. {
  643. case IDC_BUTTON_PAUSETRANSFERS:
  644. case IDC_BUTTON_CLEARFINISHED:
  645. case IDC_BUTTON_REMOVESELECTED:
  646. case IDC_BUTTON_RETRYSELECTED:
  647. {
  648. wchar_t buffer[128] = {0};
  649. GetWindowTextW(pl->hwnd, buffer, ARRAYSIZE(buffer));
  650. LRESULT idealSize = MLSkinnedButton_GetIdealSize(pl->hwnd, buffer);
  651. LONG width = LOWORD(idealSize) + WASABI_API_APP->getScaleX(6);
  652. SETLAYOUTPOS(pl, rg.left, rg.bottom - WASABI_API_APP->getScaleY(HIWORD(idealSize)),
  653. width, WASABI_API_APP->getScaleY(HIWORD(idealSize)));
  654. pl->flags |= ((rg.right - rg.left) > width) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  655. if (SWP_SHOWWINDOW & pl->flags) rg.left += (pl->cx + WASABI_API_APP->getScaleX(4));
  656. break;
  657. }
  658. case IDC_STATUS:
  659. SETLAYOUTPOS(pl, rg.left, rg.top, rg.right - rg.left, (rg.bottom - rg.top));
  660. pl->flags |= (pl->cx > WASABI_API_APP->getScaleX(16)) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  661. break;
  662. case IDC_LIST_TRANSFERS:
  663. SETLAYOUTPOS(pl, rg.left, rg.top + 1, (rg.right - rg.left) - WASABI_API_APP->getScaleX(2), (rg.bottom - rg.top) - WASABI_API_APP->getScaleY(1));
  664. break;
  665. }
  666. SETLAYOUTFLAGS(pl, ri);
  667. if (LAYOUTNEEEDUPDATE(pl))
  668. {
  669. if (SWP_NOSIZE == ((SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_NOSIZE) & pl->flags) &&
  670. ri.left == (pl->x + offsetX) && ri.top == (pl->y + offsetY) && !fUpdateAll && IsWindowVisible(pl->hwnd))
  671. {
  672. SetRect(&ri, pl->x, pl->y, pl->cx + pl->x, pl->y + pl->cy);
  673. ValidateRect(hwnd, &ri);
  674. }
  675. pl++;
  676. }
  677. else if (!fUpdateAll && (fRedraw || (!offsetX && !offsetY)) && IsWindowVisible(pl->hwnd))
  678. {
  679. ValidateRect(hwnd, &ri);
  680. if (GetUpdateRect(pl->hwnd, NULL, FALSE))
  681. {
  682. if (!rgn) rgn = CreateRectRgn(0,0,0,0);
  683. GetUpdateRgn(pl->hwnd, rgn, FALSE);
  684. OffsetRgn(rgn, pl->x, pl->y);
  685. InvalidateRgn(hwnd, rgn, FALSE);
  686. }
  687. }
  688. }
  689. if (pl != layout)
  690. {
  691. LAYOUT *pc;
  692. HDWP hdwp = BeginDeferWindowPos((INT)(pl - layout));
  693. for (pc = layout; pc < pl && hdwp; pc++)
  694. {
  695. hdwp = DeferWindowPos(hdwp, pc->hwnd, NULL, pc->x, pc->y, pc->cx, pc->cy, pc->flags);
  696. }
  697. if (hdwp) EndDeferWindowPos(hdwp);
  698. if (!rgn) rgn = CreateRectRgn(0, 0, 0, 0);
  699. if (fRedraw)
  700. {
  701. GetUpdateRgn(hwnd, rgn, FALSE);
  702. for (pc = layout; pc < pl && hdwp; pc++)
  703. {
  704. if (pc->rgn)
  705. {
  706. OffsetRgn(pc->rgn, pc->x, pc->y);
  707. CombineRgn(rgn, rgn, pc->rgn, RGN_OR);
  708. }
  709. }
  710. RedrawWindow(hwnd, NULL, rgn, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN);
  711. }
  712. if (g_rgnUpdate)
  713. {
  714. GetUpdateRgn(hwnd, g_rgnUpdate, FALSE);
  715. for (pc = layout; pc < pl && hdwp; pc++)
  716. {
  717. if (pc->rgn)
  718. {
  719. OffsetRgn(pc->rgn, pc->x, pc->y);
  720. CombineRgn(g_rgnUpdate, g_rgnUpdate, pc->rgn, RGN_OR);
  721. }
  722. }
  723. }
  724. for (pc = layout; pc < pl && hdwp; pc++)
  725. if (pc->rgn) DeleteObject(pc->rgn);
  726. }
  727. if (rgn) DeleteObject(rgn);
  728. ValidateRgn(hwnd, NULL);
  729. }
  730. static void
  731. TransferView_UpdateFont(HWND hwnd, BOOL redraw)
  732. {
  733. TransferView *self;
  734. HWND elementWindow;
  735. HDWP hdwp;
  736. const int buttonList[] =
  737. {
  738. IDC_BUTTON_PAUSETRANSFERS,
  739. IDC_BUTTONCANCELSELECTED,
  740. IDC_BUTTON_CLEARFINISHED,
  741. IDC_BUTTON_REMOVESELECTED,
  742. IDC_BUTTON_RETRYSELECTED
  743. };
  744. TRANSFERVIEW_RET_VOID(self, hwnd);
  745. if (FALSE == Graphics_GetWindowBaseUnits(hwnd, &self->unitSize.cx, &self->unitSize.cy))
  746. {
  747. self->unitSize.cx = 6;
  748. self->unitSize.cy = 13;
  749. }
  750. elementWindow = GetDlgItem(hwnd, IDC_LIST_TRANSFERS);
  751. if (NULL != elementWindow)
  752. {
  753. elementWindow = (HWND)SendMessage(elementWindow, LVM_GETHEADER, 0, 0L);
  754. if (NULL != elementWindow)
  755. MLSkinnedHeader_SetHeight(elementWindow, -1);
  756. }
  757. hdwp = BeginDeferWindowPos(ARRAYSIZE(buttonList) + 1);
  758. if (NULL != hdwp)
  759. {
  760. LRESULT idealSize;
  761. SIZE buttonSize;
  762. elementWindow = GetDlgItem(hwnd, IDC_STATUS);
  763. if (NULL != elementWindow)
  764. {
  765. hdwp = DeferWindowPos(hdwp, elementWindow, NULL, 0, 0, 100, self->unitSize.cy,
  766. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
  767. }
  768. for(size_t index = 0; index < ARRAYSIZE(buttonList) && NULL != hdwp; index++)
  769. {
  770. elementWindow = GetDlgItem(hwnd, buttonList[index]);
  771. if (NULL == elementWindow)
  772. continue;
  773. if (IDC_BUTTON_PAUSETRANSFERS == buttonList[index])
  774. {
  775. wchar_t buffer[128] = {0};
  776. WASABI_API_LNGSTRINGW_BUF(IDS_RESUME, buffer, ARRAYSIZE(buffer));
  777. idealSize = MLSkinnedButton_GetIdealSize(elementWindow, buffer);
  778. buttonSize.cx = LOWORD(idealSize);
  779. buttonSize.cy = HIWORD(idealSize);
  780. WASABI_API_LNGSTRINGW_BUF(IDS_PAUSE, buffer, ARRAYSIZE(buffer));
  781. idealSize = MLSkinnedButton_GetIdealSize(elementWindow, buffer);
  782. if (buttonSize.cx < LOWORD(idealSize))
  783. buttonSize.cx = LOWORD(idealSize);
  784. if (buttonSize.cy < HIWORD(idealSize))
  785. buttonSize.cy = HIWORD(idealSize);
  786. }
  787. else
  788. {
  789. idealSize = MLSkinnedButton_GetIdealSize(elementWindow, NULL);
  790. buttonSize.cx = LOWORD(idealSize);
  791. buttonSize.cy = HIWORD(idealSize);
  792. }
  793. hdwp = DeferWindowPos(hdwp, elementWindow, NULL, 0, 0, buttonSize.cx, buttonSize.cy,
  794. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
  795. }
  796. if (NULL != hdwp)
  797. EndDeferWindowPos(hdwp);
  798. }
  799. TransferView_UpdateLayout(hwnd, redraw);
  800. }
  801. static int
  802. TransferView_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
  803. {
  804. HWND controlWindow;
  805. const int skinList[] =
  806. {
  807. IDC_BUTTON_PAUSETRANSFERS,
  808. IDC_BUTTONCANCELSELECTED,
  809. IDC_BUTTON_CLEARFINISHED,
  810. IDC_BUTTON_REMOVESELECTED,
  811. IDC_BUTTON_RETRYSELECTED,
  812. IDC_STATUS,
  813. };
  814. TransferView *self = (TransferView*)calloc(1, sizeof(TransferView));
  815. if (NULL != self)
  816. {
  817. if (FALSE == SetViewData(hwnd, self))
  818. {
  819. free(self);
  820. self = NULL;
  821. }
  822. }
  823. if (NULL == self)
  824. {
  825. DestroyWindow(hwnd);
  826. return 0;
  827. }
  828. device = (DeviceView *)param;
  829. transferListContents.Init();
  830. transferListContents.lock();
  831. transferListContents.FullUpdate();
  832. listTransfers = new SkinnedListView(&transferListContents,IDC_LIST_TRANSFERS,plugin.hwndLibraryParent, hwnd);
  833. listTransfers->DialogProc(hwnd,WM_INITDIALOG, (WPARAM)focusWindow, param);
  834. transferListContents.unlock();
  835. SetDlgItemText(hwnd,IDC_BUTTON_PAUSETRANSFERS,
  836. WASABI_API_LNGSTRINGW((device->transferContext.IsPaused()?IDS_RESUME:IDS_PAUSE)));
  837. MLSkinWindow2(plugin.hwndLibraryParent, hwnd, SKINNEDWND_TYPE_DIALOG,
  838. SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
  839. for(size_t index = 0; index < ARRAYSIZE(skinList); index++)
  840. {
  841. controlWindow = GetDlgItem(hwnd, skinList[index]);
  842. if (NULL != controlWindow)
  843. {
  844. MLSkinWindow2(plugin.hwndLibraryParent, controlWindow,
  845. (skinList[index] != IDC_STATUS ? SKINNEDWND_TYPE_BUTTON : SKINNEDWND_TYPE_STATIC),
  846. SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
  847. }
  848. }
  849. TransferView_UpdateFont(hwnd, FALSE);
  850. SetTimer(hwnd,1,500,NULL);
  851. updateStatus(hwnd);
  852. return 0;
  853. }
  854. static void
  855. TransferView_OnDestroy(HWND hwnd)
  856. {
  857. TransferView *self;
  858. self = (TransferView *)RemoveViewData(hwnd);
  859. if (NULL == self)
  860. return;
  861. KillTimer(hwnd, 1);
  862. device = 0;
  863. SkinnedListView * lt = listTransfers;
  864. if (NULL != lt)
  865. {
  866. transferListContents.lock();
  867. listTransfers=NULL;
  868. transferListContents.unlock();
  869. delete lt;
  870. }
  871. free(self);
  872. }
  873. static void
  874. TransferView_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
  875. {
  876. if (NULL == windowPos)
  877. return;
  878. if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & windowPos->flags))
  879. {
  880. TransferView_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & windowPos->flags));
  881. }
  882. }
  883. static void
  884. TransferView_OnDisplayChanged(HWND hwnd, INT bpp, INT dpi_x, INT dpi_y)
  885. {
  886. UpdateWindow(hwnd);
  887. TransferView_UpdateFont(hwnd, TRUE);
  888. }
  889. static void
  890. TransferView_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
  891. {
  892. TransferView *self;
  893. TRANSFERVIEW_RET_VOID(self, hwnd);
  894. self->font = font;
  895. }
  896. static HFONT
  897. TransferView_OnGetFont(HWND hwnd)
  898. {
  899. TransferView *self;
  900. TRANSFERVIEW_RET_VAL(self, hwnd, NULL);
  901. return self->font;
  902. }
  903. static void
  904. TransferView_OnSetUpdateRegion(HWND hwnd, HRGN updateRegion, POINTS regionOffset)
  905. {
  906. TransferView *self;
  907. TRANSFERVIEW_RET_VOID(self, hwnd);
  908. self->updateRegion = updateRegion;
  909. self->updateOffset.x = regionOffset.x;
  910. self->updateOffset.y = regionOffset.y;
  911. }
  912. INT_PTR CALLBACK pmp_queue_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  913. {
  914. if (NULL != listTransfers)
  915. {
  916. INT_PTR processed = listTransfers->DialogProc(hwndDlg,uMsg,wParam,lParam);
  917. if (0 != processed)
  918. return processed;
  919. }
  920. switch (uMsg)
  921. {
  922. case WM_INITDIALOG: return TransferView_OnInitDialog(hwndDlg, (HWND)wParam, lParam);
  923. case WM_DESTROY: TransferView_OnDestroy(hwndDlg); break;
  924. case WM_WINDOWPOSCHANGED: TransferView_OnWindowPosChanged(hwndDlg, (WINDOWPOS*)lParam); return TRUE;
  925. case WM_DISPLAYCHANGE: TransferView_OnDisplayChanged(hwndDlg, (INT)wParam, LOWORD(lParam), HIWORD(lParam)); return TRUE;
  926. case WM_GETFONT: DIALOG_RESULT(hwndDlg, TransferView_OnGetFont(hwndDlg));
  927. case WM_SETFONT: TransferView_OnSetFont(hwndDlg, (HFONT)wParam, LOWORD(lParam)); return TRUE;
  928. case WM_TIMER:
  929. if (wParam == 1)
  930. {
  931. updateStatus(hwndDlg);
  932. /*if (device_update_map[device] == true)
  933. {
  934. device_update_map[device] = false;*/
  935. transferListContents.FullUpdate();
  936. /*}*/
  937. }
  938. break;
  939. case WM_NOTIFY:
  940. {
  941. LPNMHDR l=(LPNMHDR)lParam;
  942. if (l->idFrom==IDC_LIST_TRANSFERS)
  943. {
  944. switch (l->code)
  945. {
  946. case NM_RETURN: // enter!
  947. //case NM_RCLICK: // right click!
  948. case LVN_KEYDOWN:
  949. {
  950. int row = 0;
  951. C_ItemList items;
  952. if (!AddSelectedItems(&items, &listTransfers->listview, getTransferQueue(device), row, device))
  953. return 0;
  954. if (!AddSelectedItems(&items, &listTransfers->listview, getFinishedTransferQueue(device), row, device))
  955. return 0;
  956. if (items.GetSize())
  957. {
  958. // TODO need to check the handling of this...
  959. /*if (l->code == NM_RCLICK)
  960. {
  961. LPNMITEMACTIVATE lva=(LPNMITEMACTIVATE)lParam;
  962. handleContextMenuResult(showContextMenu(7,l->hwndFrom,device->dev,lva->ptAction),&items,device);
  963. }
  964. else*/ if (l->code == NM_RETURN)
  965. {
  966. handleContextMenuResult((!GetAsyncKeyState(VK_SHIFT)?ID_TRACKSLIST_PLAYSELECTION:ID_TRACKSLIST_ENQUEUESELECTION),&items,device);
  967. }
  968. else if (l->code == LVN_KEYDOWN)
  969. {
  970. switch (((LPNMLVKEYDOWN)lParam)->wVKey)
  971. {
  972. case VK_DELETE:
  973. {
  974. if (!(GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
  975. {
  976. handleContextMenuResult(ID_TRACKSLIST_DELETE,&items,device);
  977. }
  978. }
  979. break;
  980. case 0x45: //E
  981. if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
  982. {
  983. handleContextMenuResult(ID_TRACKSLIST_EDITSELECTEDITEMS,&items,device);
  984. }
  985. break;
  986. }
  987. }
  988. }
  989. break;
  990. }
  991. }
  992. }
  993. }
  994. break;
  995. case WM_COMMAND:
  996. switch (LOWORD(wParam))
  997. {
  998. case IDC_BUTTON_CLEARFINISHED:
  999. {
  1000. LinkedQueue * finishedTX = getFinishedTransferQueue(device);
  1001. if (finishedTX)
  1002. {
  1003. finishedTX->lock();
  1004. int j=finishedTX->GetSize();
  1005. while (j-- > 0) delete(CopyInst*)finishedTX->Del(j);
  1006. finishedTX->unlock();
  1007. }
  1008. transferListContents.FullUpdate();
  1009. }
  1010. break;
  1011. case IDC_BUTTON_REMOVESELECTED:
  1012. {
  1013. int row = transferListContents.GetNumRows();
  1014. RemoveSelectedItems(device, &listTransfers->listview, getTransferQueue(device), row, false);
  1015. RemoveSelectedItems(device, &listTransfers->listview, getFinishedTransferQueue(device), row, true);
  1016. transferListContents.FullUpdate();
  1017. }
  1018. break;
  1019. case IDC_BUTTON_PAUSETRANSFERS:
  1020. {
  1021. if (false != device->transferContext.IsPaused())
  1022. device->transferContext.Resume();
  1023. else
  1024. device->transferContext.Pause();
  1025. SetDlgItemText(hwndDlg,IDC_BUTTON_PAUSETRANSFERS,WASABI_API_LNGSTRINGW((device->transferContext.IsPaused()?IDS_RESUME:IDS_PAUSE)));
  1026. TransferView_UpdateLayout(hwndDlg, TRUE);
  1027. }
  1028. break;
  1029. case IDC_BUTTONCANCELSELECTED:
  1030. {
  1031. int row = transferListContents.GetNumRows();
  1032. CancelSelectedItems(device, &listTransfers->listview, &cloudTransferQueue, row);
  1033. transferListContents.FullUpdate();
  1034. }
  1035. break;
  1036. case IDC_BUTTON_RETRYSELECTED:
  1037. {
  1038. int row = transferListContents.GetNumRows();
  1039. RetrySelectedItems(device, &listTransfers->listview, &cloudTransferQueue, &cloudFinishedTransfers, row);
  1040. transferListContents.FullUpdate();
  1041. }
  1042. break;
  1043. }
  1044. break;
  1045. // gen_ml flickerless drawing
  1046. case WM_USER + 0x200: DIALOG_RESULT(hwndDlg, 1);
  1047. case WM_USER + 0x201: TransferView_OnSetUpdateRegion(hwndDlg, (HRGN)lParam, MAKEPOINTS(wParam)); return TRUE;
  1048. }
  1049. return 0;
  1050. }