size_t VMenu2::SetUserData(LPCVOID Data, size_t Size, intptr_t Position) { if(Position<0) Position=GetSelectPos(); FarListItemData flid={sizeof(FarListItemData), Position, Size, const_cast<void*>(Data)}; return SendMessage(DM_LISTSETDATA, 0, &flid); }
LISTITEMFLAGS VMenu2::GetItemFlags(int Position) { if(Position<0) Position=GetSelectPos(); FarListGetItem flgi={sizeof(FarListGetItem), Position}; SendMessage(DM_LISTGETITEM, 0, &flgi); return flgi.Item.Flags; }
void VMenu2::UpdateItemFlags(int Pos, UINT64 NewFlags) { if(Pos<0) Pos=GetSelectPos(); FarListGetItem flgi={sizeof(FarListGetItem), Pos}; SendMessage(DM_LISTGETITEM, 0, &flgi); flgi.Item.Flags=NewFlags; FarListUpdate flu={sizeof(FarListUpdate), Pos, flgi.Item}; SendMessage(DM_LISTUPDATE, 0, &flu); }
void *VMenu2::GetUserData(void *Data, size_t Size, intptr_t Position) { if(Position<0) Position=GetSelectPos(); void *d=(void*)SendMessage(DM_LISTGETDATA, 0, (void*)Position); size_t s=SendMessage(DM_LISTGETDATASIZE, 0, (void*)Position); if (d && Size && Data && Size>=s) memcpy(Data, d, s); return d; }
intptr_t VMenu2::GetExitCode() { if(cancel || Dialog::GetExitCode()<0) return -1; return GetSelectPos(); }
intptr_t VMenu2::VMenu2DlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) { _DIALOG(CleverSysLog CL(L"VMenu2::VMenu2DlgProc()")); _DIALOG(SysLog(L"hDlg=%p, Msg=%s, Param1=%d (0x%08X), Param2=%d (0x%08X)",Dlg,_DLGMSG_ToName(Msg),Param1,Param1,Param2,Param2)); switch(Msg) { case DN_CTLCOLORDIALOG: { FarColor *color=(FarColor*)Param2; *color=colors::PaletteColorToFarColor(COL_MENUBOX); return true; } case DN_CTLCOLORDLGLIST: { FarDialogItemColors *colors=(FarDialogItemColors*)Param2; PaletteColors MenuColors[]= { COL_MENUBOX, // подложка COL_MENUBOX, // рамка COL_MENUTITLE, // заголовок - верхний и нижний COL_MENUTEXT, // Текст пункта COL_MENUHIGHLIGHT, // HotKey COL_MENUBOX, // separator COL_MENUSELECTEDTEXT, // Выбранный COL_MENUSELECTEDHIGHLIGHT, // Выбранный - HotKey COL_MENUSCROLLBAR, // ScrollBar COL_MENUDISABLEDTEXT, // Disabled COL_MENUARROWS, // Arrow COL_MENUARROWSSELECTED, // Выбранный - Arrow COL_MENUARROWSDISABLED, // Arrow Disabled COL_MENUGRAYTEXT, // "серый" COL_MENUSELECTEDGRAYTEXT, // выбранный "серый" }; for(size_t i=0; i<colors->ColorsCount && i<ARRAYSIZE(MenuColors); ++i) colors->Colors[i]=colors::PaletteColorToFarColor(MenuColors[i]); return true; } case DN_CLOSE: if(!ForceClosing && !Param1 && GetItemFlags() & (LIF_GRAYED|LIF_DISABLE)) return false; if(Call(Msg, (void*)(Param1<0 ? Param1 : GetSelectPos()))) return false; break; case DN_LISTHOTKEY: if (!Call(Msg, Param2)) Dlg->SendMessage( DM_CLOSE, -1, nullptr); break; case DN_DRAWDLGITEMDONE: //??? case DN_DRAWDIALOGDONE: if(DefRec.EventType) { INPUT_RECORD rec=DefRec; ClearStruct(DefRec); if(!Call(DN_INPUT, &rec)) Dlg->SendMessage( DM_KEY, 1, &rec); } break; case DN_CONTROLINPUT: case DN_INPUT: if(!cancel) { if (Msg==DN_CONTROLINPUT) { auto ir = static_cast<INPUT_RECORD*>(Param2); int key=InputRecordToKey(ir); if(ListBox().ProcessFilterKey(key)) return true; } if(Call(DN_INPUT, Param2)) return Msg==DN_CONTROLINPUT; } break; case DN_LISTCHANGE: case DN_ENTERIDLE: if(!cancel) { if(Call(Msg, Param2)) return false; } break; case DN_RESIZECONSOLE: if(!cancel) { INPUT_RECORD ReadRec={WINDOW_BUFFER_SIZE_EVENT}; ReadRec.Event.WindowBufferSizeEvent.dwSize=*(COORD*)Param2; if(Call(DN_INPUT, &ReadRec)) return false; else Resize(); } break; default: if(Global->CloseFARMenu) ProcessKey(Manager::Key(KEY_ESC)); break; } return Dlg->DefProc(Msg, Param1, Param2); }
void ShowProcessList() { static bool Active = false; if (Active) return; Active = true; SCOPE_EXIT{ Active = false; }; const auto ProcList = VMenu2::create(msg(lng::MProcessListTitle), {}, ScrY - 4); ProcList->SetMenuFlags(VMENU_WRAPMODE); ProcList->SetPosition({ -1, -1, 0, 0 }); bool ShowImage = false; const auto FillProcList = [&] { ProcList->clear(); ProcInfo Info{ ProcList.get(), ShowImage }; if (!EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&Info))) { rethrow_if(Info.ExceptionPtr); return false; } ProcList->SortItems([](const MenuItemEx& a, const MenuItemEx& b, SortItemParam&) { return string_sort::less(std::any_cast<const menu_data&>(a.ComplexUserData).Title, std::any_cast<const menu_data&>(b.ComplexUserData).Title); }); return true; }; if (!FillProcList()) return; ProcList->AssignHighlights(FALSE); ProcList->SetBottomTitle(msg(lng::MProcessListBottom)); ProcList->Run([&](const Manager::Key& RawKey) { const auto Key=RawKey(); int KeyProcessed = 1; switch (Key) { case KEY_F1: help::show(L"TaskList"sv); break; case KEY_NUMDEL: case KEY_DEL: { if (const auto MenuData = ProcList->GetComplexUserDataPtr<menu_data>()) { if (Message(MSG_WARNING, msg(lng::MKillProcessTitle), { msg(lng::MAskKillProcess), MenuData->Title, msg(lng::MKillProcessWarning) }, { lng::MKillProcessKill, lng::MCancel }) == Message::first_button) { const os::handle Process(OpenProcess(PROCESS_TERMINATE, FALSE, MenuData->Pid)); if (!Process || !TerminateProcess(Process.native_handle(), 0xFFFFFFFF)) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MKillProcessTitle), { msg(lng::MCannotKillProcess) }, { lng::MOk }); } } } } [[fallthrough]]; case KEY_CTRLR: case KEY_RCTRLR: { if (!FillProcList()) ProcList->Close(-1); break; } case KEY_F2: { // TODO: change titles, don't enumerate again ShowImage = !ShowImage; const auto SelectPos = ProcList->GetSelectPos(); if (!FillProcList()) { ProcList->Close(-1); } else { ProcList->SetSelectPos(SelectPos); } break; } default: KeyProcessed = 0; } return KeyProcessed; }); if (ProcList->GetExitCode() < 0) return; const auto MenuData = ProcList->GetComplexUserDataPtr<menu_data>(); if (!MenuData) return; SwitchToWindow(MenuData->Hwnd); }
void ShowProcessList() { static bool Active = false; if (Active) return; Active = true; auto ProcList = VMenu2::create(MSG(MProcessListTitle), nullptr, 0, ScrY - 4); ProcList->SetMenuFlags(VMENU_WRAPMODE); ProcList->SetPosition(-1,-1,0,0); static bool bShowImage = false; ProcInfo pi = {ProcList.get(), bShowImage}; if (EnumWindows(EnumWindowsProc,(LPARAM)&pi)) { ProcList->AssignHighlights(FALSE); ProcList->SetBottomTitle(MSG(MProcessListBottom)); ProcList->SortItems(TaskSort); ProcList->Run([&](const Manager::Key& RawKey)->int { const auto Key=RawKey.FarKey(); int KeyProcessed = 1; switch (Key) { case KEY_F1: { Help::create(L"TaskList"); break; } case KEY_NUMDEL: case KEY_DEL: { auto ProcWnd = *static_cast<HWND*>(ProcList->GetUserData(nullptr, 0)); if (ProcWnd) { wchar_t_ptr Title; int LenTitle=GetWindowTextLength(ProcWnd); if (LenTitle) { Title.reset(LenTitle + 1); if (Title && (LenTitle=GetWindowText(ProcWnd, Title.get(), LenTitle+1))) Title[LenTitle]=0; } DWORD ProcID; GetWindowThreadProcessId(ProcWnd,&ProcID); if (!Message(MSG_WARNING,2,MSG(MKillProcessTitle),MSG(MAskKillProcess), NullToEmpty(Title.get()),MSG(MKillProcessWarning),MSG(MKillProcessKill),MSG(MCancel))) { if (KillProcess(ProcID)) Sleep(500); else { Global->CatchError(); Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MKillProcessTitle),MSG(MCannotKillProcess),MSG(MOk)); } } } } case KEY_CTRLR: case KEY_RCTRLR: { ProcList->DeleteItems(); if (!EnumWindows(EnumWindowsProc,(LPARAM)&pi)) ProcList->Close(-1); else ProcList->SortItems(TaskSort); break; } case KEY_F2: { pi.bShowImage=(bShowImage=!bShowImage); int SelectPos=ProcList->GetSelectPos(); ProcList->DeleteItems(); if (!EnumWindows(EnumWindowsProc,(LPARAM)&pi)) ProcList->Close(-1); else { ProcList->SortItems(TaskSort); ProcList->SetSelectPos(SelectPos); } break; } default: KeyProcessed = 0; } return KeyProcessed; }); if (ProcList->GetExitCode()>=0) { auto ProcWnd = *static_cast<HWND*>(ProcList->GetUserData(nullptr, 0)); if (ProcWnd) { //SetForegroundWindow(ProcWnd); // Allow SetForegroundWindow on Win98+. DWORD dwMs; // Remember the current value. BOOL bSPI = SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &dwMs, 0); if (bSPI) // Reset foreground lock timeout bSPI = SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0); SetForegroundWindow(ProcWnd); if (bSPI) // Restore old value SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ToPtr(dwMs), 0); WINDOWPLACEMENT wp = { sizeof(wp) }; if (!GetWindowPlacement(ProcWnd,&wp) || wp.showCmd!=SW_SHOWMAXIMIZED) ShowWindowAsync(ProcWnd,SW_RESTORE); } } } Active = false; }