Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Перетаскивание окна за рабочую область


Автор: ButtonOFF 6.4.2012, 19:06
Делаю так, перетаскивается рывками и криво

Код

...
    case WM_LBUTTONDOWN:
        xPos = GET_X_LPARAM(lParam); yPos = GET_Y_LPARAM(lParam);
        break;
...

    case WM_MOUSEMOVE:
        if (wParam == MK_LBUTTON)
        {
            xPos -= GET_X_LPARAM(lParam); yPos -= GET_Y_LPARAM(lParam);
            GetWindowRect(hwnd, &rect);
            SetWindowPos(hwnd, 0, rect.left+xPos, rect.top+yPos, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
        }
        break;
...


А окно у меня без заголовка и рамки ... кроме как рабочей области нет ничего

Код

CreateWindowEx(WS_EX_APPWINDOW, L"", L"", WS_VISIBLE|WS_POPUP, x, y, APP_WIDTH, APP_HEIGHT, NULL, NULL, hInstance, 0);



WM_NCHITTEST не предлагать, с таким кодом перетаскивается конечно отлично, НО не работают "WM_BUTTON-что-нибудь"
Код

    case WM_NCHITTEST:
        if (HTCLIENT == DefWindowProc(hwnd, msg, wParam, lParam))
        return HTCAPTION;
        break;


Желательно подправить первый вариант, кто делал помогите плз

Автор: Dem_max 6.4.2012, 19:20
Код

void OnLeftButtonDown(WPARAM wParam, LPARAM lParam)
{
    SetCapture(hWnd);
}
//------------------------------------------------------------------------------
void OnLeftButtonUp(WPARAM wParam, LPARAM lParam)
{
    ReleaseCapture();
}

void OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    if(wParam & MK_LBUTTON)
    {
        POINT ptScrCurPos;
        GetCursorPos(&ptScrCurPos);
                            RECT rc;
                           GetClientRect(hWnd, &rc);
                            MoveWindow(hWnd, ptScrCurPos.x, ptScrCurPos.y, rc.right, rc.bottom, FALSE);
    }
}

Автор: ButtonOFF 6.4.2012, 19:25
Dem_max,  Спасибо работает, но почти так же как и у меня. Когда я щелкаю и только начинаю тащить окно, оно резко срывается левым верхним углом под мышку...

Автор: Dem_max 6.4.2012, 19:32
Код

void OnLeftButtonDown(WPARAM wParam, LPARAM lParam)
{
    SetCapture(m_hWnd);
    m_ptClientCurPos.x = GET_X_LPARAM(lParam);
    m_ptClientCurPos.y = GET_Y_LPARAM(lParam);
}

void OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    if(wParam & MK_LBUTTON)
    {
        POINT ptScrCurPos;
        GetCursorPos(&ptScrCurPos);
        ptScrCurPos.x = ptScrCurPos.x - m_ptClientCurPos.x;
        ptScrCurPos.y = ptScrCurPos.y - m_ptClientCurPos.y;
        SetPosition(&ptScrCurPos);
    }
}

void SetPosition(LPPOINT pos)
{
    if(!pos) return;

    RECT rc;
    GetClientRect(m_hWnd, &rc);
    MoveWindow(m_hWnd, pos->x, pos->y, rc.right, rc.bottom, FALSE);
    m_ptWinPos.x = pos->x;
    m_ptWinPos.y = pos->y;
}

Автор: ButtonOFF 6.4.2012, 19:56
Dem_max,  Вообще запутался, так оно у меня не двигается вообще, в общем что-то тут с математикой, поидее берем позицию курсора, потом как-нибуть ищем дельту перемещения, и уже смещаем угол окна на эту дэльту... а это еще не самое сложное  smile  надо еще сделать прозрачный фон окна(именно поэтому нет заголовка и прочих рамочек/кнопочек), при чем что бы он стирался (пока что он у меня не стирается smile  ), я там рисую, хочется сделать все красиво   smile 

Автор: Ne1tr1n0 6.4.2012, 23:38
А что-нить типа такого не пойдет?
Код

...
case WM_LBUTTONDOWN:
    ReleaseCapture();
    SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
...

Автор: volatile 6.4.2012, 23:43
Все делается проще:

Код

   case WM_LBUTTONDOWN :
         SendMessage(hWnd, WM_SYSCOMMAND, 0xF012, 0);

это всё! то есть, больше ничё не недо.

код рабочий, взят из старого проекта. делал когда-то винамп-подобный интерфейс.. 

