Вы будете смеяться, но предположение о том, что Word установлен на 100% компьютеров, неверно. Всегда есть риск натолкнуться на любителя, который пользуется WordPerfect, Лексиконом или даже WordPad. Поэтому первым делом надо проверить, установлен ли Word на компьютере. А после этого перед обращением к СОМ-серверу нужно проверить, не запущен ли Word, и, если это так, настоятельно посоветовать пользователю закрыть его. Дело в том, что возможна ситуация, когда Word будет получать команды одновременно от вашей программы и от пользователя, нажимающего кнопочки на клавиатуре. Такого издевательства Word обычно не выдерживает и с горя вешается.
ОБЩЕЕ ПРАВИЛО: при работе с любым СОМ-сервером запретите пользователю им пользоваться, пока с СОМ-сервером работает ваша программа.
Чтобы проверить факт наличия на компьютере Microsoft Word, надо заглянуть в системный реестр Windows и выяснить, если там запись 'Word.Application' в разделе HKEY_CLASSES_ROOT. Для доступа к системному реестру в Delphi предусмотрен специальный тип данных Tregistry:
function IsWordInstalled: Boolean;
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
Reg.RootKey := HKEY_CLASSES_ROOT;
Result := Reg.KeyExists('Word.Application');
Reg.Free
end;
Теперь проверим, не запущен ли Word в данный момент и при необходимости предложим пользователю закрыть его. Делается это так:
FUNCTION WordClosed:BOOLEAN;
function FindNextWnd(StartHWND: HWND; AString : String): HWND;
var
Buffer : array [0..255] of char;
s:STRING;
i:BYTE;
begin
FillChar(Buffer,256,#0);
Result := StartHWND;
repeat
Result := FindWindowEx(0, Result, nil, nil);
GetWindowText(Result, Buffer, SizeOf(Buffer));
i:=0;
s:='';
WHILE (i<=255) AND (buffer[i]<>#0) DO
BEGIN
s:=s+buffer[i];
INC(i)
END;
IF s<>'' THEN
if Pos(ANSIUpperCase(AString),ANSIUpperCase(s))<>0 then
Break;
until (Result = 0);
end;
VAR h:HWND; r:INTEGER;
CONST MSW='Microsoft Word';
BEGIN
r:=mrRetry;
REPEAT
h:=FindNextWnd(Self.Handle,MSW);
IF h<>0 THEN
r:=MessageDlg('Завершите работу '+MSW,mtConfirmation,[mbRetry, mbCancel],0)
UNTIL (h=0) OR (r=mrCancel);
Result:=r<>mrCancel
END;
Функция FindNextWnd перебирает заголовки всех открытых в Windows окон и ищет, есть ли среди них окно с текстом "Microsoft Word". Если запустить Word, то можно увидеть, что в заголовке его окна эти слова всегда присутствуют (Рис. 22.3).
Рис. 26.3 Заголовок окна Word.
Внутри цикла REPEAT…UNTIL проверяется, запущен ли Word, и выводится сообщение пользователю "Завершите работу Microsoft Word" с двумя вариантами ответа: "Повторить" (при этом пользователь должен переключиться в Word и завершить его работу) и "Отмена". Вся функция WordClosed возвращает True, если Word закрыт, и False, если пользователь нажал кнопку "Отмена".
При такой проверке запуска Word возможна ситуация, когда на панели задач Word'а явно нет, а функция WordClosed упорно сообщает, что Word запущен. Дело в том, что Word виснет не менее часто, чем остальные программы, оставаясь при этом в списке процессов Widows в "полумертвом" состоянии, где его и находит наша функция. В таком случае придется нажать Ctrl+Alt+Del, найти в списке процессов WINWORD.EXE и завершить зависший процесс вручную (Рис. 22.4).