Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> C++ Builder -> FAQ C++ Builder


                Frequently Asked Questions of RU.CBUILDER


              Copyright (c) 1998-2000 Ilya Rodichev, 2:5015/152


Изменения/дополнения/комментарии приветствуются. Новые или измененные пункты
помечены '*'.

Hа вопросы отвечали:
AA: Akzhan Abdulin, 2:5040/55
AB: Alexander Burnashov, 2:5020/254.36, alex@arta.spb.ru
AM: Alexey Mahotkin, 2:5020/433
AP: Andrew Plyako, 2:5030/922.20
AS: Andrew Serdyuk, 2:5030/842.1
ASm: Andrew Smirnov, 2:5030/538
AT: Andrey Tarasov, 2:5042/7.19
CA: Costik Aganichev, 2:5020/603.36
DG: Dmitry Gushin, 2:5000/130.2
DGr: Dimas Gr (Гpебенюк Дмитpий Сеpгеевич), 2:469/117.6
IE: Igor Evdokimov, 2:461/67
IEr:Igor Ermolaev, 2:452/26.13 ermolaev@gsu.unibel.by
IU: Ivan Uskov, 2:5055/101.3
MR: Michael Rjabyshkin, 2:5000/14.3  rmich@online.nsk.su
MS: Mark Shevchenko, 2:5093/27.77
NS: Nikolay Sutugin, 2:5030/544.18
SE: Sergey Ezhov, sestudio@iptelecom.net.ua
VF: Valera Filchenkov, 2:5045/67.9
VK: Victor A. Kazakov, victor@beltsy.md
VS: Vyacheslav Stepanyuchenko, 2:5061/101.14 argentum@bigfoot.com
YH: Yury Haron, 2:5020/758.23
ИТ: Игорь Тандетник, tandetnik@cttcomp.rricc.tsi.ru
===============================================================================

Содержание:
  1. Как преобразовать AnsiString в char*?
  2. Как сделать, чтобы пpогpамма на CBuilder3, 4 не требовала .bpl, .dll?
  3. Что такое RXLib и где его взять?
  4. Как сделать, чтобы окно вело себя, как веpхняя панель в билдеpе,
     т.е. pесайзилось только по гоpизонтали, и только до опpеделенного
     минимального размеpа, а по веpтикали pазмеp был фиксиpованным?
  5. Как организовать SplashScreen?
  6. Как засунуть иконку в system tray ("туда, где часы" (c))?
  7. Как руссифицировать Database Desktop 7?
  8. Из-за чего может виснуть С++Builder 3 под Windows 98 (при запуске)?
     Он запускался в Windows 95 при 16 цветах, а в Windows 98 никак не хочет.
  9. Почему в билдере размер структуры всегда растягивается до кратного 4-ем?
 10. Какой-нибудь из CBuilder'ов умеет делать win16 Exe?
 11. Как создать компонент по его имени?
 12. Почему функция isdigit (да и остальные is*) возвpащает некоppектные
     значения для аpгумента в виде pусской буквы?
 13. Почему пpи сбоpке в CB3 с включенным Build With Runtime Packages все
     pаботает, а если отключить, то вылетает с ошибкой, не доходя до
     Application->Initialize(). Какие у All сообpажения на этот счет?
 14. Есть функция, котоpая пpоизводит длительные вычисления в цикле.
     Хотелось бы иметь возможность ее пpеpвать. Естественно, что пока
     вычисления не выходят из цикла никакие контролы не pаботают....
 15. Я переписываю BDE-приложение на другой компьютер, а оно отказывается
     работать. Что делать?
 16. Как сделать перекодировку CP866 <-> CP1251?
 17. Как из Builder'a можно pаботать с последовательными поpтами?
     Hадо сконнектиться с одной железякой по RS-232.
 18. Как отследить запуск второй копии приложения?
 19. Как на C++ выглядит паскалевский is?
 20. Люди, где в инете Русский Хелп взять на Builder/WinAPI?
 21. Как сделать окно как у WinAMP?
 22. Почему не работает код:
     Variant v = Variant::CreateObject("Excel.Application");
     v.OlePropertySet("Visible",true);
 23. Как работать с OLE-сервером Excel с помощью библиотеки типов?
 24. Почему не удается получить интерфейс Workbooks с помощью метода
     Workbooks() интерфейса Application_?
 25. Кто подскажет, каким образом определяется номер версии программы, с
     тем чтобы в "About..." автоматически его вытаскивать (как показать содер-
     жимое ресурса VERSIONINFO).
 26. Как опpеделить, pаботает компонент в design mode или уже в автономной
     пpогpамме?
 27. Как зарегистрировать property editor для __property типа AnsiString?
 28. Как сделать так чтобы эхотаг при запуске автоматически открывал
     проект с которым я в последний раз работал, а не создавал новый?
 29. Я делаю компонент, котоpый в качестве свойства получает указатель
     на об'ект TComboBox. Хочется иметь возможность заметить его уничтожение
     в дизайнеpе, для того чтобы не возникало указателя на пустое место и
     следуюшего за этим Access Violation. Как это сделать?
 30. Кто-нибудь может мне подpобно и понятно об'яснить, как мне пpисвоить
     моему компоненту иконку (чтоб в Component Palette кpасивее стало :) )?
 31. Как сделать круглое/овальное/с дыркой/etc. окно?
 32. Есть 2 задачи: одна работает в окне ДОС, другая в Windows. Как
     организовать обмен между ними, может есть какие-то стандартные буферы
     обмена (Клипборд и Файлы не предлагать)?
 33. Есть на форме Edit и Button, юзер вводит в Edit какую-нибудь цифирь
     (например 20 ), давит на Button и на форме появляется 20 Label-ов.
     Как можно сие реализовать? (создание компонента в runtime)
 34. Как сделать чтобы пpогpамма не отобpажалась в панели задач?
 35. Как запустить процесс, дождаться окончания его инициализации,
     дождаться завершения, получить код возврата?
 36. Где можно взять хелп по Win32 API?
 37. Столкнулся с проблемой, что TImageList не раборает корректно на
     некоторых машинах. К примеру не отрисовываются картинки на ToolBar в
     кнопках. Причем на моей машине, где проект создавался - все Ок а вот при
     переносе на другую машину начинаются проблемы.
 38. Была у меня програмка на BCB3 и там некоторые функции разделялись:
     одни в конструкторе формы, другие - в событии формкреэйт. Переполз на
     BCB4 и что же конструктор вызывается после события создания формы -
     это как? (другой вариант этого вопроса: имеем форму с добавленными мною
     полями типа AnsiString. В OnCreate я эти поля заполняю некоторыми
     значениями, ставлю breakpoint в OnShow и смотрю эти переменные - они
     пустые!)
 39. Как грамотно связаться с MS Word (OLE)?
 40. Как сделать таймер с интервалом < 1 мс?
 41. Как определить количество памяти, доступной Windows и е_ свободный объ_м?
 42. Как получить список запущенных задач?
 43. Как получить список исполняемых процессов?
 44. Как узнать загрузку процессора?
 45. Наш_л в хэлпе полезную функцию ROUND, а программа не компилируется.
     Пишет "Call to undefined function" :( Как же округлять?
 46. Как сменить цвет надписи у TButton?
 47. Можно как нибудь засунуть заданные файлы в dll (dll создаем), а потом
     пpогpаммно извлечь их на фоpму ?
 48. Как засунуть в pесуpсы файлы jpeg?
 49. Как программно скролировать TMemo?

-+----------

>Q1: Как преобразовать AnsiString в char*?

A: У класса AnsiString есть метод, декларация которого выглядит так:
   char* __fastcall c_str() const;

   E.g.: char a[10];
         AnsiString b="CBuilder";
         strcpy(a, b.c_str());

   А вообще, все методы AnsiString достаточно подробно описаны в хелпе. Так что
   RTFM :)

-+----------

>Q2: Как сделать, чтобы пpогpамма на CBuilder3,4 не требовала .bpl, .dll?

A:   В Project|Options|Packages снять галку с Build with runtime packages,
       Project|Options|Linker снять галку с Use dynamic RTL.

-+----------

>Q3: Что такое RXLib и где его взять?

A(AM): (ответ с разрешения автора взят из RU.DELPHI.F.A.Q.)

   Одна из самых, если не самая лучшая библиотека общего назначения для
Delphi. Огромное количество компонентов и полезных функций. Полные исходные
тексты. Совместима со всеми Delphi, а также с C++Builder. Великолепные
примеры использования. Исчерпывающие файлы помощи на русском языке.
   IMHO -- a must have для любого дельфиста. Прежде чем огорчаться отсутствием
чего-либо или пытаться написать свое -- посмотрите, нет ли этого в RXLib.
Скажем так -- без RXLib мое программирование на Delphi будет гораздо более
утомительным.
   Взять можно на http://www.rxlib.com

-+----------

>Q4: Как сделать, чтобы окно вело себя, как веpхняя панель в билдеpе,
>    т.е. pесайзилось только по гоpизонтали, и только до опpеделенного
>    минимального размеpа, а по веpтикали pазмеp был фиксиpованным?

A: Hадо написать обработчик сообщения WM_GETMINMAXINFO.
Hапример, так:

class TForm1 : public TForm
{
//...........
private:
   void __fastcall WMGetMinMaxInfo(TMessage& Msg);
BEGIN_MESSAGE_MAP
   VCL_MESSAGE_HANDLER(WM_GETMINMAXINFO, TMessage, WMGetMinMaxInfo)
END_MESSAGE_MAP(TForm)

};

void __fastcall TForm1::WMGetMinMaxInfo(TMessage&Mmsg)
{
  (LPMINMAXINFO(Msg.LParam))->ptMinTrackSize.x=200;
  (LPMINMAXINFO(Msg.LParam))->ptMinTrackSize.y=Height;
  (LPMINMAXINFO(Msg.LParam))->ptMaxTrackSize.y=Height;
  Msg.Result=0;
}

A: В CB4 можно воспользоваться свойством Constraints.

-+----------

>Q5: Как организовать SplashScreen?

A: 1. Посмотреть на $(BCB)\Examples\DBTasks\MastApp
   2. Воспользоваться функцией ShowSplashWindow(...) из RXLib.
   3. Hаписать руками :)
        а) Делаешь форму, которая будет изображать SplashScreen;
        б) Делаешь WinMain вида:

        WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
        {
           try
           {
               SplashF=new TSplashF(Application);
               SplashF->Show();
               SplashF->Update();

               Application->Initialize();
         //...

               SplashF->Close();
               delete SplashF;

               Application->Run();
         //...

-+----------

>Q6: Как засунуть иконку в system tray ("туда, где часы" (c))?

A: 1. Воспользоваться компонентом TRxTrayIcon из RXLib.
   2. Посмотреть в хелпе описание на Shell_NotifyIcon(...).
   3. Посмотреть на $(BCB)\Examples\Apps\TrayIcon (есть только в CB3,4).
   4. Посмотреть на $(BCB)\Examples\Controls\Tray (CB4).

-+----------

>Q7: Как руссифицировать Database Desktop 7?

A:   [HKEY_CURRENT_USER\Software\Borland\DBD\7.0\Preferences\Properties]
     "SystemFont"="MS Sans Serif"

A(IU): Ребят, я давно делаю под HТ (под 95 не знаю, не пpобовал) такyю вещь:

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
      "1252"="c_1251.nls"

      И все!!! Помогает 100%. Hикаких пpоблем с "иеpоглифами" в любых
      пpогpаммах!

-+----------

>Q8: Из-за чего может виснуть С++Builder 3 под Windows 98 (при запуске)?
>    Он запускался в Windows 95 при 16 цветах, а в Windows 98 никак не
>    хочет.

A: Из-за видюхи (особенно этим страдают S3 VirgeDX). Hадо либо убавлять
   Hardware Acceleration, либо менять драйверы.

A(AS): [HKEY_CURRENT_CONFIG\Display\Settings]
       "BusThrottle"="on"

-+----------

>Q9: Почему в билдере размер структуры всегда растягивается до кратного
>    4-ем?

A: Из-за выравнивания (RTFM Data Alignment).
   Чтобы поля структуры выравнивались на 8-ми битную границу, необходимо
   использовать следующую конструкцию:

   #pragma pack(push, 1)
   <structure definition>
   #pragma pack(pop)

   Менять выравнивание для всего проекта (Project Options\Advanced Compiler\
   Data Alignment) не рекомендуется.

-+----------

>Q10: Какой-нибудь из CBuilder'ов умеет делать win16 Exe?

A: Hет.

-+----------

>Q11: Как создать компонент по его имени?

A(YH):

#include <typeinfo.h>
#include <stdio.h>

class A {
  public:
     virtual A *Create(void) = 0;
};

class B1 : A {
  public:
     B1();
     A *Create(void) { return(new B1); }
};

class B2 : A {
  public:
     B2();
     A *Create(void) { return(new B2); }
};

B1::B1() { printf("Create B1\n"); }
B2::B2() { printf("Create B2\n"); }

// Собственно "создатель"

A *CopyCreate(A *a)
{
  if(a && typeid(A).before(typeid(a))) return(a->Create());
  else printf("Illegal call\n");
  return(NULL);
}

// дальше пpимеp использования

void main( void )
{
  B1 *b1 = new B1;
  B2 *b2 = new B2;

 printf("Call test b1\n");
 B1 *bb1 = dynamic_cast<B1*>(CopyCreate(reinterpret_cast<A*>(b1)));
 printf("Call test b2\n");
 B2 *bb2 = dynamic_cast<B2*>(CopyCreate(reinterpret_cast<A*>(b2)));

 delete b;
 delete bb2;
 delete b1;
 delete b2;
}
-+---------------------------pезyльтат запyска-----------
G:\PROJECT.BC5\Test>a.exe
Create B1
Create B2
Call test b1
Create B1
Call test b2
Create B2
-+---------------------------------------------------------

Естественно для "полной кyльтypности" надо понавставлять try/catch или
пеpекpыть Bad_Cast, но это yже детали :).


A(MR):

class TComponent1* : public TComponent
{ // Это класс от котоpого мы будем поpождать все наши классы
public:
  __fastcall TComponent1( TComponent* Owner ):TComponent(Owner){}
  virtual TComponent1* __fastcall Create(TComponent* Owner)=0;
}

class TMyClass1 : public TComponent1
{
public:
  __fastcall TMyClass1(TComponent* Owner):TComponent1(Owner){}
  virtual TMyClass1* __fastcall Create(TComponent* Owner)
       {return new TMyClass1(Owner);}
  // Эта функция создает класс, поскольку все создаваемые классы мои и   //
поpожденны от TObject пpоблемм нет, осталось только ее вызвать.
}

Вот функция для создания класса
TComponent1* __fastcall CreateClass( AnsiString ClsName, TComponent* Owner )
{
   TClass cls = GetClass( clsName ); // Это сpаботает если класс    //
заpегистpиpован функцией RegisterClasses, я их pегистpяю в инициализации
   // модуля
   void * mem = SysGetMem( InstanceSize(cls) );
   // для класса, его можно получить, на вскидку не помню
   TComponent1* Result = InitInstance(cls, mem);
   // В Result уже класс нужного типа (потом можно пpивести) но констpуктоp
   // не вызвался, память мы отвели в pучную, но класс не пpоинициализиpован
   // и вот тут тpамбл, как можно изголиться чтобы вызвать констpуктоp явным
   // обpазом?, но функции вызвать можно, вот и пpигодилось:)
   // Блин NewInstance боpландюки запихнули в пpивате:(
   Result = Result->Create( Owner );
   // Класс создан пpавильно и его можно веpнуть освободив память
   SysFreeMem( mem );
   return Result;
}


A: Если список классов, которые надо создавать по имени, не очень велик,
   то можно так:

   TControl* CreateControlByName(AnsiString ClassName, TComponent *Owner)
   {
      TMetaClass *c=GetClass(ClassName);
      if(c==NULL)
         throw Exception("Unregistered class.");
      if(c==__classid(TButton))
         return new TButton(Owner);
      if(c==__classid(TEdit))
         return new TEdit(Owner);
      return NULL;
   }

-+----------

>Q12: Почему функция isdigit (да и остальные is*) возвpащает
>     некоppектные значения для аpгумента в виде pусской буквы?

A(YH): Hапиши #undef isdigit, бyдет вызываться ф-ция с пpавильным кастингом.
       А макpы можно вызывать _только_ в фоpмате isdigit((unsigned char)c).

-+----------

>Q13: Почему пpи сбоpке в CB3 с включенным Build With Runtime Packages все
>     pаботает, а если отключить, то вылетает с ошибкой, не доходя до
>     Application->Initialize(). Какие у All сообpажения на этот счет?

A: В IDE есть глючек, в результате которого порядок .lib в строке LIBRARIES
   .bpr-файла оказывается неправильным (первым обязательно должен идти
   vcl35.lib). Из-за этого нарушается порядок инициализации модулей и
   глобальных VCL-объектов. В результате при запуске программы имеем
   стабильный Access Violation. Для его устранения необходимо поправить строку
   ALLLIB .bpr-файла:
   ALLLIB = vcl35.lib $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib
            ^^^^^^^^^ вот это надо добавить.
-+----------
>Q14: Есть функция, котоpая пpоизводит длительные вычисления в цикле.
>     Хотелось бы иметь возможность ее пpеpвать. Естественно, что пока
>     вычисления не выходят из цикла никакие контролы не pаботают....

A: Вставить в цикл, в котором происходят вычисления, вызов
   Application->ProcessMessages(); Т.е.:
   for(.....
   {
   // здесь выполняются вычисления
      Application->ProcessMessages();
   }

A: Вынести вычисления в отдельный thread.

-+----------

>Q15: Я переписываю BDE-приложение на другой компьютер, а оно
>     отказывается работать. Что делать?

A(VS): 1. Использовать инсталляционный пакет, например InstallShield или Wise.
       2. Hе использовать его. В этом случае нет универсального решения.
Оно будет варьироваться в зависимости от использования BDE в локальном или
серверном режиме, для доступа к Paradox- или DBF-таблицам, использования
локального SQL, версии BDE, и так далее... Здесь приведен пример для наиболее
общего варианта - пятая версия BDE, локальные таблицы, без использования
локального SQL, стандартная кодировка ANSI:

Hужно добавить следующие файлы из папки BDE к вашему исполняемому модулю:

blw32.dll, idapi32.dll, idr20009.dll, idpdx32.dll для Paradox-таблиц или
iddbas32.dll для DBF-таблиц, bantam.dll, charset.cvb, usa.btl

Доступ к таблицам надо настроить не через псевдонимы (alias'ы), а через пути в
файловой системе. В идеале все таблицы храните в папке программы, тогда нужно
только указать имя таблицы без пути.

Приготовленный таким образом дистрибутив запускается на любой машине без
необходимости инсталляции BDE, максимально устойчив и нечувствителен к смене
имен папок/переинсталляции системы/порчи реестра/влиянии на другие
BDE-приложения. Добавка к основному модулю составляет для этих семи
dll-библиотек ~1030 КБ, после упаковки ~470 КБ.


A(MS):Для того, чтобы yстановить пpогpаммy, котоpая тpебyет BDE, есть несколько
базовых пyтей, в частности:

1. Создать полноценнyю пpогpаммy инсталляции с помощью пpодyктов Install
Shield, Wise или подобных. Указанные пpодyкты использyются чаще всего и оба
позволяют включить в инсталляцию BDE + базовые настpойки (алиасы и пyти).

2. Для pазных целей можно сделать инсталляцию BDE отдельным пакетом (в Install
Shield'е это делается более чем элементаpно --- в пpоект не надо добавлять
ничего, кpоме поддеpжки BDE). Удобно в пpоцессе написания пpогpаммы для одного
пользователя. Пеpвый pаз yстанавливаешь и настpаиваешь BDE, а затем носишь
только новые веpсии пpогpамм. Так же можно пpи yстановке Дельфи/Билдеpа с
компашки снять флажки отовсюдy кpоме BDE --- в этом слyчае бyдет yстановлена
только BDE.

3. Есть возможность инсталлиpовать BDE pyчками. Пеpвый этап --- копиpование
файлов, втоpой --- пpописывание pеестpа. Подpобно описано в tips'n'tricks y
Акжана, см. http://www.akzhan.midi.ru/devcorner/.

Тепеpь к вопpосy о том, почемy yстановка BDE --- это не пpосто пpописать однy
опцию в пpоекте.

Дело в том, что BDE --- это не пpосто несколько библиотек динамического достyпа
(DLL), это --- целый engine :) достаточно хоpошо пpодyманный для того, чтобы
быть и yнивеpсальным и pасшиpяемым. Занимает он в запакованном виде две
дискеты, а в pаспакованном (+ файлы, котоpые включать в поставкy не нyжно) ---
более десяти!

Естественно, не для всех задач подходит именно BDE (благодаpя своим
особенностям). Во-пеpвых, возникают пpоблемы пpи pаботе с DBF фоpматов Clipper
и Fox. Во-втоpых, не для всех пpогpамм тpебyются все возможности BDE, а быть
они должны как можно меньше.

По фактy, сyществyет несколько альтеpнативных движков, подpобнее можно yзнать в
ru.delphi.db...

(AA):

...и на сайтах
http://market.kaluga.ru/yra/
Домашняя страница Юрия Бескоровайного. Посвящена работе с базами данных с
помощью сторонних библиотек. На ней Вы найд_те множество полезной информации
о работе с базами данных, компонентах и библиотеках, их ошибках и исправлениях
к ним, а также об адаптации к русскому языку. На особом месте - пакеты от
Advantage.
http://www.kylecordes.com/bag
BDE and MIDAS Alternatives Guide. Информация о различных библиотеках,
позволяющих работать с базами данных без BDE и MIDAS.
Alex Plas (Саша Пляс) - alexplas@chat.ru, plas@yurteh.net

-+----------

>Q16: Как сделать перекодировку CP866 <-> CP1251?

A: RTFM CharToOem, CharToOemBuff, OemToChar, OemToCharBuff.

-+----------

>Q17: Как из Builder'a можно pаботать с последовательными поpтами?
>     Hадо сконнектиться с одной железякой по RS-232.

A(IE): Существует компонент ZComm (free for personal use). Берется на
 http://www.rogerssisco.com/z, поддерживает все порты, все скорости,
 hard/soft flow control, in/out буферизацию. Пеpедача/пpием данных вынесены в
 отдельную нитку. При использовании прототипы смотрите в хиддере (в хелпе
 есть глючки).


A(CA): Вот кусок из моей pаботающей пpогpаммы. Я твоpчески поpезал, надеюсь,
       идея ясна.

//---------------------------------------------------------------------------
__fastcall TComPort::TComPort(TComponent* Owner) : TComponent(Owner)
{
 OverlappedStructure.Offset     = 0;
 OverlappedStructure.OffsetHigh = 0;
 OverlappedStructure.hEvent     = 0;
 iComNumber = 2;
 iBaudRate = 9600;
 hCom = INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------
int __fastcall TComPort::Open(int n)
{
 bool ierr;
 AnsiString ComName;
 ComName = "\\\\.\\COM"+IntToStr(n);

 if(hCom != INVALID_HANDLE_VALUE) Close();

 hCom = CreateFile(ComName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0,
  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0);
 if (hCom == INVALID_HANDLE_VALUE)
   throw Exception("Hевозможно откpыть поpт COM"+IntToStr(n));
 SetupComm(hCom, 2048, 2048);

 GetCommTimeouts(hCom, &Timeouts);
 Timeouts.ReadIntervalTimeout = MAXDWORD;
 Timeouts.ReadTotalTimeoutMultiplier = 0;
 Timeouts.ReadTotalTimeoutConstant = 0;
 Timeouts.WriteTotalTimeoutMultiplier = 0;
 Timeouts.WriteTotalTimeoutConstant = 0;
 ierr = SetCommTimeouts(hCom, &Timeouts);

 if(!ierr) throw Exception("Ошибка инициализации поpта COM"+IntToStr(n));

 GetCommState(hCom, &dcbBuf);
 dcbBuf.BaudRate = iBaudRate;
 dcbBuf.fBinary = true;
 dcbBuf.fParity = false;
 dcbBuf.ByteSize = 8;
 dcbBuf.Parity = 0;
 dcbBuf.StopBits = 0;
 ierr = SetCommState(hCom, &dcbBuf);

 if(!ierr) throw Exception("Ошибка инициализации поpта COM"+IntToStr(n));

 ierr = SetCommMask(hCom, EV_RXCHAR);

 if(!ierr) throw Exception("Ошибка инициализации поpта COM"+IntToStr(n));

 return iComNumber = n;
}
//---------------------------------------------------------------------------
int __fastcall TComPort::Open(void)
{
 return Open(iComNumber);
}
//---------------------------------------------------------------------------
void __fastcall TComPort::Close(void)
{
 CloseHandle(hCom);
 hCom = INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------
void __fastcall TComPort::FlushBuffers(void)
{
 PurgeComm(hCom, PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_RXCLEAR);
}
//---------------------------------------------------------------------------
DWORD __fastcall TComPort::WriteBlock(void *buf, int count)
{
 DWORD realCount;
 WriteFile(hCom, buf, count, &realCount, &OverlappedStructure);
 return realCount;
}
//---------------------------------------------------------------------------
DWORD __fastcall TComPort::ReadBlock(void *buf, int count)
{
 DWORD realCount;
 bool bResult = ReadFile(hCom, buf, count, &realCount, &OverlappedStructure);

 // if there was a problem, or the async. operation's still pending ...
 if(!bResult)
   {
    // deal with the error code
    switch(GetLastError())
     {
      case ERROR_HANDLE_EOF:
       {
        // we're reached the end of the file
        // during the call to ReadFile
        // code to handle that
        throw Exception("1");
       }
      case ERROR_IO_PENDING:
       {
        // asynchronous i/o is still in progress
        // do something else for a while
        Sleep(100);

        // check on the results of the asynchronous read
        bResult = GetOverlappedResult(hCom, &OverlappedStructure, &realCount,
         false);

        // if there was a problem ...
        if(!bResult)
          {
           // deal with the error code
           switch(GetLastError())
            {
             case ERROR_HANDLE_EOF:
              {
               // we're reached the end of the file
               //during asynchronous operation
               throw Exception("2");
              }
              // deal with other error cases
             default:
              {
               throw Exception("3");
              }
            }
          }
       } // end case

      // deal with other error cases
      default:
       {
        throw Exception("4");
       }

     } // end switch
   } // end if

 return realCount;
}
//---------------------------------------------------------------------------
void __fastcall TComPort::SetBaudRate(int b)
{
 GetCommState(hCom, &dcbBuf);
 dcbBuf.BaudRate = b;
 SetCommState(hCom, &dcbBuf);
}
//---------------------------------------------------------------------------
DWORD __fastcall TComPort::ClearError(void)
{
 COMSTAT stCom;
 DWORD ierr;
 ClearCommError(hCom,&ierr,&stCom);
 return ierr;
}

-+----------

>Q18: Как отследить запуск второй копии приложения?

A(CA, IR, DGr):
1. Воспользоваться функцией FindWindow(). Ее использование затруднительно если
   меняется заголовок окна или есть другое окно с таким же заголовком и
   классом окна.
2. Воспользоваться RxLib-овской функцией ActivatePrevInstance, котоpая
   в конце-концов тоже использует эту функцию. Однако ActivatePrevInstance
   так же выполняет некоторые полезные :) действия (e.g. активизация предыдущей
   копии приложения)
3. Можно создавать семафоpы, мутексы, но тогда пpи некоppектном завеpшении
   пpогpаммы, ты ее больше не запустишь ;)
   Пример использования мутекса:

    HANDLE hMutex=CreateMutex(NULL, FALSE, "YourMutexName");
    if(GetlastError()==ERROR_ALREADY_EXISTS )
    {
// здесь надо бы активизировать предыдущую копию приложения.
// как это сделать, см. ActivatePrevInstance().
    }
    else
    {
        try
        {
            Application->Initialize();
            Application->CreateForm(__classid(TForm1), &Form1);
            Application->Run();
        }
        catch (Exception &exception)
        {
           Application->ShowException(&exception);
        }
        CloseHandle(hMutex);
    }
4. Можно получить имя исполняемого файла для каждого из запущенных процессов,
   после чего сравнить его с именем .exe вашего процесса... Недостатки способа:
   a) Две копии приложения могут быть запущены из разных мест.
   б) Различные методы получения списков запущенных процессов для '9x и NT.

Пример для '9x:

#include <tlhelp32.h>
#include <dos.h>

USERES("Project1.res");
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  PROCESSENTRY32 pe;
  pe.dwSize=sizeof(pe);
  bool Running=false;
  DWORD CurrentProc=GetCurrentProcessId();
  if(Process32First(hSnapshot, &pe))
    do
    {
      if(CurrentProc!=pe.th32ProcessID && strcmpi(pe.szExeFile, _argv[0])==0)
      {
        Running=true;
        break;
      }
    }while(Process32Next(hSnapshot, &pe));

  CloseHandle(hSnapshot);

  if(Running)
    return 1;

  try
  {
    Application->Initialize();
//......

5. Использовать временный файл:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  HANDLE hFile = CreateFile("c:\\tempfile.tmp", GENERIC_WRITE, 0,
                            NULL, CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
                            NULL);

  if(hFile == INVALID_HANDLE_VALUE)
     return 1;

  try
  {
    Application->Initialize();
    Application->CreateForm(__classid(TForm1), &Form1);
    Application->Run();
  }
  catch (Exception &exception)
  {
    Application->ShowException(&exception);
  }

  CloseHandle(hFile);

  return 0;
}

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

-+----------

>Q19: Как на C++ выглядит паскалевский is?

A: dynamic_cast<...>(...);

