Главная > Программирование > Языки 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 - Предыдущая - Следующая
Вернуться в раздел "Языки C/C++/Builder" - Обсудить эту статью на Форуме |
Главная - Поиск по сайту - О проекте - Форум - Обратная связь |