BOOL CALLBACK ProcessViewerDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
int wmID, wmEvent, procCount;
PAINTSTRUCT ps;
HDC hdc;
switch(uMessage)
{
case WM_INITDIALOG:
{
SHINITDLGINFO shidi;
SHMENUBARINFO mbi;
memset(&shidi, 0, sizeof(shidi));
memset(&mbi, 0, sizeof(mbi));
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
mbi.cbSize = sizeof(mbi);
mbi.hwndParent = hDlg;
mbi.nToolBarId = IDR_MENU_PROCVIEWER;
mbi.hInstRes = g_hInst;
if(!SHCreateMenuBar(&mbi))
{
printf("ProcViewer: Error creating menu bar, errcode:0x%x\n", GetLastError());
}
else
{
g_hWndMenuBar = mbi.hwndMB;
}
AllignComponents(hDlg);
//initialise the list view control column headers
InitializeListViewControl(hDlg);
procCount = GetRunningProcesses();
RefreshProcessListView(hDlg, procCount);
}
return TRUE;
case WM_COMMAND:
{
wmID = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmID)
{
case IDM_EXIT:
EndDialog(hDlg, IDM_EXIT);
break;
case IDM_REFRESH:
UpdateProcessView(hDlg);
break;
}
}
break;
case WM_PAINT:
{
hdc = BeginPaint(hDlg, &ps);
//add drawing code here
EndPaint(hDlg, &ps);
}
break;
case WM_NOTIFY:
{
switch(((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED:
{
LPNMLISTVIEW lpnm = (LPNMLISTVIEW)lParam;
//get info about which item was selected.
int temp = lpnm->uNewState ^ lpnm->uOldState;
/*
when you select an item you get about 3 LVN_ITEMCHANGED notification.
So process only one of them, i.e when the item is selected and focused, both.
*/
if((temp & LVIS_SELECTED) && (temp & LVIS_FOCUSED))
{
if(lpnm->iItem < MAX_PROCESSES)
{
ShowProcInfo(hDlg, &ProcessList[lpnm->iItem]);
}
}
}
break;
}
}
break;
case WM_CLOSE:
{
EndDialog(hDlg, uMessage);
return TRUE;
}
}
return FALSE;
}
HINSTANCE g_hInst;
HWND g_hWndMenuBar;
PROCESSENTRY32 ProcessList[MAX_PROCESSES];
#define MAX_PROCESSES 32
//this function alligns the controls on the dialog, beautifies.
BOOL AllignComponents(HWND hWnd)
{
HWND hWndListView = NULL;
HWND hTemp;
RECT rectMainDlg, rect;
int x, y, width, height;
memset(&rectMainDlg, 0 , sizeof(RECT));
//get the client area of the main dialog
GetClientRect(hWnd, &rectMainDlg);
hWndListView = GetDlgItem(hWnd, IDC_LISTVIEW_PROCESSES);
if(!hWndListView)
{
printf("GetDlgItem failed errcode:%d line:%d\n", GetLastError(), __LINE__);
return FALSE;
}
//position List view wrt to main dialog
x = rectMainDlg.left + 1;
y = rectMainDlg.top + 1;
width = rectMainDlg.right – rectMainDlg.left – 2;
height = (rectMainDlg.bottom – rectMainDlg.top)/2;
if(!MoveWindow(hWndListView, x, y, width, height, FALSE))
{
printf("MoveWindow failed! errcode:%d line:%d\n", GetLastError(), __LINE__);
}
//position GROUPBOX wrt List view
hTemp = GetDlgItem(hWnd, IDC_STATIC_GROUPBOX);
if(!hTemp)
{
printf("GetDlgItem failed errcode:%d line:%d\n", GetLastError(), __LINE__);
return FALSE;
}
memset(&rect, 0, sizeof(RECT));
GetWindowRect(hWndListView, &rect);
x = rect.left;
y = rectMainDlg.top + (rect.bottom – rect.top) + 5;
width = rect.right – rect.left;
height = (rectMainDlg.bottom – rectMainDlg.top)/2 – 15;
if(!MoveWindow(hTemp, x, y, width, height, FALSE))
{
printf("MoveWindow failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
//beautify other labels
memset(&rect, 0, sizeof(RECT));
GetWindowRect(GetDlgItem(hWnd, IDC_STATIC_GROUPBOX), &rect);
x = rect.left + 8;
y = rect.top + 4;
width = rect.right – rect.left – 20;
height = 20;
//beautify Proc ID label wrt to group box
if(!MoveWindow(GetDlgItem(hWnd, IDC_STATIC_PROCID), x, y, width, height, FALSE))
{
printf("MoveWindow failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
//beautify No of Threads label wrt to PROC ID label
y = y + height + 4;
if(!MoveWindow(GetDlgItem(hWnd, IDC_STATIC_NTHREADS), x, y, width, height, FALSE))
{
printf("MoveWindow failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
//beautify Load Addr label wrt No Of Threads label
y = y + height + 4;
if(!MoveWindow(GetDlgItem(hWnd, IDC_STATIC_LOADADDR), x, y, width, height, FALSE))
{
printf("MoveWindow failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
return TRUE;
}
BOOL InitializeListViewControl(HWND hDlg)
{
HWND hWndListView = NULL;
LVCOLUMN lvc;
RECT rect;
//column headers
TCHAR *szColText[2] = { TEXT("S. No"), TEXT("Process Name") };
const int numCols = 2;
memset(&lvc, 0, sizeof(lvc));
hWndListView = GetDlgItem(hDlg, IDC_LISTVIEW_PROCESSES);
if(!hWndListView)
{
printf("+++ Failed to get list view handle! errcode:%d", GetLastError());
return FALSE;
}
//get the window rect of list view, we’ll use this to set column widths
GetWindowRect(hWndListView, &rect);
//set list view styles
SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_REPORT);
//SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);
SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_SINGLESEL);
SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
//add columns to list view
for(int i=0; i < numCols; i++)
{
lvc.iSubItem = i;
lvc.pszText = szColText[i];
//set 20% of width for S.No and 80% width for Process Name
if(i == 0)
{
lvc.cx = (rect.right – rect.left)/5;
}
else if(i == 1)
{
lvc.cx = ((rect.right – rect.left)*4)/5;
}
lvc.fmt = LVCFMT_LEFT;
if (ListView_InsertColumn(hWndListView, i, &lvc) == -1)
{
printf("+++ ListView_InsertColumn failed! errcode:%d\n", GetLastError());
return FALSE;
}
}
//InsertItems(hWndListView);
//ListView_SetItemState(hWndListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
return TRUE;
}
//this function fills the ProcessList array with all the current running processes
DWORD GetRunningProcesses()
{
int index = 0;
HANDLE hSnapShot;
PROCESSENTRY32 *pProcess = &ProcessList[0];
PROCESSENTRY32 prevProcess;
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPNOHEAPS, 0);
if(hSnapShot == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot failed errcode:%d line:%d\n", GetLastError(), __LINE__);
return FALSE;
}
memset(pProcess, 0, sizeof(PROCESSENTRY32));
pProcess->dwSize = sizeof(PROCESSENTRY32);
if(!Process32First(hSnapShot, pProcess))
{
printf("Process32First failed errcode:%d line:%d\n", GetLastError(), __LINE__);
return -1;
}
memcpy(&prevProcess, pProcess, sizeof(PROCESSENTRY32));
index = 1;
while(Process32Next(hSnapShot, &prevProcess))
{
if(++index >= MAX_PROCESSES)
break;
pProcess++;
memcpy(pProcess, &prevProcess, sizeof(PROCESSENTRY32));
}
CloseToolhelp32Snapshot(hSnapShot);
return index;
}
BOOL Process32Next(
HANDLE hSnapshot,
LPPROCESSENTRY32 *lppe);
hSnapshot: handle to the snapshot returned from a previous call to CreateToolhelp32Snapshot function.
lppe: Pointer to a PROCESSENTRY32 structure.
BOOL RefreshProcessListView(HWND hDlg, int procCount)
{
LVITEM lvi;
TCHAR szSNo[8] = TEXT("");
HWND hListView = GetDlgItem(hDlg, IDC_LISTVIEW_PROCESSES);
if(!hListView)
{
printf("GetDlgItem failed errcode:%d line:%d\n", GetLastError(), __LINE__);
return FALSE;
}
memset(&lvi, 0, sizeof(LVITEM));
//delete all items from list view
SendMessage(hListView, LVM_DELETEALLITEMS, 0, 0);
lvi.mask = LVIF_TEXT | LVIF_STATE;
lvi.state = 0;
lvi.stateMask = 0;
for(int i = 0; i < procCount; i++)
{
wsprintf(szSNo, L"%d", i+1);
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.pszText = szSNo;
if(ListView_InsertItem(hListView, &lvi) == -1)
{
printf("ListView_InsertItem failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
lvi.iItem = i;
lvi.iSubItem = 1;
lvi.pszText = ProcessList[i].szExeFile;
if(ListView_SetItem(hListView, &lvi) == -1)
{
printf("ListView_SetItem failed errcode:%d line:%d\n", GetLastError(), __LINE__);
}
}
//select the first item in the list (default)
ListView_SetItemState(hListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
ShowProcInfo(hDlg, &ProcessList[0]);
return TRUE;
}
ListView_SetItemState(hListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
//update the text control under group box
BOOL ShowProcInfo(HWND hDlg, PROCESSENTRY32 *pProcess)
{
TCHAR wszStr[64] = TEXT("");
HWND hTemp;
hTemp = GetDlgItem(hDlg, IDC_STATIC_PROCID);
if(hTemp)
{
//wsprintf(wszStr, L"Process Id: %x", pProcess->th32ProcessID);
wsprintf(wszStr, L"%-18s 0x%08x", L"Process Id:", pProcess->th32ProcessID);
SetWindowText(hTemp, wszStr);
}
hTemp = GetDlgItem(hDlg, IDC_STATIC_NTHREADS);
if(hTemp)
{
//wsprintf(wszStr, L"No of Threads: %d", pProcess->cntThreads);
wsprintf(wszStr, L"%-15s %d", L"No of Threads:", pProcess->cntThreads);
SetWindowText(hTemp, wszStr);
}
hTemp = GetDlgItem(hDlg, IDC_STATIC_LOADADDR);
if(hTemp)
{
//wsprintf(wszStr, L"Load Address: %x", pProcess->th32MemoryBase);
wsprintf(wszStr, L"%-15s 0x%08x", L"Load Address:", pProcess->th32MemoryBase);
SetWindowText(hTemp, wszStr);
}
return TRUE;
}
BOOL UpdateProcessView(HWND hDlg)
{
int procCount = 0;
procCount = GetRunningProcesses();
RefreshProcessListView(hDlg, procCount);
return TRUE;
}
case WM_NOTIFY:
{
switch(((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED:
{
LPNMLISTVIEW lpnm = (LPNMLISTVIEW)lParam;
//get info about which item was selected.
int temp = lpnm->uNewState ^ lpnm->uOldState;
/*
when you select an item you get about 3 LVN_ITEMCHANGED notification.
So process only one of them, i.e when the item is selected and focused, both.
*/
if((temp & LVIS_SELECTED) && (temp & LVIS_FOCUSED))
{
if(lpnm->iItem < MAX_PROCESSES)
{
ShowProcInfo(hDlg, &ProcessList[lpnm->iItem]);
}
}
}
break;
}
}
break;