Подтвердить что ты не робот

Как сделать зависание над кнопками "Минимизировать", "Максимизировать" и "Закрыть"?

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

  • Минимизация
  • Maximize
  • Восстановление

он не ведет себя правильно:

введите описание изображения здесь

Сравните с приложением, которое ведет себя правильно:

введите описание изображения здесь

Шаг для воспроизведения

  • Нажмите Файл, Новый, Приложение VCL Forms - Delphi
  • Нажмите Выполнить (F9)
  • Наведите курсор на кнопки "Минимизировать", "Развернуть" или "Закрыть".

Как исправить?

  • Windows 10, 64-разрядная (выполняется на настольном ПК)
  • Delphi XE6

Изменить. Он также не работает с Delphi 7:

введите описание изображения здесь

и в Delphi 5:

введите описание изображения здесь

и в Delphi 4:

введите описание изображения здесь

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

Режимы совместимости

  • none: не работает
  • Windows 8: сбой
  • Windows 7: сбой
  • Windows Vista (Service Pack 2): не работает
  • Windows Vista (Service Pack 2): не работает
  • Windows Vista​​strong > : не работает
  • Windows XP (с пакетом обновления 3) (исключение из области без клиентов): работает
  • Windows XP (с пакетом обновления 2) (исключение из области без клиентов): работает
  • Windows 98/Windows Me (исключение из области без клиентов): работает
  • Windows 95 (исключение из области без клиентов): работает

Skype

Также не удается выполнить Skype; также написано в Delphi:

введите описание изображения здесь

Высокий DPI - это триггер

Наконец-то я понял, почему он терпит неудачу на каждой машине Windows 10, которую я использовал; но не для всех. Высокий dpi.

Установите ваши значения dpi на 97 (101%) или выше.

Закрыть достаточно

Решения Dalija:

введите описание изображения здесь

Мы проигнорируем проблему с помощью всплывающей подсказки и будем жить в следующий день.

Следует также отметить, что Windows 10 предложит, чтобы вам пришлось подписаться и подписаться, чтобы некоторые приложения могли корректно работать после изменения DPI. Это определенно верно для Delphi.

Следует также отметить, что Delphi не терпит изменения DPI за его спиной. Это включает настройку ползунка масштабирования. Это также включает размещение приложения на любом мониторе, кроме основного монитора.

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

Отчет об ошибках QC

Потому что Bor... Impr... CodeG... Embarca... Сайт Idera QC находится за платной, здесь копия отчет об ошибке:

Как вы можете видеть: никто не заботится.

4b9b3361

Ответ 1

Высокий DPI - это триггер, и это приводит к решению.

Приложения, которые демонстрируют эту проблему, не осведомлены о высоком значении DPI. Решение проблемы зависания состоит в том, чтобы информировать их или включить соответствующий режим совместимости, используя одно из решений под 1, 2 или 3.

Примечание. Будет ли остальная часть приложения вести себя корректно при включении высокой осведомленности о DPI, является другой проблемой и будет отличаться от приложения к приложению.

  • В режиме совместимости установите флажок "Отключить масштабирование дисплея при высоких настройках DPI"

  • Вызвать SetProcessDPIAware как первый вызов в файле .dpr - как отметил Ян Бойд, вызов этой функции может привести к состоянию гонки, а предпочтительный способ - использовать манифест. SetProcessDPIAware

  • Использовать пользовательский манифест с настройками true или true/PM (дефолт Delphi, включенный в "Включить темы времени выполнения", не отличается высоким уровнем DPI)

В текущих версиях фреймворков Delphi VCL и FMX отсутствует поддержка для каждого монитора DPI, поэтому используйте true/PM манифест, только если вы обрабатываете каждый монитор DPI самостоятельно. Сообщается QP как VCL и FireMonkey не поддерживают поддержку DPI для Windows 8.1 (и Windows 10)


  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

или

  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true/PM</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

Update:

Delphi VCL является источником ошибочного поведения, в частности, вопрос находится где-то в классе TForm или его предках. Когда используется прямой интерфейс Windows API, в результате окна ведут себя нормально.

Код API Windows, который ведет себя правильно:

  MessageBox(0, 'Correct', 'Caption', MB_OK); 

  ShowMessage('Correct'); // if themes are enabled -> Windows Task dialog is used

Полное приложение примера Delphi, которое создает главное окно без использования VCL - ведет себя правильно

program win;

{$R *.res}

uses
  Windows,
  Messages,
  SysUtils;

var
  Msg: TMSG;
  LWndClass: TWndClass;
  hMainHandle: HWND;

function WindowProc(HWND, Msg: Longint; wParam: wParam; lParam: lParam): Longint; stdcall;
begin
  if Msg = WM_DESTROY then PostQuitMessage(0);
  Result := DefWindowProc(HWND, Msg, wParam, lParam);
end;

begin
  LWndClass.hInstance := hInstance;
  with LWndClass do
    begin
      lpszClassName := 'WinApiWnd';
      Style := CS_PARENTDC or CS_BYTEALIGNCLIENT;
      hIcon := LoadIcon(hInstance, 'MAINICON');
      lpfnWndProc := @WindowProc;
      hbrBackground := COLOR_BTNFACE + 1;
      hCursor := LoadCursor(0, IDC_ARROW);
    end;

  RegisterClass(LWndClass);
  hMainHandle := CreateWindow(LWndClass.lpszClassName, 'Window Title', WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE, 0, 0, 360, 200, 0, 0, hInstance, nil);

  while GetMessage(Msg, 0, 0, 0) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
end.

Неверные формы VCL:

var
  f: TForm;

  f := CreateMessageDialog('Broken', mtWarning, mbOKCancel, mbOk);
  f.ShowModal;
  f.Free;

  f := TForm.Create(nil);
  f.ShowModal;
  f.Free;