// заполнение меню int FillUserMenu(VMenu& FarUserMenu,DList<UserMenuItem> *Menu,int MenuPos,int *FuncPos,const string& Name,const string& ShortName) { FarUserMenu.DeleteItems(); MenuItemEx FarUserMenuItem; int NumLines=0; for (UserMenuItem *MenuItem=Menu->First(); MenuItem; MenuItem=Menu->Next(MenuItem), NumLines++) { FarUserMenuItem.Clear(); int FuncNum=0; // сепаратором является случай, когда хоткей == "--" if (!StrCmp(MenuItem->strHotKey,L"--")) { FarUserMenuItem.Flags|=LIF_SEPARATOR; FarUserMenuItem.strName=MenuItem->strLabel; if (NumLines==MenuPos) { MenuPos++; } } else { string strLabel = MenuItem->strLabel; SubstFileName(strLabel,Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); apiExpandEnvironmentStrings(strLabel, strLabel); string strHotKey = MenuItem->strHotKey; FuncNum = PrepareHotKey(strHotKey); int Offset = strHotKey.At(0)==L'&'?5:4; FarUserMenuItem.strName=FormatString()<<((!strHotKey.IsEmpty() && !FuncNum)?L"&":L"")<<fmt::LeftAlign()<<fmt::ExactWidth(Offset)<<strHotKey; FarUserMenuItem.strName+=strLabel; if (MenuItem->Submenu) { FarUserMenuItem.Flags|=MIF_SUBMENU; } FarUserMenuItem.SetSelect(NumLines==MenuPos); } int ItemPos=FarUserMenu.AddItem(&FarUserMenuItem); FarUserMenu.SetUserData(&MenuItem,sizeof(MenuItem),ItemPos); if (FuncNum>0) { FuncPos[FuncNum-1]=ItemPos; } } FarUserMenuItem.Clear(); FarUserMenuItem.SetSelect(NumLines==MenuPos); FarUserMenu.AddItem(&FarUserMenuItem); return NumLines; }
static int FillFileTypesMenu(VMenu *TypesMenu,int MenuPos) { int DizWidth=GetDescriptionWidth(); MenuItemEx TypesMenuItem; TypesMenu->DeleteItems(); int NumLine=0; for (;; NumLine++) { string strRegKey; strRegKey.Format(FTS.TypeFmt,NumLine); TypesMenuItem.Clear(); string strMask; if (!GetRegKey(strRegKey,FTS.Mask,strMask,L"")) { break; } string strMenuText; if (DizWidth) { string strDescription; GetRegKey(strRegKey,FTS.Desc,strDescription,L""); string strTitle=strDescription; size_t Pos=0; bool Ampersand=strTitle.Pos(Pos,L'&'); if (DizWidth+Ampersand > ScrX/2 && Ampersand && static_cast<int>(Pos) > DizWidth) Ampersand=false; strMenuText.Format(L"%-*.*s %c ",DizWidth+Ampersand,DizWidth+Ampersand,strTitle.CPtr(),BoxSymbols[BS_V1]); } //TruncStr(strMask,ScrX-DizWidth-14); strMenuText += strMask; TypesMenuItem.strName = strMenuText; TypesMenuItem.SetSelect(NumLine==MenuPos); TypesMenu->AddItem(&TypesMenuItem); } TypesMenuItem.strName.Clear(); TypesMenuItem.SetSelect(NumLine==MenuPos); TypesMenu->AddItem(&TypesMenuItem); return NumLine; }
static void AddToPrintersMenu(VMenu *PrinterList, PRINTER_INFO *pi, int PrinterNumber) { // Получаем принтер по умолчанию string strDefaultPrinter; DWORD pcchBuffer = 0; if (!GetDefaultPrinter(nullptr, &pcchBuffer) && ERROR_INSUFFICIENT_BUFFER==GetLastError()) { if (!GetDefaultPrinter(strDefaultPrinter.GetBuffer(pcchBuffer), &pcchBuffer)) strDefaultPrinter.ReleaseBuffer(0); else strDefaultPrinter.ReleaseBuffer(); } // Элемент меню MenuItemEx Item; // Признак наличия принтера по умолчанию bool bDefaultPrinterFound = false; // Заполняем список принтеров for (int i=0; i<PrinterNumber; i++) { PRINTER_INFO *printer = &pi[i]; Item.Clear(); Item.strName = printer->pPrinterName; if (!StrCmp(printer->pPrinterName, strDefaultPrinter)) { bDefaultPrinterFound = true; Item.SetCheck(TRUE); Item.SetSelect(TRUE); } PrinterList->SetUserData(printer->pPrinterName,0,PrinterList->AddItem(&Item)); } if (!bDefaultPrinterFound) PrinterList->SetSelectPos(0, 1); }
/* $ 06.07.2001 + Используем CFileMask вместо GetCommaWord, этим самым добиваемся того, что можно использовать маски исключения - Убрал непонятный мне запрет на использование маски файлов типа "*.*" (был когда-то, вроде, такой баг-репорт) */ bool ProcessLocalFileTypes(const wchar_t *Name, const wchar_t *ShortName, int Mode, bool AlwaysWaitFinish) { RenumKeyRecord(FTS.Associations,FTS.TypeFmt,FTS.Type0); MenuItemEx TypesMenuItem; VMenu TypesMenu(MSG(MSelectAssocTitle),nullptr,0,ScrY-4); TypesMenu.SetHelp(FTS.Help); TypesMenu.SetFlags(VMENU_WRAPMODE); TypesMenu.SetPosition(-1,-1,0,0); int DizWidth=GetDescriptionWidth(Name, ShortName); int ActualCmdCount=0; // отображаемых ассоциаций в меню CFileMask FMask; // для работы с масками файлов string strCommand, strDescription; int CommandCount=0; for (int I=0;; I++) { strCommand.Clear(); string strRegKey, strMask; strRegKey.Format(FTS.TypeFmt,I); if (!GetRegKey(strRegKey,FTS.Mask,strMask,L"")) break; if (FMask.Set(strMask,FMF_SILENT)) { if (FMask.Compare(Name)) { LPCWSTR Type=nullptr; switch (Mode) { case FILETYPE_EXEC: Type=FTS.Execute; break; case FILETYPE_VIEW: Type=FTS.View; break; case FILETYPE_EDIT: Type=FTS.Edit; break; case FILETYPE_ALTEXEC: Type=FTS.AltExec; break; case FILETYPE_ALTVIEW: Type=FTS.AltView; break; case FILETYPE_ALTEDIT: Type=FTS.AltEdit; break; } DWORD State=GetRegKey(strRegKey,FTS.State,0xffffffff); if (State&(1<<Mode)) { string strNewCommand; GetRegKey(strRegKey,Type,strNewCommand,L""); if (!strNewCommand.IsEmpty()) { strCommand = strNewCommand; GetRegKey(strRegKey,FTS.Desc,strDescription,L""); CommandCount++; } } } if (strCommand.IsEmpty()) continue; } TypesMenuItem.Clear(); string strCommandText = strCommand; SubstFileName(strCommandText,Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); // все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strCommandText)) continue; ActualCmdCount++; string strMenuText; if (DizWidth) { string strTitle; if (!strDescription.IsEmpty()) { strTitle = strDescription; SubstFileName(strTitle, Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); } size_t Pos=0; bool Ampersand=strTitle.Pos(Pos,L'&'); if (DizWidth+Ampersand>ScrX/2 && Ampersand && static_cast<int>(Pos)>DizWidth) Ampersand=false; strMenuText.Format(L"%-*.*s %c ",DizWidth+Ampersand,DizWidth+Ampersand,strTitle.CPtr(),BoxSymbols[BS_V1]); } TruncStr(strCommandText,ScrX-DizWidth-14); strMenuText += strCommandText; TypesMenuItem.strName = strMenuText; TypesMenuItem.SetSelect(!I); TypesMenu.SetUserData(strCommand.CPtr(),0,TypesMenu.AddItem(&TypesMenuItem)); } if (!CommandCount) return false; if (!ActualCmdCount) return true; int ExitCode=0; if (ActualCmdCount>1) { TypesMenu.Process(); ExitCode=TypesMenu.Modal::GetExitCode(); if (ExitCode<0) return true; } int Size=TypesMenu.GetUserDataSize(ExitCode); LPWSTR Command=strCommand.GetBuffer(Size/sizeof(wchar_t)); TypesMenu.GetUserData(Command,Size,ExitCode); strCommand.ReleaseBuffer(Size); string strListName, strAnotherListName; string strShortListName, strAnotherShortListName; int PreserveLFN=SubstFileName(strCommand,Name,ShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); bool ListFileUsed=!strListName.IsEmpty()||!strAnotherListName.IsEmpty()||!strShortListName.IsEmpty()||!strAnotherShortListName.IsEmpty(); // Снова все "подставлено", теперь проверим условия "if exist" if (ExtractIfExistCommand(strCommand)) { PreserveLongName PreserveName(ShortName,PreserveLFN); RemoveExternalSpaces(strCommand); if (!strCommand.IsEmpty()) { bool isSilent=(strCommand.At(0)==L'@'); if (isSilent) { strCommand.LShift(1); } ProcessOSAliases(strCommand); if (!isSilent) { CtrlObject->CmdLine->ExecString(strCommand,AlwaysWaitFinish, false, false, ListFileUsed); if (!(Opt.ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTFARASS) && !AlwaysWaitFinish) //AN CtrlObject->CmdHistory->AddToHistory(strCommand); } else { #if 1 SaveScreen SaveScr; CtrlObject->Cp()->LeftPanel->CloseFile(); CtrlObject->Cp()->RightPanel->CloseFile(); Execute(strCommand,AlwaysWaitFinish, 0, 0, 0, ListFileUsed, true); #else // здесь была бага с прорисовкой (и... вывод данных // на команду "@type !@!" пропадал с экрана) // сделаем по аналогии с CommandLine::CmdExecute() { RedrawDesktop RdrwDesktop(TRUE); Execute(strCommand,AlwaysWaitFinish, 0, 0, 0, ListFileUsed); ScrollScreen(1); // обязательно, иначе деструктор RedrawDesktop // проредравив экран забьет последнюю строку вывода. } CtrlObject->Cp()->LeftPanel->UpdateIfChanged(UIC_UPDATE_FORCE); CtrlObject->Cp()->RightPanel->UpdateIfChanged(UIC_UPDATE_FORCE); CtrlObject->Cp()->Redraw(); #endif } if (FrameManager->GetCurrentFrame()->GetType()==MODALTYPE_VIEWER) { TypesMenu.ResetCursor(); } } } if (!strListName.IsEmpty()) apiDeleteFile(strListName); if (!strAnotherListName.IsEmpty()) apiDeleteFile(strAnotherListName); if (!strShortListName.IsEmpty()) apiDeleteFile(strShortListName); if (!strAnotherShortListName.IsEmpty()) apiDeleteFile(strAnotherShortListName); return true; }
/* Return: -1 - Error??? 0 - Esc 1 - Enter 2 - Shift-Enter 3 - Ctrl-Enter 4 - F3 5 - F4 6 - Ctrl-Shift-Enter 7 - Ctrl-Alt-Enter */ int History::ProcessMenu(string &strStr, const wchar_t *Title, VMenu &HistoryMenu, int Height, int &Type, Dialog *Dlg) { MenuItemEx MenuItem; HistoryRecord *SelectedRecord=nullptr; FarListPos Pos={0,0}; int Code=-1; int RetCode=1; bool Done=false; bool SetUpMenuPos=false; if (TypeHistory == HISTORYTYPE_DIALOG && HistoryList.Empty()) return 0; while (!Done) { bool IsUpdate=false; HistoryMenu.DeleteItems(); HistoryMenu.Modal::ClearDone(); // заполнение пунктов меню for (const HistoryRecord *HistoryItem=TypeHistory==HISTORYTYPE_DIALOG?HistoryList.Last():HistoryList.First(); HistoryItem ; HistoryItem=TypeHistory==HISTORYTYPE_DIALOG?HistoryList.Prev(HistoryItem):HistoryList.Next(HistoryItem)) { string strRecord = HistoryItem->strName; strRecord.Clear(); if (TypeHistory == HISTORYTYPE_VIEW) { strRecord += GetTitle(HistoryItem->Type); strRecord += L":"; strRecord += (HistoryItem->Type==4?L"-":L" "); } /* TODO: возможно здесь! или выше.... char Date[16],Time[16], OutStr[32]; ConvertDate(HistoryItem->Timestamp,Date,Time,5,TRUE,FALSE,TRUE,TRUE); а дальше strRecord += дату и время */ strRecord += HistoryItem->strName;; if (TypeHistory != HISTORYTYPE_DIALOG) ReplaceStrings(strRecord, L"&",L"&&", -1); MenuItem.Clear(); MenuItem.strName = strRecord; MenuItem.SetCheck(HistoryItem->Lock?1:0); if (!SetUpMenuPos) MenuItem.SetSelect(CurrentItem==HistoryItem || (!CurrentItem && HistoryItem==HistoryList.Last())); HistoryMenu.SetUserData(HistoryItem,sizeof(HistoryItem),HistoryMenu.AddItem(&MenuItem)); } //MenuItem.Clear (); //MenuItem.strName = L" "; //if (!SetUpMenuPos) //MenuItem.SetSelect(CurLastPtr==-1 || CurLastPtr>=HistoryList.Length); //HistoryMenu.SetUserData(nullptr,sizeof(OneItem *),HistoryMenu.AddItem(&MenuItem)); if (TypeHistory == HISTORYTYPE_DIALOG) Dlg->SetComboBoxPos(); else HistoryMenu.SetPosition(-1,-1,0,0); if (SetUpMenuPos) { Pos.SelectPos=Pos.SelectPos < (int)HistoryList.Count() ? Pos.SelectPos : (int)HistoryList.Count()-1; Pos.TopPos=Min(Pos.TopPos,HistoryMenu.GetItemCount()-Height); HistoryMenu.SetSelectPos(&Pos); SetUpMenuPos=false; } /*BUGBUG??? if (TypeHistory == HISTORYTYPE_DIALOG) { // Перед отрисовкой спросим об изменении цветовых атрибутов BYTE RealColors[VMENU_COLOR_COUNT]; FarListColors ListColors={0}; ListColors.ColorCount=VMENU_COLOR_COUNT; ListColors.Colors=RealColors; HistoryMenu.GetColors(&ListColors); if(DlgProc((HANDLE)this,DN_CTLCOLORDLGLIST,CurItem->ID,(LONG_PTR)&ListColors)) HistoryMenu.SetColors(&ListColors); } */ HistoryMenu.Show(); while (!HistoryMenu.Done()) { if (TypeHistory == HISTORYTYPE_DIALOG && (!Dlg->GetDropDownOpened() || HistoryList.Empty())) { HistoryMenu.ProcessKey(KEY_ESC); continue; } int Key=HistoryMenu.ReadInput(); if (TypeHistory == HISTORYTYPE_DIALOG && Key==KEY_TAB) // Tab в списке хистори диалогов - аналог Enter { HistoryMenu.ProcessKey(KEY_ENTER); continue; } HistoryMenu.GetSelectPos(&Pos); HistoryRecord *CurrentRecord=(HistoryRecord *)HistoryMenu.GetUserData(nullptr,sizeof(HistoryRecord *),Pos.SelectPos); switch (Key) { case KEY_CTRLR: // обновить с удалением недоступных { if (TypeHistory == HISTORYTYPE_FOLDER || TypeHistory == HISTORYTYPE_VIEW) { bool ModifiedHistory=false; for (HistoryRecord *HistoryItem=HistoryList.First(); HistoryItem ; HistoryItem=HistoryList.Next(HistoryItem)) { if (HistoryItem->Lock) // залоченные не трогаем continue; // убить запись из истории if (apiGetFileAttributes(HistoryItem->strName) == INVALID_FILE_ATTRIBUTES) { HistoryItem=HistoryList.Delete(HistoryItem); ModifiedHistory=true; } } if (ModifiedHistory) // избавляемся от лишних телодвижений { SaveHistory(); // сохранить HistoryMenu.Modal::SetExitCode(Pos.SelectPos); HistoryMenu.SetUpdateRequired(TRUE); IsUpdate=true; } ResetPosition(); } break; } case KEY_CTRLSHIFTNUMENTER: case KEY_CTRLNUMENTER: case KEY_SHIFTNUMENTER: case KEY_CTRLSHIFTENTER: case KEY_CTRLENTER: case KEY_SHIFTENTER: case KEY_CTRLALTENTER: case KEY_CTRLALTNUMENTER: { if (TypeHistory == HISTORYTYPE_DIALOG) break; HistoryMenu.Modal::SetExitCode(Pos.SelectPos); Done=true; RetCode = Key==KEY_CTRLALTENTER||Key==KEY_CTRLALTNUMENTER?7:(Key==KEY_CTRLSHIFTENTER||Key==KEY_CTRLSHIFTNUMENTER?6:(Key==KEY_SHIFTENTER||Key==KEY_SHIFTNUMENTER?2:3)); break; } case KEY_F3: case KEY_F4: case KEY_NUMPAD5: case KEY_SHIFTNUMPAD5: { if (TypeHistory == HISTORYTYPE_DIALOG) break; HistoryMenu.Modal::SetExitCode(Pos.SelectPos); Done=true; RetCode=(Key==KEY_F4? 5 : 4); break; } // $ 09.04.2001 SVS - Фича - копирование из истории строки в Clipboard case KEY_CTRLC: case KEY_CTRLINS: case KEY_CTRLNUMPAD0: { if (CurrentRecord) CopyToClipboard(CurrentRecord->strName); break; } // Lock/Unlock case KEY_INS: case KEY_NUMPAD0: { if (HistoryMenu.GetItemCount()/* > 1*/) { CurrentItem=CurrentRecord; CurrentItem->Lock=CurrentItem->Lock?false:true; HistoryMenu.Hide(); ResetPosition(); SaveHistory(); HistoryMenu.Modal::SetExitCode(Pos.SelectPos); HistoryMenu.SetUpdateRequired(TRUE); IsUpdate=true; SetUpMenuPos=true; } break; } case KEY_SHIFTNUMDEL: case KEY_SHIFTDEL: { if (HistoryMenu.GetItemCount()/* > 1*/) { if (!CurrentRecord->Lock) { HistoryMenu.Hide(); Delete(CurrentRecord); HistoryMenu.Modal::SetExitCode(Pos.SelectPos); HistoryMenu.SetUpdateRequired(TRUE); IsUpdate=true; SetUpMenuPos=true; } } break; } case KEY_NUMDEL: case KEY_DEL: { if (HistoryMenu.GetItemCount()/* > 1*/ && (!Opt.Confirm.HistoryClear || (Opt.Confirm.HistoryClear && !Message(MSG_WARNING,2, MSG((TypeHistory==HISTORYTYPE_CMD || TypeHistory==HISTORYTYPE_DIALOG?MHistoryTitle: (TypeHistory==HISTORYTYPE_FOLDER?MFolderHistoryTitle:MViewHistoryTitle))), MSG(MHistoryClear), MSG(MClear),MSG(MCancel))))) { for (HistoryRecord *HistoryItem=HistoryList.First(); HistoryItem ; HistoryItem=HistoryList.Next(HistoryItem)) { if (HistoryItem->Lock) // залоченные не трогаем continue; HistoryItem=HistoryList.Delete(HistoryItem); } ResetPosition(); HistoryMenu.Hide(); SaveHistory(); HistoryMenu.Modal::SetExitCode(Pos.SelectPos); HistoryMenu.SetUpdateRequired(TRUE); IsUpdate=true; } break; } default: HistoryMenu.ProcessInput(); break; } } if (IsUpdate) continue; Done=true; Code=HistoryMenu.Modal::GetExitCode(); if (Code >= 0) { SelectedRecord=(HistoryRecord *)HistoryMenu.GetUserData(nullptr,sizeof(HistoryRecord *),Code); if (!SelectedRecord) return -1; //BUGUBUG: eliminate those magic numbers! if (SelectedRecord->Type != 2 && SelectedRecord->Type != 3 // ignore external && RetCode != 3 && ((TypeHistory == HISTORYTYPE_FOLDER && !SelectedRecord->Type) || TypeHistory == HISTORYTYPE_VIEW) && apiGetFileAttributes(SelectedRecord->strName) == INVALID_FILE_ATTRIBUTES) { SetLastError(ERROR_FILE_NOT_FOUND); if (SelectedRecord->Type == 1 && TypeHistory == HISTORYTYPE_VIEW) // Edit? тогда спросим и если надо создадим { if (!Message(MSG_WARNING|MSG_ERRORTYPE,2,Title,SelectedRecord->strName,MSG(MViewHistoryIsCreate),MSG(MHYes),MSG(MHNo))) break; } else { Message(MSG_WARNING|MSG_ERRORTYPE,1,Title,SelectedRecord->strName,MSG(MOk)); } Done=false; SetUpMenuPos=true; HistoryMenu.Modal::SetExitCode(Pos.SelectPos=Code); continue; } } } if (Code < 0 || !SelectedRecord) return 0; if (KeepSelectedPos) { CurrentItem = SelectedRecord; } strStr = SelectedRecord->strName; if (RetCode < 4 || RetCode == 6 || RetCode == 7) { Type=SelectedRecord->Type; } else { Type=RetCode-4; if (Type == 1 && SelectedRecord->Type == 4) Type=4; RetCode=1; } return RetCode; }
/*! \return Возвращает nullptr если нажат "отказ" или если нажат текущий фрейм. Другими словами, если немодальный фрейм не поменялся. Если же фрейм поменялся, то тогда функция должна возвратить указатель на предыдущий фрейм. */ Frame *Manager::FrameMenu() { /* $ 28.04.2002 KM Флаг для определения того, что меню переключения экранов уже активировано. */ static int AlreadyShown=FALSE; if (AlreadyShown) return nullptr; int ExitCode, CheckCanLoseFocus=CurrentFrame->GetCanLoseFocus(); { MenuItemEx ModalMenuItem; VMenu2 ModalMenu(MSG(MScreensTitle),nullptr,0,ScrY-4); ModalMenu.SetHelp(L"ScrSwitch"); ModalMenu.SetFlags(VMENU_WRAPMODE); ModalMenu.SetPosition(-1,-1,0,0); if (!CheckCanLoseFocus) ModalMenuItem.SetDisable(TRUE); for (int I=0; I<FrameCount; I++) { string strType, strName, strNumText; FrameList[I]->GetTypeAndName(strType, strName); ModalMenuItem.Clear(); if (I<10) strNumText.Format(L"&%d. ",I); else if (I<36) strNumText.Format(L"&%c. ",I+55); // 55='A'-10 else strNumText = L"& "; //TruncPathStr(strName,ScrX-24); ReplaceStrings(strName,L"&",L"&&",-1); /* добавляется "*" если файл изменен */ ModalMenuItem.strName.Format(L"%s%-10.10s %c %s", strNumText.CPtr(), strType.CPtr(),(FrameList[I]->IsFileModified()?L'*':L' '), strName.CPtr()); ModalMenuItem.SetSelect(I==FramePos); ModalMenu.AddItem(&ModalMenuItem); } AlreadyShown=TRUE; ExitCode=ModalMenu.Run(); AlreadyShown=FALSE; } if (CheckCanLoseFocus) { if (ExitCode>=0) { ActivateFrame(ExitCode); return (ActivatedFrame==CurrentFrame || !CurrentFrame->GetCanLoseFocus()?nullptr:CurrentFrame); } return (ActivatedFrame==CurrentFrame?nullptr:CurrentFrame); } return nullptr; }