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