Merging r37048, r37051, r37052, r37055 from the-real-msvc branch
[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-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 16,
292 16);
293 if (hImageList == NULL)
294 return FALSE;
295
296 ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool,
297 TB_SETIMAGELIST,
298 0,
299 (LPARAM)hImageList));
300
301 SendMessage(Info->hTool,
302 TB_ADDBUTTONS,
303 numButtons,
304 (LPARAM)Buttons);
305
306 return TRUE;
307 }
308
309 return FALSE;
310 }
311
312 static BOOL
313 CreateStatusBar(PMAIN_WND_INFO Info)
314 {
315 INT StatWidths[] = {110, -1}; /* widths of status bar */
316
317 Info->hStatus = CreateWindowEx(0,
318 STATUSCLASSNAME,
319 NULL,
320 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
321 0, 0, 0, 0,
322 Info->hMainWnd,
323 (HMENU)IDC_STATUSBAR,
324 hInstance,
325 NULL);
326 if(Info->hStatus == NULL)
327 return FALSE;
328
329 SendMessage(Info->hStatus,
330 SB_SETPARTS,
331 sizeof(StatWidths) / sizeof(INT),
332 (LPARAM)StatWidths);
333
334 return TRUE;
335 }
336
337
338 static BOOL
339 InitMainWnd(PMAIN_WND_INFO Info)
340 {
341 if (!pCreateToolbar(Info))
342 {
343 DisplayString(_T("error creating toolbar"));
344 return FALSE;
345 }
346
347 if (!CreateListView(Info))
348 {
349 DisplayString(_T("error creating list view"));
350 return FALSE;
351 }
352
353 if (!CreateStatusBar(Info))
354 DisplayString(_T("error creating status bar"));
355
356 /* Create Popup Menu */
357 Info->hShortcutMenu = LoadMenu(hInstance,
358 MAKEINTRESOURCE(IDR_POPUP));
359
360 Info->bIsUserAnAdmin = IsUserAnAdmin();
361 if (Info->bIsUserAnAdmin)
362 {
363 HMENU hMainMenu = GetMenu(Info->hMainWnd);
364
365 SendMessage(Info->hTool,
366 TB_SETSTATE,
367 ID_CREATE,
368 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
369 if (hMainMenu)
370 {
371 EnableMenuItem(hMainMenu,
372 ID_CREATE,
373 MF_ENABLED);
374 }
375 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0),
376 ID_CREATE,
377 MF_ENABLED);
378 }
379
380 return TRUE;
381 }
382
383
384 static VOID
385 MainWndCommand(PMAIN_WND_INFO Info,
386 WORD CmdId,
387 HWND hControl)
388 {
389 UNREFERENCED_PARAMETER(hControl);
390
391 switch (CmdId)
392 {
393 case ID_PROP:
394 {
395 if (Info->SelectedItem != NO_ITEM_SELECTED)
396 {
397 Info->bDlgOpen = TRUE;
398 OpenPropSheet(Info);
399 Info->bDlgOpen = FALSE;
400 SetMenuAndButtonStates(Info);
401 }
402 }
403 break;
404
405 case ID_REFRESH:
406 {
407 RefreshServiceList(Info);
408 Info->SelectedItem = NO_ITEM_SELECTED;
409
410 /* disable menus and buttons */
411 SetMenuAndButtonStates(Info);
412
413 /* clear the service in the status bar */
414 SendMessage(Info->hStatus,
415 SB_SETTEXT,
416 1,
417 _T('\0'));
418 }
419 break;
420
421 case ID_EXPORT:
422 {
423 ExportFile(Info);
424 SetFocus(Info->hListView);
425 }
426 break;
427
428 case ID_CREATE:
429 {
430 INT ret;
431
432 ret = DialogBoxParam(hInstance,
433 MAKEINTRESOURCE(IDD_DLG_CREATE),
434 Info->hMainWnd,
435 (DLGPROC)CreateDialogProc,
436 (LPARAM)Info);
437 if (ret == IDOK)
438 RefreshServiceList(Info);
439
440 SetFocus(Info->hListView);
441 }
442 break;
443
444 case ID_DELETE:
445 {
446 if (Info->pCurrentService->ServiceStatusProcess.dwCurrentState != SERVICE_RUNNING)
447 {
448 DialogBoxParam(hInstance,
449 MAKEINTRESOURCE(IDD_DLG_DELETE),
450 Info->hMainWnd,
451 (DLGPROC)DeleteDialogProc,
452 (LPARAM)Info);
453 }
454 else
455 {
456 TCHAR Buf[60];
457 LoadString(hInstance,
458 IDS_DELETE_STOP,
459 Buf,
460 sizeof(Buf) / sizeof(TCHAR));
461 DisplayString(Buf);
462 }
463
464 SetFocus(Info->hListView);
465
466 }
467 break;
468
469 case ID_START:
470 {
471 if (DoStart(Info))
472 {
473 UpdateServiceStatus(Info->pCurrentService);
474 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
475 SetMenuAndButtonStates(Info);
476 SetFocus(Info->hListView);
477 }
478 }
479 break;
480
481 case ID_STOP:
482 if (DoStop(Info))
483 {
484 UpdateServiceStatus(Info->pCurrentService);
485 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
486 SetMenuAndButtonStates(Info);
487 SetFocus(Info->hListView);
488 }
489 break;
490
491 case ID_PAUSE:
492 DoPause(Info);
493 break;
494
495 case ID_RESUME:
496 DoResume(Info);
497 break;
498
499 case ID_RESTART:
500 if (DoStop(Info))
501 {
502 DoStart(Info);
503 UpdateServiceStatus(Info->pCurrentService);
504 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
505 SetMenuAndButtonStates(Info);
506 SetFocus(Info->hListView);
507 }
508 break;
509
510 case ID_HELP:
511 MessageBox(NULL,
512 _T("Help is not yet implemented\n"),
513 _T("Note!"),
514 MB_OK | MB_ICONINFORMATION);
515 SetFocus(Info->hListView);
516 break;
517
518 case ID_EXIT:
519 PostMessage(Info->hMainWnd,
520 WM_CLOSE,
521 0,
522 0);
523 break;
524
525 case ID_VIEW_LARGE:
526 SetListViewStyle(Info->hListView,
527 LVS_ICON);
528 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
529 ID_VIEW_LARGE,
530 ID_VIEW_DETAILS,
531 ID_VIEW_LARGE,
532 MF_BYCOMMAND);
533 break;
534
535 case ID_VIEW_SMALL:
536 SetListViewStyle(Info->hListView,
537 LVS_SMALLICON);
538 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
539 ID_VIEW_LARGE,
540 ID_VIEW_DETAILS,
541 ID_VIEW_SMALL,
542 MF_BYCOMMAND);
543 break;
544
545 case ID_VIEW_LIST:
546 SetListViewStyle(Info->hListView,
547 LVS_LIST);
548 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
549 ID_VIEW_LARGE,
550 ID_VIEW_DETAILS,
551 ID_VIEW_LIST,
552 MF_BYCOMMAND);
553 break;
554
555 case ID_VIEW_DETAILS:
556 SetListViewStyle(Info->hListView,
557 LVS_REPORT);
558 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
559 ID_VIEW_LARGE,
560 ID_VIEW_DETAILS,
561 ID_VIEW_DETAILS,
562 MF_BYCOMMAND);
563 break;
564
565 case ID_VIEW_CUST:
566 break;
567
568 case ID_ABOUT:
569 DialogBox(hInstance,
570 MAKEINTRESOURCE(IDD_ABOUTBOX),
571 Info->hMainWnd,
572 (DLGPROC)AboutDialogProc);
573 SetFocus(Info->hListView);
574 break;
575
576 }
577 }
578
579
580 static VOID CALLBACK
581 MainWndResize(PMAIN_WND_INFO Info,
582 WORD cx,
583 WORD cy)
584 {
585 RECT rcClient, rcTool, rcStatus;
586 int lvHeight, iToolHeight, iStatusHeight;
587
588 /* Size toolbar and get height */
589 SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
590 GetWindowRect(Info->hTool, &rcTool);
591 iToolHeight = rcTool.bottom - rcTool.top;
592
593 /* Size status bar and get height */
594 SendMessage(Info->hStatus, WM_SIZE, 0, 0);
595 GetWindowRect(Info->hStatus, &rcStatus);
596 iStatusHeight = rcStatus.bottom - rcStatus.top;
597
598 /* Calculate remaining height and size list view */
599 GetClientRect(Info->hMainWnd, &rcClient);
600 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
601 SetWindowPos(Info->hListView,
602 NULL,
603 0,
604 iToolHeight,
605 rcClient.right,
606 lvHeight,
607 SWP_NOZORDER);
608 }
609
610
611 static LRESULT CALLBACK
612 MainWndProc(HWND hwnd,
613 UINT msg,
614 WPARAM wParam,
615 LPARAM lParam)
616 {
617 PMAIN_WND_INFO Info;
618 LRESULT Ret = 0;
619
620 /* Get the window context */
621 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
622 GWLP_USERDATA);
623 if (Info == NULL && msg != WM_CREATE)
624 {
625 goto HandleDefaultMessage;
626 }
627
628 switch(msg)
629 {
630 case WM_CREATE:
631 {
632 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
633
634 /* Initialize the main window context */
635 Info->hMainWnd = hwnd;
636 Info->SelectedItem = NO_ITEM_SELECTED;
637
638 SetWindowLongPtr(hwnd,
639 GWLP_USERDATA,
640 (LONG_PTR)Info);
641
642 if (!InitMainWnd(Info))
643 return -1;
644
645 /* Show the window */
646 ShowWindow(hwnd,
647 Info->nCmdShow);
648
649 RefreshServiceList(Info);
650 }
651 break;
652
653 case WM_SIZE:
654 {
655 MainWndResize(Info,
656 LOWORD(lParam),
657 HIWORD(lParam));
658 }
659 break;
660
661 case WM_NOTIFY:
662 {
663 LPNMHDR pnmhdr = (LPNMHDR)lParam;
664
665 switch (pnmhdr->code)
666 {
667 case NM_DBLCLK:
668 {
669 POINT pt;
670 RECT rect;
671
672 GetCursorPos(&pt);
673 GetWindowRect(Info->hListView, &rect);
674
675 if (PtInRect(&rect, pt))
676 {
677 SendMessage(hwnd,
678 WM_COMMAND,
679 //ID_PROP,
680 MAKEWPARAM((WORD)ID_PROP, (WORD)0),
681 0);
682 }
683
684 //OpenPropSheet(Info);
685 }
686 break;
687
688 case LVN_COLUMNCLICK:
689 {
690 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
691
692 (void)ListView_SortItems(Info->hListView,
693 CompareFunc,
694 pnmv->iSubItem);
695 bSortAscending = !bSortAscending;
696 }
697 break;
698
699 case LVN_ITEMCHANGED:
700 {
701 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
702
703 if (pnmv->uNewState != 0)
704 {
705 ListViewSelectionChanged(Info, pnmv);
706 SetMenuAndButtonStates(Info);
707 }
708 }
709 break;
710
711 case TTN_GETDISPINFO:
712 {
713 LPTOOLTIPTEXT lpttt;
714 UINT idButton;
715
716 lpttt = (LPTOOLTIPTEXT)lParam;
717
718 /* Specify the resource identifier of the descriptive
719 * text for the given button. */
720 idButton = (UINT)lpttt->hdr.idFrom;
721 switch (idButton)
722 {
723 case ID_PROP:
724 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
725 break;
726
727 case ID_REFRESH:
728 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
729 break;
730
731 case ID_EXPORT:
732 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT);
733 break;
734
735 case ID_CREATE:
736 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_CREATE);
737 break;
738
739 case ID_DELETE:
740 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_DELETE);
741 break;
742
743 case ID_START:
744 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_START);
745 break;
746
747 case ID_STOP:
748 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
749 break;
750
751 case ID_PAUSE:
752 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE);
753 break;
754
755 case ID_RESTART:
756 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_RESTART);
757 break;
758 }
759 }
760 break;
761 }
762 }
763 break;
764
765 case WM_CONTEXTMENU:
766 {
767 POINT pt;
768 RECT lvRect;
769
770 INT xPos = GET_X_LPARAM(lParam);
771 INT yPos = GET_Y_LPARAM(lParam);
772
773 GetCursorPos(&pt);
774
775 /* display popup when cursor is in the list view */
776 GetWindowRect(Info->hListView, &lvRect);
777 if (PtInRect(&lvRect, pt))
778 {
779 TrackPopupMenuEx(GetSubMenu(Info->hShortcutMenu, 0),
780 TPM_RIGHTBUTTON,
781 xPos,
782 yPos,
783 Info->hMainWnd,
784 NULL);
785 }
786 }
787 break;
788
789 case WM_COMMAND:
790 {
791 MainWndCommand(Info,
792 LOWORD(wParam),
793 (HWND)lParam);
794 goto HandleDefaultMessage;
795 }
796
797 case WM_MENUSELECT:
798 {
799 if (Info->hStatus != NULL)
800 {
801 if (!MainWndMenuHint(Info,
802 LOWORD(wParam),
803 MainMenuHintTable,
804 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
805 IDS_HINT_BLANK))
806 {
807 MainWndMenuHint(Info,
808 LOWORD(wParam),
809 SystemMenuHintTable,
810 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
811 IDS_HINT_BLANK);
812 }
813 }
814 }
815 break;
816
817 case WM_ENTERMENULOOP:
818 {
819 Info->bInMenuLoop = TRUE;
820 UpdateMainStatusBar(Info);
821 break;
822 }
823
824 case WM_EXITMENULOOP:
825 {
826 Info->bInMenuLoop = FALSE;
827 UpdateMainStatusBar(Info);
828 break;
829 }
830
831 case WM_CLOSE:
832 {
833 HeapFree(ProcessHeap,
834 0,
835 Info->pAllServices);
836
837 DestroyMenu(Info->hShortcutMenu);
838 DestroyWindow(hwnd);
839 }
840 break;
841
842 case WM_DESTROY:
843 {
844 HeapFree(ProcessHeap,
845 0,
846 Info);
847 SetWindowLongPtr(hwnd,
848 GWLP_USERDATA,
849 0);
850
851 PostQuitMessage(0);
852 }
853 break;
854
855 default:
856 {
857 HandleDefaultMessage:
858
859 Ret = DefWindowProc(hwnd,
860 msg,
861 wParam,
862 lParam);
863 }
864 break;
865 }
866
867 return Ret;
868 }
869
870
871
872 HWND
873 CreateMainWindow(LPCTSTR lpCaption,
874 int nCmdShow)
875 {
876 PMAIN_WND_INFO Info;
877 HWND hMainWnd = NULL;
878
879 Info = (MAIN_WND_INFO*) HeapAlloc(ProcessHeap,
880 HEAP_ZERO_MEMORY,
881 sizeof(MAIN_WND_INFO));
882
883 if (Info != NULL)
884 {
885 Info->nCmdShow = nCmdShow;
886
887 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
888 szMainWndClass,
889 lpCaption,
890 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
891 CW_USEDEFAULT,
892 CW_USEDEFAULT,
893 650,
894 450,
895 NULL,
896 NULL,
897 hInstance,
898 Info);
899 if (hMainWnd == NULL)
900 {
901 int ret;
902 ret = GetLastError();
903 GetError();
904 HeapFree(ProcessHeap,
905 0,
906 Info);
907 }
908 }
909
910 return hMainWnd;
911 }
912
913 BOOL
914 InitMainWindowImpl(VOID)
915 {
916 WNDCLASSEX wc = {0};
917
918 wc.cbSize = sizeof(WNDCLASSEX);
919 wc.lpfnWndProc = MainWndProc;
920 wc.hInstance = hInstance;
921 wc.hIcon = LoadIcon(hInstance,
922 MAKEINTRESOURCE(IDI_SM_ICON));
923 wc.hCursor = LoadCursor(NULL,
924 IDC_ARROW);
925 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
926 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
927 wc.lpszClassName = szMainWndClass;
928 wc.hIconSm = (HICON)LoadImage(hInstance,
929 MAKEINTRESOURCE(IDI_SM_ICON),
930 IMAGE_ICON,
931 16,
932 16,
933 LR_SHARED);
934
935 return RegisterClassEx(&wc) != (ATOM)0;
936 }
937
938
939 VOID
940 UninitMainWindowImpl(VOID)
941 {
942 UnregisterClass(szMainWndClass,
943 hInstance);
944 }