Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Зависает при вызове MoveWindow  (Прочитано 13731 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« : 02-07-2005 09:31 » 

 Всем добрый день.
Сам не люблю вопросы типа "сделайте, чтоб у меня все работало", но...

 По каким причинам может быть  следующее:
   при вызове MoveWindow программа виснет, т.е. под отладчиком дохожу до этой функции, а из нее не выходит?

Параметры передаю корректные. Проверял не раз.

Думаю что скорее, всего дело в функции - обработчике сообщений окна (которое пытаюсь двигать), но там только

LRESULT CALLBACK DMarkFunc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{     
 switch (msg)
  {
    case WM_LBUTTONDOWN:
       MessageBox(NULL, "", "", MB_OK);
       break;

    case WM_DESTROY:
       PostQuitMessage(0);
       break;
  }

 return DefWindowProc(hwnd, msg, wParam, lParam);
}

З.Ы. Окно, которое пытаюсь двигать -- дочернее. двигаю внутри  и относительно родительского.

З.З.Ы. Думаю ошибка должна быть на уровне "начинающий". Вот только ищу ее уже не один день Жаль

« Последнее редактирование: 02-07-2005 09:35 от Артем » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 02-07-2005 10:31 » 

Ну первое, ты можеш дать полную версию, вообше как ты вызываеш данную функцию. И естественно предварительный текст.
Второе, Если ты дал обратную функцию дочернего окна, то в нем нельзя вызывать PostQuitMessage(0);. При любом  закрытии дочернего окна будет закрываться также и все приложение.
Третье, свою функцию обратного вызова лучше сделай в такой форме:
Код:
LRESULT CALLBACK DMarkFunc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{     
switch (msg)
  {
    case WM_LBUTTONDOWN:
       MessageBox(NULL, "", "", MB_OK);
       break;

    case WM_DESTROY:
       PostQuitMessage(0);
       break;
default:
          return DefWindowProc(hWindow, Message, wParam, lParam);
  }

return 0;
}

Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #2 : 02-07-2005 11:06 » 

 2-ое и 3-е   -- исправил
Большое спасибо Улыбаюсь

Что касается первого.
 вызываю функция вот так:
if (!MoveWindow(hwndMark, XPos, YPos, 10,  10,  FALSE) ) // вот тут она и виснет Улыбаюсь
  MessageBox (NULL, "CANNOT MOVE MARK", "Error", MB_OK);

Полная верси довольно велика Улыбаюсь. Лучше я на словах опишу алгоритм:
 
 В проге создается дочернее окно (назавем его "экран").
 В этом дочернем окне ("экране") создается (в разное время работы проги) еще с десяток дочерних окон ("меток"), которые ползают по "экрану".
 Так вот эти "метки" прекрасно ползают по "экрану" ( с помощью той самой MoveWindow),
   но когда я начинаю двигать (опять же MoveWindow) эти "метки" в ответ на сообщения ScrollBar-a "экрана"... тут то эта неприятность и происходит...
 
P.S.На самом деле я не совсем корректно поставил вопрос:
         надо было написать, что он адресован людям, которые  сталкивались с подобной проблемой...
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 02-07-2005 11:23 » 

1. можеш ли превести код, который сушествует в обработчике событий от скролов?
2. Чтобы двигать метки, ты завел код  в одну функцию или данный код разбросал по всей программе?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #4 : 02-07-2005 11:48 » 

1. обработчик события от скролла:

case WM_VSCROLL:
    {
      // считаем  dу  из wParam, а dx = 0;
       ...
       SetMarkParam(p, dx, dy); // где p -- это указатель на структуру, в которой хранятся текущие параметры метки
      return 0;
    }

а вот и
SetMarkParam(p, dx, dy) // где p -- это указатель на структуру, в которой хранятся текущие параметры метки
{
  p->XPos = p->XPos + dx;
  p->YPos = p->YPos + dy;

  if (!MoveWindow(p->hwndMark, p->XPos, p->YPos, 10, 10, FALSE) )
     MessageBox (NULL, "CANNOT MOVE MARK", "Error", MB_OK);

  return S_OK;
}



2. Метки по экрану двигаю этой же функцией-- SetMarkParam(p, dx, dy).
  т.е. когда ее вызываю из другого места--все работает, а когда из обработчика скролла -- виснет в MoveWindow.
Хотя параметры (p->hwndMark, p->XPos, p->YPos, 10, 10, FALSE) одинаковые и в том и другом случае...
« Последнее редактирование: 02-07-2005 11:51 от Артем » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 02-07-2005 12:30 » 

После скролинга, p->XPos и p->YPos какие значения приобретают, когда поподают на ошибку. И всегда ли это происходит, или только после определенных действий?

Вот маленькая выдержка из MSDN
Цитата
nPos

Value of the high-order word of wParam. Specifies the current position of the scroll box if the nScrollCode parameter is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise, nPos is not used.
Отсюда следует, что ты не во всех случаях получиш правильное nPos.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #6 : 04-07-2005 06:38 » 

   Значения p->XPos и p->YPos я вообще забивал константами ( = 40, например).
Результат, тот же--ошибка возникает только при определенных действиях, и скроллинг--только одно из них.
Я тут на выходных посидел и пришел к выводу, что ошибка не из-за скроллинга и, даже,  не из-за MoveWindow, а где-то в другом месте...

Например, я еще не до конца понимаю, что должна содержать корректная оконная функция обработки сообщений. И чем эта функция дочернего окна отличается от "простого", не дочернего...  Я думаю, что ошибка где-то в этих функциях...

Поэтому я и поставил вопрос в общей форме:
Цитата
  По каким причинам может быть  следующее:
   при вызове MoveWindow программа виснет, т.е. под отладчиком дохожу до этой функции, а из нее не выходит?

Но, похоже, таких причин может быть очень много.

Записан
Chaa
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 04-07-2005 07:09 » 

На мой взгляд виснуть программа может из-за следующего:
1) Из обработчика сообщения WM_SCROLL вызывается MoveWindow.
2) В ответ на вызов MoveWindow окну посылаются сообщения WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, WM_NCCALCSIZE.
3) В одном из этих сообщений изменяется состояние скролбара так, что он посылает окну сообщение WM_SCROLL, в обработчике которого вновь вызывается MoveWindow...
Записан
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #8 : 04-07-2005 07:43 » 

Да, Chaa,  похоже что-то подобное и происходит Жаль

 Вот только, явно я не обрабатываю  WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, WM_NCCALCSIZE.

А не может ли обработчик по умолчанию, DefWindowProc или DefMDIChildProc посылать сообщения типа WM_SCROLL?
Кстати, а на сколько сильно разняться функции DefWindowProc,  DefMDIChildProc и т.д.? Может я не ту функция вызываю?
Записан
Chaa
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 04-07-2005 08:11 » 

DefMDIChildProc обрабатывает WM_MOVE и пересчитывает размеры и позиции в скролбарах. Хотя к посылке сообщения WM_VSCROLL это не должно приводить.
DefWindowProc не должна ничего делать со скролбарами, она вообще почти ничего не делает.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 04-07-2005 18:58 » 

Кстати Артем Тебе не кажется, что в твоей проге есть логическая ошибка. Или я чего то не понимаю в твоей логике. Строка Скролинга обычно служит для сдвига экрана. При этом Твоя метка будет сдвигаться не относительно движка скрола.
Пример: три раза шелкаеш по стрелки скрола. Допустим что скрол был в нулевой позиции.
1 шелчек - метка сместится на 1 пиксель.
2 шелчек - метка сместится на 2 пикселя
3 шелчек - метка сместится на 3 пикселя
Итого смешения на 6 пикселей. Хотя ты сделал всего 3 шелчка. Это маленький пример. А если ты вдруг захочеш сместить в обратную сторону. То у тебя вообше не получится. Твоя метка будет улетать все равно вниз. Или останется на месте.

Сначало попробуй решить эту проблему.

В принципе ты знаеш координаты окна, где бегают метки и его размеры. Знаеш также Где находятся метки. В принципе, если метка вышла за область экрана. Ее можно просто спрятать. Некуда не двигая.
Насколько я знаю, Range у скрола и страницу скрола можно задавать вручную. Я по крайней мере так делал. Там только есть ограничение, максимальное значение не может быть больше 32536 помоему. 

Второе, так ли уж обязательно, чтобы метки были окнами со своим хэндлом?
« Последнее редактирование: 04-07-2005 19:17 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #11 : 05-07-2005 07:01 » 

Finch, наверное я не совсем правильно описал логику. На самом деле я конечно же при скроллинге, функции SetMarkParam (в которой вызываю MoveWindow) передаю "current position of the scroll box". Из этого расчитываю dx (или dy) прибавляю его к текущему положению окна и передаю в MoveWindow.

Цитата
В принципе, если метка вышла за область экрана. Ее можно просто спрятать. Некуда не двигая.
-- это верно, но пока я максимально упростил прогу, что бы легче было искать ошибку.

Насчет второго. Мне надо чтобы при наведении курсора на метку появлялась соответствующая инфа в статус баре, а при кликании на нее -- выскакивало некое окошко для редактирования. Можно, конечно, отслеживать координаты ВСЕХ меток. Но мне казалось что проще и правильней будет сделать их окошками.
Записан
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #12 : 05-07-2005 07:49 » 

 Так, я тут с большой долей вероятности выяснил что трабл не в MoveWindow (или не только в ней Улыбаюсь ).

Прога виснит с подобными симптомами при неких других действиях, не заходя в  MoveWindow.

Буду искать какие сообщения приводят к зависанию.
MoveWindow посылает  WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, and WM_NCCALCSIZE,
вот только не понятно : если последний параметр у MoveWindow  FALSE, она посылает WM_PAINT?

Просто похоже, что все падает при посылке (кем-то) сообщения WM_PAINT.

Только не спрашивайте, почему этого раньше не проявилось Улыбаюсь
« Последнее редактирование: 05-07-2005 08:18 от Артем » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #13 : 05-07-2005 12:00 » 

Артем, есть способ запретить прорисовку окна через сообшение WM_SETREDRAW:
Цитата
An application sends the WM_SETREDRAW message to a window to allow changes in that window to be redrawn or to prevent changes in that window from being redrawn.

WM_SETREDRAW 
wParam = (WPARAM) fRedraw;  // state of redraw flag
lParam = 0;                 // not used; must be zero
 

Parameters

fRedraw

Value of wParam. Specifies the state of the redraw flag. If this parameter is TRUE, the redraw flag is set. If the parameter is FALSE, the flag is cleared.

 

Return Values

An application should return zero if it processes this message.

Remarks

This message sets or clears the redraw flag. If the redraw flag is cleared, the content of the given window is not updated after each change, and the window is not repainted until the redraw flag is set. For example, an application that must add several items to a list box can clear the redraw flag, add the items, and then set the redraw flag. Finally, the application can call the InvalidateRect function to cause the list box to be repainted.
Ради разнообразия ты можеш дать полный текст функции SetMarkParam и полный текст обработчика WM_VSCROLL. Также описание действий связаных со скролом, при которых происходит зависание.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Артем
Опытный

nz
Offline Offline
Пол: Мужской
Beware the wolf in sheep's clothing.


« Ответ #14 : 13-07-2005 08:15 » 

 Finch, Chaa  спасибо большое за советы! Теперь прога, которую я пишу,  будет работать чуть корректнее Улыбаюсь

  Что касается этого глобального глюка, то найти его на расстоянии -- это unreal (хотя бы потому, что модуль, куда я пытаюсь встроить метку не мой, и как выяснилось, у них свои обработчики по умолчанию написаны, в корректности работы которых, в моем случае я сомневаюсь).

   Пока я продолжу поиск самостоятельно, о результатах постораюсь сообщить. Улыбаюсь


Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines