Borland C++ Builder VCL FAQ

ОГЛАВЛЕНИЕ

Часто задаваемые вопросы по Borland C++ VCL

Какой способ очистки TCanvas самый быстрый?

АПИ функция PatBlt.
Пример:
PatBlt(PaintBox1->Canvas->Handle, // Handle Canvas'а
      0,                         // начальная координата по X
      0,                         // начальная координата по Y
      PaintBox1->Width,          // конечная координата по X
      PaintBox1->Height,         // конечная координата по Y
      WHITENESS                  // как закрашивать
      );



Почему у меня RichEdit не хочет откpывать и сохpанять RTF'ы?

Надо для этого RichEdit установить свойство PlainText в true.



Как с помощью TMediaPlayer узнать, сколько длится фильм в миллисекундах и в кадрах?

MediaPlayer1->TimeFormat = tfFrames;  // устанавливаем формат времени в кадрах
ShowMessage("Длина в кадрах: " + IntToStr(MediaPlayer1->Length));
MediaPlayer1->TimeFormat = tfMilliseconds;  // устанавливаем формат времени в миллисекундах
ShowMessage("Длина в миллисекундах: " + IntToStr(MediaPlayer1->Length));



Как работать с ресурсами?

Один из вариантов:

Вручную в блокноте создаём файл с именем, например, "resource.rc".
Внутри формат такой:
[имя_ресурса_без_пробелов] [тип_ресурса_без_пробелов] "[имя файла]"

В него пишем, например:
BOLSHOI_FILE BIG_FILES "bigfile.txt"

Подключаем файл .rc к программе (Shift + F11 а там выбираем наш файл).

А где-то в программе:
TResourceStream *res_stream = new TResourceStream(0,              // берём из нашего exe
                                                 "BOLSHOI_FILE", // имя ресурса
                                                 "BIG_FILES"     // тип ресурса
                                                 );
res_stream->SaveToFile("big_file.bin");
delete res_stream;
Таким образом, получаем наш "bigfile.txt", сохранённый под именем "big_file.bin".

Естественно, лучше сделать обработку исключений!  


Дата и время( TDateTime ) - общие вопросы

Для начала краткая информация: TDateTime - по сути всего лишь число с плавающей точкой двойной точности, со всеми вытекающими последствиями. То есть , например, для того, чтобы вычислить разницу между двумя датами, достаточно вычесть одно из другого:
TDateTime datetime1 = ...;
TDateTime datetime2 = ...;
double difference = (double)( datetime2 - datetime1 );
При этом получившееся значение будет представлять точное значение с учетом дней, часов, минут и секунд. Например, значение 3.25 - это три дня и еще 0.25 дня( т.е. 6 часов )



Как узнать текущие дату и/или время?

Нет ничего проще:
TDateTime CurrentDate = Date();	// это текущая дата
TDateTime CurrentTime = Time(); // это текущее время
TDateTime CurrentDateTime = Now(); // это текущие дата и время



Как сдвинуть дату на заданный промежуток?

TDateTime datetime = ...;
datetime += 1.0 / 24; // сдвигаем на час вперед
datetime -= 1.0; // сдвигам на день назад
datetime += 7.0; // сдвигаем на неделю вперед
datetime = IncMonth( datetime, -1 ); // сдвигаем на месяц назад



Как определить день недели?

TDateTime datetime = ...;
int day_of_week = ( datetime.DayOfWeek() + 5 ) % 7; // считаем с понедельника и с нуля



Как определить номер недели в году?

Следует иметь в виду, что первая неделя в году может быть неполной.
int week_num;
Word year, month, day;
TDateTime dt = ...; // "подопытная" дата
dt.DecodeDate(&year,&month,&day); // раскладываем нашу дату на составляющие
TDateTime _1_jan(year,1,1); // 1-е января того года, которому соответствует дата
int _1_jan_day_of_week = (_1_jan.DayOfWeek()+5)%7; // день недели 1-го января
week_num = (int)(dt-TDateTime(year,1,1)+_1_jan_day_of_week)/7; // искомый номер недели(с 0)



Как узнать, сколько дней в месяце?

Количество дней в месяце хранится в глобальном массиве MonthDays, получить значение можно так:
MonthDays[IsLeapYear(номер_года)][номер_месяца]



Как изменить один из компонентов TDateTime, не затрагивая другой?

TDateTime datetime1 = ...;
TDateTime datetime2 = ...;
ReplaceDate(datetime1,datetime2); // datetime1 теперь содержит ту же дату, что и datetime2
// но время осталось прежним
ReplaceTime(datetime2,datetime1); // а теперь datetime2 содержит то же время, что и datetime1
// но дата осталась прежней



Как определить, является ли год високосным?

Для этого надо использовать функцию IsLeapYear. Например, следующий код покажет окно с текстом о том, является ли год високосным или нет:
int year = 2100;  // тут какой надо год
ShowMessage( IntToStr(year) + " год - " + ((IsLeapYear(year)) ? "" : "не ") + "високосный" );
Как видно, функция IsLeapYear принимает параметр - год и возвращает true, если он високосный и false в противном случае.

P.S. Троеточие в примерах заменяет некоторое выражение, позволяющее записать в объект корректное значение.



Компоненты - динамическое создание

Например, так:
for (int i=0;i<5;i++)
       {
       TEdit *edit = new TEdit(this);
       edit->Parent = this;
       edit->Name = "edit"+AnsiString(i);
       edit->Height = 16;
       edit->Width = 104;
       edit->Left = 0;
       edit->Top = i*edit->Height;
       edit->Text = AnsiString(i);
       }
Этот код создаст 5 TEdit'ов.
Обращатся к ним можно так (по имени):
for (int i=0;i<5;i++)
       {
       TEdit *edit = (TEdit*)FindComponent("edit"+AnsiString(i));
       edit->Text = "www.sources.ru";
       }
Или совершенно другой вариант - использование массива:
TEdit *edit[5];

for (int i=0;i<5;i++)
       {
       edit[i] = new TEdit(this);
       edit[i]->Parent = this;
       edit[i]->Name = "edit"+AnsiString(i);
       edit[i]->Height = 16;
       edit[i]->Width = 104;
       edit[i]->Left = 0;
       edit[i]->Top = i * edit[i]->Height;
       edit[i]->Text = AnsiString(i);
       }

for (int i=0;i<5;i++)
       {
       edit[i]->Text = "www.sources.ru";
       }



Строки(AnsiString) - общие вопросы

AnsiString - класс динамической строки емкостью до 232-1 символов. Базой для создания этого класса послужил паскалевский тип String, который был расширен в соответствии с возможностями C++.
Особенностью его является то, что два экземпляра этого класса могут физически занимать один и тот же участок памяти. Экземпляр этого класса содержит счетчик ссылок к нему, когда этот счетчик обнуляется, экземпляр автоматически уничтожается. Если попытаться изменить экземпляр, к которому имеется более одной ссылки, то будет создана новая копия этой строки, которая и будет изменяться. Это уменьшает портебность программы в памяти, но и уменьшает скорость обработки.
Наследием Паскаля является также то, что символы в нем нумеруются с 1, а не с 0, как это принято в C/C++



Создание строки

Благодаря наличию перегруженных конструкторов строку можно создавать из большого количества базовых типов языка C++, например:
AnsiString empty_string;	 /* пустая строка */
AnsiString one = 1; /* строка one будет содержать "1" */
AnsiString one_and_half = 1.5; /* в one_and_half содержится строка "1.5" */
AnsiString one_charachter = 'a'; /* в one_charachter содержится строка "a" */
AnsiString dup_string = AnsiString::StringOfChar('A',5); /* dup_string получит значение "AAAAA" */
AnsiString simply_string = "string";
AnsiString shorten("Длинная строка",7); /* в shorten попадут только первые 7 символов */



Получение символа из строки

Получить символ из строки типа AnsiString можно с помощью индексного оператора:
AnsiString ansi_string = "Строка";
char character = ansi_string[1]; /* получаем самый первый символ */
ansi_string[6] = 'и'; /* заменим 6-й на букву 'и' */



Получение символьного массива, содержащего значение AnsiString

Функции библиотеки исполнения C и функции WinAPI требуют, чтобы строки передавались им в виде символьных массивов. В AnsiString для этого предназначены функции c_str и data. Разница между ними в том, что для пустой строки c_str возвращает "", а data - NULL. Это отличие может быть проиллюстрировано следующим примером:
AnsiString ansi_string;
char * str1 = ansi_string.c_str();
char * str2 = (char *)ansi_string.data();



Копирование значения AnsiString в символьный массив Unicode

Для этого предназначена функция WideChar, а размер требуемого массива можно узнать, воспользовавшись функцией WideCharBufSize
AnsiString ansi_string = "Строка AnsiString";   /* наша строка */
wchar_t * UnicodeString = new wchar_t[ansi_string.WideCharBufSize()]; /* массив-получатель */
ansi_string.WideChar(UnicodeString,ansi_string.WideCharBufSize());
// используем полученную строку, затем удаляем
delete [] UnicodeString;



Как узнать, сколько символов в строке?

Для этого надо воспользоваться функцией Length.



Как удалить в строке концевые пробелы?

Это делают функции Trim, TrimLeft и TrimRight соответственно с обоих концов, только с начала и только с конца.



Работа с фрагментами строки

AnsiString предоставлякт возможность поиcка(Pos), вставки(Insert), удаления(Delete) и получения копии(SubString) фрагмента текста в строке:
AnsiString ansi_string = "Строка";
int index = ansi_string.Pos("ка"); /* найдем окончание слова */
if( index != 0 ) {
ansi_string.Insert("чеч",index); /* теперь строка имеет вид "Строчечка" */
ansi_string.Delete(index,2); /* а теперь - "Строчка" */
}



Как зарезервировать строке определенный размер

Иногда бывает нужно зарезервировать для строки пространство, достаточное для хранения определенного количества символов. Сделать это можно при помощи функции SetLength



Строки( AnsiString ) - преобразования - другие типы

Возможны следующие преобразования:



AnsiString в целочисленный тип(int,long):

AnsiString int_as_AnsiString = "123";
int int_as_int_1 = int_as_AnsiString.ToInt();
int int_as_int_2 = StrToInt(int_as_AnsiString);



AnsiString в число с плавающей точкой(float,double):

AnsiString float_as_AnsiString = "3.14";
float float_as_float_1 = float_as_AnsiString.ToDouble();
float float_as_float_2 = StrToFloat(float_as_AnsiString);



AnsiString <-> цвет(TColor):

AnsiString ansi_string = "clBtnText";
TColor color = StringToColor(ansi_string); /* цвет в строку */
AnsiString color_string = ColorToString(clWhite); /* строку в цвет */



AnsiString <-> курсор(TCursor):

AnsiString ansi_string = "crHandPoint";
TCursor cursor = StringToCursor(ansi_string); /* строка в курсор */
AnsiString cursor_string = CursorToString(crHelp); /* курсор в строку */



Запись в двоичный файл

