Кнопка C++ MFC исчезает при изменении размера окна

У меня есть диалог в MFC C++, к которому прикреплен CButton. Я хочу изменить OnSize(), чтобы кнопка привязывалась к левому нижнему углу.

if (btn.m_hWnd) {
        CRect winRect;
        GetWindowRect(&winRect);

        int width = winRect.right - winRect.left;
        int height = winRect.bottom - winRect.top;

        int x = width - wndWidth;
        int y = height - wndHeight;


        CRect rect;
        btn.GetWindowRect(&rect);
        rect.left += x;
        rect.top += y;
        btn.MoveWindow(&rect);
        ScreenToClient(&rect);
        btn.ShowWindow(SW_SHOW);
    }

x и y - разница того, насколько сильно изменилось окно, и будет ли оно добавлено к начальным координатам кнопки.

Я не уверен насчет последних 2 команд (я мог бы также удалить их), но затем я запускаю программу, кнопка исчезает.

Мне нужно знать способ перемещения кнопки по x и y.

2 ответа

Решение

Исходный код использовал неправильную систему координат как для родительского диалога, так и для кнопки.

Правильный способ стыковки в левом нижнем углу будет выглядеть так:

if (btn.m_hWnd) { 
    CRect winRect; 
    GetClientRect(&winRect); 

    CRect rect; 
    btn.GetWindowRect(&rect); 
    ScreenToClient(&rect); 

    int btnWidth = rect.Width();
    int btnHeight = rect.Width();
    rect.left = winRect.right-btnWidth; 
    rect.top  = winRect.bottom-btnHeight;
    rect.right = winRect.right;
    rect.bottom = winRect.bottom; 
    btn.MoveWindow(&rect); 
}

ИЛИ ЖЕ

if (btn.m_hWnd) { 
    CRect winRect; 
    GetClientRect(&winRect); 

    CRect rect; 
    btn.GetWindowRect(&rect); 
    ScreenToClient(&rect); 

    int btnWidth = rect.Width();
    int btnHeight = rect.Width();
    btn.SetWindowPos(NULL,winRect.right-btnWidth,winRect.bottom-btnHeight,0,0,SWP_NOSIZE|SWP_NOZORDER);
}

По сути, ответом должно быть сделать ScreenToClient перед MoveWindow!

Немного подробнее: вам необходимо ознакомиться с тем, какая функция возвращает или использует клиентские координаты (и относительно того, что представляют собой эти клиентские координаты) и какие экранные координаты; это одна из частей MFC, которая может сбивать с толку. Что касается вашего вопроса:

CWnd:: GetWindowRect возвращает координаты экрана; CWnd:: MoveWindow ожидает координаты относительно родительского CWnd (или экрана, если это окно верхнего уровня). Поэтому перед вызовом MoveWindow необходимо преобразовать прямоугольник, возвращаемый GetWindowRect, в клиентские координаты вашего родительского окна; предположим, что pParent является CWnd * в родительское окно btnтогда ваш движущийся код должен выглядеть так:

CRect rect;
btn.GetWindowRect(&rect);
pParent->ScreenToClient(&rect);  // this line and it's position is important
rect.left += x;
rect.top += y;
btn.MoveWindow(&rect);

Если вы находитесь в методе родительского окна (как я думаю, так как вы упоминаете OnSize диалогового окна), то просто пропустите pParent->, То, как вы делаете ScreenToClient в данный момент, не влияет на MoveWindow, так как выполняется после него!

Другие вопросы по тегам