procpage.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. * ReactOS Task Manager
  3. *
  4. * procpage.c
  5. *
  6. * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  21. */
  22. #include <ctype.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <windows.h>
  26. #include <commctrl.h>
  27. #include <winnt.h>
  28. #include "taskmgr.h"
  29. #include "perfdata.h"
  30. #include "column.h"
  31. HWND hProcessPage; /* Process List Property Page */
  32. HWND hProcessPageListCtrl; /* Process ListCtrl Window */
  33. HWND hProcessPageHeaderCtrl; /* Process Header Control */
  34. HWND hProcessPageEndProcessButton; /* Process End Process button */
  35. HWND hProcessPageShowAllProcessesButton;/* Process Show All Processes checkbox */
  36. static int nProcessPageWidth;
  37. static int nProcessPageHeight;
  38. static HANDLE hProcessPageEvent = NULL; /* When this event becomes signaled then we refresh the process list */
  39. static void CommaSeparateNumberString(LPWSTR strNumber, int nMaxCount)
  40. {
  41. WCHAR temp[260];
  42. UINT i, j, k;
  43. int len = lstrlenW(strNumber);
  44. for (i=0; i < len % 3; i++)
  45. temp[i] = strNumber[i];
  46. for (k=0,j=i; i < len; i++,j++,k++) {
  47. if ((k % 3 == 0) && (j > 0))
  48. temp[j++] = ',';
  49. temp[j] = strNumber[i];
  50. }
  51. temp[j++] = 0;
  52. memcpy(strNumber, temp, min(nMaxCount, j) * sizeof(WCHAR));
  53. }
  54. static void ProcessPageShowContextMenu(DWORD dwProcessId)
  55. {
  56. HMENU hMenu;
  57. HMENU hSubMenu;
  58. HMENU hPriorityMenu;
  59. POINT pt;
  60. SYSTEM_INFO si;
  61. HANDLE hProcess;
  62. DWORD dwProcessPriorityClass;
  63. WCHAR strDebugger[260];
  64. DWORD dwDebuggerSize;
  65. HKEY hKey;
  66. UINT Idx;
  67. static const WCHAR wszAeDebugRegPath[] = {
  68. 'S','o','f','t','w','a','r','e','\\',
  69. 'M','i','c','r','o','s','o','f','t','\\',
  70. 'W','i','n','d','o','w','s',' ','N','T','\\',
  71. 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
  72. 'A','e','D','e','b','u','g',0};
  73. memset(&si, 0, sizeof(SYSTEM_INFO));
  74. GetCursorPos(&pt);
  75. GetSystemInfo(&si);
  76. hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_PROCESS_PAGE_CONTEXT));
  77. hSubMenu = GetSubMenu(hMenu, 0);
  78. hPriorityMenu = GetSubMenu(hSubMenu, 4);
  79. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
  80. dwProcessPriorityClass = GetPriorityClass(hProcess);
  81. CloseHandle(hProcess);
  82. if (si.dwNumberOfProcessors < 2)
  83. RemoveMenu(hSubMenu, ID_PROCESS_PAGE_SETAFFINITY, MF_BYCOMMAND);
  84. switch (dwProcessPriorityClass) {
  85. case REALTIME_PRIORITY_CLASS:
  86. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, MF_BYCOMMAND);
  87. break;
  88. case HIGH_PRIORITY_CLASS:
  89. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_HIGH, MF_BYCOMMAND);
  90. break;
  91. case ABOVE_NORMAL_PRIORITY_CLASS:
  92. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL, MF_BYCOMMAND);
  93. break;
  94. case NORMAL_PRIORITY_CLASS:
  95. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_NORMAL, MF_BYCOMMAND);
  96. break;
  97. case BELOW_NORMAL_PRIORITY_CLASS:
  98. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL, MF_BYCOMMAND);
  99. break;
  100. case IDLE_PRIORITY_CLASS:
  101. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_LOW, MF_BYCOMMAND);
  102. break;
  103. }
  104. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszAeDebugRegPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  105. {
  106. static const WCHAR wszDebugger[] = {'D','e','b','u','g','g','e','r',0};
  107. dwDebuggerSize = 260;
  108. if (RegQueryValueExW(hKey, wszDebugger, NULL, NULL, (LPBYTE)strDebugger, &dwDebuggerSize) == ERROR_SUCCESS)
  109. {
  110. static const WCHAR wszDRWTSN32[] = {'D','R','W','T','S','N','3','2',0};
  111. for (Idx=0; Idx < lstrlenW(strDebugger); Idx++)
  112. strDebugger[Idx] = toupper(strDebugger[Idx]);
  113. if (wcsstr(strDebugger, wszDRWTSN32))
  114. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  115. }
  116. else
  117. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  118. RegCloseKey(hKey);
  119. } else {
  120. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  121. }
  122. TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
  123. DestroyMenu(hMenu);
  124. }
  125. static void ProcessPageOnNotify(LPARAM lParam)
  126. {
  127. LPNMHDR pnmh;
  128. NMLVDISPINFOW* pnmdi;
  129. LVITEMW lvitem;
  130. ULONG Index, Count;
  131. ULONG ColumnIndex;
  132. IO_COUNTERS iocounters;
  133. TIME time;
  134. static const WCHAR wszFmtD[] = {'%','d',0};
  135. static const WCHAR wszFmt02D[] = {'%','0','2','d',0};
  136. static const WCHAR wszUnitK[] = {' ','K',0};
  137. pnmh = (LPNMHDR) lParam;
  138. pnmdi = (NMLVDISPINFOW*) lParam;
  139. if (pnmh->hwndFrom == hProcessPageListCtrl)
  140. {
  141. switch (pnmh->code)
  142. {
  143. case LVN_GETDISPINFOW:
  144. if (!(pnmdi->item.mask & LVIF_TEXT))
  145. break;
  146. ColumnIndex = pnmdi->item.iSubItem;
  147. Index = pnmdi->item.iItem;
  148. if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME)
  149. PerfDataGetImageName(Index, pnmdi->item.pszText, pnmdi->item.cchTextMax);
  150. if (ColumnDataHints[ColumnIndex] == COLUMN_PID)
  151. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetProcessId(Index));
  152. if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME)
  153. PerfDataGetUserName(Index, pnmdi->item.pszText, pnmdi->item.cchTextMax);
  154. if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID)
  155. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetSessionId(Index));
  156. if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE)
  157. wsprintfW(pnmdi->item.pszText, wszFmt02D, PerfDataGetCPUUsage(Index));
  158. if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME)
  159. {
  160. DWORD dwHours;
  161. DWORD dwMinutes;
  162. DWORD dwSeconds;
  163. ULONGLONG secs;
  164. static const WCHAR timefmt[] = {'%','d',':','%','0','2','d',':','%','0','2','d',0};
  165. time = PerfDataGetCPUTime(Index);
  166. secs = time.QuadPart / 10000000;
  167. dwHours = secs / 3600;
  168. dwMinutes = (secs % 3600) / 60;
  169. dwSeconds = (secs % 3600) % 60;
  170. wsprintfW(pnmdi->item.pszText, timefmt, dwHours, dwMinutes, dwSeconds);
  171. }
  172. if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE)
  173. {
  174. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetWorkingSetSizeBytes(Index) / 1024);
  175. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  176. wcscat(pnmdi->item.pszText, wszUnitK);
  177. }
  178. if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE)
  179. {
  180. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024);
  181. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  182. wcscat(pnmdi->item.pszText, wszUnitK);
  183. }
  184. if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA)
  185. {
  186. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetWorkingSetSizeDelta(Index) / 1024);
  187. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  188. wcscat(pnmdi->item.pszText, wszUnitK);
  189. }
  190. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS)
  191. {
  192. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPageFaultCount(Index));
  193. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  194. }
  195. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA)
  196. {
  197. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPageFaultCountDelta(Index));
  198. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  199. }
  200. if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE)
  201. {
  202. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetVirtualMemorySizeBytes(Index) / 1024);
  203. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  204. wcscat(pnmdi->item.pszText, wszUnitK);
  205. }
  206. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL)
  207. {
  208. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPagedPoolUsagePages(Index) / 1024);
  209. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  210. wcscat(pnmdi->item.pszText, wszUnitK);
  211. }
  212. if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL)
  213. {
  214. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetNonPagedPoolUsagePages(Index) / 1024);
  215. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  216. wcscat(pnmdi->item.pszText, wszUnitK);
  217. }
  218. if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY)
  219. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetBasePriority(Index));
  220. if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT)
  221. {
  222. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetHandleCount(Index));
  223. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  224. }
  225. if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT)
  226. {
  227. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetThreadCount(Index));
  228. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  229. }
  230. if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS)
  231. {
  232. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetUSERObjectCount(Index));
  233. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  234. }
  235. if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS)
  236. {
  237. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetGDIObjectCount(Index));
  238. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  239. }
  240. if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS)
  241. {
  242. PerfDataGetIOCounters(Index, &iocounters);
  243. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.ReadOperationCount); */
  244. _ui64tow(iocounters.ReadOperationCount, pnmdi->item.pszText, 10);
  245. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  246. }
  247. if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES)
  248. {
  249. PerfDataGetIOCounters(Index, &iocounters);
  250. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.WriteOperationCount); */
  251. _ui64tow(iocounters.WriteOperationCount, pnmdi->item.pszText, 10);
  252. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  253. }
  254. if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER)
  255. {
  256. PerfDataGetIOCounters(Index, &iocounters);
  257. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.OtherOperationCount); */
  258. _ui64tow(iocounters.OtherOperationCount, pnmdi->item.pszText, 10);
  259. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  260. }
  261. if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES)
  262. {
  263. PerfDataGetIOCounters(Index, &iocounters);
  264. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.ReadTransferCount); */
  265. _ui64tow(iocounters.ReadTransferCount, pnmdi->item.pszText, 10);
  266. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  267. }
  268. if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES)
  269. {
  270. PerfDataGetIOCounters(Index, &iocounters);
  271. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.WriteTransferCount); */
  272. _ui64tow(iocounters.WriteTransferCount, pnmdi->item.pszText, 10);
  273. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  274. }
  275. if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES)
  276. {
  277. PerfDataGetIOCounters(Index, &iocounters);
  278. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.OtherTransferCount); */
  279. _ui64tow(iocounters.OtherTransferCount, pnmdi->item.pszText, 10);
  280. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  281. }
  282. break;
  283. case NM_RCLICK:
  284. Count = SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
  285. for (Index=0; Index<Count; Index++)
  286. {
  287. lvitem.mask = LVIF_STATE;
  288. lvitem.stateMask = LVIS_SELECTED;
  289. lvitem.iItem = Index;
  290. lvitem.iSubItem = 0;
  291. SendMessageW(hProcessPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &lvitem);
  292. if (lvitem.state & LVIS_SELECTED)
  293. break;
  294. }
  295. if ((SendMessageW(hProcessPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0) == 1) &&
  296. (PerfDataGetProcessId(Index) != 0))
  297. {
  298. ProcessPageShowContextMenu(PerfDataGetProcessId(Index));
  299. }
  300. break;
  301. }
  302. }
  303. else if (pnmh->hwndFrom == hProcessPageHeaderCtrl)
  304. {
  305. switch (pnmh->code)
  306. {
  307. case HDN_ITEMCLICKW:
  308. /*
  309. * FIXME: Fix the column sorting
  310. *
  311. *ListView_SortItems(hApplicationPageListCtrl, ApplicationPageCompareFunc, NULL);
  312. *bSortAscending = !bSortAscending;
  313. */
  314. break;
  315. case HDN_ITEMCHANGEDW:
  316. UpdateColumnDataHints();
  317. break;
  318. case HDN_ENDDRAG:
  319. UpdateColumnDataHints();
  320. break;
  321. }
  322. }
  323. }
  324. void RefreshProcessPage(void)
  325. {
  326. /* Signal the event so that our refresh thread */
  327. /* will wake up and refresh the process page */
  328. SetEvent(hProcessPageEvent);
  329. }
  330. static DWORD WINAPI ProcessPageRefreshThread(void *lpParameter)
  331. {
  332. ULONG OldProcessorUsage = 0;
  333. ULONG OldProcessCount = 0;
  334. WCHAR wszCPU_Usage[255];
  335. WCHAR wszProcesses[255];
  336. LoadStringW(hInst, IDS_STATUS_BAR_CPU_USAGE, wszCPU_Usage, ARRAY_SIZE(wszCPU_Usage));
  337. LoadStringW(hInst, IDS_STATUS_BAR_PROCESSES, wszProcesses, ARRAY_SIZE(wszProcesses));
  338. /* Create the event */
  339. hProcessPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
  340. /* If we couldn't create the event then exit the thread */
  341. if (!hProcessPageEvent)
  342. return 0;
  343. while (1) {
  344. DWORD dwWaitVal;
  345. /* Wait on the event */
  346. dwWaitVal = WaitForSingleObject(hProcessPageEvent, INFINITE);
  347. /* If the wait failed then the event object must have been */
  348. /* closed and the task manager is exiting so exit this thread */
  349. if (dwWaitVal == WAIT_FAILED)
  350. return 0;
  351. if (dwWaitVal == WAIT_OBJECT_0) {
  352. WCHAR text[256];
  353. /* Reset our event */
  354. ResetEvent(hProcessPageEvent);
  355. if (SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0) != PerfDataGetProcessCount())
  356. SendMessageW(hProcessPageListCtrl, LVM_SETITEMCOUNT, PerfDataGetProcessCount(), /*LVSICF_NOINVALIDATEALL|*/LVSICF_NOSCROLL);
  357. if (IsWindowVisible(hProcessPage))
  358. InvalidateRect(hProcessPageListCtrl, NULL, FALSE);
  359. if (OldProcessorUsage != PerfDataGetProcessorUsage()) {
  360. OldProcessorUsage = PerfDataGetProcessorUsage();
  361. wsprintfW(text, wszCPU_Usage, OldProcessorUsage);
  362. SendMessageW(hStatusWnd, SB_SETTEXTW, 1, (LPARAM)text);
  363. }
  364. if (OldProcessCount != PerfDataGetProcessCount()) {
  365. OldProcessCount = PerfDataGetProcessCount();
  366. wsprintfW(text, wszProcesses, OldProcessCount);
  367. SendMessageW(hStatusWnd, SB_SETTEXTW, 0, (LPARAM)text);
  368. }
  369. }
  370. }
  371. return 0;
  372. }
  373. INT_PTR CALLBACK
  374. ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  375. {
  376. RECT rc;
  377. int nXDifference;
  378. int nYDifference;
  379. int cx, cy;
  380. switch (message) {
  381. case WM_INITDIALOG:
  382. /*
  383. * Save the width and height
  384. */
  385. GetClientRect(hDlg, &rc);
  386. nProcessPageWidth = rc.right;
  387. nProcessPageHeight = rc.bottom;
  388. /* Update window position */
  389. SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  390. /*
  391. * Get handles to the controls
  392. */
  393. hProcessPageListCtrl = GetDlgItem(hDlg, IDC_PROCESSLIST);
  394. hProcessPageHeaderCtrl = (HWND)SendMessageW(hProcessPageListCtrl, LVM_GETHEADER, 0, 0);
  395. hProcessPageEndProcessButton = GetDlgItem(hDlg, IDC_ENDPROCESS);
  396. hProcessPageShowAllProcessesButton = GetDlgItem(hDlg, IDC_SHOWALLPROCESSES);
  397. /* Enable manual column reordering, set full select */
  398. SendMessageW(hProcessPageListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP,
  399. LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
  400. AddColumns();
  401. /*
  402. * Subclass the process list control so we can intercept WM_ERASEBKGND
  403. */
  404. OldProcessListWndProc = (WNDPROC)SetWindowLongPtrW(hProcessPageListCtrl, GWLP_WNDPROC, (LONG_PTR)ProcessListWndProc);
  405. /* Start our refresh thread */
  406. CloseHandle( CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, NULL));
  407. return TRUE;
  408. case WM_DESTROY:
  409. /* Close the event handle, this will make the */
  410. /* refresh thread exit when the wait fails */
  411. CloseHandle(hProcessPageEvent);
  412. SaveColumnSettings();
  413. break;
  414. case WM_COMMAND:
  415. /* Handle the button clicks */
  416. switch (LOWORD(wParam))
  417. {
  418. case IDC_ENDPROCESS:
  419. ProcessPage_OnEndProcess();
  420. }
  421. break;
  422. case WM_SIZE:
  423. if (wParam == SIZE_MINIMIZED)
  424. return 0;
  425. cx = LOWORD(lParam);
  426. cy = HIWORD(lParam);
  427. nXDifference = cx - nProcessPageWidth;
  428. nYDifference = cy - nProcessPageHeight;
  429. nProcessPageWidth = cx;
  430. nProcessPageHeight = cy;
  431. /* Reposition the application page's controls */
  432. GetWindowRect(hProcessPageListCtrl, &rc);
  433. cx = (rc.right - rc.left) + nXDifference;
  434. cy = (rc.bottom - rc.top) + nYDifference;
  435. SetWindowPos(hProcessPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
  436. InvalidateRect(hProcessPageListCtrl, NULL, TRUE);
  437. GetClientRect(hProcessPageEndProcessButton, &rc);
  438. MapWindowPoints(hProcessPageEndProcessButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
  439. cx = rc.left + nXDifference;
  440. cy = rc.top + nYDifference;
  441. SetWindowPos(hProcessPageEndProcessButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  442. InvalidateRect(hProcessPageEndProcessButton, NULL, TRUE);
  443. GetClientRect(hProcessPageShowAllProcessesButton, &rc);
  444. MapWindowPoints(hProcessPageShowAllProcessesButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
  445. cx = rc.left;
  446. cy = rc.top + nYDifference;
  447. SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  448. InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE);
  449. break;
  450. case WM_NOTIFY:
  451. ProcessPageOnNotify(lParam);
  452. break;
  453. }
  454. return 0;
  455. }