Автор: Akira 7.4.2012, 00:03
volatile
Забыл ReleaseCapture() в некоторых приложениях без этой функи может быть ахтунг, а так сам таким пользуюсь только в место константы SC_MOVE + 2. нагляднее но не принципиально.

Автор: Dem_max 7.4.2012, 04:57
Ну в последнем приведенном мной коде смысл такой. Правда у меня случай когда неклиентской области совсем нету, есть только клиентская.
Допустим у нас размер окна 100х100, мы ткнули мышкой в центр окна и хотим двигать.
Так вот тут при нажатии левой кнопки мыши, узнаем положение курсора в клиентской области внутри окна.
Получается для нашего примера 50х50 положение курсора.
Код

    m_ptClientCurPos.x = GET_X_LPARAM(lParam);
    m_ptClientCurPos.y = GET_Y_LPARAM(lParam);


При движении курсора, узнаем его позицию глобальную на рабочем столе.
допустим курсор глобально в положении 500х500.
Итоговое положение окна становится начальные координаты х  = y = 500 - 50 = 450
Код

        POINT ptScrCurPos;
        GetCursorPos(&ptScrCurPos);
        ptScrCurPos.x = ptScrCurPos.x - m_ptClientCurPos.x;
        ptScrCurPos.y = ptScrCurPos.y - m_ptClientCurPos.y;
        SetPosition(&ptScrCurPos);

Устанавливаем новое положение окна
Код

    RECT rc;
    GetClientRect(m_hWnd, &rc);
    MoveWindow(m_hWnd, pos->x, pos->y, rc.right, rc.bottom, FALSE);

Двигаем окно на позицию
MoveWindow(m_hWnd,450, 450, 100, 100, FALSE);

При этом окно находится на позиции 450х450, а курсор на позиции 500х500, так вот при движении курсора, положение окна будет изменяться, а положение курсора в окне будет постоянно в середине окна для нашего примера.

Пример работы тут http://www.ir-max.ru/test/Server%20IR%20OSD%20Editor.zip

Добавлено @ 05:00
Цитата

SendMessage(hWnd, WM_SYSCOMMAND, 0xF012, 0);

Это не документированная функция, не стоит ее использовать.

Автор: Akira 7.4.2012, 11:51
Dem_max
SendMessage(hWnd, WM_SYSCOMMAND, 0xF012, 0); Это не документированная функция, не стоит ее использовать.
С каких пор? Функа подробно описана в MSDN, константа определена в каком то хидере, сам мелкософт использует этот способ.

Автор: Dem_max 7.4.2012, 17:59
Можно узнать в каком хидере объявлена константа 0xF012 ????

Автор: volatile 7.4.2012, 23:48
Цитата(Dem_max @  7.4.2012,  04:57 Найти цитируемый пост)
Это не документированная функция, не стоит ее использовать.

Возможно, но эта фиговина работает на всех мастдаях начиная с 95 и вплоть до самых последних новаций от м$.
Чего, кстати нельзя сказать о целой куче вполне документированных функций, поддержка которых прекратилась. smile 
Так что ...

Добавлено через 2 минуты и 12 секунд
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx

Автор: Akira 8.4.2012, 00:34
Dem_max
>> Можно узнать в каком хидере объявлена константа 0xF012 ???? 
Каюсь, постоянно забываю что исходники NT в поставку студии не входят. smile 

volatile
Способ норм. это же не ядерный андок и то там по большей части смена адресов, а так кочует из версии к версии и это способ давался в пере книг от мелкософт пресс (напамять не помню ибо их у них чуть меньше чем ***). smile 

Автор: Dem_max 8.4.2012, 03:56
У всех приведенных методов кроме моего есть один недостаток, окно нельзя переместить вверх за границу экрана  !!! (это можно сделать влево, вправо, вниз), если тебе конечно этого не нужно, то можно воспользоваться простым методом.

Автор: GremlinProg 9.4.2012, 07:06
Цитата(ButtonOFF @  6.4.2012,  21:06 Найти цитируемый пост)
WM_NCHITTEST не предлагать, с таким кодом перетаскивается конечно отлично, НО не работают "WM_BUTTON-что-нибудь"

что за ересь?

какие еще WM_BUTTON не работают?
WM_xBUTTONxxx?

они не не работают, они просто переходят в другой диапазон сообщений: WM_NCxBUTTONxxx, т.к. WM_xBUTTONxxx привязаны исключительно к HTCLIENT'у

чтобы при этом отрабатывали WM_xBUTTONxxx надо доделать начатое с WM_NCHITTEST,
т.е. пометить HTCLIENT'ом те области, над которыми эти WM_xBUTTONxxx должны проходить

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)