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); }
/* 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; }
bool FileFilter::FilterEdit() { if (bMenuOpen) return false; Changed = true; bMenuOpen = true; MenuItemEx ListItem; int ExitCode; bool bNeedUpdate=false; VMenu FilterList(MSG(MFilterTitle),nullptr,0,ScrY-6); FilterList.SetHelp(L"FiltersMenu"); FilterList.SetPosition(-1,-1,0,0); FilterList.SetBottomTitle(MSG(MFilterBottom)); FilterList.SetFlags(/*VMENU_SHOWAMPERSAND|*/VMENU_WRAPMODE); for (size_t i=0; i<FilterData.getCount(); i++) { ListItem.Clear(); MenuString(ListItem.strName,FilterData.getItem(i)); if (!i) ListItem.Flags|=LIF_SELECTED; int Check = GetCheck(FilterData.getItem(i)); if (Check) ListItem.SetCheck(Check); FilterList.AddItem(&ListItem); } ListItem.Clear(); if (!FilterData.getCount()) ListItem.Flags|=LIF_SELECTED; FilterList.AddItem(&ListItem); if (m_FilterType != FFT_CUSTOM) { wchar_t *ExtPtr=nullptr; int ExtCount=0; { enumFileFilterFlagsType FFFT = GetFFFT(); for (size_t i=0; i<TempFilterData.getCount(); i++) { //AY: Будем показывать только те выбранные авто фильтры //(для которых нету файлов на панели) которые выбраны в области данного меню if (!TempFilterData.getItem(i)->GetFlags(FFFT)) continue; const wchar_t *FMask; TempFilterData.getItem(i)->GetMask(&FMask); string strMask = FMask; Unquote(strMask); if (!ParseAndAddMasks(&ExtPtr,strMask,0,ExtCount,GetCheck(TempFilterData.getItem(i)))) break; } } ListItem.Clear(); ListItem.Flags|=LIF_SEPARATOR; FilterList.AddItem(&ListItem); ListItem.Clear(); FoldersFilter.SetTitle(MSG(MFolderFileType)); MenuString(ListItem.strName,&FoldersFilter,false,L'0'); int Check = GetCheck(&FoldersFilter); if (Check) ListItem.SetCheck(Check); FilterList.AddItem(&ListItem); if (GetHostPanel()->GetMode()==NORMAL_PANEL) { string strCurDir, strFileName; FAR_FIND_DATA_EX fdata; GetHostPanel()->GetCurDir(strCurDir); ScanTree ScTree(FALSE,FALSE); ScTree.SetFindPath(strCurDir,L"*"); while (ScTree.GetNextName(&fdata,strFileName)) if (!ParseAndAddMasks(&ExtPtr,fdata.strFileName,fdata.dwFileAttributes,ExtCount,0)) break; } else { string strFileName; DWORD FileAttr; for (int i=0; GetHostPanel()->GetFileName(strFileName,i,FileAttr); i++) if (!ParseAndAddMasks(&ExtPtr,strFileName,FileAttr,ExtCount,0)) break; } far_qsort((void *)ExtPtr,ExtCount,MAX_PATH*sizeof(wchar_t),ExtSort); ListItem.Clear(); for (int i=0, h=L'1'; i<ExtCount; i++, (h==L'9'?h=L'A':(h==L'Z'||h?h++:h=0))) { wchar_t *CurExtPtr=ExtPtr+i*MAX_PATH; MenuString(ListItem.strName,nullptr,false,h,true,CurExtPtr,MSG(MPanelFileType)); int Length = StrLength(CurExtPtr)+1; ListItem.SetCheck(CurExtPtr[Length]); FilterList.SetUserData(CurExtPtr, Length*sizeof(wchar_t), FilterList.AddItem(&ListItem)); } xf_free(ExtPtr); } FilterList.Show(); while (!FilterList.Done()) { int Key=FilterList.ReadInput(); if (Key==KEY_ADD) Key=L'+'; else if (Key==KEY_SUBTRACT) Key=L'-'; else if (Key==L'i') Key=L'I'; else if (Key==L'x') Key=L'X'; switch (Key) { case L'+': case L'-': case L'I': case L'X': case KEY_SPACE: case KEY_BS: { int SelPos=FilterList.GetSelectPos(); if (SelPos<0 || SelPos==(int)FilterData.getCount()) break; int Check=FilterList.GetCheck(SelPos); int NewCheck; if (Key==KEY_BS) NewCheck = 0; else if (Key==KEY_SPACE) NewCheck = Check ? 0 : L'+'; else NewCheck = (Check == Key) ? 0 : Key; FilterList.SetCheck(NewCheck,SelPos); FilterList.SetSelectPos(SelPos,1); FilterList.SetUpdateRequired(TRUE); FilterList.FastShow(); FilterList.ProcessKey(KEY_DOWN); bNeedUpdate=true; break; } case KEY_SHIFTBS: { for (int I=0; I < FilterList.GetItemCount(); I++) { FilterList.SetCheck(FALSE, I); } FilterList.SetUpdateRequired(TRUE); FilterList.FastShow(); break; } case KEY_F4: { int SelPos=FilterList.GetSelectPos(); if (SelPos<0) break; if (SelPos<(int)FilterData.getCount()) { if (FileFilterConfig(FilterData.getItem(SelPos))) { ListItem.Clear(); MenuString(ListItem.strName,FilterData.getItem(SelPos)); int Check = GetCheck(FilterData.getItem(SelPos)); if (Check) ListItem.SetCheck(Check); FilterList.DeleteItem(SelPos); FilterList.AddItem(&ListItem,SelPos); FilterList.SetSelectPos(SelPos,1); FilterList.SetUpdateRequired(TRUE); FilterList.FastShow(); bNeedUpdate=true; } } else if (SelPos>(int)FilterData.getCount()) { Message(MSG_WARNING,1,MSG(MFilterTitle),MSG(MCanEditCustomFilterOnly),MSG(MOk)); } break; } case KEY_NUMPAD0: case KEY_INS: case KEY_F5: { int pos=FilterList.GetSelectPos(); if (pos<0) break; size_t SelPos=pos; size_t SelPos2=pos+1; SelPos = Min(FilterData.getCount(), SelPos); FileFilterParams *NewFilter = FilterData.insertItem(SelPos); if (!NewFilter) break; if (Key==KEY_F5) { if (SelPos2 < FilterData.getCount()) { *NewFilter = *FilterData.getItem(SelPos2); NewFilter->SetTitle(L""); NewFilter->ClearAllFlags(); } else if (SelPos2 == FilterData.getCount()+2) { *NewFilter = FoldersFilter; NewFilter->SetTitle(L""); NewFilter->ClearAllFlags(); } else if (SelPos2 > FilterData.getCount()+2) { NewFilter->SetMask(1,static_cast<const wchar_t*>(FilterList.GetUserData(nullptr, 0, static_cast<int>(SelPos2-1)))); //Авто фильтры они только для файлов, папки не должны к ним подходить NewFilter->SetAttr(1,0,FILE_ATTRIBUTE_DIRECTORY); } else { FilterData.deleteItem(SelPos); break; } } else { //AY: Раз создаём новый фильтр то думаю будет логично если он будет только для файлов NewFilter->SetAttr(1,0,FILE_ATTRIBUTE_DIRECTORY); } if (FileFilterConfig(NewFilter)) { ListItem.Clear(); MenuString(ListItem.strName,NewFilter); FilterList.AddItem(&ListItem,static_cast<int>(SelPos)); FilterList.SetSelectPos(static_cast<int>(SelPos),1); FilterList.SetPosition(-1,-1,0,0); FilterList.Show(); bNeedUpdate=true; } else FilterData.deleteItem(SelPos); break; } case KEY_NUMDEL: case KEY_DEL: { int SelPos=FilterList.GetSelectPos(); if (SelPos<0) break; if (SelPos<(int)FilterData.getCount()) { string strQuotedTitle=FilterData.getItem(SelPos)->GetTitle(); InsertQuote(strQuotedTitle); if (!Message(0,2,MSG(MFilterTitle),MSG(MAskDeleteFilter), strQuotedTitle,MSG(MDelete),MSG(MCancel))) { FilterData.deleteItem(SelPos); FilterList.DeleteItem(SelPos); FilterList.SetSelectPos(SelPos,1); FilterList.SetPosition(-1,-1,0,0); FilterList.Show(); bNeedUpdate=true; } } else if (SelPos>(int)FilterData.getCount()) { Message(MSG_WARNING,1,MSG(MFilterTitle),MSG(MCanDeleteCustomFilterOnly),MSG(MOk)); } break; } case KEY_CTRLUP: case KEY_RCTRLUP: case KEY_CTRLDOWN: case KEY_RCTRLDOWN: { int SelPos=FilterList.GetSelectPos(); if (SelPos<0) break; if (SelPos<(int)FilterData.getCount() && !((Key==KEY_CTRLUP || Key==KEY_RCTRLUP) && !SelPos) && !((Key==KEY_CTRLDOWN || Key==KEY_RCTRLDOWN) && SelPos==(int)(FilterData.getCount()-1))) { int NewPos = SelPos + ((Key == KEY_CTRLDOWN || Key == KEY_RCTRLDOWN) ? 1 : -1); MenuItemEx CurItem = *FilterList.GetItemPtr(SelPos); MenuItemEx NextItem = *FilterList.GetItemPtr(NewPos); FilterData.swapItems(NewPos,SelPos); if (NewPos<SelPos) { FilterList.DeleteItem(NewPos,2); FilterList.AddItem(&CurItem,NewPos); FilterList.AddItem(&NextItem,SelPos); } else { FilterList.DeleteItem(SelPos,2); FilterList.AddItem(&NextItem,SelPos); FilterList.AddItem(&CurItem,NewPos); } FilterList.SetSelectPos(NewPos,1); FilterList.SetUpdateRequired(TRUE); FilterList.FastShow(); bNeedUpdate=true; } break; } default: { FilterList.ProcessInput(); //заставляем хоткеи позиционировать курсор на пункте но не закрывать меню if (Key!=KEY_NUMENTER && Key!=KEY_ENTER && Key!=KEY_ESC && Key!=KEY_F10 && (IsAlphaNum(Key) || Key&(KEY_ALT|KEY_RALT))) FilterList.ClearDone(); } } } FilterList.Hide(); ExitCode=FilterList.Modal::GetExitCode(); if (ExitCode!=-1) ProcessSelection(&FilterList); if (Opt.AutoSaveSetup) SaveFilters(); if (ExitCode!=-1 || bNeedUpdate) { if (m_FilterType == FFT_PANEL) { GetHostPanel()->Update(UPDATE_KEEP_SELECTION); GetHostPanel()->Redraw(); } } bMenuOpen = false; return (ExitCode!=-1); }