ReactOS 0.4.15-dev-6068-g8061a6f
graph.c File Reference
#include "precomp.h"
Include dependency graph for graph.c:

Go to the source code of this file.

Functions

void Graph_DrawCpuUsageGraph (HDC hDC, HWND hWnd)
 
void Graph_DrawMemUsageGraph (HDC hDC, HWND hWnd)
 
void Graph_DrawMemUsageHistoryGraph (HDC hDC, HWND hWnd)
 
INT_PTR CALLBACK Graph_WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 

Variables

int nlastBarsUsed = 0
 
WNDPROC OldGraphWndProc
 

Function Documentation

◆ Graph_DrawCpuUsageGraph()

void Graph_DrawCpuUsageGraph ( HDC  hDC,
HWND  hWnd 
)

Definition at line 132 of file graph.c.

133{
134 RECT rcClient;
135 RECT rcBarLeft;
136 RECT rcBarRight;
137 RECT rcText;
138 COLORREF crPrevForeground;
139 WCHAR Text[260];
140 HFONT hOldFont;
141 ULONG CpuUsage;
142 ULONG CpuKernelUsage;
143 int nBars;
144 int nBarsUsed;
145/* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
146 int nBarsUsedKernel;
147/* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
148 int nBarsFree;
149/* Top bars that are "unused", i.e. are dark green, representing free cpu time */
150 int i;
151
152 /*
153 * Get the client area rectangle
154 */
155 GetClientRect(hWnd, &rcClient);
156
157 /*
158 * Fill it with blackness
159 */
160 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
161
162 /*
163 * Get the CPU usage
164 */
165 CpuUsage = PerfDataGetProcessorUsage();
166 if (CpuUsage <= 0) CpuUsage = 0;
167 if (CpuUsage > 100) CpuUsage = 100;
168
169 wsprintfW(Text, L"%d%%", (int)CpuUsage);
170
171 /*
172 * Draw the font text onto the graph
173 */
174 rcText = rcClient;
175 InflateRect(&rcText, -2, -2);
176 crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
179 SelectObject(hDC, hOldFont);
180 SetTextColor(hDC, crPrevForeground);
181
182 /*
183 * Now we have to draw the graph
184 * So first find out how many bars we can fit
185 */
186 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
187 nBarsUsed = (nBars * CpuUsage) / 100;
188 if ((CpuUsage) && (nBarsUsed == 0))
189 {
190 nBarsUsed = 1;
191 }
192 nBarsFree = nBars - (nlastBarsUsed>nBarsUsed ? nlastBarsUsed : nBarsUsed);
193
195 {
196 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
197 if (CpuKernelUsage <= 0) CpuKernelUsage = 0;
198 if (CpuKernelUsage >= 100) CpuKernelUsage = 100;
199 nBarsUsedKernel = (nBars * CpuKernelUsage) / 100;
200 }
201 else
202 {
203 nBarsUsedKernel = 0;
204 }
205
206 /*
207 * Now draw the bar graph
208 */
209 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
210 rcBarLeft.right = rcBarLeft.left + 16;
211 rcBarRight.left = rcBarLeft.left + 17;
212 rcBarRight.right = rcBarLeft.right + 17;
213 rcBarLeft.top = rcBarRight.top = 5;
214 rcBarLeft.bottom = rcBarRight.bottom = 7;
215
216 if (nBarsUsed < 0) nBarsUsed = 0;
217 if (nBarsUsed > nBars) nBarsUsed = nBars;
218
219 if (nBarsFree < 0) nBarsFree = 0;
220 if (nBarsFree > nBars) nBarsFree = nBars;
221
222 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
223 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
224
225 /*
226 * Draw the "free" bars
227 */
228 for (i=0; i<nBarsFree; i++)
229 {
230 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
231 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
232
233 rcBarLeft.top += 3;
234 rcBarLeft.bottom += 3;
235
236 rcBarRight.top += 3;
237 rcBarRight.bottom += 3;
238 }
239
240 /*
241 * Draw the last "used" bars
242 */
243 if ((nlastBarsUsed - nBarsUsed) > 0) {
244 for (i=0; i< (nlastBarsUsed - nBarsUsed); i++)
245 {
246 if (nlastBarsUsed > 5000) nlastBarsUsed = 5000;
247
248 FillSolidRect(hDC, &rcBarLeft, MEDIUM_GREEN);
249 FillSolidRect(hDC, &rcBarRight, MEDIUM_GREEN);
250
251 rcBarLeft.top += 3;
252 rcBarLeft.bottom += 3;
253
254 rcBarRight.top += 3;
255 rcBarRight.bottom += 3;
256 }
257 }
258 nlastBarsUsed = nBarsUsed;
259 /*
260 * Draw the "used" bars
261 */
262 for (i=0; i<nBarsUsed; i++)
263 {
264 if (nBarsUsed > 5000) nBarsUsed = 5000;
265
266 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
267 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
268
269 rcBarLeft.top += 3;
270 rcBarLeft.bottom += 3;
271
272 rcBarRight.top += 3;
273 rcBarRight.bottom += 3;
274 }
275
276 /*
277 * Draw the "used" kernel bars
278 */
279
280 rcBarLeft.top -=3;
281 rcBarLeft.bottom -=3;
282
283 rcBarRight.top -=3;
284 rcBarRight.bottom -=3;
285
286 for (i=0; i<nBarsUsedKernel; i++)
287 {
288
289 FillSolidRect(hDC, &rcBarLeft, RED);
290 FillSolidRect(hDC, &rcBarRight, RED);
291
292 rcBarLeft.top -=3;
293 rcBarLeft.bottom -=3;
294
295 rcBarRight.top -=3;
296 rcBarRight.bottom -=3;
297
298 }
299
300 SelectObject(hDC, hOldFont);
301}
static HDC hDC
Definition: 3dtext.c:33
HWND hWnd
Definition: settings.c:17
char * Text
Definition: combotst.c:136
#define RGB(r, g, b)
Definition: precomp.h:62
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int nlastBarsUsed
Definition: graph.c:25
#define DARK_GREEN
Definition: graph.h:32
#define MEDIUM_GREEN
Definition: graph.h:31
#define BRIGHT_GREEN
Definition: graph.h:30
#define RED
Definition: graph.h:33
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:16
#define L(x)
Definition: ntvdm.h:50
ULONG PerfDataGetProcessorSystemUsage(void)
Definition: perfdata.c:481
ULONG PerfDataGetProcessorUsage(void)
Definition: perfdata.c:472
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
TASKMANAGER_SETTINGS TaskManagerSettings
Definition: taskmgr.c:52
void FillSolidRect(HDC hDC, LPCRECT lpRect, COLORREF clr)
Definition: taskmgr.c:534
uint32_t ULONG
Definition: typedefs.h:59
DWORD COLORREF
Definition: windef.h:300
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define DEFAULT_GUI_FONT
Definition: wingdi.h:909
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
#define DT_NOPREFIX
Definition: winuser.h:537
#define DT_CENTER
Definition: winuser.h:527
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define DT_SINGLELINE
Definition: winuser.h:540
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define DT_BOTTOM
Definition: winuser.h:525
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by Graph_WndProc().

