faqs.org.ru

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

FAQ по C++Builder

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

#include "MSWordLoc.h"
#include "VMessage.h"
#pragma package(smart_init)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   Под W95/98:

   #include <tlhelp32.h>

   PROCESSENTRY32 PC32;

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

   Под NT:

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

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

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

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

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

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

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

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

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

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

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

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

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

#include <math.h>

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

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

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

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

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

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

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

A(VF):

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

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

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

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

  hDllHandle = LoadLibrary("MyDll.dll");

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

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

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

A(AP):

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

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

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

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

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

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

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

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

[end of FAQ]

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

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

© faqs.org.ru