[SERVMAN]
[reactos.git] / reactos / base / applications / mscutils / servman / mainwnd.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/mainwnd.c
5 * PURPOSE: Main window message handler
6 * COPYRIGHT: Copyright 2006-20015 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 #include <windowsx.h>
13
14 static const WCHAR szMainWndClass[] = L"ServManWndClass";
15
16 /* Toolbar buttons */
17 static const TBBUTTON Buttons [] =
18 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
19 {TBICON_PROP, ID_PROP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0}, /* properties */
20 {TBICON_REFRESH, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* refresh */
21 {TBICON_EXPORT, ID_EXPORT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* export */
22
23 /* Note: First item for a separator is its width in pixels */
24 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
25
26 {TBICON_CREATE, ID_CREATE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* create */
27 {TBICON_DELETE, ID_DELETE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* delete */
28
29 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
30
31 {TBICON_START, ID_START, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* start */
32 {TBICON_STOP, ID_STOP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* stop */
33 {TBICON_PAUSE, ID_PAUSE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* pause */
34 {TBICON_RESTART, ID_RESTART, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* restart */
35 };
36
37
38 /* menu hints */
39 static const MENU_HINT MainMenuHintTable[] = {
40 /* File Menu */
41 {ID_EXPORT, IDS_HINT_EXPORT},
42 {ID_EXIT, IDS_HINT_EXIT},
43
44 /* Action Menu */
45 {ID_CONNECT, IDS_HINT_CONNECT},
46 {ID_START, IDS_HINT_START},
47 {ID_STOP, IDS_HINT_STOP},
48 {ID_PAUSE, IDS_HINT_PAUSE},
49 {ID_RESUME, IDS_HINT_RESUME},
50 {ID_RESTART, IDS_HINT_RESTART},
51 {ID_REFRESH, IDS_HINT_REFRESH},
52 {ID_EDIT, IDS_HINT_EDIT},
53 {ID_CREATE, IDS_HINT_CREATE},
54 {ID_DELETE, IDS_HINT_DELETE},
55 {ID_PROP, IDS_HINT_PROP},
56
57 /* View menu */
58 {ID_VIEW_LARGE, IDS_HINT_LARGE},
59 {ID_VIEW_SMALL, IDS_HINT_SMALL},
60 {ID_VIEW_LIST, IDS_HINT_LIST},
61 {ID_VIEW_DETAILS, IDS_HINT_DETAILS},
62 {ID_VIEW_CUST, IDS_HINT_CUST},
63
64 /* Help Menu */
65 {ID_HELP, IDS_HINT_HELP},
66 {ID_ABOUT, IDS_HINT_ABOUT}
67 };
68 /* system menu hints */
69 static const MENU_HINT SystemMenuHintTable[] = {
70 {SC_RESTORE, IDS_HINT_SYS_RESTORE},
71 {SC_MOVE, IDS_HINT_SYS_MOVE},
72 {SC_SIZE, IDS_HINT_SYS_SIZE},
73 {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
74 {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
75 {SC_CLOSE, IDS_HINT_SYS_CLOSE},
76 };
77
78
79 static BOOL
80 MainWndMenuHint(PMAIN_WND_INFO Info,
81 WORD CmdId,
82 const MENU_HINT *HintArray,
83 DWORD HintsCount,
84 UINT DefHintId)
85 {
86 BOOL Found = FALSE;
87 const MENU_HINT *LastHint;
88 UINT HintId = DefHintId;
89
90 LastHint = HintArray + HintsCount;
91 while (HintArray != LastHint)
92 {
93 if (HintArray->CmdId == CmdId)
94 {
95 HintId = HintArray->HintId;
96 Found = TRUE;
97 break;
98 }
99 HintArray++;
100 }
101
102 StatusBarLoadString(Info->hStatus,
103 SB_SIMPLEID,
104 hInstance,
105 HintId);
106
107 return Found;
108 }
109
110
111 static VOID
112 UpdateMainStatusBar(PMAIN_WND_INFO Info)
113 {
114 if (Info->hStatus != NULL)
115 {
116 SendMessage(Info->hStatus,
117 SB_SIMPLE,
118 (WPARAM)Info->bInMenuLoop,
119 0);
120 }
121 }
122
123 VOID
124 UpdateServiceCount(PMAIN_WND_INFO Info)
125 {
126 LPWSTR lpNumServices;
127
128 if (AllocAndLoadString(&lpNumServices,
129 hInstance,
130 IDS_NUM_SERVICES))
131 {
132 WCHAR szNumServices[32];
133
134 INT NumListedServ = ListView_GetItemCount(Info->hListView);
135
136 _snwprintf(szNumServices,
137 31,
138 lpNumServices,
139 NumListedServ);
140
141 SendMessage(Info->hStatus,
142 SB_SETTEXT,
143 0,
144 (LPARAM)szNumServices);
145
146 LocalFree(lpNumServices);
147 }
148 }
149
150
151 VOID SetMenuAndButtonStates(PMAIN_WND_INFO Info)
152 {
153 HMENU hMainMenu;
154 UINT i;
155
156 /* get handle to menu */
157 hMainMenu = GetMenu(Info->hMainWnd);
158
159 /* set all to greyed */
160 for (i = ID_START; i <= ID_RESTART; i++)
161 {
162 EnableMenuItem(hMainMenu, i, MF_GRAYED);
163 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), i, MF_GRAYED);
164 SendMessage(Info->hTool, TB_SETSTATE, i,
165 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
166 }
167
168 if (Info->SelectedItem != NO_ITEM_SELECTED)
169 {
170 LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
171 DWORD Flags, State;
172
173 /* allow user to delete service */
174 if (Info->bIsUserAnAdmin)
175 {
176 SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
177 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
178 EnableMenuItem(hMainMenu, ID_DELETE, MF_ENABLED);
179 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_ENABLED);
180 }
181
182 Flags = Info->pCurrentService->ServiceStatusProcess.dwControlsAccepted;
183 State = Info->pCurrentService->ServiceStatusProcess.dwCurrentState;
184
185 lpServiceConfig = GetServiceConfig(Info->pCurrentService->lpServiceName);
186
187 if (lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED)
188 {
189 if (State == SERVICE_STOPPED)
190 {
191 EnableMenuItem(hMainMenu, ID_START, MF_ENABLED);
192 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_START, MF_ENABLED);
193 SendMessage(Info->hTool, TB_SETSTATE, ID_START,
194 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
195 }
196
197 if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
198 {
199 EnableMenuItem(hMainMenu, ID_RESTART, MF_ENABLED);
200 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_RESTART, MF_ENABLED);
201 SendMessage(Info->hTool, TB_SETSTATE, ID_RESTART,
202 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
203 }
204 }
205
206 if(lpServiceConfig)
207 HeapFree(GetProcessHeap(), 0, lpServiceConfig);
208
209 if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
210 {
211 EnableMenuItem(hMainMenu, ID_STOP, MF_ENABLED);
212 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_STOP, MF_ENABLED);
213 SendMessage(Info->hTool, TB_SETSTATE, ID_STOP,
214 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
215 }
216
217 if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) )
218 {
219 EnableMenuItem(hMainMenu, ID_PAUSE, MF_ENABLED);
220 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PAUSE, MF_ENABLED);
221 SendMessage(Info->hTool, TB_SETSTATE, ID_PAUSE,
222 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
223 }
224 }
225 else
226 {
227 /* disable tools which rely on a selected service */
228 EnableMenuItem(hMainMenu, ID_PROP, MF_GRAYED);
229 EnableMenuItem(hMainMenu, ID_DELETE, MF_GRAYED);
230 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PROP, MF_GRAYED);
231 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_GRAYED);
232 SendMessage(Info->hTool, TB_SETSTATE, ID_PROP,
233 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
234 SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
235 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
236 }
237
238 }
239
240
241 static INT CALLBACK
242 CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
243 {
244 PMAIN_WND_INFO Info = (PMAIN_WND_INFO)lParamSort;
245 WCHAR Item1[256], Item2[256];
246
247 ListView_GetItemText(Info->hListView, lParam1, Info->SortSelection, Item1, sizeof(Item1) / sizeof(WCHAR));
248 ListView_GetItemText(Info->hListView, lParam2, Info->SortSelection, Item2, sizeof(Item2) / sizeof(WCHAR));
249
250 return wcscmp(Item1, Item2) * Info->SortDirection;
251 }
252
253
254 static BOOL
255 pCreateToolbar(PMAIN_WND_INFO Info)
256 {
257 INT numButtons = sizeof(Buttons) / sizeof(Buttons[0]);
258
259 Info->hTool = CreateWindowEx(0,
260 TOOLBARCLASSNAME,
261 NULL,
262 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
263 0, 0, 0, 0,
264 Info->hMainWnd,
265 0,
266 hInstance,
267 NULL);
268 if(Info->hTool != NULL)
269 {
270 HIMAGELIST hImageList;
271
272 SendMessage(Info->hTool,
273 TB_SETEXTENDEDSTYLE,
274 0,
275 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
276
277 SendMessage(Info->hTool,
278 TB_BUTTONSTRUCTSIZE,
279 sizeof(Buttons[0]),
280 0);
281
282 hImageList = InitImageList(IDB_PROP,
283 IDB_RESTART,
284 GetSystemMetrics(SM_CXSMICON),
285 GetSystemMetrics(SM_CXSMICON),
286 IMAGE_BITMAP);
287 if (hImageList == NULL)
288 return FALSE;
289
290 ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool,
291 TB_SETIMAGELIST,
292 0,
293 (LPARAM)hImageList));
294
295 SendMessage(Info->hTool,
296 TB_ADDBUTTONS,
297 numButtons,
298 (LPARAM)Buttons);
299
300 return TRUE;
301 }
302
303 return FALSE;
304 }
305
306 static BOOL
307 CreateStatusBar(PMAIN_WND_INFO Info)
308 {
309 INT StatWidths[] = {110, -1}; /* widths of status bar */
310
311 Info->hStatus = CreateWindowEx(0,
312 STATUSCLASSNAME,
313 NULL,
314 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
315 0, 0, 0, 0,
316 Info->hMainWnd,
317 (HMENU)IDC_STATUSBAR,
318 hInstance,
319 NULL);
320 if(Info->hStatus == NULL)
321 return FALSE;
322
323 SendMessage(Info->hStatus,
324 SB_SETPARTS,
325 sizeof(StatWidths) / sizeof(INT),
326 (LPARAM)StatWidths);
327
328 return TRUE;
329 }
330
331
332 static BOOL
333 InitMainWnd(PMAIN_WND_INFO Info)
334 {
335 if (!pCreateToolbar(Info))
336 {
337 DisplayString(L"error creating toolbar");
338 return FALSE;
339 }
340
341 if (!CreateListView(Info))
342 {
343 DisplayString(L"error creating list view");
344 return FALSE;
345 }
346
347 if (!CreateStatusBar(Info))
348 DisplayString(L"error creating status bar");
349
350 /* Create Popup Menu */
351 Info->hShortcutMenu = LoadMenu(hInstance,
352 MAKEINTRESOURCE(IDR_POPUP));
353
354 Info->bIsUserAnAdmin = TRUE;// IsUserAnAdmin();
355 if (Info->bIsUserAnAdmin)
356 {
357 HMENU hMainMenu = GetMenu(Info->hMainWnd);
358
359 SendMessage(Info->hTool,
360 TB_SETSTATE,
361 ID_CREATE,
362 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
363 if (hMainMenu)
364 {
365 EnableMenuItem(hMainMenu,
366 ID_CREATE,
367 MF_ENABLED);
368 }
369 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0),
370 ID_CREATE,
371 MF_ENABLED);
372 }
373
374 return TRUE;
375 }
376
377
378 static VOID
379 MainWndCommand(PMAIN_WND_INFO Info,
380 WORD CmdId,
381 HWND hControl)
382 {
383 UNREFERENCED_PARAMETER(hControl);
384
385 switch (CmdId)
386 {
387 case ID_PROP:
388 {
389 if (Info->SelectedItem != NO_ITEM_SELECTED)
390 {
391 Info->bDlgOpen = TRUE;
392 OpenPropSheet(Info);
393 Info->bDlgOpen = FALSE;
394 SetMenuAndButtonStates(Info);
395 }
396 }
397 break;
398
399 case ID_REFRESH:
400 {
401 RefreshServiceList(Info);
402 Info->SelectedItem = NO_ITEM_SELECTED;
403
404 /* disable menus and buttons */
405 SetMenuAndButtonStates(Info);
406
407 /* clear the service in the status bar */
408 SendMessage(Info->hStatus,
409 SB_SETTEXT,
410 1,
411 L'\0');
412 }
413 break;
414
415 case ID_EXPORT:
416 {
417 ExportFile(Info);
418 SetFocus(Info->hListView);
419 }
420 break;
421
422 case ID_CREATE:
423 {
424 INT ret;
425
426 ret = DialogBoxParam(hInstance,
427 MAKEINTRESOURCE(IDD_DLG_CREATE),
428 Info->hMainWnd,
429 CreateDialogProc,
430 (LPARAM)Info);
431 if (ret == IDOK)
432 RefreshServiceList(Info);
433
434 SetFocus(Info->hListView);
435 }
436 break;
437
438 case ID_DELETE:
439 {
440 if (Info->pCurrentService->ServiceStatusProcess.dwCurrentState != SERVICE_RUNNING)
441 {
442 DialogBoxParam(hInstance,
443 MAKEINTRESOURCE(IDD_DLG_DELETE),
444 Info->hMainWnd,
445 DeleteDialogProc,
446 (LPARAM)Info);
447 }
448 else
449 {
450 WCHAR Buf[60];
451 LoadString(hInstance,
452 IDS_DELETE_STOP,
453 Buf,
454 sizeof(Buf) / sizeof(WCHAR));
455 DisplayString(Buf);
456 }
457
458 SetFocus(Info->hListView);
459
460 }
461 break;
462
463 case ID_START:
464 {
465 RunActionWithProgress(Info->hMainWnd,
466 Info->pCurrentService->lpServiceName,
467 Info->pCurrentService->lpDisplayName,
468 ACTION_START,
469 NULL); //FIXME: Add start params
470
471 UpdateServiceStatus(Info->pCurrentService);
472 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
473 SetMenuAndButtonStates(Info);
474 SetFocus(Info->hListView);
475
476 }
477 break;
478
479 case ID_STOP:
480 RunActionWithProgress(Info->hMainWnd,
481 Info->pCurrentService->lpServiceName,
482 Info->pCurrentService->lpDisplayName,
483 ACTION_STOP,
484 NULL);
485
486 UpdateServiceStatus(Info->pCurrentService);
487 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
488 SetMenuAndButtonStates(Info);
489 SetFocus(Info->hListView);
490
491 break;
492
493 case ID_PAUSE:
494 RunActionWithProgress(Info->hMainWnd,
495 Info->pCurrentService->lpServiceName,
496 Info->pCurrentService->lpDisplayName,
497 ACTION_PAUSE,
498 NULL);
499
500 UpdateServiceStatus(Info->pCurrentService);
501 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
502 SetMenuAndButtonStates(Info);
503 SetFocus(Info->hListView);
504 break;
505
506 case ID_RESUME:
507 RunActionWithProgress(Info->hMainWnd,
508 Info->pCurrentService->lpServiceName,
509 Info->pCurrentService->lpDisplayName,
510 ACTION_RESUME,
511 NULL);
512
513 UpdateServiceStatus(Info->pCurrentService);
514 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
515 SetMenuAndButtonStates(Info);
516 SetFocus(Info->hListView);
517 break;
518
519 case ID_RESTART:
520 RunActionWithProgress(Info->hMainWnd,
521 Info->pCurrentService->lpServiceName,
522 Info->pCurrentService->lpDisplayName,
523 ACTION_RESTART,
524 NULL);
525
526 UpdateServiceStatus(Info->pCurrentService);
527 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
528 SetMenuAndButtonStates(Info);
529 SetFocus(Info->hListView);
530 break;
531
532 case ID_HELP:
533 MessageBoxW(NULL,
534 L"Help is not yet implemented\n",
535 L"Note!",
536 MB_OK | MB_ICONINFORMATION);
537 SetFocus(Info->hListView);
538 break;
539
540 case ID_EXIT:
541 PostMessage(Info->hMainWnd,
542 WM_CLOSE,
543 0,
544 0);
545 break;
546
547 case ID_VIEW_LARGE:
548 SetListViewStyle(Info->hListView, LVS_ICON);
549 ListView_Arrange(Info->hListView, LVA_DEFAULT);
550
551 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
552 ID_VIEW_LARGE,
553 ID_VIEW_DETAILS,
554 ID_VIEW_LARGE,
555 MF_BYCOMMAND);
556 break;
557
558 case ID_VIEW_SMALL:
559 SetListViewStyle(Info->hListView, LVS_SMALLICON);
560 ListView_Arrange(Info->hListView, LVA_DEFAULT);
561
562 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
563 ID_VIEW_LARGE,
564 ID_VIEW_DETAILS,
565 ID_VIEW_SMALL,
566 MF_BYCOMMAND);
567 break;
568
569 case ID_VIEW_LIST:
570 SetListViewStyle(Info->hListView,
571 LVS_LIST);
572 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
573 ID_VIEW_LARGE,
574 ID_VIEW_DETAILS,
575 ID_VIEW_LIST,
576 MF_BYCOMMAND);
577 break;
578
579 case ID_VIEW_DETAILS:
580 SetListViewStyle(Info->hListView,
581 LVS_REPORT);
582 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
583 ID_VIEW_LARGE,
584 ID_VIEW_DETAILS,
585 ID_VIEW_DETAILS,
586 MF_BYCOMMAND);
587 break;
588
589 case ID_VIEW_CUST:
590 break;
591
592 case ID_ABOUT:
593 DialogBox(hInstance,
594 MAKEINTRESOURCE(IDD_ABOUTBOX),
595 Info->hMainWnd,
596 AboutDialogProc);
597 SetFocus(Info->hListView);
598 break;
599
600 }
601 }
602
603
604 static VOID CALLBACK
605 MainWndResize(PMAIN_WND_INFO Info,
606 WORD cx,
607 WORD cy)
608 {
609 RECT rcClient, rcTool, rcStatus;
610 int lvHeight, iToolHeight, iStatusHeight;
611
612 /* Size toolbar and get height */
613 SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
614 GetWindowRect(Info->hTool, &rcTool);
615 iToolHeight = rcTool.bottom - rcTool.top;
616
617 /* Size status bar and get height */
618 SendMessage(Info->hStatus, WM_SIZE, 0, 0);
619 GetWindowRect(Info->hStatus, &rcStatus);
620 iStatusHeight = rcStatus.bottom - rcStatus.top;
621
622 /* Calculate remaining height and size list view */
623 GetClientRect(Info->hMainWnd, &rcClient);
624 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
625 SetWindowPos(Info->hListView,
626 NULL,
627 0,
628 iToolHeight,
629 rcClient.right,
630 lvHeight,
631 SWP_NOZORDER);
632 }
633
634
635 static LRESULT CALLBACK
636 MainWndProc(HWND hwnd,
637 UINT msg,
638 WPARAM wParam,
639 LPARAM lParam)
640 {
641 PMAIN_WND_INFO Info;
642 LRESULT Ret = 0;
643
644 /* Get the window context */
645 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
646 GWLP_USERDATA);
647 if (Info == NULL && msg != WM_CREATE)
648 {
649 goto HandleDefaultMessage;
650 }
651
652 switch(msg)
653 {
654 case WM_CREATE:
655 {
656 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
657
658 /* Initialize the main window context */
659 Info->hMainWnd = hwnd;
660 Info->SelectedItem = NO_ITEM_SELECTED;
661
662 SetWindowLongPtr(hwnd,
663 GWLP_USERDATA,
664 (LONG_PTR)Info);
665
666 if (!InitMainWnd(Info))
667 return -1;
668
669 /* Fill the list-view before showing the main window */
670 RefreshServiceList(Info);
671
672 /* Show the window */
673 ShowWindow(hwnd,
674 Info->nCmdShow);
675
676 SetFocus(Info->hListView);
677 }
678 break;
679
680 case WM_SIZE:
681 {
682 MainWndResize(Info,
683 LOWORD(lParam),
684 HIWORD(lParam));
685 }
686 break;
687
688 case WM_NOTIFY:
689 {
690 LPNMHDR pnmhdr = (LPNMHDR)lParam;
691
692 switch (pnmhdr->code)
693 {
694 case NM_DBLCLK:
695 {
696 POINT pt;
697 RECT rect;
698
699 GetCursorPos(&pt);
700 GetWindowRect(Info->hListView, &rect);
701
702 if (PtInRect(&rect, pt))
703 {
704 SendMessage(hwnd,
705 WM_COMMAND,
706 //ID_PROP,
707 MAKEWPARAM((WORD)ID_PROP, (WORD)0),
708 0);
709 }
710
711 //OpenPropSheet(Info);
712 }
713 break;
714
715 case NM_RETURN:
716 {
717 SendMessage(hwnd,
718 WM_COMMAND,
719 //ID_PROP,
720 MAKEWPARAM((WORD)ID_PROP, (WORD)0),
721 0);
722 }
723 break;
724
725 case LVN_COLUMNCLICK:
726 {
727 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
728 HDITEM hdi;
729
730 /* get pending sort direction for clicked column */
731 hdi.mask = HDI_LPARAM;
732 (void)Header_GetItem(Info->hHeader, pnmv->iSubItem, &hdi);
733
734 /* get new sort parameters */
735 Info->SortSelection = pnmv->iSubItem;
736 Info->SortDirection = hdi.lParam;
737
738 /* set new sort direction and save */
739 hdi.lParam = (hdi.lParam == ORD_ASCENDING) ?
740 ORD_DESCENDING : ORD_ASCENDING;
741
742 (void)Header_SetItem(Info->hHeader, pnmv->iSubItem, &hdi);
743
744 (void)ListView_SortItemsEx(Info->hListView,
745 CompareFunc,
746 (LPARAM)Info);
747 }
748 break;
749 case LVN_ITEMCHANGED:
750 {
751 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
752
753 if (pnmv->uNewState != 0)
754 {
755 ListViewSelectionChanged(Info, pnmv);
756 SetMenuAndButtonStates(Info);
757 }
758 }
759 break;
760
761 case TTN_GETDISPINFO:
762 {
763 LPTOOLTIPTEXT lpttt;
764 UINT idButton;
765
766 lpttt = (LPTOOLTIPTEXT)lParam;
767
768 /* Specify the resource identifier of the descriptive
769 * text for the given button. */
770 idButton = (UINT)lpttt->hdr.idFrom;
771 switch (idButton)
772 {
773 case ID_PROP:
774 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
775 break;
776
777 case ID_REFRESH:
778 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
779 break;
780
781 case ID_EXPORT:
782 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT);
783 break;
784
785 case ID_CREATE:
786 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_CREATE);
787 break;
788
789 case ID_DELETE:
790 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_DELETE);
791 break;
792
793 case ID_START:
794 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_START);
795 break;
796
797 case ID_STOP:
798 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
799 break;
800
801 case ID_PAUSE:
802 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE);
803 break;
804
805 case ID_RESTART:
806 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_RESTART);
807 break;
808 }
809 }
810 break;
811 }
812 }
813 break;
814
815 case WM_CONTEXTMENU:
816 {
817 POINT pt;
818 RECT lvRect;
819
820 INT xPos = GET_X_LPARAM(lParam);
821 INT yPos = GET_Y_LPARAM(lParam);
822
823 GetCursorPos(&pt);
824
825 /* display popup when cursor is in the list view */
826 GetWindowRect(Info->hListView, &lvRect);
827 if (PtInRect(&lvRect, pt))
828 {
829 TrackPopupMenuEx(GetSubMenu(Info->hShortcutMenu, 0),
830 TPM_RIGHTBUTTON,
831 xPos,
832 yPos,
833 Info->hMainWnd,
834 NULL);
835 }
836 }
837 break;
838
839 case WM_COMMAND:
840 {
841 MainWndCommand(Info,
842 LOWORD(wParam),
843 (HWND)lParam);
844 goto HandleDefaultMessage;
845 }
846
847 case WM_MENUSELECT:
848 {
849 if (Info->hStatus != NULL)
850 {
851 if (!MainWndMenuHint(Info,
852 LOWORD(wParam),
853 MainMenuHintTable,
854 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
855 IDS_HINT_BLANK))
856 {
857 MainWndMenuHint(Info,
858 LOWORD(wParam),
859 SystemMenuHintTable,
860 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
861 IDS_HINT_BLANK);
862 }
863 }
864 }
865 break;
866
867 case WM_ENTERMENULOOP:
868 {
869 Info->bInMenuLoop = TRUE;
870 UpdateMainStatusBar(Info);
871 break;
872 }
873
874 case WM_EXITMENULOOP:
875 {
876 Info->bInMenuLoop = FALSE;
877 UpdateMainStatusBar(Info);
878 break;
879 }
880
881 case WM_CLOSE:
882 {
883 FreeServiceList(Info);
884 DestroyMenu(Info->hShortcutMenu);
885 DestroyWindow(hwnd);
886 }
887 break;
888
889 case WM_DESTROY:
890 {
891 HeapFree(ProcessHeap,
892 0,
893 Info);
894 SetWindowLongPtr(hwnd,
895 GWLP_USERDATA,
896 0);
897
898 PostQuitMessage(0);
899 }
900 break;
901
902 default:
903 {
904 HandleDefaultMessage:
905
906 Ret = DefWindowProc(hwnd,
907 msg,
908 wParam,
909 lParam);
910 }
911 break;
912 }
913
914 return Ret;
915 }
916
917
918
919 HWND
920 CreateMainWindow(LPCTSTR lpCaption,
921 int nCmdShow)
922 {
923 PMAIN_WND_INFO Info;
924 HWND hMainWnd = NULL;
925
926 Info = (MAIN_WND_INFO*) HeapAlloc(ProcessHeap,
927 HEAP_ZERO_MEMORY,
928 sizeof(MAIN_WND_INFO));
929
930 if (Info != NULL)
931 {
932 Info->nCmdShow = nCmdShow;
933
934 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
935 szMainWndClass,
936 lpCaption,
937 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
938 CW_USEDEFAULT,
939 CW_USEDEFAULT,
940 680,
941 450,
942 NULL,
943 NULL,
944 hInstance,
945 Info);
946 if (hMainWnd == NULL)
947 {
948 //int ret;
949 //ret = GetLastError();
950 GetError();
951 HeapFree(ProcessHeap,
952 0,
953 Info);
954 }
955 }
956
957 return hMainWnd;
958 }
959
960 BOOL
961 InitMainWindowImpl(VOID)
962 {
963 WNDCLASSEX wc = {0};
964
965 wc.cbSize = sizeof(WNDCLASSEX);
966 wc.lpfnWndProc = MainWndProc;
967 wc.hInstance = hInstance;
968 wc.hIcon = LoadIcon(hInstance,
969 MAKEINTRESOURCE(IDI_SM_ICON));
970 wc.hCursor = LoadCursor(NULL,
971 IDC_ARROW);
972 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
973 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
974 wc.lpszClassName = szMainWndClass;
975 wc.hIconSm = (HICON)LoadImage(hInstance,
976 MAKEINTRESOURCE(IDI_SM_ICON),
977 IMAGE_ICON,
978 16,
979 16,
980 LR_SHARED);
981
982 return RegisterClassEx(&wc) != (ATOM)0;
983 }
984
985
986 VOID
987 UninitMainWindowImpl(VOID)
988 {
989 UnregisterClass(szMainWndClass,
990 hInstance);
991 }