◆ Graph_DrawMemUsageGraph()

void Graph_DrawMemUsageGraph ( HDC  hDC,
HWND  hWnd 
)

Definition at line 303 of file graph.c.

304{
305 RECT rcClient;
306 RECT rcBarLeft;
307 RECT rcBarRight;
308 RECT rcText;
309 COLORREF crPrevForeground;
310 WCHAR Text[260];
311 HFONT hOldFont;
312 ULONGLONG CommitChargeTotal;
313 ULONGLONG CommitChargeLimit;
314 int nBars;
315 int nBarsUsed = 0;
316/* Bottom bars that are "used", i.e. are bright green, representing used memory */
317 int nBarsFree;
318/* Top bars that are "unused", i.e. are dark green, representing free memory */
319 int i;
320
321 /*
322 * Get the client area rectangle
323 */
324 GetClientRect(hWnd, &rcClient);
325
326 /*
327 * Fill it with blackness
328 */
329 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
330
331 /*
332 * Get the memory usage
333 */
334 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
335 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
336
337 if (CommitChargeTotal > 1024)
338 wsprintfW(Text, L"%d MB", (int)(CommitChargeTotal / 1024));
339 else
340 wsprintfW(Text, L"%d K", (int)CommitChargeTotal);
341 /*
342 * Draw the font text onto the graph
343 */
344 rcText = rcClient;
345 InflateRect(&rcText, -2, -2);
346 crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
349 SelectObject(hDC, hOldFont);
350 SetTextColor(hDC, crPrevForeground);
351
352 /*
353 * Now we have to draw the graph
354 * So first find out how many bars we can fit
355 */
356 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
357 if (CommitChargeLimit)
358 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
359 nBarsFree = nBars - nBarsUsed;
360
361 if (nBarsUsed < 0) nBarsUsed = 0;
362 if (nBarsUsed > nBars) nBarsUsed = nBars;
363
364 if (nBarsFree < 0) nBarsFree = 0;
365 if (nBarsFree > nBars) nBarsFree = nBars;
366
367 /*
368 * Now draw the bar graph
369 */
370 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
371 rcBarLeft.right = rcBarLeft.left + 16;
372 rcBarRight.left = rcBarLeft.left + 17;
373 rcBarRight.right = rcBarLeft.right + 17;
374 rcBarLeft.top = rcBarRight.top = 5;
375 rcBarLeft.bottom = rcBarRight.bottom = 7;
376
377 /*
378 * Draw the "free" bars
379 */
380 for (i=0; i<nBarsFree; i++)
381 {
382 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
383 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
384
385 rcBarLeft.top += 3;
386 rcBarLeft.bottom += 3;
387
388 rcBarRight.top += 3;
389 rcBarRight.bottom += 3;
390 }
391
392 /*
393 * Draw the "used" bars
394 */
395 for (i=0; i<nBarsUsed; i++)
396 {
397 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
398 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
399
400 rcBarLeft.top += 3;
401 rcBarLeft.bottom += 3;
402
403 rcBarRight.top += 3;
404 rcBarRight.bottom += 3;
405 }
406
407 SelectObject(hDC, hOldFont);
408}
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
ULONG PerfDataGetCommitChargeLimitK(void)
Definition: perfdata.c:954
ULONG PerfDataGetCommitChargeTotalK(void)
Definition: perfdata.c:937
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by Graph_WndProc().

◆ Graph_DrawMemUsageHistoryGraph()

void Graph_DrawMemUsageHistoryGraph ( HDC  hDC,
HWND  hWnd 
)

Definition at line 410 of file graph.c.

411{
412 RECT rcClient;
413 //ULONGLONG CommitChargeLimit;
414 int i;
415 static int offset = 0;
416
417 if (offset++ >= 10)
418 offset = 0;
419
420 /*
421 * Get the client area rectangle
422 */
423 GetClientRect(hWnd, &rcClient);
424
425 /*
426 * Fill it with blackness
427 */
428 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
429
430 /*
431 * Get the memory usage
432 */
433 //CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
434
435 /*
436 * Draw the graph background
437 *
438 * Draw the horizontal bars
439 */
440 for (i=0; i<rcClient.bottom; i++)
441 {
442 if ((i % 11) == 0)
443 {
444 /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
445 }
446 }
447 /*
448 * Draw the vertical bars
449 */
450 for (i=11; i<rcClient.right + offset; i++)
451 {
452 if ((i % 11) == 0)
453 {
454 /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
455 }
456 }
457
458 /*
459 * Draw the memory usage
460 */
461 for (i=rcClient.right; i>=0; i--)
462 {
463 }
464}
GLintptr offset
Definition: glext.h:5920

Referenced by Graph_WndProc().

◆ Graph_WndProc()

INT_PTR CALLBACK Graph_WndProc ( HWND  hWnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 34 of file graph.c.

35{
36 HDC hdc;
37 PAINTSTRUCT ps;
38 LONG WindowId;
39
40 switch (message)
41 {
42 case WM_ERASEBKGND:
43 return TRUE;
44
45 /*
46 * Filter out mouse & keyboard messages
47 */
48 /* case WM_APPCOMMAND: */
51 case WM_LBUTTONDOWN:
52 case WM_LBUTTONUP:
54 case WM_MBUTTONDOWN:
55 case WM_MBUTTONUP:
57 case WM_MOUSEHOVER:
58 case WM_MOUSELEAVE:
59 case WM_MOUSEMOVE:
60 /* case WM_MOUSEWHEEL: */
61 case WM_NCHITTEST:
64 case WM_NCLBUTTONUP:
67 case WM_NCMBUTTONUP:
68 /* case WM_NCMOUSEHOVER: */
69 /* case WM_NCMOUSELEAVE: */
70 case WM_NCMOUSEMOVE:
73 case WM_NCRBUTTONUP:
74 /* case WM_NCXBUTTONDBLCLK: */
75 /* case WM_NCXBUTTONDOWN: */
76 /* case WM_NCXBUTTONUP: */
78 case WM_RBUTTONDOWN:
79 case WM_RBUTTONUP:
80 /* case WM_XBUTTONDBLCLK: */
81 /* case WM_XBUTTONDOWN: */
82 /* case WM_XBUTTONUP: */
83 case WM_ACTIVATE:
84 case WM_CHAR:
85 case WM_DEADCHAR:
86 case WM_GETHOTKEY:
87 case WM_HOTKEY:
88 case WM_KEYDOWN:
89 case WM_KEYUP:
90 case WM_KILLFOCUS:
91 case WM_SETFOCUS:
92 case WM_SETHOTKEY:
93 case WM_SYSCHAR:
94 case WM_SYSDEADCHAR:
95 case WM_SYSKEYDOWN:
96 case WM_SYSKEYUP:
97
98 case WM_NCCALCSIZE:
99 return 0;
100
101 case WM_PAINT:
102
103 hdc = BeginPaint(hWnd, &ps);
104
105 WindowId = GetWindowLongPtrW(hWnd, GWLP_ID);
106
107 switch (WindowId)
108 {
111 break;
114 break;
117 break;
118 }
119
120 EndPaint(hWnd, &ps);
121
122 return 0;
123
124 }
125
126 /*
127 * We pass on all non-handled messages
128 */
130}
#define IDC_MEM_USAGE_HISTORY_GRAPH
Definition: resource.h:120
#define IDC_MEM_USAGE_GRAPH
Definition: resource.h:118
#define IDC_CPU_USAGE_GRAPH
Definition: resource.h:114
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define TRUE
Definition: types.h:120
void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
Definition: graph.c:303
void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
Definition: graph.c:410
void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
Definition: graph.c:132
WNDPROC OldGraphWndProc
Definition: graph.c:27
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:92
long LONG
Definition: pedump.c:60
#define WM_MOUSELEAVE
Definition: commctrl.h:4975
#define WM_MOUSEHOVER
Definition: commctrl.h:4974
Definition: tftpd.h:60
#define WM_PAINT
Definition: winuser.h:1610
#define WM_ERASEBKGND
Definition: winuser.h:1615
#define WM_GETHOTKEY
Definition: winuser.h:1643
#define GetWindowLongPtrW
Definition: winuser.h:4819
#define WM_KEYUP
Definition: winuser.h:1706
#define WM_SETHOTKEY
Definition: winuser.h:1642
#define WM_CAPTURECHANGED
Definition: winuser.h:1798
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1768
#define WM_NCHITTEST
Definition: winuser.h:1676
#define WM_RBUTTONUP
Definition: winuser.h:1770
#define WM_NCRBUTTONDBLCLK
Definition: winuser.h:1687
#define WM_RBUTTONDBLCLK
Definition: winuser.h:1771
#define WM_SETFOCUS
Definition: winuser.h:1603
#define WM_MOUSEMOVE
Definition: winuser.h:1765
#define WM_NCMBUTTONUP
Definition: winuser.h:1689
#define WM_LBUTTONDOWN
Definition: winuser.h:1766
#define WM_NCLBUTTONDBLCLK
Definition: winuser.h:1684
#define WM_ACTIVATE
Definition: winuser.h:1602
#define WM_RBUTTONDOWN
Definition: winuser.h:1769
#define WM_NCMOUSEMOVE
Definition: winuser.h:1681
#define WM_SYSCHAR
Definition: winuser.h:1711
#define WM_SYSDEADCHAR
Definition: winuser.h:1712
#define WM_NCMBUTTONDOWN
Definition: winuser.h:1688
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define WM_MBUTTONDBLCLK
Definition: winuser.h:1774
#define WM_SYSKEYUP
Definition: winuser.h:1710
#define WM_MOUSEACTIVATE
Definition: winuser.h:1627
#define WM_LBUTTONUP
Definition: winuser.h:1767
#define WM_CHAR
Definition: winuser.h:1707
#define WM_NCLBUTTONUP
Definition: winuser.h:1683
#define GWLP_ID
Definition: winuser.h:854
#define WM_HOTKEY
Definition: winuser.h:1869
#define WM_NCRBUTTONUP
Definition: winuser.h:1686
#define WM_KEYDOWN
Definition: winuser.h:1705
#define WM_NCMBUTTONDBLCLK
Definition: winuser.h:1690
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
LRESULT WINAPI CallWindowProcW(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_NCCALCSIZE
Definition: winuser.h:1675
#define WM_MBUTTONUP
Definition: winuser.h:1773
#define WM_DEADCHAR
Definition: winuser.h:1708
#define WM_KILLFOCUS
Definition: winuser.h:1604
#define WM_SYSKEYDOWN
Definition: winuser.h:1709
#define WM_NCLBUTTONDOWN
Definition: winuser.h:1682
#define WM_MBUTTONDOWN
Definition: winuser.h:1772
#define WM_NCRBUTTONDOWN
Definition: winuser.h:1685

Referenced by PerformancePageWndProc().

Variable Documentation

◆ nlastBarsUsed

int nlastBarsUsed = 0

Definition at line 25 of file graph.c.

Referenced by Graph_DrawCpuUsageGraph().

◆ OldGraphWndProc

WNDPROC OldGraphWndProc

Definition at line 27 of file graph.c.

Referenced by Graph_WndProc(), and PerformancePageWndProc().