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