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