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