InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 
                Frequently Asked Questions of RU.CBUILDER


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

                     Редакция 1.28 от 11 июня 2000 г.
                        
 последняя версия этого документа (txt, html, hlp варианты) всегда доступна на
                       http://www.boom.newmail.ru

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

На вопросы отвечали:
AA: Akzhan Abdulin, 2:5040/55
AB: Alexander Burnashov, 2:5020/254.36, alex@arta.spb.ru
AM: Alexey Mahotkin, 2:5020/433
AS: Andrew Smirnov, 2:5030/538
AS: Andrew Serdyuk, 2:5030/842.1
AT: Andrey Tarasov, 2:5042/7.19
CA: Costik Aganichev, 2:5020/603.36
DG: Dmitry Gushin, 2:5000/130.2
DGr: Dimas Gr (Гребенюк Дмитрий Сергеевич), 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
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. Как сделать, чтобы программа на CBuilder3, 4 не требовала .bpl, .dll?
  3. Что такое RXLib и где его взять?
  4. Как сделать, чтобы окно вело себя, как верхняя панель в билдере,
     т.е. ресайзилось только по горизонтали, и только до определенного
     минимального размера, а по вертикали размер был фиксированным?
  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*) возвращает некорректные
     значения для аргумента в виде русской буквы?
 13. Почему при сборке в CB3 с включенным Build With Runtime Packages все
     работает, а если отключить, то вылетает с ошибкой, не доходя до
     Application->Initialize(). Какие у All соображения на этот счет?
 14. Есть функция, которая производит длительные вычисления в цикле.
     Хотелось бы иметь возможность ее прервать. Естественно, что пока
     вычисления не выходят из цикла никакие контролы не работают....
 15. Я переписываю BDE-приложение на другой компьютер, а оно отказывается
     работать. Что делать?
 16. Как сделать перекодировку CP866 <-> CP1251?
 17. Как из Builder'a можно работать с последовательными портами?
     Надо сконнектиться с одной железякой по RS-232.
 18. Как отследить запуск второй копии приложения?
 19. Как на C++ выглядит паскалевский is?
*20. Люди, где в инете Русский Хелп взять на Builder 3.0/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. Как определить, работает компонент в design mode или уже в автономной
     программе?
 27. Как зарегистрировать property editor для __property типа AnsiString?
 28. Как сделать так чтобы эхотаг при запуске автоматически открывал
     проект с которым я в последний раз работал, а не создавал новый?
 29. Я делаю компонент, который в качестве свойства получает указатель
     на об'ект TComboBox. Хочется иметь возможность заметить его уничтожение
     в дизайнере, для того чтобы не возникало указателя на пустое место и
     следуюшего за этим Access Violation. Как это сделать?
 30. Кто-нибудь может мне подробно и понятно об'яснить, как мне присвоить
     моему компоненту иконку (чтоб в Component Palette красивее стало :) )?
 31. Как сделать круглое/овальное/с дыркой/etc. окно?
 32. Есть 2 задачи: одна работает в окне ДОС, другая в Windows. Как 
     организовать обмен между ними, может есть какие-то стандартные буферы 
     обмена (Клипборд и Файлы не предлагать)?
 33. Есть на форме Edit и Button, юзер вводит в Edit какую-нибудь цифирь
     (например 20 ), давит на Button и на форме появляется 20 Label-ов.
     Как можно сие реализовать? (создание компонента в runtime)
 34. Как сделать чтобы программа не отображалась в панели задач?
*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?
-+----------

>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: Как сделать, чтобы программа на 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: Как сделать, чтобы окно вело себя, как верхняя панель в билдере,
>    т.е. ресайзилось только по горизонтали, и только до определенного
>    минимального размера, а по вертикали размер был фиксированным?

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

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. Написать руками :)
        а) Делаешь форму, которая будет изображать 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): Ребят, я давно делаю под НТ (под 95 не знаю, не пробовал) такую вещь:

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

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

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

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

A: Из-за видюхи (особенно этим страдают S3 VirgeDX). Надо либо убавлять
   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: Нет.

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

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

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

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;
}
-+---------------------------результат запуска-----------
G:\PROJECT.BC5\Test>a.exe
Create B1
Create B2
Call test b1
Create B1
Call test b2
Create B2
-+---------------------------------------------------------

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


A(MR):

class TComponent1* : public TComponent
{ // Это класс от которого мы будем порождать все наши классы
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);}
  // Эта функция создает класс, поскольку все создаваемые классы мои и   //
порожденны от TObject проблемм нет, осталось только ее вызвать.
}

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

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

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

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

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

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

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

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

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

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

Нужно добавить следующие файлы из папки 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):Для того, чтобы установить программу, которая требует BDE, есть несколько
базовых путей, в частности:

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

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

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

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

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

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

По факту, существует несколько альтернативных движков, подробнее можно узнать в
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 можно работать с последовательными портами?
>     Надо сконнектиться с одной железякой по RS-232.

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


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

//---------------------------------------------------------------------------
__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("Невозможно открыть порт 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("Ошибка инициализации порта 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("Ошибка инициализации порта COM"+IntToStr(n));

 ierr = SetCommMask(hCom, EV_RXCHAR);

 if(!ierr) throw Exception("Ошибка инициализации порта 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, которая
   в конце-концов тоже использует эту функцию. Однако ActivatePrevInstance
   так же выполняет некоторые полезные :) действия (e.g. активизация предыдущей
   копии приложения)
3. Можно создавать семафоры, мутексы, но тогда при некорректном завершении 
   программы, ты ее больше не запустишь ;)
   Пример использования мутекса:

    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.
    Необходимо использовать библиотеку типов Excel.

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

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

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

Шаг 1.
*******
Подключаем библиотеку типов Excel к своему проекту.
Выбираем Project|Import Type Library. Нажимаем кнопку 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):

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

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

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

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

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


A(SE):

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

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

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

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



A(AS): Пример работы с 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

following up a message from Andrew Smirnov to all:

//.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, вы не ДОЛЖНЫ ПЕРЕДАВАТЬ НА
СЕРВЕР НИКАКИХ АРГУМЕНТОВ! Если мы посмотрим 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();
}

Т.е. используя этот код, вы ВСЕГДА ТРЕБУЕТЕ ОТ СЕРВЕРА ЭЛЕМЕНТ
КОЛЛЕКЦИИ -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: Как определить, работает компонент в design mode или уже в
>   автономной программе?

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):

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

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

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

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

     return typeInfo;
 }

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

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

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

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

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

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

>Q29: Я делаю компонент, который в качестве свойства получает указатель
>    на об'ект TComboBox. Хочется иметь возможность заметить его уничтожение
>    в дизайнере, для того чтобы не возникало указателя на пустое место и
>    следуюшего за этим 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: Кто-нибудь может мне подробно и понятно об'яснить, как мне присвоить
>    моему компоненту иконку (чтоб в Component Palette красивее стало :) )?

A(AS): Создаешь .res файл, делаешь там битмап по имени класса компонента
 (например TMYCOMPONENT) размером 24x24. Левая нижняя точка - цвет
 прозрачности. Полученный .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: Как сделать чтобы программа не отображалась в панели задач?

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.

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

>45: Нашёл в хэлпе полезную функцию 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.

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

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

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

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

[end of FAQ]


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua