Удалить границу окна?

У меня есть окно со сплошной рамкой вокруг него. Как удалить границу (всю неклиентскую область) с помощью SetWindowLong и GetWindowLong?


person Kristina Brooks    schedule 08.03.2010    source источник


Ответы (4)


In C/C++

LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
SetWindowLong(hwnd, GWL_STYLE, lStyle);

WS_CAPTION определяется как (WS_BORDER | WS_DLGFRAME). Вы можете удалить только эти два стиля, так как меню сворачивания, развертывания и системное меню исчезнут, когда исчезнет заголовок, но лучше удалить и их.

Также лучше удалить расширенные стили границ.

LONG lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle);

И, наконец, чтобы ваше окно перерисовывалось с измененными стилями, вы можете использовать SetWindowPos.

SetWindowPos(hwnd, NULL, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
person John Knoeller    schedule 08.03.2010
comment
@NathanGoings Не могли бы вы объяснить, почему, по вашему мнению, это устарело и что вместо этого актуально? - person RamboNo5; 09.05.2014
comment
@RamboNo5: функция SetWindowLong() заменена функцией SetWindowLongPtr(). - person dns; 02.07.2014
comment
@dns Понятно, спасибо. Но пока вы ориентируетесь только на 32-битную Windows, все равно. - person RamboNo5; 02.07.2014
comment
В качестве примечания, использование WS_MAXIMIZE и WS_MINIMIZE, похоже, приводит к сбою окна в Windows 10, устанавливая его состояние как Свернутое/Развернутое. Вы должны заменить их на WS_MAXIMIZEBOX и WS_MINIMIZEBOX, чтобы избежать этой проблемы. - person user780756; 26.05.2017
comment
WS_MAXIMIZE и WS_MINIMIZE влияют на начальное состояние окна. - person NathanAldenSr; 22.05.2020

Следующие коды Delphi делают это:

  SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) and not WS_BORDER and not WS_SIZEBOX and not WS_DLGFRAME );
  SetWindowPos(Handle, HWND_TOP, Left, Top, Width, Height, SWP_FRAMECHANGED);

Конечно, эти вызовы API выглядят одинаково на всех языках.

person Andreas Rejbrand    schedule 08.03.2010

Эта строка кода ниже удаляет границу любого заданного окна и остается только его клиентом:

SetWindowLong(hWnd /*The handle of the window to remove its borders*/, GWL_STYLE, WS_POPUP);

Вместо этого вы можете использовать WS_POPUPWINDOW в третьем параметре функции SetWindowLong. Он также удаляет границы данного окна и тоже работает, но разница в том, что он также рисует очерченный черный прямоугольник по всему оставшемуся клиенту окна. Толщина этого выделенного прямоугольника составляет 1 пиксель. WS_POPUP не рисует этот прямоугольник, на самом деле ничего не рисует, только удаляет границы окна.

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

GetWindowLong(hWnd /*The handle of the window that you want to remove its borders and later return them back to it*/, GWL_STYLE);

но, конечно, эта функция перенастраивает стили окна, поэтому создайте новую переменную, которая сохранит эти стили, т.е. установите эту переменную в возвращаемое значение этой функции.

Затем вы используете SetWindowLong, как я показал выше, чтобы удалить его границы, и когда вы захотите позже восстановить его границы обратно, просто снова вспомните SetWindowLong, первые два параметра одинаковы (hWnd и GWL_STYLE), но третий параметр - это стили окно, возвращенное из GetWindowLong. Если вы не хотите вызывать GetWindowLong, но все равно возвращаете границы окна, то вы можете использовать SetWindowLong с теми же первыми двумя параметрами, а в третьем параметре можно использовать один из следующих: WS_OVERLAPPED или/и WS_OVERLAPPEDWINDOW или/и WS_SIZEFRAME.

ПРИМЕЧАНИЕ. Если вы попробуете мой ответ, но он не сработает для вас, это может быть связано с тем, что обе функции SetWindowLong и GetWindowLong были заменены и не работают для вас, а также потому, что они совместимы только с 32-разрядной версией Windows. Возможно, вы используете 64-разрядную версию Windows, тогда используйте вместо нее SetWindowLongPtr и GetWindowLongPtr, которые совместимы с обеими 32-разрядными и >64-битные версии Windows. MSDN сообщает об этих функциях в разделе Примечание. Просто найдите их на этом сайте. Вот ссылки на них:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms633584(v=vs.85).aspx

Надеюсь, что все это отвечает на ваш вопрос.

person Community    schedule 24.08.2014
comment
Спасибо, что напомнили об использовании WS_POPUP, это единственный метод, работающий с созданием уже окон без полей. - person weaknespase; 15.10.2015

Это удаляет строку заголовка и вертикальные полосы прокрутки...

int main()
{
    HWND hwnd = GetConsoleWindow();
    // remove title bar
    LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
    lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
    SetWindowLong(hwnd, GWL_STYLE, lStyle);
    //remove vertical scrollbar
    ShowScrollBar(hwnd, SB_VERT, FALSE);

    cout << "Hello World! \n";
    system("pause");

    return 0;
}
person pollaris    schedule 13.06.2018
comment
Вы знаете, как убрать границу, но сохранить строку заголовка? - person Emile; 19.06.2018
comment
просто используйте ShowScrollBar(hwnd, SB_VERT, FALSE); - person pollaris; 20.06.2018