mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 12:53:33 +00:00
997 lines
30 KiB
C
997 lines
30 KiB
C
/*
|
|
* PROJECT: ReactOS Services
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/applications/mscutils/servman/mainwnd.c
|
|
* PURPOSE: Main window message handler
|
|
* COPYRIGHT: Copyright 2006-2017 Ged Murphy <gedmurphy@reactos.org>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <windowsx.h>
|
|
#include <shellapi.h>
|
|
|
|
static const WCHAR szMainWndClass[] = L"ServManWndClass";
|
|
|
|
/* Toolbar buttons */
|
|
static const TBBUTTON Buttons [] =
|
|
{ /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
|
|
{TBICON_PROP, ID_PROP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0}, /* properties */
|
|
{TBICON_REFRESH, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* refresh */
|
|
{TBICON_EXPORT, ID_EXPORT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* export */
|
|
|
|
/* Note: First item for a separator is its width in pixels */
|
|
{15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
|
|
|
|
{TBICON_CREATE, ID_CREATE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* create */
|
|
{TBICON_DELETE, ID_DELETE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* delete */
|
|
|
|
{15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
|
|
|
|
{TBICON_START, ID_START, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* start */
|
|
{TBICON_STOP, ID_STOP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* stop */
|
|
{TBICON_PAUSE, ID_PAUSE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* pause */
|
|
{TBICON_RESTART, ID_RESTART, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* restart */
|
|
};
|
|
|
|
|
|
/* menu hints */
|
|
static const MENU_HINT MainMenuHintTable[] = {
|
|
/* File Menu */
|
|
{ID_EXPORT, IDS_HINT_EXPORT},
|
|
{ID_EXIT, IDS_HINT_EXIT},
|
|
|
|
/* Action Menu */
|
|
{ID_CONNECT, IDS_HINT_CONNECT},
|
|
{ID_START, IDS_HINT_START},
|
|
{ID_STOP, IDS_HINT_STOP},
|
|
{ID_PAUSE, IDS_HINT_PAUSE},
|
|
{ID_RESUME, IDS_HINT_RESUME},
|
|
{ID_RESTART, IDS_HINT_RESTART},
|
|
{ID_REFRESH, IDS_HINT_REFRESH},
|
|
{ID_EDIT, IDS_HINT_EDIT},
|
|
{ID_CREATE, IDS_HINT_CREATE},
|
|
{ID_DELETE, IDS_HINT_DELETE},
|
|
{ID_PROP, IDS_HINT_PROP},
|
|
|
|
/* View menu */
|
|
{ID_VIEW_LARGE, IDS_HINT_LARGE},
|
|
{ID_VIEW_SMALL, IDS_HINT_SMALL},
|
|
{ID_VIEW_LIST, IDS_HINT_LIST},
|
|
{ID_VIEW_DETAILS, IDS_HINT_DETAILS},
|
|
{ID_VIEW_CUST, IDS_HINT_CUST},
|
|
|
|
/* Help Menu */
|
|
{ID_HELP, IDS_HINT_HELP},
|
|
{ID_ABOUT, IDS_HINT_ABOUT}
|
|
};
|
|
/* system menu hints */
|
|
static const MENU_HINT SystemMenuHintTable[] = {
|
|
{SC_RESTORE, IDS_HINT_SYS_RESTORE},
|
|
{SC_MOVE, IDS_HINT_SYS_MOVE},
|
|
{SC_SIZE, IDS_HINT_SYS_SIZE},
|
|
{SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
|
|
{SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
|
|
{SC_CLOSE, IDS_HINT_SYS_CLOSE},
|
|
};
|
|
|
|
|
|
static BOOL
|
|
MainWndMenuHint(PMAIN_WND_INFO Info,
|
|
WORD CmdId,
|
|
const MENU_HINT *HintArray,
|
|
DWORD HintsCount,
|
|
UINT DefHintId)
|
|
{
|
|
BOOL Found = FALSE;
|
|
const MENU_HINT *LastHint;
|
|
UINT HintId = DefHintId;
|
|
|
|
LastHint = HintArray + HintsCount;
|
|
while (HintArray != LastHint)
|
|
{
|
|
if (HintArray->CmdId == CmdId)
|
|
{
|
|
HintId = HintArray->HintId;
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
HintArray++;
|
|
}
|
|
|
|
StatusBarLoadString(Info->hStatus,
|
|
SB_SIMPLEID,
|
|
hInstance,
|
|
HintId);
|
|
|
|
return Found;
|
|
}
|
|
|
|
|
|
static VOID
|
|
UpdateMainStatusBar(PMAIN_WND_INFO Info)
|
|
{
|
|
if (Info->hStatus != NULL)
|
|
{
|
|
SendMessage(Info->hStatus,
|
|
SB_SIMPLE,
|
|
(WPARAM)Info->bInMenuLoop,
|
|
0);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
UpdateServiceCount(PMAIN_WND_INFO Info)
|
|
{
|
|
LPWSTR lpNumServices;
|
|
|
|
if (AllocAndLoadString(&lpNumServices,
|
|
hInstance,
|
|
IDS_NUM_SERVICES))
|
|
{
|
|
WCHAR szNumServices[32];
|
|
|
|
INT NumListedServ = ListView_GetItemCount(Info->hListView);
|
|
|
|
_snwprintf(szNumServices,
|
|
31,
|
|
lpNumServices,
|
|
NumListedServ);
|
|
|
|
SendMessage(Info->hStatus,
|
|
SB_SETTEXT,
|
|
0,
|
|
(LPARAM)szNumServices);
|
|
|
|
LocalFree(lpNumServices);
|
|
}
|
|
}
|
|
|
|
|
|
VOID SetMenuAndButtonStates(PMAIN_WND_INFO Info)
|
|
{
|
|
HMENU hMainMenu;
|
|
UINT i;
|
|
|
|
/* get handle to menu */
|
|
hMainMenu = GetMenu(Info->hMainWnd);
|
|
|
|
/* set all to greyed */
|
|
for (i = ID_START; i <= ID_RESTART; i++)
|
|
{
|
|
EnableMenuItem(hMainMenu, i, MF_GRAYED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), i, MF_GRAYED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, i,
|
|
(LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
|
|
}
|
|
|
|
if (Info->SelectedItem != NO_ITEM_SELECTED)
|
|
{
|
|
LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
|
|
DWORD Flags, State;
|
|
|
|
/* allow user to delete service */
|
|
if (Info->bIsUserAnAdmin)
|
|
{
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
EnableMenuItem(hMainMenu, ID_DELETE, MF_ENABLED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_ENABLED);
|
|
}
|
|
|
|
Flags = Info->pCurrentService->ServiceStatusProcess.dwControlsAccepted;
|
|
State = Info->pCurrentService->ServiceStatusProcess.dwCurrentState;
|
|
|
|
lpServiceConfig = GetServiceConfig(Info->pCurrentService->lpServiceName);
|
|
|
|
if (lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED)
|
|
{
|
|
if (State == SERVICE_STOPPED)
|
|
{
|
|
EnableMenuItem(hMainMenu, ID_START, MF_ENABLED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_START, MF_ENABLED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_START,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
}
|
|
|
|
if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
|
|
{
|
|
EnableMenuItem(hMainMenu, ID_RESTART, MF_ENABLED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_RESTART, MF_ENABLED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_RESTART,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
}
|
|
}
|
|
|
|
if(lpServiceConfig)
|
|
HeapFree(GetProcessHeap(), 0, lpServiceConfig);
|
|
|
|
if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
|
|
{
|
|
EnableMenuItem(hMainMenu, ID_STOP, MF_ENABLED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_STOP, MF_ENABLED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_STOP,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
}
|
|
|
|
if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) )
|
|
{
|
|
EnableMenuItem(hMainMenu, ID_PAUSE, MF_ENABLED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PAUSE, MF_ENABLED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_PAUSE,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* disable tools which rely on a selected service */
|
|
EnableMenuItem(hMainMenu, ID_PROP, MF_GRAYED);
|
|
EnableMenuItem(hMainMenu, ID_DELETE, MF_GRAYED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PROP, MF_GRAYED);
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_GRAYED);
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_PROP,
|
|
(LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
|
|
SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
|
|
(LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static INT CALLBACK
|
|
CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
PMAIN_WND_INFO Info = (PMAIN_WND_INFO)lParamSort;
|
|
WCHAR Item1[256], Item2[256];
|
|
|
|
ListView_GetItemText(Info->hListView, lParam1, Info->SortSelection, Item1, sizeof(Item1) / sizeof(WCHAR));
|
|
ListView_GetItemText(Info->hListView, lParam2, Info->SortSelection, Item2, sizeof(Item2) / sizeof(WCHAR));
|
|
|
|
return wcscmp(Item1, Item2) * Info->SortDirection;
|
|
}
|
|
|
|
|
|
static BOOL
|
|
pCreateToolbar(PMAIN_WND_INFO Info)
|
|
{
|
|
INT numButtons = sizeof(Buttons) / sizeof(Buttons[0]);
|
|
|
|
Info->hTool = CreateWindowEx(0,
|
|
TOOLBARCLASSNAME,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
|
|
0, 0, 0, 0,
|
|
Info->hMainWnd,
|
|
0,
|
|
hInstance,
|
|
NULL);
|
|
if(Info->hTool != NULL)
|
|
{
|
|
HIMAGELIST hImageList;
|
|
|
|
SendMessage(Info->hTool,
|
|
TB_SETEXTENDEDSTYLE,
|
|
0,
|
|
TBSTYLE_EX_HIDECLIPPEDBUTTONS);
|
|
|
|
SendMessage(Info->hTool,
|
|
TB_BUTTONSTRUCTSIZE,
|
|
sizeof(Buttons[0]),
|
|
0);
|
|
|
|
hImageList = InitImageList(IDB_PROP,
|
|
IDB_RESTART,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
IMAGE_BITMAP);
|
|
if (hImageList == NULL)
|
|
return FALSE;
|
|
|
|
ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool,
|
|
TB_SETIMAGELIST,
|
|
0,
|
|
(LPARAM)hImageList));
|
|
|
|
SendMessage(Info->hTool,
|
|
TB_ADDBUTTONS,
|
|
numButtons,
|
|
(LPARAM)Buttons);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL
|
|
CreateStatusBar(PMAIN_WND_INFO Info)
|
|
{
|
|
INT StatWidths[] = {130, -1}; /* widths of status bar */
|
|
|
|
Info->hStatus = CreateWindowEx(0,
|
|
STATUSCLASSNAME,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
|
|
0, 0, 0, 0,
|
|
Info->hMainWnd,
|
|
(HMENU)IDC_STATUSBAR,
|
|
hInstance,
|
|
NULL);
|
|
if(Info->hStatus == NULL)
|
|
return FALSE;
|
|
|
|
SendMessage(Info->hStatus,
|
|
SB_SETPARTS,
|
|
sizeof(StatWidths) / sizeof(INT),
|
|
(LPARAM)StatWidths);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static BOOL
|
|
InitMainWnd(PMAIN_WND_INFO Info)
|
|
{
|
|
if (!pCreateToolbar(Info))
|
|
{
|
|
DisplayString(L"error creating toolbar");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateListView(Info))
|
|
{
|
|
DisplayString(L"error creating list view");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateStatusBar(Info))
|
|
DisplayString(L"error creating status bar");
|
|
|
|
/* Create Popup Menu */
|
|
Info->hShortcutMenu = LoadMenu(hInstance,
|
|
MAKEINTRESOURCE(IDR_POPUP));
|
|
|
|
Info->bIsUserAnAdmin = TRUE;// IsUserAnAdmin();
|
|
if (Info->bIsUserAnAdmin)
|
|
{
|
|
HMENU hMainMenu = GetMenu(Info->hMainWnd);
|
|
|
|
SendMessage(Info->hTool,
|
|
TB_SETSTATE,
|
|
ID_CREATE,
|
|
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
|
|
if (hMainMenu)
|
|
{
|
|
EnableMenuItem(hMainMenu,
|
|
ID_CREATE,
|
|
MF_ENABLED);
|
|
}
|
|
EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0),
|
|
ID_CREATE,
|
|
MF_ENABLED);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static VOID
|
|
MainWndCommand(PMAIN_WND_INFO Info,
|
|
WORD CmdId,
|
|
HWND hControl)
|
|
{
|
|
WCHAR szAppName[256];
|
|
WCHAR szAppAuthors[256];
|
|
HICON hIcon;
|
|
|
|
UNREFERENCED_PARAMETER(hControl);
|
|
|
|
switch (CmdId)
|
|
{
|
|
case ID_PROP:
|
|
{
|
|
if (Info->SelectedItem != NO_ITEM_SELECTED)
|
|
{
|
|
Info->bDlgOpen = TRUE;
|
|
OpenPropSheet(Info);
|
|
Info->bDlgOpen = FALSE;
|
|
SetMenuAndButtonStates(Info);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_REFRESH:
|
|
{
|
|
RefreshServiceList(Info);
|
|
Info->SelectedItem = NO_ITEM_SELECTED;
|
|
|
|
/* disable menus and buttons */
|
|
SetMenuAndButtonStates(Info);
|
|
|
|
/* clear the service in the status bar */
|
|
SendMessage(Info->hStatus,
|
|
SB_SETTEXT,
|
|
1,
|
|
L'\0');
|
|
}
|
|
break;
|
|
|
|
case ID_EXPORT:
|
|
{
|
|
ExportFile(Info);
|
|
SetFocus(Info->hListView);
|
|
}
|
|
break;
|
|
|
|
case ID_CREATE:
|
|
{
|
|
INT ret;
|
|
|
|
ret = DialogBoxParam(hInstance,
|
|
MAKEINTRESOURCE(IDD_DLG_CREATE),
|
|
Info->hMainWnd,
|
|
CreateDialogProc,
|
|
(LPARAM)Info);
|
|
if (ret == IDOK)
|
|
RefreshServiceList(Info);
|
|
|
|
SetFocus(Info->hListView);
|
|
}
|
|
break;
|
|
|
|
case ID_DELETE:
|
|
{
|
|
if (Info->pCurrentService->ServiceStatusProcess.dwCurrentState != SERVICE_RUNNING)
|
|
{
|
|
DialogBoxParam(hInstance,
|
|
MAKEINTRESOURCE(IDD_DLG_DELETE),
|
|
Info->hMainWnd,
|
|
DeleteDialogProc,
|
|
(LPARAM)Info);
|
|
}
|
|
else
|
|
{
|
|
WCHAR Buf[60];
|
|
LoadString(hInstance,
|
|
IDS_DELETE_STOP,
|
|
Buf,
|
|
sizeof(Buf) / sizeof(WCHAR));
|
|
DisplayString(Buf);
|
|
}
|
|
|
|
SetFocus(Info->hListView);
|
|
|
|
}
|
|
break;
|
|
|
|
case ID_START:
|
|
{
|
|
RunActionWithProgress(Info->hMainWnd,
|
|
Info->pCurrentService->lpServiceName,
|
|
Info->pCurrentService->lpDisplayName,
|
|
ACTION_START,
|
|
NULL); //FIXME: Add start params
|
|
|
|
UpdateServiceStatus(Info->pCurrentService);
|
|
ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
|
|
SetMenuAndButtonStates(Info);
|
|
SetFocus(Info->hListView);
|
|
|
|
}
|
|
break;
|
|
|
|
case ID_STOP:
|
|
RunActionWithProgress(Info->hMainWnd,
|
|
Info->pCurrentService->lpServiceName,
|
|
Info->pCurrentService->lpDisplayName,
|
|
ACTION_STOP,
|
|
NULL);
|
|
|
|
UpdateServiceStatus(Info->pCurrentService);
|
|
ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
|
|
SetMenuAndButtonStates(Info);
|
|
SetFocus(Info->hListView);
|
|
|
|
break;
|
|
|
|
case ID_PAUSE:
|
|
RunActionWithProgress(Info->hMainWnd,
|
|
Info->pCurrentService->lpServiceName,
|
|
Info->pCurrentService->lpDisplayName,
|
|
ACTION_PAUSE,
|
|
NULL);
|
|
|
|
UpdateServiceStatus(Info->pCurrentService);
|
|
ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
|
|
SetMenuAndButtonStates(Info);
|
|
SetFocus(Info->hListView);
|
|
break;
|
|
|
|
case ID_RESUME:
|
|
RunActionWithProgress(Info->hMainWnd,
|
|
Info->pCurrentService->lpServiceName,
|
|
Info->pCurrentService->lpDisplayName,
|
|
ACTION_RESUME,
|
|
NULL);
|
|
|
|
UpdateServiceStatus(Info->pCurrentService);
|
|
ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
|
|
SetMenuAndButtonStates(Info);
|
|
SetFocus(Info->hListView);
|
|
break;
|
|
|
|
case ID_RESTART:
|
|
RunActionWithProgress(Info->hMainWnd,
|
|
Info->pCurrentService->lpServiceName,
|
|
Info->pCurrentService->lpDisplayName,
|
|
ACTION_RESTART,
|
|
NULL);
|
|
|
|
UpdateServiceStatus(Info->pCurrentService);
|
|
ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
|
|
SetMenuAndButtonStates(Info);
|
|
SetFocus(Info->hListView);
|
|
break;
|
|
|
|
case ID_HELP:
|
|
MessageBoxW(NULL,
|
|
L"Help is not yet implemented\n",
|
|
L"Note!",
|
|
MB_OK | MB_ICONINFORMATION);
|
|
SetFocus(Info->hListView);
|
|
break;
|
|
|
|
case ID_EXIT:
|
|
PostMessage(Info->hMainWnd,
|
|
WM_CLOSE,
|
|
0,
|
|
0);
|
|
break;
|
|
|
|
case ID_VIEW_LARGE:
|
|
SetListViewStyle(Info->hListView, LVS_ICON);
|
|
ListView_Arrange(Info->hListView, LVA_DEFAULT);
|
|
|
|
CheckMenuRadioItem(GetMenu(Info->hMainWnd),
|
|
ID_VIEW_LARGE,
|
|
ID_VIEW_DETAILS,
|
|
ID_VIEW_LARGE,
|
|
MF_BYCOMMAND);
|
|
break;
|
|
|
|
case ID_VIEW_SMALL:
|
|
SetListViewStyle(Info->hListView, LVS_SMALLICON);
|
|
ListView_Arrange(Info->hListView, LVA_DEFAULT);
|
|
|
|
CheckMenuRadioItem(GetMenu(Info->hMainWnd),
|
|
ID_VIEW_LARGE,
|
|
ID_VIEW_DETAILS,
|
|
ID_VIEW_SMALL,
|
|
MF_BYCOMMAND);
|
|
break;
|
|
|
|
case ID_VIEW_LIST:
|
|
SetListViewStyle(Info->hListView,
|
|
LVS_LIST);
|
|
CheckMenuRadioItem(GetMenu(Info->hMainWnd),
|
|
ID_VIEW_LARGE,
|
|
ID_VIEW_DETAILS,
|
|
ID_VIEW_LIST,
|
|
MF_BYCOMMAND);
|
|
break;
|
|
|
|
case ID_VIEW_DETAILS:
|
|
SetListViewStyle(Info->hListView,
|
|
LVS_REPORT);
|
|
CheckMenuRadioItem(GetMenu(Info->hMainWnd),
|
|
ID_VIEW_LARGE,
|
|
ID_VIEW_DETAILS,
|
|
ID_VIEW_DETAILS,
|
|
MF_BYCOMMAND);
|
|
break;
|
|
|
|
case ID_VIEW_CUST:
|
|
break;
|
|
|
|
case ID_ABOUT:
|
|
LoadStringW(hInstance, IDS_APPNAME, szAppName, _countof(szAppName));
|
|
LoadStringW(hInstance, IDS_APPAUTHORS, szAppAuthors, _countof(szAppAuthors));
|
|
|
|
hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_SM_ICON));
|
|
ShellAboutW(Info->hMainWnd, szAppName, szAppAuthors, hIcon);
|
|
DestroyIcon(hIcon);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static VOID CALLBACK
|
|
MainWndResize(PMAIN_WND_INFO Info,
|
|
WORD cx,
|
|
WORD cy)
|
|
{
|
|
RECT rcClient, rcTool, rcStatus;
|
|
int lvHeight, iToolHeight, iStatusHeight;
|
|
|
|
/* Size toolbar and get height */
|
|
SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
|
|
GetWindowRect(Info->hTool, &rcTool);
|
|
iToolHeight = rcTool.bottom - rcTool.top;
|
|
|
|
/* Size status bar and get height */
|
|
SendMessage(Info->hStatus, WM_SIZE, 0, 0);
|
|
GetWindowRect(Info->hStatus, &rcStatus);
|
|
iStatusHeight = rcStatus.bottom - rcStatus.top;
|
|
|
|
/* Calculate remaining height and size list view */
|
|
GetClientRect(Info->hMainWnd, &rcClient);
|
|
lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
|
|
SetWindowPos(Info->hListView,
|
|
NULL,
|
|
0,
|
|
iToolHeight,
|
|
rcClient.right,
|
|
lvHeight,
|
|
SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
MainWndProc(HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PMAIN_WND_INFO Info;
|
|
LRESULT Ret = 0;
|
|
|
|
/* Get the window context */
|
|
Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
|
|
GWLP_USERDATA);
|
|
if (Info == NULL && msg != WM_CREATE)
|
|
{
|
|
goto HandleDefaultMessage;
|
|
}
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
|
|
|
|
/* Initialize the main window context */
|
|
Info->hMainWnd = hwnd;
|
|
Info->SelectedItem = NO_ITEM_SELECTED;
|
|
|
|
SetWindowLongPtr(hwnd,
|
|
GWLP_USERDATA,
|
|
(LONG_PTR)Info);
|
|
|
|
if (!InitMainWnd(Info))
|
|
return -1;
|
|
|
|
/* Fill the list-view before showing the main window */
|
|
RefreshServiceList(Info);
|
|
|
|
/* Show the window */
|
|
ShowWindow(hwnd,
|
|
Info->nCmdShow);
|
|
|
|
SetFocus(Info->hListView);
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
MainWndResize(Info,
|
|
LOWORD(lParam),
|
|
HIWORD(lParam));
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR pnmhdr = (LPNMHDR)lParam;
|
|
|
|
switch (pnmhdr->code)
|
|
{
|
|
case NM_DBLCLK:
|
|
{
|
|
POINT pt;
|
|
RECT rect;
|
|
|
|
GetCursorPos(&pt);
|
|
GetWindowRect(Info->hListView, &rect);
|
|
|
|
if (PtInRect(&rect, pt))
|
|
{
|
|
SendMessage(hwnd,
|
|
WM_COMMAND,
|
|
//ID_PROP,
|
|
MAKEWPARAM((WORD)ID_PROP, (WORD)0),
|
|
0);
|
|
}
|
|
|
|
//OpenPropSheet(Info);
|
|
}
|
|
break;
|
|
|
|
case NM_RETURN:
|
|
{
|
|
SendMessage(hwnd,
|
|
WM_COMMAND,
|
|
//ID_PROP,
|
|
MAKEWPARAM((WORD)ID_PROP, (WORD)0),
|
|
0);
|
|
}
|
|
break;
|
|
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
|
|
HDITEM hdi;
|
|
|
|
/* get pending sort direction for clicked column */
|
|
hdi.mask = HDI_LPARAM;
|
|
(void)Header_GetItem(Info->hHeader, pnmv->iSubItem, &hdi);
|
|
|
|
/* get new sort parameters */
|
|
Info->SortSelection = pnmv->iSubItem;
|
|
Info->SortDirection = hdi.lParam;
|
|
|
|
/* set new sort direction and save */
|
|
hdi.lParam = (hdi.lParam == ORD_ASCENDING) ?
|
|
ORD_DESCENDING : ORD_ASCENDING;
|
|
|
|
(void)Header_SetItem(Info->hHeader, pnmv->iSubItem, &hdi);
|
|
|
|
(void)ListView_SortItemsEx(Info->hListView,
|
|
CompareFunc,
|
|
(LPARAM)Info);
|
|
}
|
|
break;
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
|
|
|
|
if (pnmv->uNewState != 0)
|
|
{
|
|
ListViewSelectionChanged(Info, pnmv);
|
|
SetMenuAndButtonStates(Info);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TTN_GETDISPINFO:
|
|
{
|
|
LPTOOLTIPTEXT lpttt;
|
|
UINT idButton;
|
|
|
|
lpttt = (LPTOOLTIPTEXT)lParam;
|
|
|
|
/* Specify the resource identifier of the descriptive
|
|
* text for the given button. */
|
|
idButton = (UINT)lpttt->hdr.idFrom;
|
|
switch (idButton)
|
|
{
|
|
case ID_PROP:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
|
|
break;
|
|
|
|
case ID_REFRESH:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
|
|
break;
|
|
|
|
case ID_EXPORT:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT);
|
|
break;
|
|
|
|
case ID_CREATE:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_CREATE);
|
|
break;
|
|
|
|
case ID_DELETE:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_DELETE);
|
|
break;
|
|
|
|
case ID_START:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_START);
|
|
break;
|
|
|
|
case ID_STOP:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
|
|
break;
|
|
|
|
case ID_PAUSE:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE);
|
|
break;
|
|
|
|
case ID_RESTART:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_RESTART);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
POINT pt;
|
|
RECT lvRect;
|
|
|
|
INT xPos = GET_X_LPARAM(lParam);
|
|
INT yPos = GET_Y_LPARAM(lParam);
|
|
|
|
GetCursorPos(&pt);
|
|
|
|
/* display popup when cursor is in the list view */
|
|
GetWindowRect(Info->hListView, &lvRect);
|
|
if (PtInRect(&lvRect, pt))
|
|
{
|
|
TrackPopupMenuEx(GetSubMenu(Info->hShortcutMenu, 0),
|
|
TPM_RIGHTBUTTON,
|
|
xPos,
|
|
yPos,
|
|
Info->hMainWnd,
|
|
NULL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
MainWndCommand(Info,
|
|
LOWORD(wParam),
|
|
(HWND)lParam);
|
|
goto HandleDefaultMessage;
|
|
}
|
|
|
|
case WM_MENUSELECT:
|
|
{
|
|
if (Info->hStatus != NULL)
|
|
{
|
|
if (!MainWndMenuHint(Info,
|
|
LOWORD(wParam),
|
|
MainMenuHintTable,
|
|
sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
|
|
IDS_HINT_BLANK))
|
|
{
|
|
MainWndMenuHint(Info,
|
|
LOWORD(wParam),
|
|
SystemMenuHintTable,
|
|
sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
|
|
IDS_HINT_BLANK);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_ENTERMENULOOP:
|
|
{
|
|
Info->bInMenuLoop = TRUE;
|
|
UpdateMainStatusBar(Info);
|
|
break;
|
|
}
|
|
|
|
case WM_EXITMENULOOP:
|
|
{
|
|
Info->bInMenuLoop = FALSE;
|
|
UpdateMainStatusBar(Info);
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
FreeServiceList(Info);
|
|
DestroyMenu(Info->hShortcutMenu);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
HeapFree(ProcessHeap,
|
|
0,
|
|
Info);
|
|
SetWindowLongPtr(hwnd,
|
|
GWLP_USERDATA,
|
|
0);
|
|
|
|
PostQuitMessage(0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
HandleDefaultMessage:
|
|
|
|
Ret = DefWindowProc(hwnd,
|
|
msg,
|
|
wParam,
|
|
lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
HWND
|
|
CreateMainWindow(LPCTSTR lpCaption,
|
|
int nCmdShow)
|
|
{
|
|
PMAIN_WND_INFO Info;
|
|
HWND hMainWnd = NULL;
|
|
|
|
Info = (MAIN_WND_INFO*) HeapAlloc(ProcessHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(MAIN_WND_INFO));
|
|
|
|
if (Info != NULL)
|
|
{
|
|
Info->nCmdShow = nCmdShow;
|
|
|
|
hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
|
|
szMainWndClass,
|
|
lpCaption,
|
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
680,
|
|
450,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
Info);
|
|
if (hMainWnd == NULL)
|
|
{
|
|
//int ret;
|
|
//ret = GetLastError();
|
|
GetError();
|
|
HeapFree(ProcessHeap,
|
|
0,
|
|
Info);
|
|
}
|
|
}
|
|
|
|
return hMainWnd;
|
|
}
|
|
|
|
BOOL
|
|
InitMainWindowImpl(VOID)
|
|
{
|
|
WNDCLASSEX wc = {0};
|
|
|
|
wc.cbSize = sizeof(WNDCLASSEX);
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(hInstance,
|
|
MAKEINTRESOURCE(IDI_SM_ICON));
|
|
wc.hCursor = LoadCursor(NULL,
|
|
IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
|
|
wc.lpszClassName = szMainWndClass;
|
|
wc.hIconSm = (HICON)LoadImage(hInstance,
|
|
MAKEINTRESOURCE(IDI_SM_ICON),
|
|
IMAGE_ICON,
|
|
16,
|
|
16,
|
|
LR_SHARED);
|
|
|
|
return RegisterClassEx(&wc) != (ATOM)0;
|
|
}
|
|
|
|
|
|
VOID
|
|
UninitMainWindowImpl(VOID)
|
|
{
|
|
UnregisterClass(szMainWndClass,
|
|
hInstance);
|
|
}
|