На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> Пишем Файл-броузер , BCB
    Пишем файл-броузер

    Итак попробуем написать файл броузер собственными руками на базе компонентов DirectoryListBox, DriveComboBox, FileListBox.

    Поставим задачу расширения дизайна этих компонентов. Мы не будем менять их код. Мы создадим на форме три кнопки, DriveComboBox, FileListBox сделаем невидимыми, в заменим их
    ComboBox и ListBox компонентами соответсвенно.

    Сначала проиницилизируем ComboBox:
    ExpandedWrap disabled
      #define USER_PATH DriveComboBox1->Items->Count


    Стандартные папки:
    ExpandedWrap disabled
      AnsiString SystemDir, WindowsDir, TempDir;
      AnsiString MyDocumentsFolder ,Desktop;
       
      ...
       
       char specfolder[MAX_PATH];
       GetSystemDirectory(specfolder,100);
       SystemDir = specfolder;
       GetWindowsDirectory(specfolder,100);
       WindowsDir=specfolder;
       TempDir = WindowsDir+"\\Temp";
       SHGetSpecialFolderPath(Handle, specfolder, 0x0005, false);
       MyDocumentsFolder = specfolder;
       SHGetSpecialFolderPath(Handle, specfolder, 0x0000, false);
       Desktop = specfolder;


    Теперь мы знаем местоположение и буквы дисков компьютера. Осталось заполнить полученными данными ComboBox.

    Напишем специальную структуру, и создадим массив на её базе:
    ExpandedWrap disabled
      enum TPathType {ptDestkop, ptNetworkDrive , ptHardDisk, ptCdrom, ptFloppy, ptDisk,
            ptMyDocuments, ptWinSystem, ptWindows, ptWinTemp,
            ptUserDefined };
       
      struct TPath {
        TPathType PathType; //Тип пути
        AnsiString DefDir;  //Каталог пути
        AnsiString Name;    //Имя пути
      }StdPath[40];


    Для определения типа пути по его каталогу и размещения полученных данных в массиве напишем функцию:
    ExpandedWrap disabled
      void AddUserPath(AnsiString DefDir, AnsiString Name, int PathID) {
         StdPath[PathID].Name = Name;
         StdPath[PathID].DefDir = DefDir;
         Form1->ComboBox1->Items->Add(DefDir+"  "+Name+"");
         if(DefDir.Length()==2) {
           switch(GetDriveType(DefDir.c_str()))  {
            case DRIVE_CDROM:
             StdPath[PathID].PathType = ptCdrom;
            return;
            case DRIVE_REMOTE:
             StdPath[PathID].PathType = ptNetworkDrive;
            return;
            case DRIVE_FIXED:
             StdPath[PathID].PathType = ptHardDisk;
            return;
            case DRIVE_REMOVABLE:
              StdPath[PathID].PathType = ptFloppy;
            return;
            default:
             StdPath[PathID].PathType = ptDisk;
            return;
           }
         }
         if(DefDir==MyDocumentsFolder) {
            StdPath[PathID].PathType = ptMyDocuments;
            return;
         }
         if(DefDir==SystemDir) {
            StdPath[PathID].PathType = ptWinSystem;
            return;
         }
         if(DefDir==WindowsDir) {
            StdPath[PathID].PathType = ptWindows;
            return;
         }
         if(DefDir==TempDir) {
            StdPath[PathID].PathType = ptWinTemp;
            return;
         }
         if(DefDir==Desktop) {
            StdPath[PathID].PathType = ptDestkop;
            return;
         }
         StdPath[PathID].PathType = ptUserDefined;
      }


    Благодаря функции GetDriveType мы узнаём тип данного диска.

    Теперь мы можем проинициализировать ComboBox:
    ExpandedWrap disabled
       for(int i=0; i<DriveComboBox1->Items->Count; i++) {
         AddUserPath(DriveComboBox1->Items->Strings[i].SubString(1,2),DriveComboBox1->Items->Strings[i].c_str()+3,i);
       }
       AddUserPath(SystemDir, "Системная папка", USER_PATH);
       AddUserPath(WindowsDir, "Папка Windows", USER_PATH+1);
       AddUserPath(TempDir, "Временные файлы", USER_PATH+2);
       AddUserPath(MyDocumentsFolder, "Мои документы", USER_PATH+3);
       AddUserPath(Desktop, "Рабочий стол", USER_PATH+4);


    Для каждого типа пути нужна своя картинка. Проинициализируем её.
    Мы разместим все картинки в папочке Interface. Каждому типу пути поставим в соответствие свою картинку:

    ExpandedWrap disabled
      AnsiString PathIconNames[] = {
        "Destkop.bmp",
        "NetDisk.bmp",
        "HardDisk.bmp",
        "CDDisk.bmp",
        "Floppy.bmp",
        "Disk.bmp",
        "Mydocs.bmp",
        "Winsys.bmp",
        "Windows.bmp",
        "WinTemp.bmp",
        "User.bmp"
      };
       
      Graphics::TBitmap* PathIcons[ptUserDefined+1];


    Проинициализируем их:
    ExpandedWrap disabled
       for(int i=0; i<ptUserDefined+1; i++) {
          PathIcons[i] = new Graphics::TBitmap();
          PathIcons[i]->LoadFromFile("interface\\" + PathIconNames[i]);
          PathIcons[i]->Transparent = true;
       }


    И удалим:
    ExpandedWrap disabled
       
      void __fastcall TForm1::FormDestroy(TObject *Sender)
      {
       for(int i=0; i<ptUserDefined+1; i++) {
          delete PathIcons[i];
       }
      }


    Теперь самое интересное - отрисовка элементов ComboBox. Для этого свойство Style надо установить в csOwnerDrawFixed (только отрисовка), выбрать ItemHeight по размерам картинок (у меня было значение 24 для картинок 16 на 16), а событие OnDrawItem заполнить следующим кодом:
    ExpandedWrap disabled
      void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
            TRect &Rect, TOwnerDrawState State)
      {
         ComboBox1->Canvas->FillRect(Rect);
         ComboBox1->Canvas->Draw(Rect.Left+4,Rect.Top+4, PathIcons[StdPath[Index].PathType]);
      if(StdPath[Index].PathType>=ptNetworkDrive && StdPath[Index].PathType<=ptDisk) {
          ComboBox1->Canvas->TextOut(Rect.Left+48, Rect.Top+6, StdPath[Index].Name);
          ComboBox1->Canvas->TextOut(Rect.Left+28, Rect.Top+6, StdPath[Index].DefDir);
       }
      else {
         ComboBox1->Canvas->TextOut(Rect.Left+28, Rect.Top+6, StdPath[Index].Name);
      }
      }


    Половина дела сделанa. Теперь на очереди FileListBox.
    Так как картинки из этого компонента нам не подходят, а TIcon не может менять размеры значка, мы опять всё пишем руками :)
    Сначала напишем функцию SetPath. Онабудет вызываться при изменении текущей папки.
    ExpandedWrap disabled
       
      void SetPath(AnsiString NewPath) {
        if(DirectoryExists(NewPath)) {
         Path = NewPath;
         Form1->FileListBox1->Directory=Path;
         if(Form1->DirectoryListBox1->Directory!=Path) Form1->DirectoryListBox1->Directory=Path;
         Form1->ListBox1->Clear();
         Form1->ListBox1->Items->AddStrings(Form1->FileListBox1->Items);
        }
      }

    В конструктор добавится следующая строка: SetPath(MyDocumentsFolder); Теперь при стрте приложения текущей папкой будет "мои документы".
    Наполнится кодом OnChange ComboBox'а:
    ExpandedWrap disabled
      void __fastcall TForm1::ComboBox1Change(TObject *Sender)
      {
       SetPath(StdPath[ComboBox1->ItemIndex].DefDir);
      }


    Теперь осталось написать отрисовку элемента в ListBox. Установим Для этого свойство Style надо установить в lbOwnerDrawVariable (отрисовка и подготовка к отрисовке). Выполним подготовительные действия для значков: установим папку со значками и их размер:

    ExpandedWrap disabled
      int IconSize=16;
      AnsiString IconsDir;
       
      ...
       
      IconsDir = ExtractFilePath(Application->ExeName)+"\\interface\\files16\\";


    Сама отрисовка:
    ExpandedWrap disabled
       
      void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,
            TRect &Rect, TOwnerDrawState State)
      {
          HICON hTypeIcon;
          ListBox1->Canvas->Brush->Style = bsSolid;
          ListBox1->Canvas->Rectangle(Rect);
          ListBox1->Canvas->Brush->Style = bsClear;
          ListBox1->Canvas->TextOut(Rect.Left+IconSize+4,Rect.Top+Rect.Height()/2-10,ListBox1->Items->Strings[Index]);
          if(FileExists(IconsDir+AnsiLowerCase(ExtractFileExt(ListBox1->Items->Strings[Index]).SubString(2,3))+".ico")) { //Если есть значок для этого типа файлов грузим его, если нет то грузим default.ico.
              hTypeIcon = LoadImage(NULL, (IconsDir+AnsiLowerCase(ExtractFileExt(ListBox1->Items->Strings[Index]).SubString(2,3))+".ico").c_str(), IMAGE_ICON, IconSize, IconSize, LR_LOADFROMFILE);
          }
           else {
            hTypeIcon = LoadImage(NULL, "interface\\files16\\default.ico", IMAGE_ICON, IconSize, IconSize, LR_LOADFROMFILE);
           }
           DrawIconEx(ListBox1->Canvas->Handle, Rect.Left+2, Rect.Top+2, hTypeIcon, IconSize,IconSize, 0, NULL, DI_NORMAL);
           DestroyIcon(hTypeIcon);
      }
      //---------------------------------------------------------------------------
      void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,
            int Index, int &Height)
      {
          //Подготока к отрисовке
          ListBox1->Canvas->Pen->Color = 0xFAFAFA;
          if(ListBox1->ItemIndex == Index) { //Если этот элемент текущий
            ListBox1->Canvas->Brush->Color=clNavy;
          }
          else {
            ListBox1->Canvas->Brush->Color=clWhite;
          }
       
         Height = IconSize+4; //Высота элемента
       
      }


    Мы использовали функцию LoadImage. Это универсальная функция загрузки иконок, курсоров, битмапов из ресурса. Если использовать флаг LR_LOADFROMFILE, загрузка происходит из файла. Первыц параметр - Имя ресурса или путь к файлу. Второй параметр - тип картинки. Третий и четвёртый - размеры.

    И, наконец, последний штрих, выбор размера значков. Для этого нам нужны три кнопки с заговками 16, 32 и 48

    ExpandedWrap disabled
       
      void __fastcall TForm1::Button1Click(TObject *Sender)
      {
       IconSize=16;
       ListBox1->Repaint();
      }
      //---------------------------------------------------------------------------
      void __fastcall TForm1::Button2Click(TObject *Sender)
      {
       IconSize=32;
       ListBox1->Repaint();
      }
      //---------------------------------------------------------------------------
      void __fastcall TForm1::Button3Click(TObject *Sender)
      {
       IconSize=48;
       ListBox1->Repaint();
      }


    Файл-броузер готов!

    Оригинал и все необходимые файлы можно найти здесь: Пишем файл-броузер
    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
    0 пользователей:


    Рейтинг@Mail.ru
    [ Script execution time: 0,0263 ]   [ 15 queries used ]   [ Generated: 1.05.24, 05:53 GMT ]