Для того, чтобы записать AnsiString в бинарный файл, его нужно сначала преобразовать к массиву char.
Пример записи в файл
TFileStream *out = new TFileStream("info", fmCreate); // создаем файл
f( out != NULL ) {
  AnsiString text = "www.sources.ru"; // исходная строка
  int size = text.Length();
  out->Write(&size, sizeof(size));
  if( size != 0 ) out->Write(text->data(), size);
delete out;



Чтение из двоичного файла

Пример реализации:

AnsiString text;
FileStream *in = new TFileStream("info",fmOpenRead); // открываем файл
if( in != NULL ) {
  int size;
  in->Read(&size, sizeof(size));
  if( size != 0 ) {
     try {
        text.SetLength(size);
        in->Read((void *)(text.data()), size);
     } catch( EOutOfMemory& ) {}
  }
delete in;
ShowMessage(text);



Как получить TColor, имея значения красной, синей и зелёной составляющих?

int red = random(255);		  // красная составляющая
int blue = random(255); // синяя составляющая
int green = random(255); // зеленая составляющая
Label1->Font->Color = (TColor)RGB(red,green,blue);



Как имея TColor, получить значения красной, синей и зелёной составляющих?

TColor color = ...;
unsigned red = GetRValue(color); // красная составляющая
unsigned green = GetGValue(color); // зеленая составляющая
unsigned blue = GetBValue(color); // синяя составляющая



Как узнать яркость цвета?

TColor color = ...;
unsigned luminosity = (GetRValue(color)*77 + GetGValue(color)*151 + GetBValue(color)*28) >> 8;



Преобразование файлового времени в объект TDateTime

Используйте следующую функцию для преобразования файлового времени в объект TDateTime:
TDateTime __fastcall TSTFLFileInfo::FileTimeToDateTime(FILETIME &AFileTime)
{
    SYSTEMTIME SystemTime;
    FILETIME LocalFileTime;

    FileTimeToLocalFileTime(&AFileTime, &LocalFileTime);
    FileTimeToSystemTime(&LocalFileTime, &SystemTime);
    TDateTime DateTime = SystemTimeToDateTime(SystemTime);
    return DateTime;
}



Выбор нескольких ячеек в TStringGrid

Несколько ячеек в TStringGrid можно выбрать непосредственно мышью или комбинацей клавиши Shift с клавишей управления курсором.



Как перевести строку из Windows-кодировки в OEM-кодировку?

Для перевода строки из Windows-кодировки в OEM-кодировку воспользуйтесь следующей функцией:
AnsiString __fastcall StringToOEMi(const AnsiString ASourceString)
{
    char *TempString = new char[ASourceString.Length()];
    AnsiString ResultString;

    CharToOemBuff(ASourceString.c_str(), TempString, ASourceString.Length());
    ResultString = TempString;

    delete [] TempString;
    return ResultString;
}



Как перевести строку из OEM-кодировки в Windows-кодировку?

Для перевода строки из OEM-кодировки в Windows-кодировку воспользуйтесь следующей функцией:
AnsiString __fastcall StringToAnsi(const AnsiString ASourceString)
{
    char *TempString = new char[ASourceString.Length()];
    AnsiString ResultString;

    OemToCharBuff(ASourceString.c_str(), TempString, ASourceString.Length());
    ResultString = TempString;

    delete [] TempString;
    return ResultString;
}



Как узнать, високосный год или нет?

Чтобы узнать, является ли указанный год високосным, воспользуйтесь функцией IsLeapYear(), объявленной в Sysutils.hpp:
IsLeapYear(Year);
где Year - год, который надо проверить на високосность. Функция возвращает true, если год високосный, и false в противном случае.



Как узнать количество параметров, переданных в командной строке?

Чтобы узнать, сколько параметров было передано приложению в командной строке, воспользуйтесь функцией ParamCount(), объявленной в System.hpp. Функция возвращает количество параметров, переданных в командной строке, в виде значения типа int.



Как получить шестнадцатеричное представление числа?

Для перевода числа в шестнадцатеричную систему счисления воспользуйтесь функцией IntToHex() из модуля Sysutils.hpp. Первый параметр функции - исходное число, второй параметр - количество знаков в шестнадцатеричном представлении числа. Функция возвращает строку, представляющую число в шестнадцатеричной системе счисления. Вот код:
int Number = 12;
AnsiString HexNumber = IntToHex(Number, 8);
В HexNumber будет содержаться "0000000С".



Как изменить стиль формы во время выполнения?

Имеются проблемы при изменении стиля формы (значение свойства FormStyle) во время выполнения. А иногда надо поменять стиль формы с fsNormal на fsStayOnTop, например. В таком случае можно воспользоваться следующим кодом:
SetWindowPos(Handle, HWND_TOPMOST, Left, Top, Width, Height, SWP_SHOWWINDOW);
где Handle - дескриптор той формы, стиль которой надо изменить, а Left, Top, Width, Height - координаты левого верхнего угла, ширина и высота формы, соответственно.
Для изменения стиля формы с fsStayOnTop на fsNormal используйте следующий код:
SetWindowPos(Handle, HWND_NOTOPMOST, Left, Top, Width, Height, SWP_SHOWWINDOW);



Всплывающие подсказки в ListView при наведении мыши на элемент списка

Поместите на форму компонент TListView (ListView1), установите у него свойство ShowHint в true и напишите обработчик события OnMouseMove следующим образом:
void __fastcall TForm1::ListView1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
    TListItem *pListItem = ListView1->GetItemAt(X, Y);
    if(pListItem) ListView1->Hint = pListItem->Caption;
}



Всплывающие подсказки в ListBox при наведении мыши на элемент списка

Поместите на форму компонент TListBox (ListBox), установите у него свойство ShowHint в true и напишите обработчик события OnMouseMove следующим образом:
void __fastcall TForm1::ListBox1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
    static int OldIndex = -1;
    int Index = ListBox1->ItemAtPos(Point(X, Y), true);

    if((Index > -1) && (Index != OldIndex))
    {
        ListBox1->Hint = ListBox1->Items->Strings[Index];
        Application->ActivateHint(Mouse->CursorPos);
    }

    OldIndex = Index;
}



Преобразование объекта TDateTime в строку

Для преобразования объекта TDateTime в строку воспользуйтесь функцией
extern PACKAGE AnsiString __fastcall DateTimeToStr(System::TDateTime DateTime).
Для ее использования не забудьте подключить Sysutils.hpp.



Как получить аргументы командной строки для приложения?

Чтобы получить аргументы командной строки, с которыми было запущено ваше приложение, можно воспользоваться переменной CmdLine из модуля System.hpp. CmdLine представляет собой указатель на завершающуюся нулем строку, содержащую аргуметы командной строки, указанные в момент запуска приложения.



Проверка буфера обмена на наличие в нем текста

Чтобы проверить буфер обмена на наличие в нем текста, вы должны подключить в свою программу файл Clipbrd.hpp и написать следующий код:
if (Clipboard()->HasFormat(CF_TEXT))
// обработка при наличии текста в буфере обмена
else
// текста в буфере обмена не существует
Метод HasFormat(CF_TEXT) вернет true, если в буфере обмена содержится текстовый фрагмент.



Прокрутка ListBox на одну строку вниз

Чтобы программно прокрутить содержимое списка (TListBox) на одну строку вниз, напишите следующий код:
SendMessage(ListBox1->Handle, WM_VSCROLL, SB_LINEDOWN, 0);
где ListBox1 - имя вашего списка.



Список всех шрифтов, установленных в системе (VCL вариант)

Список всех шрифтов, установленных в системе, содержится в свойстве Fonts глобальной переменной Screen. Нижеприведенный пример показывает заполнение именами шрифтов выпадающего списка:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    for (int i = 0; i < Screen->Fonts->Count; i++)
      ComboBox1->Items->Add(Screen->Fonts->Strings[i]);
}

Но лучше так:

void __fastcall TForm1::FormCreate(TObject *Sender)
{
      ComboBox1->Items->Assign(Screen->Fonts);
}



Preview у TChart в run-time

Чтобы в run-time у компонента TChart (Chart1) сделать preview, напишите следующий код:
  ChartPreview(this, Chart1);
Не забудьте в проект подключить файл teeprevi.hpp



Как сжать базу данных Access?

Можно воспользоваться компонентом TAccessApplication со вкладки Servers. Его использование (frmMain - ваша форма):
    frmMain->AccessApplication1->RunCommand(acCmdCompactDatabase);
frmMain->AccessApplication1->Disconnect();
База сжимается. Единственное неудобство - выводится диалог Access для задания исходной базы и сжатой.



Как получить текст выделенного элемента в TComboBox?

Чтобы получить текст выделенного элемента в TComboBox, воспользуйтесь свойством ItemIndex следующим образом (ComboBox1 - ваш выпадающий список):
AnsiString SelectedItemText = ComboBox1->Items->Strings[ComboBox1->ItemIndex];



Как добавить стpокy в RichEdit, чтобы пpи этом

кypсоp остался в конце той же стpоки? Чтобы при добавлении строки в RichEdit (TRichEdit) курсор остался в конце добавленной строки, напишите следуюзий код:
RichEdit1->Lines->Add("тестовая строка");
RichEdit1->SelStart = RichEdit1->SelStart - 1;



Как использовать стандартные средства C++Builder для работы с gif и jpeg файлами?

Для того, чтобы использовать стандартные компоненты для работы с файлами gif и jpeg в C++Builder, необходимо зарегистрировать данные типы файлов. Для регистрации напишите следующий код.

Для jpeg.
TPicture *Picture = new TPicture();
Picture->RegisterFileFormat(__classid(TJPEGImage), "jpg", "jpg", __classid(TJPEGImage));
delete Picture;
Для gif.
TPicture *Picture = new TPicture();
Picture->RegisterFileFormat(__classid(TGIFImage), "gif", "gif", __classid(TGIFImage));
delete Picture;



Preview у TChart в run-time (для TChart 6)

Чтобы в run-time у компонента TChart (Chart1) версии 6 сделать preview, напишите следующий код:
  TeePreview(Application->MainForm, Chart1);
Не забудьте в проект подключить файл teeprevi.hpp



Получение дня недели (VCL вариант)

Для получения дня недели воспользуйтесь функцией DayOfWeek() из модуля Sysutils, передав ей текущую дату. DayOfWeek возвращает значение от 1 до 7, где 1 - воскресенье, 2 - понедельник, и т. д.
int Day = DayOfWeek(Date());



Получение текущей даты и времени (VCL вариант)

Для получения текущей даты и времени воспользуйтесь функцией Now() из модуля Sysutils.hpp. Функция возвращает объект TDateTime, который потом можно преобразовать в строку функцией DateTimeToStr



Получение директории, из которой запущена программа

Для получения директории, из которой запущена программа, воспользуйтесь следующим кодом:
ExtractFileDir(Application->ExeName);
Не забудьте в проект подключить модуль Sysutils.hpp



Загрузка содержимого из файла в BLOB-поле

Для загрузки содержимого из файла в BLOB-поле можно воспользоваться следующим кодом:
ADOTable1->Insert(); 
TMemoryStream *M = new TMemoryStream();
M->LoadFromFile("h:\\my_file.doc");
TStream *B = ADOTable1->CreateBlobStream(ADOTable1->FieldByName("My_Field"),bmWrite);
B->CopyFrom(M,M->Size);
delete B;
ADOTable1->Post();
delete M;



Запись содержимого BLOB-поля в файл

Для сохранения содержимого BLOB-поля в файл можно воспользоваться следующим кодом:
TMemoryStream *M1 = new TMemoryStream(); 
TStream *B1 = ADOTable1->CreateBlobStream(ADOTable1->FieldByName("My_field"),bmRead);
M1->CopyFrom(B1,B1->Size);
M1->SaveToFile("h:\\My_file.doc");
delete B1;
delete M1;



Вывод текста по окружности

Нижеприведенная функция выводит текст по кругу:
void DrawCircularText (TCanvas *Canvas, AnsiString asFontName, int iHeight, 
char *szText, int iAngle, int iR, int iCX, int iCY, int iSector)
{
    LOGFONT lf;
    HFONT hPrevFont, hFont;
    int iPass;

    iPass = iSector/lstrlen (szText);
    ZeroMemory (&lf, sizeof (lf));
    for (int i = 0; i < lstrlen (szText); i ++)
    {
        lf.lfEscapement = 10*iAngle-(10*iPass*(i-1));
        lstrcpy (lf.lfFaceName, asFontName.c_str());
        lf.lfHeight = iHeight;
        hFont = CreateFontIndirect (&lf);
        hPrevFont = SelectObject (Canvas->Handle, hFont);
        Canvas->TextOut (iCX+iR*sin((-180+iAngle-(i-1)*iPass)*3.14/180),
        iCY+iR*cos((-180+iAngle-(i-1)*iPass)*3.14/180),
        szText [i]);
        hFont = SelectObject(Canvas->Handle, hPrevFont);
        DeleteObject (hFont);
    }
}
Изменяя аргумент iAngle, вы получаете возможность вращать начальную точку вывода текста, а если изменять агрумент iSector, то можно рисовать текст как по дуге, так и по окружности.



Определение размера свободного пространства на диске

Для определения размера свободного пространства на диске используйте функцию DiskFree, объявленную в Sysutils.hpp. В параметрах функции диску А соответствует 1, диску В - 2, и т. д., 0 - текущий диск.

Следующий код определит размер свободного пространства на диске С в байтах:
__int64 FreeSpace = DiskFree(3);



Как узнать, какой процессор установлен в системе?

Чтобы узнать, какой процессор установлен в системе, используйте следующий код:
AnsiString ProcessorName;
TRegistry *reg = new TRegistry;
reg->RootKey = HKEY_LOCAL_MACHINE;
reg->OpenKey("Hardware\\Description\\System\\CentralProcessor\\0", false);
ProcessorName=reg->ReadString("ProcessorNameString");
delete reg;
В ProcessorName будет находиться название процессора.

Не забудьте подключить в проект Registry.hpp.



Как узнать, присутствует ли мышь в системе?

Чтобы узнать, присутствует ли мышь в системе, прочитайте значение свойства MousePresent класса TMouse, воспользовавшись глобальной переменной Mouse и следующим кодом:
if(Mouse->MousePresent)
// мышь в системе присутствует
else
// мышь в системе отсутствует



Как узнать, присутствует ли у мыши колесико?

Чтобы узнать, присутствует ли у мыши колесико, прочитайте значение свойства WheelPresent класса TMouse, воспользовавшись глобальной переменной Mouse и следующим кодом:
if(Mouse->WheelPresent)
// у мыши есть колесико
else
// колесико у мыли отсутствует



Как определить, над каким элементом в ListBox находится курсор мыши?

Поместите на форму (Form1) компонент TListBox (ListBox1) и напишите следующий обработчик события OnMouseMove:
void __fastcall TForm1::ListBox1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
    if(ListBox1->ItemAtPos(TPoint(X, Y), true) != -1)
        Form1->Caption = ListBox1->Items->Strings[ListBox1->ItemAtPos(TPoint(X, Y),       true)];
}
В заголовке формы при движении мыши будут отображаться элементы ListBox1.



Закрашивание отдельной ячейки в StringGrid

Для закрашивания отдельной ячейки в StringGrid напишите следующий обработчик события OnDrawCell StringGrid (Form1 - форма, на которой размещен StringGrid1, StringGrid1 - экземпляр TStringGrid, ячейка которого закрашивается):
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
    if(ACol == 2 && ARow == 2) // определяем конкретную ячейку
    {
        StringGrid1->Canvas->Brush->Color = clRed;
        StringGrid1->Canvas->FillRect(Rect);
    }
}



Сколько мониторов установлено в системе?

Для того, чтобы узнать, сколько мониторов установлено в системе, используйте следующий код:
int MonitorCount = Screen->MonitorCount;



Прокрутка ListBox на одну строку вверх

Чтобы программно прокрутить содержимое списка (TListBox) на одну строку вверх, напишите следующий код:
SendMessage(ListBox1->Handle, WM_VSCROLL, SB_LINEUP, 0);
где ListBox1 - имя вашего списка.



Перемещение формы мышью не за заголовок

Чтобы перемещать форму мышью не за заголовок, напишите следующий обработчик события OnMouseDown формы
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
    long SC_DRAGMOVE = 0xF012;
    if(Button == mbLeft)
      {
        ReleaseCapture();
        SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
      }
}



Получение списка компьютеров в сети

BOOL EnumHandler( HWND hWnd, DWORD dwLevel, LPNETRESOURCE lpNet ) 
{
   BOOL ret=TRUE;
   DWORD dwStatus, dwSize, dwEntries, i, j;
   LPSTR lpStr=NULL;
   LPNETRESOURCE lpNewNet=NULL;
   HANDLE hEnum=NULL;

   dwStatus = WNetOpenEnum( RESOURCE_GLOBALNET,
                            RESOURCETYPE_ANY, 
                            0, lpNet, &hEnum );
   if( dwStatus != NO_ERROR ){ ret=FALSE; goto mend; }
   dwEntries = 1000;
   dwSize = sizeof(NETRESOURCE) * dwEntries;
   lpNewNet=(LPNETRESOURCE)new char[dwSize];
   if(!lpNewNet){ ret=FALSE; goto mend; }
   dwStatus = WNetEnumResource( hEnum, &dwEntries, (LPVOID)lpNewNet, &dwSize );

   if( dwStatus != NO_ERROR )
   {
      ret=FALSE; goto mend;
   }
   WNetCloseEnum( hEnum );
   hEnum=NULL;

   lpStr=new char[512];
   if(!lpStr){ ret=FALSE; goto mend; }
   for( i = 0; i < dwEntries; i++ )
   {
      if( lpNewNet[ i ].dwDisplayType==RESOURCEDISPLAYTYPE_NETWORK)
      {
            strcpy( lpStr, lpNewNet[ i ].lpProvider );
      }

      if( lpNewNet[ i ].lpRemoteName )
      {
         if( lpNewNet[ i ].dwDisplayType == RESOURCEDISPLAYTYPE_DOMAIN )
            strcpy( lpStr, "Domain..." );

         if( lpNewNet[ i ].dwDisplayType == RESOURCEDISPLAYTYPE_GENERIC )
            strcpy( lpStr, "Generic.." );

         if( lpNewNet[ i ].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER )
            strcpy( lpStr, "Server..." );

         if( lpNewNet[ i ].dwDisplayType == RESOURCEDISPLAYTYPE_SHARE )
            strcpy( lpStr, "Share...." );

         for( j = 0; j < dwLevel; j++ )
            strcat( lpStr, "......" );
         strcat( lpStr, lpNewNet[ i ].lpRemoteName );
//Добавим IP адрес к концу строки
// if( lpNewNet[ i ].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER )
//   if(!GetIP(&lpNewNet[ i ].lpRemoteName[2],lpStr))continue;
      }
      SendMessage( hWnd, LB_ADDSTRING, 0,(LPARAM)lpStr );
      UpdateWindow(hWnd);
        // Уровень детализации вы сможете установить здесь
      if(dwLevel < 2) //0=Сеть,1=Domain,2=Host,3=Resource
      EnumHandler( hWnd, dwLevel + 1, lpNewNet + i );
   }
mend:
   if(hEnum)WNetCloseEnum( hEnum );
   if(lpStr)delete lpStr;
   if(lpNewNet)delete lpNewNet;
   return ret;
}
//-------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   HCURSOR hOldCursor;
        //   ListBox1->Clear();
   SendMessage(Form1->ListBox1->Handle , LB_RESETCONTENT, 0, 0 );
   UpdateWindow(Form1->ListBox1->Handle);
   hOldCursor = ::SetCursor( LoadCursor( NULL, IDC_WAIT ) );
   EnumHandler( Form1->ListBox1->Handle, 0, NULL );
   ::SetCursor( hOldCursor );
}



Как удалить выбранные элементы в TListBox?

Для удаления нескольких выбранных элементов в TListBox воспользуйтесь следующим кодом (ListBox1 - ваш TListBox):
for(int i = ListBox1->Items->Count-1; i >= 0; i--)
if(ListBox1->Selected[i])
ListBox1->Items->Delete(i);



Изменение стиля шрифта у TTreeNode

Если существует необходимость изменить стиль шрифта у узла дерева (класс TTreeNode VCL), то можно воспользоваться следующим кодом (в данном примере устанавливается жирный шрифт в событии OnMouseMove TTreeView):
void __fastcall TForm1::TreeView1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
    TTreeNode *Node = TreeView1->GetNodeAt(X, Y);
    if(Node)
      {
        TV_ITEM tvItem;
        tvItem.hItem = Node->ItemId;
        tvItem.mask = TVIF_STATE;
        tvItem.state = TVIS_BOLD;
        tvItem.stateMask = TVIS_BOLD;
        SendMessage(TreeView1->Handle, TVM_SETITEM, 0, (LPARAM)&tvItem);
      }
// конец оператора if(Mode)
}



Очистка ячеек в StringGrid (вариант 1)

Для очистки содержимого ячеек в StringGrid (TStringGrid) напишите следующий обработчик (StringGrid1 - сетка, в которой очищаем ячейки, Button1 - кнопка на форме):
void __fastcall TForm1::Button1Click(TObject *Sender)
  {
    for(int i = 0; i < StringGrid1->ColCount; i++)
    for(int j = 0; j < StringGrid1->RowCount; j++)
    StringGrid1->Cells[i][j] = "";
  }



Удаление пустой директории

Для удаления пустой директории вы можете воспользоваться функцией RemoveDir из модуля Sysutils.hpp:
bool Result = RemoveDir("C:\\MyDir");
В случае успеха функция вернет true, в случае неудачи - false.



Отладка DLL

Для начала отладки динамически подключаемой библиотеки в проекте библиотеки надо в опциях включить Full Debug, а затем в пункте меню Run-Parameters указать в Host Application исполняемый файл приложения, которое использует dll. Дальнейшая отладка ведется обычным образом.



Как узнать размер папки?

Для получения размера папки со всеми ее подпапками можно воспользоваться следующей функцией:
void FolderSize(AnsiString Folder,int &Size,int &fCount,int &folCount) 
  {
//Функция записывает в параметры Size - размер папки в байтах
//fCount - общее количество файлов в папке
//folCount - общее количество подпапок в папке

  TSearchRec SR;
//Проверяем, заканчивается ли путь к папке на \, если да, то удаляем его,
  if(Folder[Folder.Length()] == '\\')
     Folder.SetLength(Folder.Length()-1);
  if(FindFirst(Folder+"\\*.*",faAnyFile,SR) == 0)//Делаем первый поиск
   do
      {  //Если то что мы нашли не является обратными ссылками...
         if(SR.Name != "." &&  SR.Name != "..")
         {  //Если то что мы нашли является папкой, функция вызывает саму себя
//и увеличивает счетчик кол-ва подпапок
            if((SR.Attr & faDirectory)!=0)
               {
                  FolderSize(Folder+"\\"+SR.Name,Size,fCount,folCount);
                  folCount++;
               }
            else //Если это файл - прибавляем его размер к общему размеру
               {
                  Size = Size + SR.Size;
                  fCount++;
               }
         }
      }
   while(FindNext(SR)==0);
    FindClose(SR);
  }



Печать выделенного текста на матричный принтер

Для печати выделенного текста на матричный принтер можно использовать следующий код:
#include <fstream.h>

...

fstream outfile ("LPT1");
AnsiString MyMemoPrintWin = Memo1->SelText;
char *TempString = new char[MyMemoPrintWin.Length() + 1];
CharToOemBuff(MyMemoPrintWin.c_str(), TempString, MyMemoPrintWin.Length() + 1);
outfile << TempString << endl; //пошла печать
delete[] TempString;



Преобразование битового образа в область (регион)

При создании в C++Builder окон нестандартной формы вам понадобится преобразование битового изображения в область. Это можно сделать с помощью приведенной ниже функции:
HRGN TfSettingsForm::BitmapToRegion(TPicture *APicture, TColor ATransparentColor)
  {
    HRGN Result = 0;
    for(int y = 0; y < APicture->Height; y++)
      {
        int x = 0;
        while(x < APicture->Width)
          {
// Пропускаем прозрачные точки
            while((x < APicture->Width) &&
              (APicture->Bitmap->Canvas->Pixels[x][y] == ATransparentColor))
            x++;

            if(x >= APicture->Bitmap->Width)
              break;

            int XStart = x; // Пропускаем непрозрачные точки

            while((x < APicture->Width) &&
              (APicture->Bitmap->Canvas->Pixels[x][y] != ATransparentColor))
            x++;

// Создаем новый прямоугольный регион и добавляем его к
// региону всей картинки
            if(Result == 0)
              Result = CreateRectRgn(XStart, y, x, y + 1);
            else
              CombineRgn(Result, Result, CreateRectRgn(XStart, y, x, y + 1), RGN_OR);
          }
// конец оператора while(x < APicture->Width)
      }
// конец оператора for(int y = 0; y < APicture->Height; y++)

    return Result;
  }
TPicture *APicture - указатель на изображение, которое будет фоном для вашей формы. TColor ATransparentColor - прозрачный цвет в данном изображении. Пиксели данного цвета "исчезнут", и окно сможет принять самый замысловатый вид.



Как ограничить перемещение курсора заданной областью?

Иногда вам может потребоваться органичение перемещения курсора мыши заданой прямоугольной областью. Рассмотрим, как это делается, на примере формы (Form1), а далее вы сможете переделать данный код так, как вам необходимо.

Добавьте в заголовочный файл формы в секцию private два следующих объявления:
TCursor FCursor;
bool FFlag;
А в cpp-файле напишите три следующих обработчика:
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
  {
    if(FFlag)
      {
        if(Mouse->CursorPos.x <= (Left + 50))
          SetCursorPos((Left + 50), Mouse->CursorPos.y);

        if(Mouse->CursorPos.x >= (Left + Width - 50))
          SetCursorPos((Left + Width - 50), Mouse->CursorPos.y);

        if(Mouse->CursorPos.y <= (Top + 50))
          SetCursorPos(Mouse->CursorPos.x, (Top + 50));

        if(Mouse->CursorPos.y >= (Top + Height - 50))
          SetCursorPos(Mouse->CursorPos.x, (Top + Height - 50));
      }
  }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
  {
    FFlag = true;
    FCursor = Cursor;
    Screen->Cursor = crDrag;
  }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
  {
    FFlag = false;
    Screen->Cursor = FCursor;
  }
//---------------------------------------------------------------------------
Теперь область перемещения курсора внутри формы при удерживаемой нажатой кнопке мыши будет на 50 пикселей меньше относительно каждой из границ формы, то есть, вы не сможете переместить курсор при нажатой кнопке мыше к краю формы ближе, чем на 50 пикселей.



Ошибка при регистрации собственного класса всплывающих подсказок

В шестой версии С++Builder при регистрации собственного класса всплывающих подсказок с использованием кода
HintWindowClass = __classid(TMyHintWindow);
где TMyHintWindow - класс ваших всплывающих подсказок, возникает ошибка:
[Linker Error] Unresolved external '__fastcall Controls::THintWindow::NCPaint(void *)' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\OWNHINTS\STHINTWINDOW.OBJ.
Для того, чтобы исправить данную ошибку, в код проекта перед вызовом функции
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
добавьте функцию THintWindow::NCPaint следующим образом:
void __fastcall Controls::THintWindow::NCPaint(HDC DC)
  {
    TRect R(0, 0, Width, Height);
    DrawEdge(DC, &R, BDR_RAISEDOUTER, BF_RECT);
  }



Как пpи стаpте пpогpаммы включить киpиллицу?

Для того, чтобы программа при старте запускалась с русской раскладкой клавиатуры, воспользуйтесь следующим кодом:
ActivateKeyboardLayout(LoadKeyboardLayout(IntToHex(MAKELANGID(LANG_RUSSIAN,
SUBLANG_DEFAULT), 8).c_str(), 0), 0);



Обработка событий динамически созданных компонентов

Рассмотрим обработку событий динамически созданных компонентов на примере кнопки (TButton) и ее события OnClick. Чтобы привязать обработчик события к кнопке объявите в классе формы функцию void __fastcall MyClick(TObject *Sender) и в конструкторе формы (или в обработчике события OnCreate формы) назначьте ее вашему компоненту (предположим, он называется MyButton):
MyButton->OnClick = MyClick
В определении функции MyClick напишите код, который дожен вызываться при нажатии на кнопку MyButton.

Для остальных событий все выполняется аналогичным образом, с той лишь разницей, что сигнатура объявляемой функции-обработчика должна соответствовать выбранному вами событию.



Ошибка при компиляции проекта с использованием VirtualTreeView в C++Builder 6

При использовании в проекте компонента VirtualTreeView от Майка Лишке (http://www.delphi-gems.com/VirtualTreeview/VT.php) в проекте возникает ошибка [C++ Error] VirtualTrees.hpp(1898): E2076 Overloadable operator expected. Для ее исправления в файл VirtualTrees.hpp перед строкой:
#include <UxTheme.hpp> // Pascal unit
добавьте строку:
#include 
и пересоберите проект.



Получение версии файла

Для получения версии файла в C++Builder воспользуйтесь следующим кодом:
DWORD h; 
DWORD Size=GetFileVersionInfoSize(Application->ExeName.c_str(), &h);
if(Size==0)
  return ;
char *buf;
buf=(char *)GlobalAlloc(GMEM_FIXED, Size);
if (GetFileVersionInfo(Application->ExeName.c_str(),h,Size,buf)!=0)
  {
    char *ValueBuf;
    UINT Len;
    VerQueryValue(buf, "\\VarFileInfo\\Translation", &(void *)ValueBuf,&Len);
    if (Len>=4)
      {
        AnsiString CharSet=IntToHex((int )MAKELONG(*(int *)(ValueBuf+2),*(int *)ValueBuf), 8);

        if (VerQueryValue(buf,AnsiString "\\StringFileInfo\\"+CharSet+"\\ProductName").c_str(),&(void         *)ValueBuf,&Len) !=0)
          AppName->Caption=ValueBuf;

        if (VerQueryValue(buf,AnsiString("\\StringFileInfo\\"+CharSet+"\\FileVersion").c_str(),&(void         *)ValueBuf,&Len)!=0)
          Version->Caption=ValueBuf;

       if (VerQueryValue(buf,AnsiString("\\StringFileInfo\\"+CharSet+"\\LegalCopyright").c_str(),&(void        *)ValueBuf,&Len)!=0)
          Copyright->Caption=ValueBuf;

       if (VerQueryValue(buf,AnsiString("\\StringFileInfo\\"+CharSet+"\\CompanyName").c_str(),&(void        *)ValueBuf,&Len)!=0)
         Company->Caption=ValueBuf;
      }
  }

GlobalFree(buf);
где AppName, Version, Company - имена компонентов TLabel, которые расположены на вашей форме, и которые отображают полученную информацию.



Как скрыть закладку в TPageControl?

Для сокрытия закладки в компоненте TPageControl воспользуйтесь следующим кодом:
PageControl1->Pages[1]->TabVisible = false;
где PageControl1 - ваш компонент TPageControl, расположенный на форме. Данный код скрывает закладку с индексом 1. Для сокрытия другой закладки вместо единицы должен стоять соответствующий индекс.



Как скрыть столбец в TStringGrid?

Для сокрытия какого-либо из столбцов компонента TStringGrid воспользуйтесь кодом:
StringGrid1->ColWidths[Index] = -1;
где StringGrid1 - компонент TStringGrid, размещенный на форме, Index - порядковый номер столбца. Помните, что нумерация столбцов начинается с нуля.



Ошибка при подключении к Access через ADO

При подключении к Access через ADO при запуске проекта под IDE возникает ошибка:
Project Project1.exe raised exception class EVariantTypeCastError with message
'Could not convert variant of type (Null) into type (String)'. Process
stopped. Use Step or Run to continue.
Это проблема в драйвере базы данных и есть два варианта решения данной проблемы:

1. Ничего не предпринимать, оставить как есть. Ошибка возникает только при запуске приложения под IDE - и при обычном запуске никакого сообщения об ошибке выдано не будет, приложение будет функционировать нормально.
2. Сменить драйвер доступа к БД: вместо ODBC надо использовать Jet 4.0.



Медленно работает TADODataSet->Open()

