Я изменил свою форму на форму без полей, я просто изменил свойство BorderStyle на bsNone, но теперь мое приложение теряет привязку Windows и некоторые команды, такие как
WIN + ↑ (Align the form Client)
WIN + ↓ (Minimize the form)
WIN + →(Align the form Right)
WIN + ←(Align the form Left)
Я пытался установить BorderStyle: bsSizeable и использовать приведенный ниже код внутри FormCreate, но это не сработало:
procedure TfrmBase.FormCreate(Sender: TObject);
begin
SetWindowLong(Handle
,GWL_STYLE
,GetWindowLong(Handle, GWL_STYLE)
AND (NOT WS_CAPTION)
AND (NOT WS_THICKFRAME)
);
Refresh;
FormColor := oLauncher.oCor;
end;
Это приводит к:
Изображение выше - это то, что я хочу, но команды Windows, о которых я уже упоминал, не работают.
Есть ли способ установить BorderStyle: bsNone и не потерять эти команды?
ОТРЕДАКТИРОВАНО
Если я использую WS_THICKFRAME, моя форма возвращает небольшую верхнюю границу, и команды Windows работают хорошо, но мне не нужна эта верхняя граница.
ОТРЕДАКТИРОВАНО 2
Я был очень близок к ожидаемому результату, но пока есть небольшая проблема...
Я положил это на свой FormCreate
SetWindowLong(Handle
,GWL_STYLE
,GetWindowLong(Handle, GWL_STYLE)
AND (NOT WS_CAPTION)
);
И я создаю метод
private
procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
а потом
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
begin
inherited;
if Msg.CalcValidRects then
begin
InflateRect(Msg.CalcSize_Params.rgrc[0], 0, 6);
Msg.Result := 0;
end;
end;
I got this method here
Теперь граница исчезла, но когда моя форма теряет фокус, снова отображается верхняя/нижняя граница....
Как я могу этого избежать?
РЕШЕНО
Границу я оставил как BorderStyle: bsSizeable, потом сделал так:
private
procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
[...]
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
var
R: TRect;
begin
if not Msg.CalcValidRects then
R := PRect(Msg.CalcSize_Params)^;
inherited;
if Msg.CalcValidRects then
Msg.CalcSize_Params.rgrc0 := Msg.CalcSize_Params.rgrc1
else
PRect(Msg.CalcSize_Params)^ := R;
Msg.Result := 0;
end;
procedure TfrmBase.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle
,GWL_STYLE
,WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW
);
end;
procedure TfrmBase.FormShow(Sender: TObject);
begin
Width := (Width - 1);
end;
Solution at GitHUB
I've create a repository here
@whosrdaddy Да, я уже сделал это на C# с WPF, но я не знаю, как применить эту логику в Delphi... Я сделал это на C# и не потерял команды Windows.
в основном вы делаете то же самое (переопределяете параметры createparams и переопределяете wndproc)...
Чтобы системная команда работала, у вас должна быть включена соответствующая системная команда. Я имею в виду, что вам нужен WS_SIZEBOX, например, для win->, чтобы включить SC_SIZE. Но это связано с толстой рамой. IOW, рама - это то, что заставляет это работать.
@SertacAkyuz Я пробовал это, но появляется небольшая граница, посмотрите мой вопрос еще раз, пожалуйста.
Это было моей точкой зрения.
Привет, @SertacAkyuz, я нашел твой ответ здесь, который мне немного помог. Знаете ли вы, как мне избежать проблемы с ОТРЕДАКТИРОВАНО 2?
Возможно, вы на правильном пути. Возможно, вам следует нарисовать границу самостоятельно.
Я не понимаю сделки, хотя. В конце концов, у вас есть большое окно, почему вы не хотите, чтобы оно было правильным?
Я хочу создать свою собственную строку заголовка без потери команд Windows и без использования стилей... Но если я использую BorderStyle: bsNone, моя форма теряет эти команды, тогда я использую BorderStyle: bsSizeable, и я работаю, чтобы скрыть заголовок и его верхняя граница.
RE (решено): «* оставил границу как BorderStyle: bsSizeable*» — обратите внимание на «BorderStyle := bsNone;» в обработчике события OnCreate, если вы его не укажете, это не сработает, настройка дизайна не вступит в силу. Во всяком случае, я предполагаю, что «Ширина - 1» вызывает обновление кадра, вы, вероятно, можете добиться этого с помощью SetWindowPos (SWP_FRAMECHANGED) или RedrawWindow (RDW_FRAME).
@SertacAkyuz Если я уйду BorderStyle: = bsNone;, когда я использую WIN + Arrows, окно выглядит странно, некоторые части экрана становятся черными
Хорошо спасибо. Кажется, в разных средах отображается разное поведение, мне это не нравится. Попробуйте протестировать как можно больше ОС перед развертыванием.
Это внутреннее программное обеспечение, которое помогает моей команде изо дня в день, до сих пор я тестировал на Windows 10 и Windows 7, и с этим изменением, которое я сделал, оно хорошо работает на них обоих.





Некоторые из команд, на которые вы ссылаетесь, являются системными командами, связанными с изменением размера окна. Для этого нужна толстая рамка, без нее "WIN+право" и "WIN+лево" работать не будут. Кроме того, для работы команд WIN + вверх/вниз вам понадобится окно свертывания и окно максимизации.
Лучше всего начать с нуля и включить нужные стили, иначе VCL может помешать. Если есть возможность воссоздать вашу форму, поместите стиль в переопределение CreateWnd.
procedure TForm1.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;
Тогда есть кадр, который вам не нужен. В редактировании вопроса вы раздуваете прямоугольник клиента, чтобы избавиться от него. Не угадывайте ширину/высоту кадра, сделайте это, как показано ниже.
procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R: TRect;
begin
if not Message.CalcValidRects then
R := PRect(Message.CalcSize_Params)^;
inherited;
if Message.CalcValidRects then
Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
else
PRect(Message.CalcSize_Params)^ := R;
Message.Result := 0;
end;
На этом этапе чтение документация для сообщения является обязательным, параметры имеют разные значения на разных этапах и т. д.
Вышеприведенное оставляет окно без какой-либо неклиентской области. Прямоугольник клиента равен прямоугольнику окна. Хотя заголовок не виден, вы можете активировать системное меню, нажав Alt+Пробел. Проблема в том, что система настаивает на отображении состояния активации. Теперь он рисует рамку в клиентской области!!
Избавьтесь от него, перехватив WM_NCACTIVATE, он же нужен для отрисовки вашего заголовка по статусу активации:
procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
if Message.Active then
// draw active caption
else
// draw incactive caption
// don't call inherited
end;
Возможно, вам придется иметь дело с некоторыми глюками, испорченное окно имеет последствия. Например, в моем тесте свернутая форма не имеет связанного значка в диалоговом окне alt + tab.
Ниже мой тестовый образец полностью.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
protected
procedure WMNCActivate(var Message: TWMNCActivate); message WM_NCACTIVATE;
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;
procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
if Message.Active then
// draw active caption
else
// draw incactive caption
// don't call inherited
end;
procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R: TRect;
begin
if not Message.CalcValidRects then
R := PRect(Message.CalcSize_Params)^;
inherited;
if Message.CalcValidRects then
Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
else
PRect(Message.CalcSize_Params)^ := R;
Message.Result := 0;
end;
end.
Это сработало -, ты мне очень помог!! Теперь мне просто нужно внести некоторые коррективы...
так что в основном вы хотите это?