Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация окон при использовании SetParent, возникают проблемы при перерисовке 
:(
    Опции темы
NightWishMaster
Дата 31.7.2008, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 14.4.2006

Репутация: нет
Всего: нет



На форме есть кнопка и панель. При нажатии на кнопку запускается Ворд и с помощью функции SetParent() запихивается в панельку. Код следующий (C++ Builder 6):

Код

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;
Variant WordApp;
int BorderSize, CaptionHeight;
HWND PanelHandle, WordHandle;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  PanelHandle = NULL;
  WordHandle = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  //Находим хендл окна панельки.
  POINT p;
  p.x = 5; p.y = 5;
  PanelHandle = WindowFromPoint(Panel1->ClientToScreen(p));

  //Запускаем Ворд и определяем хендл его окна.
  WordApp = ::CreateOleObject("Word.Application");
  WideString WordCaption = WordApp.OlePropertyGet("Caption");
  WordApp.OlePropertySet("Caption", "123");
  WordHandle = FindWindow(NULL, "123");
  WordApp.OlePropertySet("Caption", WordCaption);

  //Запихиваем Ворд в панельку. Сознательно игнорируем то, что
  //"The new parent window and the child window must belong to the same application",
  //т.к. другого выхода нет. Игнорируем также то, что для окна Ворда надо было бы поменять
  //WS_POPUP на WS_CHILD, т.к. в таком случае пропадет меню и кнопочные панели, что не допустимо.
  ::SetParent(WordHandle, PanelHandle);

  //Размещаем Ворд так, чтобы не было видно его шапки и границ.
  WordApp.OlePropertySet("WindowState", 0);
  BorderSize = (Width - ClientWidth)/2;
  CaptionHeight = Height - ClientHeight - BorderSize;
  FormResize(Sender);
  WordApp.OlePropertySet("Visible", true);

  Button1->Caption = "Хватит!";
  Button1->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormResize(TObject *Sender)
{
  //При изменении размеров формы изменяем размеры Ворда так, чтобы нигде не было видно шапки
  //и границ.
  if (WordHandle)
    {
      int NewX = - BorderSize;
      int NewY = - CaptionHeight;
      int NewWidth = Panel1->Width + 2*BorderSize;
      int NewHeight = Panel1->Height + CaptionHeight + BorderSize;
      SetWindowPos(WordHandle, NULL, NewX, NewY, NewWidth, NewHeight, SWP_ASYNCWINDOWPOS | SWP_NOZORDER);
    }  
}
//---------------------------------------------------------------------------


При изменении размеров формы Ворд автоматически подстраивается так, чтобы не было видно его границ и шапки. Используется функция SetWindowPos(), в которую передаем флаг 
SWP_ASYNCWINDOWPOS. Вот его описание в MSDN:

Цитата

SWP_ASYNCWINDOWPOS 
If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.


Если этот флаг не установить, то при попытке изменить размеры формы у нас происходит один вызов функции FormResize(), соответсветнно один вызов функции SetWindowPos(), размеры изменяются один раз и все – дальше движения мышки игнорируются и форма блокируется с такими размерами, пока не отпустишь и снова не потянешь за край формы. Если этот флаг стоит, то все норм, размеры Ворда синхронно изменяются, в том числе и с открытым документом. Но все это до поры, до времени smile 

Проблема возникает, если создать документ и, на пример, изменить масштаб его отображения (там где 25-50-100% и т.п.). После этого, несмотря на установленный флажок SWP_ASYNCWINDOWPOS в вызове функции SetWindowPos() все равно наблюдается описанная выше ситуация – изменения размеров происходит один раз и блокируется. Я пробовал ставить еще флажок SWP_DEFERERASE (Prevents generation of the WM_SYNCPAINT message), но это не исправляет ситуацию. Так же была мысль, что надо посылать всем дочерним окнам в моем окне ворда также сообщения с флажком SWP_ASYNCWINDOWPOS. Попробовал это с помощью функции EnumChildWindows():

Код

EnumChildWindows(WordHandle, (WNDENUMPROC)EnumChildProc, (LPARAM)0);

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
  {
    SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_DEFERERASE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
    return TRUE;
  }


Но на ситуацию это не повлияло. Как думаете – в чем проблема? Почему пока не измениш, например, масштаб отображения документа (но не только это, та же ситуация при нажатии на некоторые кнопки Ворда, хотя и не все) все работает нормально. А когда измениш – начинает стопорится?

Буду благодарен за любые размышления smile

ПС. Прикрепил исходник на C++ Builder (там есть и экзешник – для его работы нужен только установленный Ворд) - если у кого возникнет желание посмотреть, о чем это я smile


Это сообщение отредактировал(а) NightWishMaster - 31.7.2008, 14:34

Присоединённый файл ( Кол-во скачиваний: 13 )
Присоединённый файл  Word.zip 277,32 Kb
PM MAIL   Вверх
GremlinProg
Дата 31.7.2008, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



попробуй добавить ворду стиль WS_CHILD


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
NightWishMaster
Дата 31.7.2008, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 14.4.2006

Репутация: нет
Всего: нет



Цитата(GremlinProg @  31.7.2008,  23:24 Найти цитируемый пост)
попробуй добавить ворду стиль WS_CHILD 

Я писал в коментах кода, что мне это не приемлемо, т.к. в таком случае пропадает меню и панельки Ворда (дочернее окно "не имеет права" иметь меню, насколько я понял из МСДН). Я сознательно не менял стиль окна Ворда.

Проблема решается заменой функции SetWindowPos на MoveWindow:

Код

MoveWindow(WordHandle, NewX, NewY, NewWidth, NewHeight, TRUE);

PM MAIL   Вверх
rubic
Дата 3.9.2008, 04:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 3.9.2008

Репутация: нет
Всего: нет



Цитата(NightWishMaster @  31.7.2008,  14:34 Найти цитируемый пост)
 //Запихиваем Ворд в панельку. Сознательно игнорируем то, что
  //"The new parent window and the child window must belong to the same application",
  //т.к. другого выхода нет.

Не нашел такого в MSDN...
http://msdn.microsoft.com/en-us/library/ms633541(VS.85).aspx
или искал не там?

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0799 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.