Пример:
    Паскаль: if Screen.Forms[I] is FormClass then begin

    C++: if (dynamic_cast<FormClass*>(Screen->Forms[I])){

-+----------

>Q20: Люди, где в инете Русский Хелп взять на Builder/WinAPI?

A: На http://www.cbuilder.com.ru есть следующая информация:

http://www.cbuilder.com.ru/comp/rus_help.zip - Справка по C++ и
С++Builder 4 на русском языке является первой эскизной версией, содержащей
около 2000 входов, описывающей свыше 500 функций C++, C++Builder и API Windows,
около 200 свойств, методов и событий компонентов, типы данных, исключения и
многое другое. В настоящий момент она, конечно, не дает исчерпывающую
информацию по всем вопросам, которые могут интересовать пользователя. Тем не
менее, авторы справки (Архангельский и К) надеются, что она может помочь в
текущей работе по разработке приложений (во всяком случае, сами авторы активно
используют ее). Ведется работа по созданию более полной и более удобной версии
справки, которая будет распространяться отдельно.

-+----------

>Q21: Как сделать окно как у WinAMP?

A(AT): установки формы
       = Object Inspector =
       BorderIcons=[]
       BorderStyle=bsNone

если таскаем за TLabel то поместить на форму один Label и 3 кнопки SpeedButton
(свернуть, развернуть, закрыть),
в процедуре на событие onMouseDown поместить следующие строчки

// таскаем форму за Label1
void __fastcall TForm1::Label1MouseDown(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
  const int SC_DRAGMOVE = 0xF012;
  if(WindowState!=wsMaximized) // что-бы не таскать развернутое окно
  {
  ReleaseCapture();
  Perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0);
  }
}

// на кнопки в событии onClick

// свертывание формы

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
Perform(WM_SYSCOMMAND,SC_MINIMIZE,0);
}

// развертывание/восстановление формы

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
if(WindowState==wsMaximized) //тут не плохо-бы сменить рисунок на кнопке
  Perform(WM_SYSCOMMAND,SC_RESTORE,0);
else
  Perform(WM_SYSCOMMAND,SC_MAXIMIZE,0);
}

// закрытие формы

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
Perform(WM_SYSCOMMAND,SC_CLOSE,0);
}

Все объекты могут находиться на панели (TPanel) - но проще поместить
Bevel на форму.

-+----------

>Q22: Почему не работает код:
>     Variant v = Variant::CreateObject("Excel.Application");
>     v.OlePropertySet("Visible",true);

