Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Окна, которые прилипают к краям, Поведение как у панели Workspace в MS VC 
:(
    Опции темы
ANIDIM
Дата 16.7.2004, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Как создать окно, которое будет прилипать к краям другого, когда мы его будем двигать? Т.е. как создать аналого Панели Workspace, спользуемой в MS Visual Studio?

(Используя MFC)

Спасибо.

Это сообщение отредактировал(а) ANIDIM - 16.7.2004, 14:39
PM MAIL   Вверх
Coocky
Дата 16.7.2004, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

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



скачал из "первых шагов" biggrin.gif biggrin.gif biggrin.gif
Код


Для начала разберемся, что к чему прилипает.

Прилипать может главное окно к границам десктопа.
К границам своих параллельно существующих окон.
К тем окнам чьи описатели доступны.
Небольшое отступление как создать равноправные дочерние окна по типу немодального диалогового окна регистрируется класс дочернего окна со своей процедурой а затем:

hwndList[0] = CreateWindow(szChild, "Child 1", WS_OVERLAPPEDWINDOW |
WS_VISIBLE, W_USEDEFAULT, CW_USEDEFAULT,100, 50, hwnd, NULL, hInstance,
NULL);

В принципе все, что нужно это обработать WM_WINDOWPOSCHANGING и скорректировать, если необходимо положение окна те осуществить проверку на близость к конкретному объекту. И еще одно нужно знать что происходит с окном двигают ли его или изменяют размер ухватив за левую правую верхнюю нижнюю кромку эту инфу можно получить из

WM_MOVING, WM_SIZING :

Узнаем какую кромку тянем -

void DockedOnSizing(WPARAM wParam, int &fMoving)
{
fMoving&=~15;
if(wParam==9)
 fMoving|=15;
else
{
 if(wParam==1 || wParam==4 || wParam==7) fMoving|=1;
 if(wParam==2 || wParam==5 || wParam==8) fMoving|=2;
 if(wParam==3 || wParam==4 || wParam==5) fMoving|=4;
 if(wParam==6 || wParam==7 || wParam==8) fMoving|=8;
}
}

Изменяем, все кромки, просто тянем окно:

void DockedOnMoving(WPARAM wParam, int &fMoving)
{
fMoving|=15;
}

Осуществляется проверка на близость к десктопу и соответственную корректировку положения

//lpwp - это lParam WM_WINDOWPOSCHANGING
//fMoving - это ранее полученное значение кромки
//StickAt - это контролируемое расстояние
void IsCloseToDeskTop(LPWINDOWPOS lpwp, int fMoving, int StickAt)
{
RECT WorkArea;
SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
WorkArea.right -= lpwp->cx;
WorkArea.bottom -= lpwp->cy;
if( abs(WorkArea.left - lpwp->x) <= StickAt && fMoving&1)
{
if( !(fMoving&2) ) lpwp->cx +=lpwp->x - WorkArea.left;
lpwp->x = WorkArea.left;
}
if( abs(WorkArea.right - lpwp->x) <= StickAt && fMoving&2)
{
if( !(fMoving&1) ) lpwp->cx +=WorkArea.right - lpwp->x;
else lpwp->x = WorkArea.right;
}
if( abs(WorkArea.top - lpwp->y) <= StickAt && fMoving&4)
{
if( !(fMoving&8) ) lpwp->cy += lpwp->y - WorkArea.top;
lpwp->y = WorkArea.top;
}
if( abs(WorkArea.bottom - lpwp->y) <= StickAt && fMoving&8)
{
if( !(fMoving&4) ) lpwp->cy += WorkArea.bottom - lpwp->y;
else lpwp->y = WorkArea.bottom;
}
}

Анализ на близость двух окон

//hwndDockedTo - окно для анализа
//lpwp - это lParam WM_WINDOWPOSCHANGING
//fMoving - это ранее полученное значение кромки
//StickAt - это контролируемое расстояние
bool IsCloseToWindow(HWND hwndDockedTo, LPWINDOWPOS lpwp, int fMoving, int
StickAt)
{
bool DockedByX=false;
bool DockedByY=false;
RECT WorkArea;

if(hwndDockedTo) // если окно непустое
{
// анализ положения двух окон
GetWindowRect(hwndDockedTo, &WorkArea);
if( lpwp->y + lpwp->cy > WorkArea.top - StickAt && lpwp->y < WorkArea.bottom + StickAt)
{
if( fMoving&2 && abs(WorkArea.left - lpwp->cx - lpwp->x) <= StickAt)
{
if( !(fMoving&1) ) lpwp->cx = WorkArea.left-lpwp->x;
else lpwp->x = WorkArea.left-lpwp->cx;
DockedByY=true;
}
if( fMoving&1 && abs(WorkArea.right - lpwp->x) <= StickAt)
{
if( !(fMoving&2) ) lpwp->cx = lpwp->x - WorkArea.right + lpwp->cx;
lpwp->x = WorkArea.right;
DockedByY=true;
}
if(DockedByY)
{
if( WorkArea.bottom > lpwp->y + lpwp->cy/2)
if( fMoving&4 && abs(WorkArea.bottom - lpwp->cy - lpwp->y) <= StickAt) lpwp->y = WorkArea.bottom - lpwp->cy;else;
else
if( fMoving&4 && abs(WorkArea.bottom - lpwp->y) <= StickAt) lpwp->y = WorkArea.bottom;
if(WorkArea.top < lpwp->y + lpwp->cy/2)
if( fMoving&8 && abs(WorkArea.top - lpwp->y) <= StickAt) lpwp->y = WorkArea.top;else;
else
if( fMoving&8 && abs(WorkArea.top - lpwp->y - lpwp->cy) <= StickAt) lpwp->y = WorkArea.top-lpwp->cy;
}
}

if( lpwp->x + lpwp->cx > WorkArea.left && lpwp->x < WorkArea.right)
{
if( fMoving&8 && abs(WorkArea.top - lpwp->y - lpwp->cy) <= StickAt)
{
if( !
(fMoving&4) ) lpwp->cy = WorkArea.top - lpwp->y;
else lpwp->y = WorkArea.top - lpwp->cy;
DockedByX=true;
}
if( fMoving&4 && abs(WorkArea.bottom - lpwp->y ) <= StickAt)
{
if(!(fMoving&8)) lpwp->cy = lpwp->y - WorkArea.bottom + lpwp->cy;
lpwp->y = WorkArea.bottom;
DockedByX=true;
}
if(DockedByX)
{
if( fMoving&1 && abs(WorkArea.left - lpwp->x) <= StickAt) lpwp->x =
WorkArea.left;
if( fMoving&2 && abs(WorkArea.right - lpwp->x-lpwp->cx) <= StickAt)
lpwp->x = WorkArea.right-lpwp->cx;
}
}
}
return (DockedByX || DockedByY);
}

Комментировать все вычисления можно заморится основная идея взяли два прямоугольника и рассмотрели все варианты их взаимоположения и движения разных кромок Одна рекомендация StickAt делать не больше чем мин ширина окна/2 или мин высота/2. Теперь как использовать все это добро, в каждую оконную процедуру чье окно должно быть липнущим добавить

1 static int fSave; флажок активной кромки.

case WM_MOVING :
DockedOnMoving(wParam, fSave);
return true;

case WM_SIZING :
DockedOnSizing(wParam, fSave);
return true;

case WM_WINDOWPOSCHANGING :
IsCloseToDeskTop((LPWINDOWPOS)lParam, fSave, 15);
IsCloseToWindow(hwnd1, (LPWINDOWPOS)lParam, fSave, 15);
...// список окон подверженных тестироватию
IsCloseToWindow(hwndn, (LPWINDOWPOS)lParam, fSave, 15);
return 0;



Это сообщение отредактировал(а) Coocky - 16.7.2004, 22:33


--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
ANIDIM
Дата 17.7.2004, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо.

Реализуемо и понятно.

Получается, Винда (или MFC) это никак не автоматизирует. Муторно, однако… Неужели нельзя проще? А нельзя ли использовать панель CToolBarCtrl как простое окно? Оно уже «прилипать» умеет.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

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


 




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


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

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