Формы Delphi 7, якоря не работают в Vista

Программа построена на Delphi 7.

На моей машине XP размер формы меняется, как я и ожидал. Однако на двух машинах Vista у меня есть компоненты с якорями, установленными на [akLeft, akTop, akRight, akBottom], но когда я изменяю размер формы, компоненты не растягиваются вместе с формой, оставляя пустые места на правом и нижнем краю. . На станке XP компоненты правильно растягиваются вместе с формой.

Итак, похоже, что машина Vista игнорирует свойство привязки. Есть идеи, что вызывает это и как это исправить?

Важное обновление (Франсуа):
У нас была такая же проблема с нашим приложением D2007 и во всех окнах x64.
Андреас ответ действительно был исправлением. Так что это не связано ни с D7, ни с Vista.


person Robo    schedule 31.08.2009    source источник
comment
Под какой версией Windows была скомпилирована программа?   -  person Argalatyr    schedule 31.08.2009
comment
См. Ответ Аргалатыря. Имеет ли это смысл?   -  person Hemant    schedule 01.09.2009
comment
Франсуа: Да, если предположить, что проблема Робо - это тот же сбой, с которым мы только что столкнулись, а не что-то не связанное с этим.   -  person Mason Wheeler    schedule 22.09.2009


Ответы (6)