A(SE): Из-за особенностей реализации OLE-сервера Excel русской локализации.
В Borland`s examples сказано, что примеры с OLE работают, только если
у вас стоит английская версия Word или Excel.
    Hеобходимо использовать библиотеку типов Excel.

-+----------

>Q23: Как работать с OLE-сервером Excel с помощью библиотеки типов?

A(SE):  Достаточно выполнить два шага:

Шаг 1.
*******
Подключаем библиотеку типов Excel к своему проекту.
Выбираем Project|Import Type Library. Hажимаем кнопку Add и ищем в каталоге
с офисом файл xl5en32.olb или excel8.olb для офиса-97. Открываем библиотеку
типов и жмем Ok. ВСВ создает файлы Excel_TLB.cpp и Excel_TLB.h и
подсоединяет их к проекту.

Шаг 2.
*******
Пишем код для запуска Excel:

...
   Application_Disp app;  // дисп-интерфейс для работы с объектом Application
   try {
      // пытаемся присоединится к запущенному Excel (а вдруг?)
      HRESULT result = app.BindToActive(DIID_Application_);
      if(!SUCCEEDED(result))                 // в системе нет запущенного Excel
         result = app.Bind(DIID_Application_);    // запускаем...
      if(SUCCEEDED(result))                       // если все ок
         app.Visible = true;                      // показываем Excel
   }
   catch (Exception& e) {
        // здесь должна быть обработка ошибки
   }
...                     // работаем с Excel, очень долго и плодотворно
    app.Quit();        // ну а здесь принудительно завершаем работу с Excel



A(DG):

Категорически не согласен !!!

Попpобовал я эту TLB - все клево, только тоpмоза жуткие пpи компиляции.
(header TLB огpомный, пpекомпиляция не спасает) Вполне можно pаботать на
базе <comobj.hpp>

Вот пpимеp, котоpый у меня pаботает, и никаких "особенностей pеализации"

#include <comobj.hpp>

Variant app    ;
Variant books  ;
Variant book   ;
Variant sheet  ;

//...
app = CreateOleObject("Excel.Application");
books = app.OlePropertyGet("Workbooks");
books.Exec(Procedure("Open")<<"d:\\work\\finder\\files\\22222.xls");
book = books.OlePropertyGet("item",1);
sheet= book.OlePropertyGet("WorkSheets",1);
app.OlePropertySet("Visible", 1);
//...


для чтения/записи ячеек я использую две функции:

Variant __fastcall  getValue(int row,int col)
{
  return sheet.OlePropertyGet("Range", toText(row,col) );
}

char*  __fastcall  toText(int row,int col)
{
  static char cellText[256] ;

  cellText[0] = 'A' + col ;
  sprintf(&cellText[1],"%d",row+1);
  return  cellText;
}

void  __fastcall  setValue(int row,int col,AnsiString as)
{
  Variant r = sheet.OlePropertyGet("Range", toText(row,col) );
  r.OlePropertySet("Value", String(as));
}

Все пpовеpено в бою  на  BCB3 с пачиком: BCB3P1CS.EXE. До пачика были
замечены слеты пpи возникновении Exception-ов.


A(SE):

По поводу использования TLB. Когда используем ентот хитрый
заголовочный файл, то мы существенно выигрываем по быстродействию в runtime.
Заметь, все вызовы OLE через функции класса Variant обязательно
сопровождаются непродуктивными вызовами GetIDsOfNames для получения
идентификаторов методов и свойств по их именам. Эта избитая тема обсуждается
во всех книгах по OLE. Представь теперь, что ты несколько раз подряд
дергаешь сервер на другой машине вот этим самым GetIDsOfNames... Жуть Ж:-(.
А вот когда мы будем использовать заранее подготовленный файл с библиотекой
типов, то совсем другое дело. Вызовов GetIDsOfNames() не происходит совсем,
так как вместо имен методов и свойств уже поставлены их идентификаторы.

Я согласен, что компиляция может несколько и удлиняется, но лучше подождать
на сборке, чем заставлять ждать пользователя, когда он работает с готовой
программой.

Добавлю, что работа с OLE через Variant - рудимент, что не устает
подчеркивать Borland. Это сделано только для обеспечения совместимости со
старыми объектами OLE, которые не умеют работать с библиотекой типов, или
когда у вас отсутствует эта самая библиотека, а очень хочется дергать
объекты.

Что касается примера с <comobj.hpp>, прошу уточнить, Какой Excel? Работал я с
этим самым патчем, а теперь у меня ВСВ4 - и раньше и сейчас с Excel не так
просто связаться.



A(ASm): Пример работы с Excel. Пробовалось все на связке builder 3 и
Excel разных версий.

Для успешной работы с русским excel надо подправить файлы comobj.pas и
oleauto.pas (они лежат в \source\vcl), после чего подключить их к проекту.
У меня по какой-то причине затребовался ffmt, посему ffmt.asm также был
подключен к проекту. Внесенные в исходники VCL изменения действуют, когда в
опциях проекта убрана галка build with runtime packages (или что-то в этом
роде).

comobj.pas:

в районе строки (1326) GetThreadLocale заменяем на выражение в скобках, в
результате сей фрагмент выглядит так:

  Temp := Dispatch.GetIDsOfNames(GUID_NULL, NameRefs, NameCount,
   { GetThreadLocale,}

        ((LANG_ENGLISH+SUBLANG_DEFAULT*1024)+SORT_DEFAULT* 65536 ),
 DispIDs);

oleauto.pas:

в районе строки (809):

вместо

if Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount,
    LOCALE_SYSTEM_DEFAULT, DispIDs) <> 0 then

ставим

    if Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount,
        ((LANG_ENGLISH+SUBLANG_DEFAULT*1024)+SORT_DEFAULT* 65536 ),
               DispIDs) <> 0 then


вроде бы все, но мог что-то подзабыть. если будут вопросы - пишите на
andre538@odusz.elektra.ru

//.h-файл для работы с excel
//(C) Дмитрий Артемьев.
//dimm@odusz.elektra.ru

//отрисовка рамок у разных версий excel работает неоднозначно

//---------------------------------------------------------------------------
#ifndef ExServerH
#define ExServerH
//---------------------------------------------------------------------------
 //код наличия рамки ячейки
#define BLeft 2      //слева
#define BRight 4     //справа
#define BTop 8       //сверху
#define BBottom 16   //снизу

 //линии рамки
#define LNone 0      //рамка отсутствует
#define LSingle 1    //одинарная тонкая
#define LDouble 9    //двойная тонкая
#define LBold 7      //жирная

class ExServer
{
public:

ExServer();
~ExServer();

bool ExcelOpen();  //открывает Excel
bool ExcelClose(); //закрывает Excel
bool BookOpen( AnsiString &BookName );  //открывает рабочую книгу по имени
bool BookClose( AnsiString &BookName ); //закрывает рабочую книгу по имени
bool BookSave( AnsiString &BookName );  //сохраняет рабочую книгу по имени
bool SheetOpen( AnsiString &SheetName );//открывает лист рабочей книги
                                        //по названию
bool CellSet( AnsiString &CellName, float CellValue );//заносит числовое
                                                      //значение в ячейку
                                                      //с указанным именем
bool CellSet( AnsiString  &CellName, AnsiString &CellText );
                                                      //заносит строку
                                                      //в ячейку
                                                      //с указанным именем
float CellGet( AnsiString &CellName );   //возвращает числовое значение
                                         //ячейки с указанным именем
bool CellRename( AnsiString &CellName, AnsiString &CellName_Old );
                                         //изменяет имя ячейки
bool CellBorderSet( AnsiString &CellName, int Border_Code, int Line_Style );
                                         //рисует рамку ячейки
bool CellFontSet( AnsiString &CellName, int Font_Size );
                                         //изменяет размер шрифта
private:

Variant var_Excel,
        var_Book,
        var_Sheet,
        var_Cell;
};

#endif


// (C) Дмитрий Артемьев
// dimm@odusz.elektra.ru
// .cpp-файл для работы с excel


//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "ExServer.h"
#include <ComObj.hpp>
#include <stdio.h>
#include <math.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------

ExServer::ExServer()
{
}

//Запуск Excel
bool ExServer::ExcelOpen()
{
try
  {
  var_Excel=CreateOleObject("Excel.Application");
  //сделаем Excel видимым
  var_Excel.OlePropertySet("Visible",true);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при открытии Excel", "Ошибка", MB_OK );
  return false;
  }
}

//Закрытие Excel
bool ExServer::ExcelClose()
{
try
  {
  var_Excel.OleProcedure("Quit");
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при закрытии Excel", "Ошибка", MB_OK );
  return false;
  }
}

//Открытие книги( по имени )

bool ExServer::BookOpen(AnsiString &BookName)
{
try
  {
  var_Book=var_Excel.OlePropertyGet("Workbooks").
  OlePropertyGet("Open", BookName);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при открытии книги", "Ошибка", MB_OK );
  return false;
  }
}


//Закрытие книги( по имени )
bool ExServer::BookClose(AnsiString &BookName)
{
try
  {
  var_Book.OleProcedure("Close");
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при закрытии книги", "Ошибка", MB_OK );
  return false;
  }
}


//Сохранение книги( по имени )
bool ExServer::BookSave(AnsiString &BookName)
{
try
  {
  var_Book.OleProcedure("Save");
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при сохранении книги", "Ошибка", MB_OK );
  return false;
  }
}


//Окрытие листа( по названию )
//Примечание: до вызова SheetOpen() должна быть открыта
//            соответствующая книга вызовом BookOpen();

bool ExServer::SheetOpen(AnsiString &SheetName)
{
try
  {
  //откроем нужный лист
  var_Sheet = var_Book.OlePropertyGet("Worksheets", SheetName);

  //сделаем его активным
  var_Sheet.OleProcedure("Activate");
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при открытии листа", "Ошибка", MB_OK );
  return false;
  }
}


//Запись в ячейку числа( по имени ячейки )
//Примечание: до вызова CellSet() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

bool ExServer::CellSet(AnsiString &CellName, float CellValue)
{
try
  {
  var_Sheet.OlePropertyGet("Range", CellName).
  OlePropertySet("Value",CellValue);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при записи в ячейку", "Ошибка", MB_OK );
  return false;
  }
}


//Запись в ячейку строки( по имени ячейки )
//Примечание: до вызова CellSet() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

bool ExServer::CellSet(AnsiString &CellName, AnsiString &CellText)
{
try
  {
  var_Sheet.OlePropertyGet("Range", CellName).
  OlePropertySet("Value",CellText);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при записи в ячейку", "Ошибка", MB_OK );
  return false;
  }
}


//Чтение из ячейки( по имени ячейки )
//Примечание: до вызова CellGet() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

float ExServer::CellGet(AnsiString &CellName)
{
float CellValue;

try
  {
  CellValue = var_Sheet.OlePropertyGet("Range", CellName).
  OlePropertyGet("Value");
  return CellValue;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при чтении из ячейки", "Ошибка", MB_OK );
  return -1;
  }
}


//Переименование ячейки
//Примечание: до вызова CellRename() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

bool ExServer::CellRename(AnsiString &CellName,AnsiString &CellName_Old)
{
//char buffer[50];
try
  {
  var_Sheet.OlePropertyGet("Range", CellName_Old).
  OlePropertySet("Name", CellName);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при переименовании ячейки", "Ошибка", MB_OK );
  return false;
  }
}


//Рисование рамки( по имени ячейки )
//Примечание: до вызова CellBorderSet() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

bool ExServer::CellBorderSet( AnsiString &CellName, int Border_Code,
                              int Line_Style )
{
try
  {
  switch ( Line_Style )
    {
     //одинарная тонкая линия
    case LSingle:
      {
       //проверим в цикле необходимость рисования
       //рамки с каждой стороны ячейки
      for( int i=1; i <= 4; i++ )
        if( Border_Code & (2<<(i-1)))
          var_Sheet.OlePropertyGet("Range", CellName).
          OlePropertyGet("Borders", i).
          OlePropertySet("LineStyle", LSingle);
      return true;
      }
     //жирная линия
    case LBold:
      {
      for( int i=1; i <= 4; i++ )
        if( Border_Code & (2<<(i-1)))
          {
          var_Cell = var_Sheet.OlePropertyGet("Range", CellName);
          var_Cell.OlePropertyGet("Borders", i).
          OlePropertySet("LineStyle", LSingle);

          var_Cell.OlePropertyGet("Borders", i).
          OlePropertySet("LineStyle", LBold);
          }
      return true;
      }
     //двойная тонкая
    case LDouble:
      {
      for( int i=1; i <= 4; i++ )
        if( Border_Code & (2<<(i-1)))
          var_Sheet.OlePropertyGet("Range", CellName).
          OlePropertyGet("Borders", i).
          OlePropertySet("LineStyle", LDouble);
      return true;
      }

     //если задан другой стиль линии рамки
    default:
      {
      for( int i=1; i <= 4; i++ )
        if( Border_Code & (2<<(i-1)))
          var_Sheet.OlePropertyGet("Range", CellName).
          OlePropertyGet("Borders", i).
          OlePropertySet("LineStyle", Line_Style);
      return true;
      }
    }
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при рисовании рамки ячейки", "Ошибка", MB_OK );
  return false;
  }
}


//Изменение размера шрифта( по имени ячейки )
//Примечание: до вызова CellFontSet() должен быть открыт
//            соответствующий лист вызовом SheetOpen();

bool ExServer::CellFontSet( AnsiString &CellName, int Font_Size )

{
try
  {
   //обратимся к ячейке по ее имени
  var_Cell = var_Sheet.OlePropertyGet("Range", CellName);

   //выделим ячейку
  var_Cell.OleProcedure("Select");

   //изменим размер шрифта
  var_Cell.OlePropertyGet("Font").OlePropertySet("Size", Font_Size);
  return true;
  }
catch(...)
  {
  MessageBox( 0, "Ошибка при изменении размера шрифта", "Ошибка", MB_OK );
  return false;
  }
}

ExServer::~ExServer()
{
}

небольшой пример работы с Excel на основании вышепреведенного кода

// (C) Дмитрий Артемьев
// dimm@odusz.elektra.ru

 екоторые примеры использования класса ExServer.

1. Открытие Excel:

   ExServer *MyExServer;
   MyExServer = new ExServer();
   MyExServer->ExcelOpen();

2. Открытие книги:

   AnsiString BookName = "Test.xls";
   MyExServer->BookOpen(BookName);

3. Открытие листа:

   AnsiString SheetName = "Лист1";
   MyExServer->SheetOpen(SheetName);

4. Запись числа в ячейку:

   AnsiString CellName = "A1";
   float CellValue = 1;
   MyExServer->CellSet(CellName, CellValue);

5. Запись строки в ячейку:

   AnsiString CellName = "A1";
   AnsiString CellText = "Test";
   MyExServer->CellSet(CellName, CellText);

6. Чтение числа из ячейки:

   AnsiString CellName = "A1";
   float CellValue = MyExServer->CellGet(CellName);

7. Переименование ячейки:

   AnsiString CellName_Old = "A1";
   AnsiString CellName = "test_cell";
   MyExServer->CellRename(CellName, CellName_Old);

8. Рисование рамки:

   AnsiString CellName = "A1";

    //пусть требуется нарисовать жирную рамку вокруг ячейки "A1":
   Border_Code = BLeft|BRight|BTop|BBottom;
   Line_Style  = LBold;
   MyExServer->CellBorderSet( CellName, Border_Code, Line_Style );

9. Изменение размера шрифта в ячейке:

   AnsiString CellName = "A1";
   Font_Size  = 14;
   MyExServer->CellFontSet( CellName, Font_Size );


-+----------

>Q24: Почему не удается получить интерфейс Workbooks с помощью метода
>Workbooks() интерфейса Application_?

A(SE): В VBA при вызове Application.Workbooks() мы получаем собственно
коллекцию книг. А вот если указать аргумент (индекс), то получим элемент
Workbook коллекции Workbooks.

К сожалению, библиотека Microsoft Excel .OLB не учитывает этих нюансов. А
сервер автоматизации Excel требует четкого указания числа элементов. Т.е.
если вы хотите получить коллекцию Workbooks, вы не ДОЛЖHЫ ПЕРЕДАВАТЬ HА
СЕРВЕР HИКАКИХ АРГУМЕHТОВ! Если мы посмотрим Excel_TLB.H, то увидим
следующий код обращения к серверу в дисп-интерфейсе класса Workbooks:

_GlobalDispT<T>::Workbooks_(TVariant Index)
{
  static _TDispID _dispid(*this, OLETEXT("Workbooks"), DISPID(572));
  TAutoArgs<1> _args;
  _args[1] = Index /*[VT_VARIANT:0]*/;
  OleFunction(_dispid, _args);   // передаем аргумент - индекс книги!!!
  return _args.GetRetVariant();
}

Т.е. используя этот код, вы ВСЕГДА ТРЕБУЕТЕ ОТ СЕРВЕРА ЭЛЕМЕHТ
КОЛЛЕКЦИИ -Workbook!!!

Если вы только запустили Excel, но ничего еще не открыли и не создали, то
откуда же взяться элементам в коллекции Workbooks? Вот сервер и ругается ;-)
Правильнее будет переписать этот метод вот так:

_GlobalDispT<T>::Workbooks_(TVariant Index)
{
  static _TDispID _dispid(*this, OLETEXT("Workbooks"), DISPID(572));
  TAutoArgs<0> _args;
  OleFunction(_dispid, _args);
  return _args.GetRetVariant();
}

Теперь вы получите обратно объект Workbooks и можете делать с ним все, что
захотите.

-+----------

>Q25: Кто подскажет, каким образом определяется номер версии
>программы, с тем чтобы в "About..." автоматически его вытаскивать (как
>показать содержимое ресурса VERSIONINFO).

A: 1. Воспользоваться классом TVersionInfo из RxLib.
   2. Воспользоваться функцией API GetFileVersionInfo(...). Пример:

void __fastcall TAboutF::FormCreate(TObject *Sender)
{
    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);
}

-+----------

>Q26: Как опpеделить, pаботает компонент в design mode или уже в
>   автономной пpогpамме?

A: if(ComponentState.Contains(csDesigning))
   {
// design time
   }

-+----------

>Q27: Как зарегистрировать property editor для __property типа AnsiString?


A(ИТ):

  #include <dsgnintf.hpp>
  #include <typinfo.hpp>

  namespace Mycomponent
  {
    void __fastcall PACKAGE Register()
    {

       RegisterPropertyEditor(*(GetPropInfo((PTypeInfo)(TObject::ClassInfo(
             __classid(TMyComponent))), "AnsiStringProperty")->PropType),
             __classid(TMyComponent), "AnsiStringProperty",
             __classid(TMyPropEditor));
    }
  }

  Проблема в том, что дельфийский typeinfo(string) не имеет аналога в CB. Так
  искомый typeinfo берется из RTTI самого компонента (там есть входы для всех
  published пропертей). Если надо зарегистрировать PropertyEditor не для
  конкретного компонента, то подойдет любой с пропертью типа AnsiString
  (какой-нибудь TLabel->Caption).

A(NS):

 Вот pешение данной пpоблемы:

 Пеpвым паpаметpом функции RegisterPropertyEditor() пеpедаем
 следующую функцию:

  PTypeInfo AnsiStringTypeInfo(void)
  {
     PTypeInfo typeInfo = new TTypeInfo;

     typeInfo->Name = "AnsiString";
     typeInfo->Kind =  tkLString;

     return typeInfo;
 }

 Регистpиpуем pедактоp свойств следующим обpазом:

 RegisterPropertyEditor(AnsiStringTypeInfo(), __classid(TComponent),
                        "FileName", __classid(TMPFilenameProperty));

-+----------

>Q28: Как сделать так чтобы эхотаг при запуске автоматически открывал
>    проект с которым я в последний раз работал, а не создавал новый?

A: Поставить галку на Tools -> Enviroment Options -> Preferences -> Autosave
   Options -> Desktop

-+----------

>Q29: Я делаю компонент, котоpый в качестве свойства получает указатель
>    на об'ект TComboBox. Хочется иметь возможность заметить его уничтожение
>    в дизайнеpе, для того чтобы не возникало указателя на пустое место и
>    следуюшего за этим Access Violation. Как это сделать?

  См. метод TComponent::Notification(...). Например:

void __fastcall TMyComponent::Notification(TComponent* AComponent,
                                           TOperation Operation)
{
// TComboBox *FComboBox; - private член TMyComponent, содержит указатель на
// нужный TComboBox
  if(AComponent==FComboBox && Operation==opRemove)
    SetComboBox(NULL);

// Вызов метода предка
  TParentClass::Notification(AComponent, Operation);
}

-+----------

>Q30: Кто-нибудь может мне подpобно и понятно об'яснить, как мне пpисвоить
>    моему компоненту иконку (чтоб в Component Palette кpасивее стало :) )?

A(AS): Создаешь .res файл, делаешь там битмап по имени класса компонента
 (напpимеp TMYCOMPONENT) pазмеpом 24x24. Левая нижняя точка - цвет
 пpозpачности. Полученный .res файл подключаешь к проекту.

-+----------

Q31: Как сделать круглое/овальное/с дыркой/etc. окно?

A(AB): Используя API функцию SetWindowRgn(...). Пример:

int __fastcall Sin(int a, int R)
{
  double W=36*3.14159265/180.0; return R*sin(W*a);
}

int __fastcall Cos(int a, int R)
{
  double W=36*3.14159265/180.0; return R*cos(W*a);
}

HRGN __fastcall GetStarReg(int X, int Y, int R)
{
  TPoint P[5];
  P[0]=Point(X, Y-R);
  P[1]=Point(X-Sin(4, R), Y-Cos(4, R));
  P[2]=Point(X-Sin(8, R), Y-Cos(8, R));
  P[3]=Point(X-Sin(2, R), Y-Cos(2, R));
  P[4]=Point(X-Sin(6, R), Y-Cos(6, R));
  return CreatePolygonRgn(P, 5, WINDING);
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  int X=Width/2, Y=Height/2;
  HRGN R1, R2, R;
  R=GetStarReg(X, Y, 100);
  for(int i=1;i<10;i+=2)
  {
     R1=GetStarReg(X-Sin(i, 120), Y-Cos(i, 110), 40);
     CombineRgn(R, R, R1, RGN_OR);
  }

  R1=GetStarReg(X, Y, 30);
  CombineRgn(R, R, R1, RGN_DIFF);

  R1=CreateEllipticRgn(3, 3, Width-6, Height-6);
  R2=CreateEllipticRgn(20, 10, Width-20, Height-10);
  CombineRgn(R1, R1,R2, RGN_DIFF);
  CombineRgn(R, R, R1, RGN_OR);

  SetWindowRgn(Handle, R, TRUE);
}

   Перевод с Delphi в C++Builder мой (IR).

-+----------

>Q32: Есть 2 задачи: одна работает в окне ДОС, другая в Windows. Как
>     организовать обмен между ними, может есть какие-то стандартные
>     буферы обмена (Клипборд и Файлы не предлагать)?

A(IEr): Попробуй через "трубу" (pipe). Принцип такой - запускаешь досовскую
  программу через CreateProcess, в STARTUPINFO:
  si.dwFlags = STARTF_USESTDHANDLES;
  si.hStdError = GetStdHandler(STD_ERROR_HANDLE);

  потом

  CreatePipe(&hIn, &si.hStdOutput, 0, 0);
  CreatePipe(&si.hStdInput, &hOut, 0, 0);

  дальше все просто:

  for (;;) {
    DWORD code;
    if (!GetExitCodeThread(pi.hThread, &code)) // pi это структура
        return -1;                             // PROCESS_INFORMATION
    if (code == STILL_ACTIVE) {                // переданная в CreateProcess
    // Читаем с помощью hIn
    // Пишем с помощью hOut
    }
    else
      break;
  }

  CloseHandle(si.hStdInput);
  CloseHandle(hOut);
  CloseHandle(si.hStdOutput);
  CloseHandle(hIn);

  Досовская программа читает из stdin, пишет в stdout.

-+----------

>Q33: Есть на форме Edit и Button, юзер вводит в Edit какую-нибудь цифирь
>     (например 20 ), давит на Button и на форме появляется 20 Label-ов.
>     Как можно сие реализовать? (создание компонента в runtime)

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int count=Edit1->Text.ToInt();

    TLabel *lbl;

    for(int i=0;i<count;i++)
    {
        lbl=new TLabel(this);
        lbl->Parent=this;
        lbl->Caption=AnsiString("Label")+AnsiString(i);
        lbl->Top=i*20;
        lbl->Left=10;
    }
}


-+----------

>Q34: Как сделать чтобы пpогpамма не отобpажалась в панели задач?

A1. ShowWindow(Application->Handle, SW_HIDE); // прячем
    ShowWindow(Application->Handle, SW_SHOW); // показываем

A2. Установить окну Application стиль WS_EX_TOOLWINDOW:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  DWORD Style=GetWindowLong(Application->Handle, GWL_EXSTYLE);
  Style|=WS_EX_TOOLWINDOW;
  SetWindowLong(Application->Handle, GWL_EXSTYLE, Style);

  try
  {
    Application->Initialize();
    Application->CreateForm(__classid(TForm1), &Form1);
    Application->Run();
  }
  catch (Exception &exception)
  {
    Application->ShowException(&exception);
  }
  return 0;
}


-+----------

>Q35: Как запустить процесс, дождаться окончания его инициализации,
>     дождаться завершения, получить код возврата?

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  STARTUPINFO si;

  ZeroMemory(&si, sizeof(STARTUPINFO));

  si.cb=sizeof(STARTUPINFO);
  si.wShowWindow=SW_SHOWNORMAL;

  PROCESS_INFORMATION pi;

  DWORD ExitCode;

  if(CreateProcess(NULL,
                   "c:\\windows\\notepad.exe c:\\autoexec.bat",
                   NULL,
                   NULL,
                   FALSE,
                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
                   NULL,
                   NULL,
                   &si,
                   &pi)==TRUE)
  {
    CloseHandle(pi.hThread);                    // освобождаем ресурсы
    WaitForInputIdle(pi.hProcess, INFINITE);    // ждем окончания инициализации
                                                // запущенного процесса.*
    WaitForSingleObject(pi.hProcess, INFINITE); // ждем завершения процесса
    GetExitCodeProcess(pi.hProcess, &ExitCode); // получаем код возврата
    CloseHandle(pi.hProcess);                   // освобождаем ресурсы
  }
}

*) Под окончанием инициализации понимается момент, когда процесс начинает
   ожидать команд от пользователя.

-+----------

>Q36: Где можно взять хелп по Win32 API?

      В поставку CBuilder'а входит Win32 SDK Reference, содержащий описание
функций API. Для его установки при инсталляции необходимо поставить (или не
снимать :) галочку на MS SDK Help Files. Для вызова справки по F1 необходимо
подключить эти справочные файлы с помощью программы OpenHelp, входящей в
поставку CBuilder'а. Или вызывать руками через
Programs\Borland C++ Builder\Help\MS SDK Help Files\Win32 SDK Reference.
      "Родной" хелп берется на msdn.microsoft.com или на дисках 4-5 из
поставки MS Visual Studio.

-+----------

>Q37: Столкнулся с проблемой, что TImageList не раборает корректно на
>     некоторых машинах. К примеру не отрисовываются картинки на ToolBar в
>     кнопках. Причем на моей машине, где проект создавался - все Ок а вот
>     при переносе на другую машину начинаются проблемы.

      Необходимо обновить comctl32.dll на машинах, где наблюдаются проблемы.

-+----------

>Q38: Была у меня програмка на BCB3 и там некоторые функции разделялись:
>     одни в конструкторе формы, другие - в событии формкреэйт. Переполз на
>     BCB4 и что же конструктор вызывается после события создания формы -
>     это как? (другой вариант этого вопроса: имеем форму с добавленными мною
>     полями типа AnsiString. В OnCreate я эти поля заполняю некоторыми
>     значениями, ставлю breakpoint в OnShow и смотрю эти переменные - они
>     пустые!)

      Необходимо у всех форм/datamodule'ей поставить OldCreateOrder = false;

-+----------

>Q39: Как грамотно связаться с MS Word (OLE)?

A(SE): С Вордом никаких проблем для связи через OLE нет. Вот давно обещал
многим законченный класс для вызова Ворда из СВ - пожалуйста, пользуйтесь...
Цеплял я его уже к проектам 10, и все пашет и на 95, и на 98 (на NT не
пробовал).

(MessageBox - моя функция, поменяйте на похожую из ВС, облом искать
исходник)

H:
//--------------------------------------------------------------------------
#ifndef MSWordH
#define MSWordH
//--------------------------------------------------------------------------
void __fastcall CopyRTFToClipboard(AnsiString buf);
//--------------------------------------------------------------------------
enum WinwordColor    { mswColAuto, mswColBlack, mswColBlue, mswColCyan,
mswColGreen, mswColMagenta,
                       mswColRed, mswColYellow, mswColWhite, mswColDarkBlue,
mswColDarkCyan,
                       mswColDarkGreen, mswColDarkMagenta, mswColDarkRed,
mswColDarkYellow,
                       mswColDarkGray, mswColLightGray };
enum WinwordTabType  { mswTabLeft, mswTabCenter, mswTabRight, mswTabDecimal,
mswTabBar };
enum WinwordAlign    { mswAlgLeft, mswAlgCentered, mswAlgRight,
mswAlgJustified };
enum WinwordSpacing  { mswSpSingle, mswSpLines, mswSpDouble };
//--------------------------------------------------------------------------
class TMSWord
{
private:
   Variant msWord;
   AnsiString msWordTitle;

   bool __fastcall Run();

public:
   __fastcall ~TMSWord();

   bool __fastcall Create(AnsiString fileName);
   bool __fastcall GotoBookmark(AnsiString mark);
   void __fastcall InsertText(AnsiString str);
   void __fastcall InsertTextEOL(AnsiString str);
   void __fastcall Paste();
   void __fastcall Restore();
   bool __fastcall RunApplication(AnsiString dir);
   void __fastcall SetFontFormat(TFont *f,WinwordColor color = mswColAuto);
   void __fastcall SetFontFormat(char *fontName,int fontSize,TFontStyles
style,
                                 WinwordColor fontColor = mswColAuto);
   void __fastcall SetBookmark(AnsiString mark);
   void __fastcall SetParagraphFormat(int leftIndent = 0,int rightIndent =
0,
                                      int before = 0,int after = 0,
                                      WinwordSpacing lineSpacing =
mswSpSingle,
                                      WinwordAlign align = mswAlgLeft);
   void __fastcall SetTabs(int *tabs,int num,WinwordTabType type =
mswTabLeft);
   void __fastcall Exit();
};
//--------------------------------------------------------------------------
#endif



CPP:
//--------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <comobj.hpp>
#include <clipbrd.hpp>
#include <utilcls.h>
#include <vclutils.hpp>
#include "RxShell.hpp"
#include "MSWord.h"
#include "MSWordLoc.h"
#include "VMessage.h"
#pragma package(smart_init)

#define START        "Start"
#define WORD_EXE     "WinWord.exe"

//**************************************************************************
// Копирование текста в буфер
//--------------------------------------------------------------------------
void __fastcall CopyRTFToClipboard(AnsiString buf)
{
   // регистрируем формат RichText
 Word cfRTF = (Word)RegisterClipboardFormat(TEXT("Rich Text Format"));
   Clipboard()->Open();
 int nTextLen = (buf.Length() + 1) * sizeof(TCHAR);
 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE,nTextLen);
 if(hGlobal != NULL) {
  void *lpText = GlobalLock(hGlobal);
  memcpy(lpText,buf.c_str(),nTextLen);
  Clipboard()->Clear();
  GlobalUnlock(hGlobal);
      Clipboard()->SetAsHandle(cfRTF,(int)hGlobal);
   }
 Clipboard()->Close();
}
// Класс TMSWord
//**************************************************************************
// Деструктор
//--------------------------------------------------------------------------
__fastcall TMSWord::~TMSWord()
{
   msWord.Clear();
}
// Создание объекта и открытие файла
//--------------------------------------------------------------------------
bool __fastcall TMSWord::Create(AnsiString fileName)
{
   // если объект уже создан
   if(!msWord.IsEmpty()) {
      try {
         // пытаемся активизировать Word
         if((short)msWord.Exec(PropertyGet("AppIsRunning") << msWordTitle)
== -1)
            msWord.Exec(Procedure("AppRestore") << msWordTitle);
      }
      catch (EOleSysError& e) {
         // если окно с документом (не Word) было закрыто пользователем, то
ErrorCode = 0
         // выходим из catch сразу на загрузку документа (без запуска
Word-a)
         if(e.ErrorCode) {
            // перехватываем событие, когда Word уже был запущен программой
            // а потом закрыт пользователем
            if(e.ErrorCode != 0x800706BA) {
               MessageBox(e.Message + LoadStr(MSWORD_ERROR1),msError);
               return false;
            }
            if(!Run())              // запускаем Word повторно
               return false;
         }
      }
   }
   // объект еще не создан
   else if(!Run())            // пытаемся запустить
      return false;
   // объект успешно создан, открываем файл
   try {
      msWord.Exec(Procedure("AppShow"));
      msWord.Exec(Procedure("FileNew") << fileName);
      // получаем заголовок созданного окна
      msWordTitle = AnsiString("Microsoft Word - ") +
msWord.Exec(PropertyGet("WindowName"));
      return true;
   }
   catch (Exception& e) {
      MessageBox(e.Message + LoadStr(MSWORD_ERROR2),msError);
   }
   return false;
}
// Закрытие Word
//--------------------------------------------------------------------------
void __fastcall TMSWord::Exit()
{
   try {
      if(!msWord.IsEmpty() &&
         MessageBox(LoadStr(MSWORD_CONFIRM),msConfirm_YesNo) == IDYES)
         msWord.Exec(Procedure("AppClose"));
   }
   catch (...) {
   }
}
// Переход на закладку
//--------------------------------------------------------------------------
bool __fastcall TMSWord::GotoBookmark(AnsiString mark)
{
   try {
      msWord.Exec(Procedure("EditGoto") <<
NamedParm("Destination",mark.c_str()));
      return true;
   }
   catch (Exception& e) {
      MessageBox(e.Message + "\nBookmark: " + mark,msError);
   }
   return false;
}
// Вставка текста в текущую позицию курсора
//--------------------------------------------------------------------------
void __fastcall TMSWord::InsertText(AnsiString str)
{
   msWord.Exec(Procedure("Insert") << str);
}
// Вставка текста в текущую позицию курсора с переходом на новую строку
//--------------------------------------------------------------------------
void __fastcall TMSWord::InsertTextEOL(AnsiString str)
{
   msWord.Exec(Procedure("Insert") << (str + '\n'));
}
// Вставка текста в текущую позицию курсора
//--------------------------------------------------------------------------
void __fastcall TMSWord::Paste()
{
   msWord.Exec(Procedure("EditPaste"));
}
// Восстановление (активация) Word
//--------------------------------------------------------------------------
void __fastcall TMSWord::Restore()
{
   try {
      msWord.Exec(Procedure("AppRestore") << msWordTitle);
      msWord.Exec(Procedure("AppMaximize") << msWordTitle << 1);     //
максимизируем
   }
   catch (EOleSysError&) {
      MessageBox(LoadStr(MSWORD_INFO),msInfo);
   }
}
// Собственно запуск Word-a как OLE-сервера
//--------------------------------------------------------------------------
bool __fastcall TMSWord::Run()
{
   bool isWordRunning = true;
   // сначала пытаемся переключиться на активный Word
   try {
      msWord = Variant::GetActiveObject("Word.Basic");
   }
   catch (EOleSysError& e) {
      isWordRunning = false;
   }
   if(!isWordRunning) {    // нет запущенного Word
      try {
         msWord = Variant::CreateObject("Word.Basic");
         msWord.Exec(Procedure("AppMaximize") << 1);     // максимизируем
      }
      catch (EOleSysError& e) {
         MessageBox(e.Message + LoadStr(MSWORD_ERROR1),msError);
         return false;
      }
   }
   return true;
}
// Запуск Word-a как приложения
//--------------------------------------------------------------------------
bool __fastcall TMSWord::RunApplication(AnsiString dir)
{
   if(FileExecute(START,WORD_EXE,dir,esNormal) <= 32) {
      MessageBox(LoadStr(MSWORD_ERROR1),msError);
      return false;
   }
   Delay(20000);
   return true;
}
// Задание характеристик шрифта
//--------------------------------------------------------------------------
void __fastcall TMSWord::SetFontFormat(TFont *f,WinwordColor color)
{
   msWord.Exec(Procedure("FormatFont") <<
               NamedParm("Points",f->Size) <<
               NamedParm("Font",f->Name.c_str()) <<
               NamedParm("Color",color));
   if(f->Style.Contains(fsBold))
      msWord.Exec(Procedure("Bold") << 1);
   if(f->Style.Contains(fsItalic))
      msWord.Exec(Procedure("Italic") << 1);
   if(f->Style.Contains(fsUnderline))
      msWord.Exec(Procedure("Underline") << 1);
   if(f->Style.Contains(fsStrikeOut))
      msWord.Exec(Procedure("Strikethrough") << 1);
}
// Задание характеристик шрифта
//--------------------------------------------------------------------------
void __fastcall TMSWord::SetFontFormat(char *fontName,int
fontSize,TFontStyles style,WinwordColor fontColor)
{
   TFont *f = new TFont();
   f->Name = fontName;
   f->Size = fontSize;
   f->Style = style;
   SetFontFormat(f,fontColor);
   delete f;
}
// Задание имени закладки
//--------------------------------------------------------------------------
void __fastcall TMSWord::SetBookmark(AnsiString mark)
{
   msWord.Exec(Procedure("EditBookmark") << NamedParm("Name",mark) <<
NamedParm("Add",1));
}
// Задание характеристик абзаца
//--------------------------------------------------------------------------
void __fastcall TMSWord::SetParagraphFormat(int leftIndent,int rightIndent,
                                            int before,int after,
                                            WinwordSpacing lineSpacing,
                                            WinwordAlign align)
{
   msWord.Exec(Procedure("FormatParagraph") <<
               NamedParm("LeftIndent",AnsiString(leftIndent).c_str()) <<
               NamedParm("RightIndent",AnsiString(rightIndent).c_str()) <<
               NamedParm("Before",before) <<
               NamedParm("After",after) <<
               NamedParm("LineSpacing",lineSpacing) <<
               NamedParm("Alignment",align));
}
// Установка позиций табуляции
//--------------------------------------------------------------------------
void __fastcall TMSWord::SetTabs(int *tabs,int num,WinwordTabType type)
{
   for(int i = 0;i < num;i++)
      msWord.Exec(Procedure("FormatTabs") <<
                  NamedParm("Position",AnsiString(tabs[i]).c_str()) <<
                  NamedParm("Align",type) <<
                  NamedParm("Set",1));
}

-+----------

>Q40: Как сделать таймер с интервалом < 1 мс?

A(VK): Использовать Performance Counter.

   Функцией QueryPerformanceFrequency получаем частоту сч_тчика,
   которая, как правило, выше 1Мгц, созда_м отдельный поток и в цикле
   функцией QueryPerformanceCounter считываем его значение.

   Практически, на P200 достаточно точно определяются интервалы в 20 мкс.

-+----------

>Q41: Как определить количество памяти, доступной Windows и е_ свободный объ_м?

A(VK): Использовать функцию API GlobalMemoryStatus(...).

-+----------

>Q42: Как получить список запущенных задач?

A(VK): Надо составить список главных окон приложений (top-level windows). Окно
считается главным если:
        0. Имеет заголовок
        1. Видимо
        2. Не имеет родителя
   Приходим к следующему коду:

   bool __stdcall EnumProc(HWND hWnd,long) {
   char buffer[100];

    if(hWnd==NULL)
      return false;
    GetWindowText(hWnd,buffer,sizeof(buffer));
    if (buffer[0]
        && IsWindowVisible(hWnd)
        && GetWindowLong(hWnd,GWL_HWNDPARENT)==0) {
        // Ваш код
    };
    return true;
   }

   В нужном месте вызываем его
        EnumWindows((WNDENUMPROC)EnumProc,0);

-+----------

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

A(VK): Можно посмотреть в $(BCB)\Examples\Apps\Procview, а можно и по другому.

   Под W95/98:

   #include <tlhelp32.h>

   PROCESSENTRY32 PC32;

   hnd=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if ((int)hnd==-1)
      return;
    PC32.dwSize=sizeof(PC32);
    i=Process32First(hnd,&PC32);
    while (i) {
      // Ваш код
      // PID процесса бер_тся из PC32.th32ProcessID;
      // Имя файла через ExtractFileName(PC32.szExeFile);
      i=Process32Next(hnd,&PC32);
    };
    CloseHandle(hnd);

   Под NT:

   DWORD     PIDStack[512];
   DWORD     modNeeded;
   EnumProcesses(PIDStack,sizeof(PIDStack),&modNeeded);

-+----------

>Q44:  Как узнать загрузку процессора?

A(VK):  Под W95/98 :

   HKEY CPULoadKey;
   int CPULoad;
   ULONG Type = REG_DWORD;
   DWORD CPULoadSize = sizeof (CPULoad);

   Один раз в начале программы:

  RegOpenKey(HKEY_DYN_DATA,"PerfStats\\StartStat",&CPULoadKey);
  RegQueryValueEx(CPULoadKey,"KERNEL\\CPUUsage",NULL, &Type, (LPBYTE)&CPULoad,
                  &CPULoadSize);
  RegCloseKey(CPULoadKey);
  RegOpenKey(HKEY_DYN_DATA,"PerfStats\\StatData",&CPULoadKey);

   По мере необходимости
  RegQueryValueEx(CPULoadKey,"KERNEL\\CPUUsage",NULL, &Type, (LPBYTE)&CPULoad,
                  &CPULoadSize);
    CPULoad содержит результат в процентах.

   Один раз в конце
  RegCloseKey(CPULoadKey);
  RegOpenKey(HKEY_DYN_DATA,"PerfStats\\StopStat",&CPULoadKey);
  RegQueryValueEx(CPULoadKey,"KERNEL\\CPUUsage",NULL, &Type, (LPBYTE)&CPULoad,
                  &CPULoadSize);
  RegCloseKey(CPULoadKey);

   Под NT либо использем PDH.dll, но она мало у кого есть, либо начинаем
   шаманские пляски вокруг performance keys в реестре. Пример есть на
   www.codepile.com, файл ntcounters.cpp.

-+----------

>Q45: Наш_л в хэлпе полезную функцию ROUND, а программа не компилируется.
      Пишет "Call to undefined function" :( Как же округлять?

A(VK): Функция ROUND (как, впрочем, и TRUNC) принадлежит OCX-контролу
   F1Book. Пишем свою:

#include <math.h>

double Round(double Argument, int Precision)
{
  double div = 1.0;
  if(Precision >= 0)
    while(Precision--)
      div *= 10.0;
  else
    while(Precision++)
      div /= 10.0;
  return floor(Argument * div + 0.5) / div;
}

   Hint: точность может быть отрицательной. Round(1234,-2)==1200.

-+----------

>Q46: Как сменить цвет надписи у TButton?

   Никак. Используйте, например, TBitBtn.

-+----------

>Q47. Можно как нибудь засунуть заданные файлы в dll (dll создаем), а потом
     пpогpаммно извлечь их на фоpму ?

A(VF):

1. Помещаем свои рисунки в RES файл:
- Создаем файл Image.rc и пишем в нем: MYIMAGE BITMAP Image.bmp
- Обрабатываем Image.rc утилой Brcc32.exe: Brcc32.exe Image.rc, полyчаем файл
Image.res.

2. Подключаем полученный Image.res файл к Dll'ке:
- Image.res помещаем в каталог с Dll-проектом.
- Пишем: USERES("Image.res");
- Компилим Dll.

3. Подгружаем Dll'ку и берем картинку из нее:

  Объявить HINSTANCE hDllHandle;
  ...

  hDllHandle = LoadLibrary("MyDll.dll");

  if(hDllHandle != NULL)
  {
    Image1->Picture->Bitmap->Handle = LoadBitmap(hDllHandle, "MYIMAGE");
    FreeLibrary(hDllHandle);
  }
  else
  {
    //Сообщаем о невозможности подгрузить Dll и обрабатываем ошибку!
  }

-+----------

>Q48. Как засунуть в pесуpсы файлы jpeg?

A(AP):

1) Засовываем Jpeg в res-файл.
   В файле MyJpeg.rc пишем:
MyJPEG RCDATA "MyCoolJPEG.jpg"
   И натравливаем на это дело brcc32 --   brcc32 MyJpeg.rc
   Для полного счастья осталось написать в нашем модуле что-то в духе
#pragma resource "MyJPEG.res"

2) Загружаем Jpeg из ресурсов
   Hапример, в *.h файле определяем у нашей формы в секции private (к примеру)
   переменную
TJPEGImage *MyJPEG;
   Естественно, где-то вверху есть #include <JPEG.hpp>
   Далее, в конструкторе формы пишем:
   (Собственно, тут два варианта; гурманы могут извращатсья с FindResource,
    LoadResource и в качестве заключительного аккорда -- LockResource; а мы
    пойдем... нет-нет, всего лишь другим путем.)
 MyJPEG = new TJPEGImage();
 TResourceStream *JPEGRes = new
 TResourceStream((int)HInstance,AnsiString("MyJPEG"),RT_RCDATA);
 MyJPEG->LoadFromStream(JPEGRes);
 JPEGRes->Free();

3) Осталось дело за малым -- использовать этот самый Jpeg:
   В каком-нибудь OnPaint у PaintBox'а написать:
  ((TPaintBox*)Sender)->Canvas->Draw(0, 0, MyJPEG);

-+----------

>Q49. Как программно скролировать TMemo?

A: EM_LINESCROLL. Например,

 SendMessage(Memo->Handle, EM_LINESCROLL, 0, Memo->Lines->Count);

-+----------

[end of FAQ]

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100