Симптомы: при открытии таблицы с несколькими десятками тысяч записей, находящейся в файле БД Access, с помощью TADODataSet->Open() перестают обрабатываться сообщения окна, все тормозит. Полностью операция открытия завершается через 10-20 секунд. Что можно сделать?

Решение: перед открытием таблицы необходимо отключить все вычисляемые поля, в TADODataSet->ExecuteOptions выставить eoAsyncExecute в true, и после завершения открытия таблицы в обработчике события AfterOpen TADODataSet перерисовать элементы управления для отображения данных (вызывать TDBGrid->Refresh(), например).



Перечисление принтеров

Код перечисляет все принтеры и выводит данные о них в Мемо:
PRINTER_INFO_2 *Pr; 
DWORD byteNeed = 0,prCount=0;//Кол-во необходимых байт, количество принтеров
//Делаем первый вызов с буфером NULL, чтоб узнать нужный размер буфера
EnumPrinters(PRINTER_ENUM_CONNECTIONS|PRINTER_ENUM_LOCAL,NULL,2,NULL,0,&byteNeed,&prCount);
//Создаем буфер
Pr = new PRINTER_INFO_2 [byteNeed];
//Делаем второй вызов уже с нужным буфером
if(EnumPrinters(PRINTER_ENUM_CONNECTIONS|PRINTER_ENUM_LOCAL,NULL,2,(LPBYTE)Pr,byteNeed,&byteNeed,&prCount))
  {
    for(int i = 0; i < prCount; ++i)
      {
        Memo1->Lines->Add("Printer*************");
        Memo1->Lines->Add("Имя: " + AnsiString(Pr[i].pPrinterName));
        Memo1->Lines->Add("Порт: " + AnsiString(Pr[i].pPortName));
        Memo1->Lines->Add("Драйвер: " + AnsiString(Pr[i].pDriverName));
        Memo1->Lines->Add("");
      }
  }
delete Pr;



Как импортировать данные из текстового файла в Excel?

Для импорта данных в Excel из текстового файла разместите компонент TExcelApplication (ExcelApplication1) на форме и воспользуйтесь следующим кодом:
ExcelApplication1->Connect(); 
ExcelApplication1->Visible[0]=true;
ExcelApplication1->Workbooks->_OpenText(StringToOleStr("c:\\1.txt"),
  xlWindows,
  1,
  xlDelimited,
  xlDoubleQuote,
  false,
  false,
  false,
  true,
  false,
  false,
  false,
  TNoParam(),
  TNoParam(),
  TDefLCID());
Данный код импортирует данные из файла 1.txt, расположенного на диске С.



Как получить список активных процессов?

Для получения списка активных процессов воспользуйтесь следующей функцией:
//--------------------------------------------------------------------------- 
// Получить список активных просессов
// возврат: заполняет список информацией вида
// Win2k
// [SYSTEM PROCESS]
// SYSTEM
// SERVICES.EXE
// MIRANDA32.EXE
// BCB.EXE
//
// Win98
// C:\WINDOWS\SYSTEM\KERNEL32.DLL
// C:\WINDOWS\SYSTEM\MSGSRV32.EXE
// C:\WINDOWS\SYSTEM\SPOOL32.EXE
//
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#include <tlhelp32.hpp>

PACKAGE void __fastcall GetActiveAppList (TStringList *slist)
{
if (!slist) return;

slist->Clear();

TProcessEntry32 prj;
prj.dwSize = sizeof(PROCESSENTRY32);

HANDLE hss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if (((int)(hss)) == (-1)) return;

AnsiString fname;
try {
for (bool loop = Process32First(hss, &prj); loop; loop = Process32Next(hss, &prj))
{ fname = AnsiString(prj.szExeFile).Trim().UpperCase();
if (fname.IsEmpty()) continue;
slist->Add(fname);
}
} // try
catch (...) { slist->Clear(); }

CloseHandle(hss);
}

//---------------------------------------------------------------------------

void __fastcall TF_Main::BitBtn1Click(TObject *Sender)
{
TStringList *slist = new TStringList();
try { GetActiveAppList(slist); Mem_Info->Lines->Text = slist->Text; }
__finally { delete slist; }
}
//---------------------------------------------------------------------------



Как проиграть мп3-файл?

Для проигрывания мп3-файла воспользуйтесь следующим кодом:
HWND MCIHwnd = MCIWndCreate(Application->Handle, HInstance, NULL, "test.mp3"); 
MCIWndPlay(MCIHwnd);



Преобразование TColor в RGB

Для преобразования значения TColor в RGB-значение, воспользуйтесь функцией ColorToRGB из модуля Graphics.hpp:
long L = ColorToRGB(Color);
где Color - значение типа TColor.



Конвертация bmp в jpeg средствами C++Builder

Наиболее простой путь конвертации bmp-файла в jpeg-файл с использованием стандартных средств C++Builder состоит в следующем:

подключите файл "jpeg.hpp";
разместите на форме компонент TImage (Image1), где у вас будет загружен bmp-файл;
воспользуйтесь следующим кодом:
TJPEGImage *jp = new TJPEGImage();
try
  {
    jp->Assign(Image1->Picture->Bitmap);
    jp->SaveToFile("c:\\converted.jpg");
  }
__finally
  {
    delete jp;
  }



Конвертация bmp в jpeg средствами C++Builder

Наиболее простой путь конвертации bmp-файла в jpeg-файл с использованием стандартных средств C++Builder состоит в следующем:

подключите файл "jpeg.hpp";
разместите на форме компонент TImage (Image1), где у вас будет загружен bmp-файл;
воспользуйтесь следующим кодом:
TJPEGImage *jp = new TJPEGImage();
try
  {
    jp->Assign(Image1->Picture->Bitmap);
    jp->SaveToFile("c:\\converted.jpg");
  }
__finally
  {
    delete jp;
  }



Извлечение изображения из blob-поля таблицы

Для того, чтобы из blob-поля таблицы вытащить изображение и сохранить его в файл, можно воспользоваться следующим кодом:
TMemoryStream *M1 = new TMemoryStream(); 
TStream *B1 = Table1->CreateBlobStream(Table1->FieldByName("photo"),bmRead);
M1->CopyFrom(B1,B1->Size);
M1->SaveToFile("C:\\temp.jpg");
delete B1;
delete M1;
где:
Table1 - компонент TTable, соответствующий данной таблице, поле "photo" - поле в таблице, где хранятся изображения в формате jpeg.