Возможно, это связано с проблемой «переполнения стека ядра Windows», которая возникает, если у вашего элемента управления много родителей. И если вы запустите его на 64-битной системе, переполнение стека ядра произойдет намного быстрее. (подробнее об этом здесь: http://news.jrsoftware.org/news/toolbar2000/msg07779.html)

В CodeCentral Embarcadero есть обходной путь для этой ошибки (которая также почти 1: 1 скопирована в Delphi 2009 VCL): http://cc.embarcadero.com/Item/25646

person Andreas Hausladen    schedule 31.08.2009
comment
Правильно ли я полагаю, что это применимо только в том случае, если у вас есть элементы управления, вложенные примерно на 20 уровней в глубину? - person Argalatyr; 31.08.2009
comment
Это зависит от того, сколько оконных перехватчиков WH_CALLWNDPROC установлено в системе. (Logitech, например, использует перехватчики WH_CALLWNDPROC, как и TActionManager). - person Andreas Hausladen; 01.09.2009
comment
Я только что столкнулся с этим на работе и смог отследить его до этой проблемы благодаря вашему сообщению здесь. Спасибо за информацию и исправление, Андреас. Еще одно перышко в твоей и без того немалой кепке. - person Mason Wheeler; 22.09.2009
comment
Извините за очень поздний ответ. Я добавил ControlResizeBugFix.pas в проект в файле .dpr, но это не имело значения. На моем 64-битном компьютере с Windows 7 размеры элементов управления все еще не меняются. - person Robo; 19.05.2011
comment
ОК, исправлено. Это было связано с тем, что для некоторого свойства OldCreateOrder формы по умолчанию установлено значение true, а для некоторого значения по умолчанию - false, что привело к некорректной работе кода изменения размера некоторой формы. Если я изменю свойство на false, сохраню форму, а затем снова открою ее, в некоторых формах по умолчанию снова будет true. - person Robo; 19.05.2011
comment
Также есть некоторая информация об этой проблеме в сообщении блога MSDN: blogs.msdn.com/b/alejacma/archive/2008/ 20 ноября / и в этой статье базы знаний Майкрософт: support.microsoft.com/kb/ 953934 - person garethm; 30.06.2011

Это может быть из-за прозрачной рамки, которую показывает Vista. (Чтобы разные окна выглядели одинаково прозрачно.

Попробуйте использовать "Align" (alClient) вместо якорей. Поскольку вы используете все якоря, это имеет больше смысла.

person Hemant    schedule 31.08.2009
comment
Это не сработает, потому что элемент управления займет весь экран, закрывая другие элементы управления. - person Robo; 31.08.2009
comment
Например, у вас есть заметка, занимающая большую часть экрана, и у вас есть несколько кнопок внизу формы. Вы сначала размещаете панель и устанавливаете ее свойство Align на alBottom. Вы размещаете элементы управления на этой панели. Затем вы размещаете элемент управления памяткой и устанавливаете для его свойства align значение alClient (это заполнит форму, но оставит нижнюю панель). - person Hemant; 31.08.2009
comment
+1 это действительно работает (с дополнительным комментарием Хеманта). См. В качестве примера рабочий код в моем ответе (я бы отредактировал ответ Хеманта, но беспокоился, что это может быть грубо). - person Argalatyr; 01.09.2009

До того, как якоря были введены в Delphi 4, мы динамически изменяли размеры компонентов для достижения того же эффекта. Вы можете легко перемещать / настраивать компоненты в событии onresize формы.

Установка свойства doublebuffered формы на true может уменьшить мерцание за счет буферизации метода paint. Напомню, что раньше нам тоже приходилось это реализовывать!

person Argalatyr    schedule 31.08.2009

В качестве альтернативы предложенному мною динамическому изменению размера, основываясь на предложении Хеманта, я склеил рабочий код (см. Ниже). Просто создайте приложение форм VCL, установите tpanel, который не касается края формы (по умолчанию Align = alNone), и замените Unit1 приведенным ниже кодом. Когда вы запустите его, вы увидите 4 желтых панели, окружающие ту, которая была добавлена ​​изначально, а размер центральной панели изменится вместе с формой (как если бы все привязки были true).

unit Unit1;

interface

uses
  Windows, Classes, Controls, Forms, ExtCtrls, Graphics;

type
  TPanelPos = (ppLeft, ppRight, ppTop, ppBottom);
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Panels : array[TPanelPos] of tpanel;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  PanelPos : TPanelPos;
begin
  for PanelPos := ppLeft to ppBottom do
  begin
    Panels[PanelPos] := tpanel.Create(Form1);
    Panels[PanelPos].Parent := Form1;
    Panels[PanelPos].Color := clYellow;
    case PanelPos of
     ppLeft :
       begin
         Panels[PanelPos].Align := alLeft;
         Panels[PanelPos].Width := Panel1.Left - 1;
       end;
     ppRight :
       begin
         Panels[PanelPos].Align := alRight;
         Panels[PanelPos].Width := Form1.Width - Panel1.Left - Panel1.Width;
       end;
     ppTop :
       begin
         Panels[PanelPos].Align := alTop;
         Panels[PanelPos].Height := Panel1.Top - 1;
       end;
     ppBottom :
       begin
         Panels[PanelPos].Align := alBottom;
         Panels[PanelPos].Height := Form1.Height - Panel1.Top - Panel1.Height;
       end;
    end;
    Panel1.Align := alClient;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  PanelPos : TPanelPos;
begin
  for PanelPos := ppLeft to ppBottom do
    Panels[PanelPos].Free;
end;

end.
person Argalatyr    schedule 31.08.2009

Попробуйте запустить программу в режиме совместимости с XP в Vista. Программы, скомпилированные с помощью Delphi 7, могут не полностью поддерживать собственный режим Vista (на самом деле, неудивительно).

person Argalatyr    schedule 31.08.2009
comment
Клиенты захотят запускать его в родной Vista, а не в режиме совместимости, надеясь, что есть способ обойти это. - person Robo; 31.08.2009
comment
Понял. Извините, мне больше нечего предложить - я больше не использую D7, и мой ответ резюмирует мое понимание ситуации. Надеюсь, ты найдешь решение! - person Argalatyr; 31.08.2009
comment
Если вам нужна полная поддержка Vista, вам придется выполнить обновление. Это функция с Delphi 2007. Фактически, если вы действительно хотите оставаться в курсе, вам следует установить Delphi 2010, который вышел на прошлой неделе. Он имеет полную поддержку как Windows 7, так и Vista. - person Mason Wheeler; 31.08.2009
comment
Мейсон: Это правда, но это не совсем ответ на вопрос. Есть веские причины для того, чтобы придерживаться более старой версии для некоторых проектов, и найти способ удовлетворить спецификации в рамках этих ограничений - реальная проблема. - person Argalatyr; 31.08.2009

Похоже, что это довольно старый вопрос, в любом случае вот единственное решение этой проблемы во Вселенной: используйте старый метод определения размера программирования Windows с использованием API-ловушек WM_SIZE и WM_SIZING, это безошибочно и будет работать в каждой Windows, которую вы знаете .

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

В противном случае вы могли бы сделать что-то более практичное и быстрое с помощью процедуры изменения размера, например:

Control1.Left := Control2.Left + (buttonControl.Width div 2) - (buttonControl3.Width div 2);
//for example widths
Control4.Width    := (Control.Width * 4) + (Control.Left * 8) + 54 ;

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

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

iCXSCREEN := GetSystemMetrics(SM_CXSCREEN);
iCYSCREEN := GetSystemMetrics(SM_CYSCREEN);

    if ((iCXSCREEN = 1280) and (iCYSCREEN = 720)) or  ((iCXSCREEN = 1280) and (iCYSCREEN = 700)) or ((iCXSCREEN = 1280) and (iCYSCREEN = 600)) then begin

// blah blah

end;

Надежда помогает кому-то другому!

Ваше здоровье!

person Neuron    schedule 21.05.2010