procpage.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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. if (!AreDebugChannelsSupported())
  85. RemoveMenu(hSubMenu, ID_PROCESS_PAGE_DEBUGCHANNELS, MF_BYCOMMAND);
  86. switch (dwProcessPriorityClass) {
  87. case REALTIME_PRIORITY_CLASS:
  88. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, MF_BYCOMMAND);
  89. break;
  90. case HIGH_PRIORITY_CLASS:
  91. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_HIGH, MF_BYCOMMAND);
  92. break;
  93. case ABOVE_NORMAL_PRIORITY_CLASS:
  94. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL, MF_BYCOMMAND);
  95. break;
  96. case NORMAL_PRIORITY_CLASS:
  97. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_NORMAL, MF_BYCOMMAND);
  98. break;
  99. case BELOW_NORMAL_PRIORITY_CLASS:
  100. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL, MF_BYCOMMAND);
  101. break;
  102. case IDLE_PRIORITY_CLASS:
  103. CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_LOW, MF_BYCOMMAND);
  104. break;
  105. }
  106. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszAeDebugRegPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  107. {
  108. static const WCHAR wszDebugger[] = {'D','e','b','u','g','g','e','r',0};
  109. dwDebuggerSize = 260;
  110. if (RegQueryValueExW(hKey, wszDebugger, NULL, NULL, (LPBYTE)strDebugger, &dwDebuggerSize) == ERROR_SUCCESS)
  111. {
  112. static const WCHAR wszDRWTSN32[] = {'D','R','W','T','S','N','3','2',0};
  113. for (Idx=0; Idx < lstrlenW(strDebugger); Idx++)
  114. strDebugger[Idx] = toupper(strDebugger[Idx]);
  115. if (wcsstr(strDebugger, wszDRWTSN32))
  116. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  117. }
  118. else
  119. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  120. RegCloseKey(hKey);
  121. } else {
  122. EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  123. }
  124. TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
  125. DestroyMenu(hMenu);
  126. }
  127. static void ProcessPageOnNotify(LPARAM lParam)
  128. {
  129. LPNMHDR pnmh;
  130. NMLVDISPINFOW* pnmdi;
  131. LVITEMW lvitem;
  132. ULONG Index, Count;
  133. ULONG ColumnIndex;
  134. IO_COUNTERS iocounters;
  135. TIME time;
  136. static const WCHAR wszFmtD[] = {'%','d',0};
  137. static const WCHAR wszFmt02D[] = {'%','0','2','d',0};
  138. static const WCHAR wszUnitK[] = {' ','K',0};
  139. pnmh = (LPNMHDR) lParam;
  140. pnmdi = (NMLVDISPINFOW*) lParam;
  141. if (pnmh->hwndFrom == hProcessPageListCtrl)
  142. {
  143. switch (pnmh->code)
  144. {
  145. case LVN_GETDISPINFOW:
  146. if (!(pnmdi->item.mask & LVIF_TEXT))
  147. break;
  148. ColumnIndex = pnmdi->item.iSubItem;
  149. Index = pnmdi->item.iItem;
  150. if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME)
  151. PerfDataGetImageName(Index, pnmdi->item.pszText, pnmdi->item.cchTextMax);
  152. if (ColumnDataHints[ColumnIndex] == COLUMN_PID)
  153. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetProcessId(Index));
  154. if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME)
  155. PerfDataGetUserName(Index, pnmdi->item.pszText, pnmdi->item.cchTextMax);
  156. if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID)
  157. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetSessionId(Index));
  158. if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE)
  159. wsprintfW(pnmdi->item.pszText, wszFmt02D, PerfDataGetCPUUsage(Index));
  160. if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME)
  161. {
  162. DWORD dwHours;
  163. DWORD dwMinutes;
  164. DWORD dwSeconds;
  165. ULONGLONG secs;
  166. static const WCHAR timefmt[] = {'%','d',':','%','0','2','d',':','%','0','2','d',0};
  167. time = PerfDataGetCPUTime(Index);
  168. secs = time.QuadPart / 10000000;
  169. dwHours = secs / 3600;
  170. dwMinutes = (secs % 3600) / 60;
  171. dwSeconds = (secs % 3600) % 60;
  172. wsprintfW(pnmdi->item.pszText, timefmt, dwHours, dwMinutes, dwSeconds);
  173. }
  174. if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE)
  175. {
  176. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetWorkingSetSizeBytes(Index) / 1024);
  177. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  178. wcscat(pnmdi->item.pszText, wszUnitK);
  179. }
  180. if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE)
  181. {
  182. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024);
  183. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  184. wcscat(pnmdi->item.pszText, wszUnitK);
  185. }
  186. if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA)
  187. {
  188. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetWorkingSetSizeDelta(Index) / 1024);
  189. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  190. wcscat(pnmdi->item.pszText, wszUnitK);
  191. }
  192. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS)
  193. {
  194. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPageFaultCount(Index));
  195. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  196. }
  197. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA)
  198. {
  199. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPageFaultCountDelta(Index));
  200. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  201. }
  202. if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE)
  203. {
  204. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetVirtualMemorySizeBytes(Index) / 1024);
  205. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  206. wcscat(pnmdi->item.pszText, wszUnitK);
  207. }
  208. if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL)
  209. {
  210. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetPagedPoolUsagePages(Index) / 1024);
  211. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  212. wcscat(pnmdi->item.pszText, wszUnitK);
  213. }
  214. if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL)
  215. {
  216. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetNonPagedPoolUsagePages(Index) / 1024);
  217. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  218. wcscat(pnmdi->item.pszText, wszUnitK);
  219. }
  220. if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY)
  221. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetBasePriority(Index));
  222. if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT)
  223. {
  224. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetHandleCount(Index));
  225. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  226. }
  227. if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT)
  228. {
  229. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetThreadCount(Index));
  230. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  231. }
  232. if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS)
  233. {
  234. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetUSERObjectCount(Index));
  235. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  236. }
  237. if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS)
  238. {
  239. wsprintfW(pnmdi->item.pszText, wszFmtD, PerfDataGetGDIObjectCount(Index));
  240. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  241. }
  242. if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS)
  243. {
  244. PerfDataGetIOCounters(Index, &iocounters);
  245. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.ReadOperationCount); */
  246. _ui64tow(iocounters.ReadOperationCount, pnmdi->item.pszText, 10);
  247. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  248. }
  249. if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES)
  250. {
  251. PerfDataGetIOCounters(Index, &iocounters);
  252. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.WriteOperationCount); */
  253. _ui64tow(iocounters.WriteOperationCount, pnmdi->item.pszText, 10);
  254. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  255. }
  256. if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER)
  257. {
  258. PerfDataGetIOCounters(Index, &iocounters);
  259. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.OtherOperationCount); */
  260. _ui64tow(iocounters.OtherOperationCount, pnmdi->item.pszText, 10);
  261. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  262. }
  263. if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES)
  264. {
  265. PerfDataGetIOCounters(Index, &iocounters);
  266. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.ReadTransferCount); */
  267. _ui64tow(iocounters.ReadTransferCount, pnmdi->item.pszText, 10);
  268. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  269. }
  270. if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES)
  271. {
  272. PerfDataGetIOCounters(Index, &iocounters);
  273. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.WriteTransferCount); */
  274. _ui64tow(iocounters.WriteTransferCount, pnmdi->item.pszText, 10);
  275. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  276. }
  277. if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES)
  278. {
  279. PerfDataGetIOCounters(Index, &iocounters);
  280. /* wsprintfW(pnmdi->item.pszText, wszFmtD, iocounters.OtherTransferCount); */
  281. _ui64tow(iocounters.OtherTransferCount, pnmdi->item.pszText, 10);
  282. CommaSeparateNumberString(pnmdi->item.pszText, pnmdi->item.cchTextMax);
  283. }
  284. break;
  285. case NM_RCLICK:
  286. Count = SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
  287. for (Index=0; Index<Count; Index++)
  288. {
  289. lvitem.mask = LVIF_STATE;
  290. lvitem.stateMask = LVIS_SELECTED;
  291. lvitem.iItem = Index;
  292. lvitem.iSubItem = 0;
  293. SendMessageW(hProcessPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &lvitem);
  294. if (lvitem.state & LVIS_SELECTED)
  295. break;
  296. }
  297. if ((SendMessageW(hProcessPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0) == 1) &&
  298. (PerfDataGetProcessId(Index) != 0))
  299. {
  300. ProcessPageShowContextMenu(PerfDataGetProcessId(Index));
  301. }
  302. break;
  303. }
  304. }
  305. else if (pnmh->hwndFrom == hProcessPageHeaderCtrl)
  306. {
  307. switch (pnmh->code)
  308. {
  309. case HDN_ITEMCLICKW:
  310. /*
  311. * FIXME: Fix the column sorting
  312. *
  313. *ListView_SortItems(hApplicationPageListCtrl, ApplicationPageCompareFunc, NULL);
  314. *bSortAscending = !bSortAscending;
  315. */
  316. break;
  317. case HDN_ITEMCHANGEDW:
  318. UpdateColumnDataHints();
  319. break;
  320. case HDN_ENDDRAG:
  321. UpdateColumnDataHints();
  322. break;
  323. }
  324. }
  325. }
  326. void RefreshProcessPage(void)
  327. {
  328. /* Signal the event so that our refresh thread */
  329. /* will wake up and refresh the process page */
  330. SetEvent(hProcessPageEvent);
  331. }
  332. static DWORD WINAPI ProcessPageRefreshThread(void *lpParameter)
  333. {
  334. ULONG OldProcessorUsage = 0;
  335. ULONG OldProcessCount = 0;
  336. WCHAR wszCPU_Usage[255];
  337. WCHAR wszProcesses[255];
  338. LoadStringW(hInst, IDS_STATUS_BAR_CPU_USAGE, wszCPU_Usage, ARRAY_SIZE(wszCPU_Usage));
  339. LoadStringW(hInst, IDS_STATUS_BAR_PROCESSES, wszProcesses, ARRAY_SIZE(wszProcesses));
  340. /* Create the event */
  341. hProcessPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
  342. /* If we couldn't create the event then exit the thread */
  343. if (!hProcessPageEvent)
  344. return 0;
  345. while (1) {
  346. DWORD dwWaitVal;
  347. /* Wait on the event */
  348. dwWaitVal = WaitForSingleObject(hProcessPageEvent, INFINITE);
  349. /* If the wait failed then the event object must have been */
  350. /* closed and the task manager is exiting so exit this thread */
  351. if (dwWaitVal == WAIT_FAILED)
  352. return 0;
  353. if (dwWaitVal == WAIT_OBJECT_0) {
  354. WCHAR text[256];
  355. /* Reset our event */
  356. ResetEvent(hProcessPageEvent);
  357. if (SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0) != PerfDataGetProcessCount())
  358. SendMessageW(hProcessPageListCtrl, LVM_SETITEMCOUNT, PerfDataGetProcessCount(), /*LVSICF_NOINVALIDATEALL|*/LVSICF_NOSCROLL);
  359. if (IsWindowVisible(hProcessPage))
  360. InvalidateRect(hProcessPageListCtrl, NULL, FALSE);
  361. if (OldProcessorUsage != PerfDataGetProcessorUsage()) {
  362. OldProcessorUsage = PerfDataGetProcessorUsage();
  363. wsprintfW(text, wszCPU_Usage, OldProcessorUsage);
  364. SendMessageW(hStatusWnd, SB_SETTEXTW, 1, (LPARAM)text);
  365. }
  366. if (OldProcessCount != PerfDataGetProcessCount()) {
  367. OldProcessCount = PerfDataGetProcessCount();
  368. wsprintfW(text, wszProcesses, OldProcessCount);
  369. SendMessageW(hStatusWnd, SB_SETTEXTW, 0, (LPARAM)text);
  370. }
  371. }
  372. }
  373. return 0;
  374. }
  375. INT_PTR CALLBACK
  376. ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  377. {
  378. RECT rc;
  379. int nXDifference;
  380. int nYDifference;
  381. int cx, cy;
  382. switch (message) {
  383. case WM_INITDIALOG:
  384. /*
  385. * Save the width and height
  386. */
  387. GetClientRect(hDlg, &rc);
  388. nProcessPageWidth = rc.right;
  389. nProcessPageHeight = rc.bottom;
  390. /* Update window position */
  391. SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  392. /*
  393. * Get handles to the controls
  394. */
  395. hProcessPageListCtrl = GetDlgItem(hDlg, IDC_PROCESSLIST);
  396. hProcessPageHeaderCtrl = (HWND)SendMessageW(hProcessPageListCtrl, LVM_GETHEADER, 0, 0);
  397. hProcessPageEndProcessButton = GetDlgItem(hDlg, IDC_ENDPROCESS);
  398. hProcessPageShowAllProcessesButton = GetDlgItem(hDlg, IDC_SHOWALLPROCESSES);
  399. /* Enable manual column reordering, set full select */
  400. SendMessageW(hProcessPageListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP,
  401. LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
  402. AddColumns();
  403. /*
  404. * Subclass the process list control so we can intercept WM_ERASEBKGND
  405. */
  406. OldProcessListWndProc = (WNDPROC)SetWindowLongPtrW(hProcessPageListCtrl, GWLP_WNDPROC, (LONG_PTR)ProcessListWndProc);
  407. /* Start our refresh thread */
  408. CloseHandle( CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, NULL));
  409. return TRUE;
  410. case WM_DESTROY:
  411. /* Close the event handle, this will make the */
  412. /* refresh thread exit when the wait fails */
  413. CloseHandle(hProcessPageEvent);
  414. SaveColumnSettings();
  415. break;
  416. case WM_COMMAND:
  417. /* Handle the button clicks */
  418. switch (LOWORD(wParam))
  419. {
  420. case IDC_ENDPROCESS:
  421. ProcessPage_OnEndProcess();
  422. }
  423. break;
  424. case WM_SIZE:
  425. if (wParam == SIZE_MINIMIZED)
  426. return 0;
  427. cx = LOWORD(lParam);
  428. cy = HIWORD(lParam);
  429. nXDifference = cx - nProcessPageWidth;
  430. nYDifference = cy - nProcessPageHeight;
  431. nProcessPageWidth = cx;
  432. nProcessPageHeight = cy;
  433. /* Reposition the application page's controls */
  434. GetWindowRect(hProcessPageListCtrl, &rc);
  435. cx = (rc.right - rc.left) + nXDifference;
  436. cy = (rc.bottom - rc.top) + nYDifference;
  437. SetWindowPos(hProcessPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
  438. InvalidateRect(hProcessPageListCtrl, NULL, TRUE);
  439. GetClientRect(hProcessPageEndProcessButton, &rc);
  440. MapWindowPoints(hProcessPageEndProcessButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
  441. cx = rc.left + nXDifference;
  442. cy = rc.top + nYDifference;
  443. SetWindowPos(hProcessPageEndProcessButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  444. InvalidateRect(hProcessPageEndProcessButton, NULL, TRUE);
  445. GetClientRect(hProcessPageShowAllProcessesButton, &rc);
  446. MapWindowPoints(hProcessPageShowAllProcessesButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
  447. cx = rc.left;
  448. cy = rc.top + nYDifference;
  449. SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  450. InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE);
  451. break;
  452. case WM_NOTIFY:
  453. ProcessPageOnNotify(lParam);
  454. break;
  455. }
  456. return 0;
  457. }