faqs.org.ru

 Главная > Программирование > Языки C/C++/Builder >

FAQ по C++Builder

Секция 2 из 3 - Предыдущая - Следующая
Все секции - 1 - 2 - 3

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

Секция 2 из 3 - Предыдущая - Следующая

Монтаж пусконаладка подстанций http://kazes.kz
kazes.kz
http://designmakers.kz квартира и 155 дизайн
designmakers.kz

Вернуться в раздел "Языки C/C++/Builder" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru