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