Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
обновлён 2 декабря!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Слушай, дружище, зачем так мучиться с этим языком С++, ты ведь не Билл Гейтс. Возьми тот же Python и программируй, он кроссплатформенный, под Windows тоже работает. Я сам давно заметил: то что на Си пишешь в страницу кода, на питоне решается в одну-две строки. При том, питон намного проще, я его сам недавно изучил по видеокурсу вот этому. Кстати, автор отлично там объясняет. Буквально день-два и уже будешь писать на нём, чего не скажешь про сложный С++.

Пишем файл-броузер



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

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

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



Стандартные папки:
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.

Напишем специальную структуру, и создадим массив на её базе:
enum TPathType {ptDestkop, ptNetworkDrive , ptHardDisk, ptCdrom, ptFloppy, ptDisk,
ptMyDocuments, ptWinSystem, ptWindows, ptWinTemp,
ptUserDefined };

struct TPath {
TPathType PathType; //Тип пути
AnsiString DefDir; //Каталог пути
AnsiString Name; //Имя пути
}StdPath[40];



Для определения типа пути по его каталогу и размещения полученных данных в массиве напишем функцию:
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:
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. Каждому типу пути поставим в соответствие свою картинку:

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];



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



И удалим:

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 заполнить следующим кодом:
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. Онабудет вызываться при изменении текущей папки.

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'а:
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
SetPath(StdPath[ComboBox1->ItemIndex].DefDir);
}



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

int IconSize=16;
AnsiString IconsDir;

...

IconsDir = ExtractFilePath(Application->ExeName)+"\\interface\\files16\\";



Сама отрисовка:

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


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();
}



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

Оригинал и все необходимые файлы можно найти здесь: Пишем файл-броузер



<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS