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

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

ru
Offline Offline
Сообщений: 13


« : 14-03-2012 07:15 » 

(пишу для памяти, а то каждый раз спотыкаюсь об этот момент Отлично )

спасибо Зубру за интересный вариант (№1) Улыбаюсь

вариант №1 - с недокументированными константами!
Код:
//перетаскивание окна мышью

class CMyControl:CMyParent//:CWnd
{
//локальная на контроле точка начала перетаскивания
//(скорректированная на левый верхний угол родителя!!!)
CPoint m_drag_local_start_pnt;

//размер контрола во время начала перемещения
CSize  m_drag_start_size;

//режим перетаскивания включен
bool m_drag_mode;

CMyControl()
:m_drag_local_start_pnt(0,0)
,m_drag_start_size(0,0)
,m_drag_mode(false)
{

}
};

//переопределённая оконная процедура
LRESULT CALLBACK CMyControl::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(m_drag_mode)
switch(Msg)
{
case WM_LBUTTONDOWN:
{
enum{SC_DRAGMOVE=0xF012} ;
::ReleaseCapture();
::SendMessage(hWnd,WM_SYSCOMMAND, SC_DRAGMOVE, 0);
return 1;
}
break;

case WM_NCHITTEST:
{
//делаем (CStatic) осязаемым
LRESULT r=CMyParent::WndProc(hWnd,Msg,wParam,lParam);
if(HTTRANSPARENT==r)
{
return HTCLIENT;
}

return r;
}
break;
};

//return ОконнаяПроцедураПоУмолчанию(hWnd,Msg,wParam,lParam);
return CMyParent::WndProc(hWnd,Msg,wParam,lParam);
};


вариант №2 - "документированный MSDN" вариант
Код:
//перетаскивание окна мышью

class CMyControl:CMyParent//:CWnd
{
//локальная на контроле точка начала перетаскивания
//(скорректированная на левый верхний угол родителя!!!)
CPoint m_drag_local_start_pnt;

//размер контрола во время начала перемещения
CSize  m_drag_start_size;

//режим перетаскивания включен
bool m_drag_mode;

CMyControl()
:m_drag_local_start_pnt(0,0)
,m_drag_start_size(0,0)
,m_drag_mode(false)
{

}
};

//переопределённая оконная процедура
LRESULT CALLBACK CMyControl::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(m_drag_mode)
switch(Msg)
{
case WM_NCHITTEST:
{
//делаем (CStatic) осязаемым
LRESULT r=CMyParent::WndProc(hWnd,Msg,wParam,lParam);
if(HTTRANSPARENT==r)
{
return HTCLIENT;
}

return r;
}
break;

case WM_LBUTTONDOWN:
{
if(GetCapture()==0)
{
::SetCapture(hWnd);

CRect rect;
::GetWindowRect(hWnd,&rect);
m_drag_start_size=rect.Size();

::GetCursorPos(&m_drag_local_start_pnt);
::ScreenToClient(hWnd,&m_drag_local_start_pnt);

//учитываем смещение родительской клиентской области
if(HWND Parent=::GetParent(hWnd))
{
CPoint parP0(0,0);
::ClientToScreen(Parent,&parP0);

m_drag_local_start_pnt+=parP0;
}

//замена дефолтного вызова
::SetFocus(hWnd);
return 1;
}
}
break;

case WM_LBUTTONUP:
{
if(GetCapture()==hWnd)
{
::ReleaseCapture();

//замена дефолтного вызова
return 1;
}
}
break;

case WM_MOUSEMOVE:
{
if(GetCapture()==hWnd)
{
CPoint pCurr;
::GetCursorPos(&pCurr);
//::ScreenToClient(hWnd,&pCurr);

//новый прямоугольник контрола
CPoint p0=pCurr-m_drag_local_start_pnt;
::MoveWindow(hWnd,p0.x,p0.y,m_drag_start_size.cx,m_drag_start_size.cy,1);

//замена дефолтного вызова
return 1;

//примечание: CComboBox будет вести себя необычно - список не откроется
}
}
break;

};

//return ОконнаяПроцедураПоУмолчанию(hWnd,Msg,wParam,lParam);
return CMyParent::WndProc(hWnd,Msg,wParam,lParam);
};
« Последнее редактирование: 26-10-2012 06:17 от Алексей++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 14-03-2012 07:55 » 

добавил ещё поддержку для статиков - а то они по умолчанию мышь игнорируют
Записан

zubr
Гость
« Ответ #2 : 14-03-2012 08:04 » 

Алексей1153++, можно гораздо проще:
Код:
#define SC_DRAGMOVE 0xF012 

void CTest1Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CDialog::OnLButtonDown(nFlags, point);
::ReleaseCapture;
SendMessage(WM_SYSCOMMAND, SC_DRAGMOVE, NULL);
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 14-03-2012 08:08 » 

и что это, как это ?

Добавлено через 5 минут и 33 секунды:
и не работает, кстати
« Последнее редактирование: 14-03-2012 08:13 от Алексей1153 » Записан

zubr
Гость
« Ответ #4 : 14-03-2012 08:21 » 

А как ты сделал, что не работает? Могу скинуть тестик работающий.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 14-03-2012 08:40 » 

сделал в диалоге обработчик так, как ты показал. Когда щёлкаешь по контролам - в этот обработчик совсем не попадаем (ну оно и понятно)

Добавлено через 1 минуту и 55 секунд:
я, похоже, название неправильно написал у темы , ты не про то подумал Улыбаюсь Щас исправлю
« Последнее редактирование: 14-03-2012 08:42 от Алексей1153 » Записан

zubr
Гость
« Ответ #6 : 14-03-2012 12:03 » 

Ты это имел в виду? http://www.sendspace.com/file/6z5rms
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 14-03-2012 17:25 » 

zubr, да
Записан

zubr
Гость
« Ответ #8 : 14-03-2012 17:32 » 

Этот тест для быстроты я на Delphi сваял. Но принцип простой - в обработчике WM_LBUTTONDOWN
ReleaseCapture;
SendMessage(WM_SYSCOMMAND, SC_DRAGMOVE, NULL);
Правда для комбобокса немного по другому делал, там надо дочерний Edit сабклассировать.
Записан
Джон
просто
Администратор

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

« Ответ #9 : 14-03-2012 17:33 » 

Добавьте ещё HitTest для OnSetCursor, а то частенько клинит.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 15-03-2012 06:15 » 

zubr, спасибо, получилось. Не люблю, правда, недокументированные вещи )  Ну и ещё момент - моя "детализация" может в некоторых случаях тоже пригодиться для совершения всяких промежуточных вещей. А может и не пригодится- увидим.

Джон, то есть ещё по WM_NCHITTEST сделать релиз капчи ?
Записан

Джон
просто
Администратор

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

« Ответ #11 : 15-03-2012 10:38 » 

Я код не видел, но курсор иногда "залипает" после покидания контрола. Если это прсто проблема курсора, то тогда по OnSetCursor, просто делаешь хит-тест по контролам и меняешь курсор. Если капча не релизнута, тогда смотри, там было что-то с leave, ща уже точно не помню, кажется надо было окошко где-то зарегить, чтобы получать сообщение покидания.
Посмотри как это у тултипов реализовано.

зы можно попробовать и по WM_NCHITTEST для контрола. Я уже давно с нотификаторами не игрался.

ps ps Во, посмотри
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646265(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645615%28v=vs.85%29.aspx
« Последнее редактирование: 15-03-2012 10:44 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
zubr
Гость
« Ответ #12 : 15-03-2012 11:00 » 

Джон, я тест на быструю руку ваял. Там проблема залипания только у комбобокса.
Изменил немного процедуру сабклассированного editа:
Старый вариант
Код:
function WindowProc_(h: HWND; uMsg, wParam, lParam: DWord): DWord; stdcall;
begin
    case uMsg of
    WM_LBUTTONDOWN: SendMessage(GetParent(h), WM_SysCommand, SC_DRAGMOVE, 0);    
    WM_LBUTTONUP: ReleaseCapture;
  end;
  Result := CallWindowProc(Pointer(oldWndProc), h, uMsg, wParam, lParam);
end;
Новый вариант:
Код:
function WindowProc_(h: HWND; uMsg, wParam, lParam: DWord): DWord; stdcall;
begin
   Result := CallWindowProc(Pointer(oldWndProc), h, uMsg, wParam, lParam);
    case uMsg of
    WM_LBUTTONDOWN: begin
      ReleaseCapture;
      SendMessage(GetParent(h), WM_SysCommand, $F012, 0);
    end;
    WM_LBUTTONUP: ReleaseCapture;
  end;
end;
Сейчас на комбобоксе не залипает курсор.
http://www.sendspace.com/file/g1gsw1
Записан
Джон
просто
Администратор

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

« Ответ #13 : 15-03-2012 15:10 » 

Джон, я тест на быструю руку ваял.

Не ну эт понятно. Я ж в общем случае, для релиза. Чтобы не забыли.

Там проблема залипания только у комбобокса.

не,  не только у комбобокса. После Edit тоже остаётся "двутавровая балка", пока куда-нить не кликнешь.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
zubr
Гость
« Ответ #14 : 15-03-2012 16:15 » 

Цитата
не,  не только у комбобокса. После Edit тоже остаётся "двутавровая балка", пока куда-нить не кликнешь.
Странно, я у себя такого эффекта не получаю. Проверял в xp и 7-ке.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 24-10-2012 15:05 » 

zubr, вот и недостаток вскрылся : перетаскивание правой кнопкой или средней не прокатывает Улыбаюсь

Ну а когда надо левую кнопку - способ замечательный
Записан

zubr
Гость
« Ответ #16 : 25-10-2012 03:08 » 

Ну правая кнопка обычно под контекстное меню используется. Кстати, если подергать WM_SYSCOMMAND с параметром wParam в интервале 0xF001 - 0xF009 интересные эффекты можно получить, связанные с изменениями размеров окна и перетаскиванием.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 25-10-2012 03:28 » 

zubr, а где-то документация есть на это ?
Записан

zubr
Гость
« Ответ #18 : 25-10-2012 04:11 » 

Нет.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 25-10-2012 04:14 » 

вот то-то и оно. Как в следующей версии откажутся от F012 вообще и привет )
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines