Как заставить приложение Windows Forms C # игнорировать, когда пользователь выбирает 125% или 150% для размера шрифта ОС?

Каков наилучший способ реализации констант в Java?

Один из подходов, который нам действительно следует избегать : использование интерфейсов для определения констант.
[1 156]

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

Даже если интерфейс уже существует для удовлетворения конкретной потребности, объявление констант в них не имеет смысла, так как константы не должны составлять часть API и контракта, предоставляемого клиентским классам.


Чтобы упростить, мы имеем в целом 4 действительных подхода .

С полем static final String/Integer:

  • 1) используя класс, который объявляет константы внутри, но не только.
  • 1 вариант) создание класса, предназначенного только для объявления констант.

С Java 5 enum:

  • 2) объявить перечисление в связанном классе цели (так, как вложенный класс).
  • 2 варианта) создание перечисления как отдельного класса (определено в его собственном файле классов).

TLDR: какой путь лучше и где найти константы?

В большинстве случаев путь enum, вероятно, лучше, чем static final String/Integer путь и лично я считаю, что путь static final String/Integer следует использовать только в том случае, если у нас есть веские причины не использовать перечисления.
И о том, где мы должны объявлять постоянные значения, идея состоит в том, чтобы искать, существует ли единственный существующий класс, который обладает определенной и сильной функциональной связностью с постоянными значениями. Если мы найдем такой класс, мы должны использовать его в качестве держателя констант . В противном случае константа не должна быть связана ни с одним конкретным классом.


static final String / static final Integer против enum

Использование перечислений действительно является способом, который настоятельно рекомендуется.
Перечисления имеют большое преимущество перед постоянным полем String или Integer.
Они устанавливают более сильное ограничение компиляции. Если вы определяете метод, который принимает перечисление в качестве параметра, вы можете передать только значение перечисления, определенное в классе перечисления (или ноль).
С помощью String и Integer вы можете заменить их любыми значениями совместимого типа, и компиляция будет в порядке, даже если значение не является определенной константой в полях static final String / static final Integer.

Например, ниже двух констант, определенных в классе как поля static final String:

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

Здесь метод, который предполагает использовать одну из этих констант в качестве параметра:

public void process(String constantExpected){
    ...    
}

Вы можете вызвать его следующим образом:

process(MyClass.ONE_CONSTANT);

или

process(MyClass.ANOTHER_CONSTANT);

Но никакое ограничение компиляции не мешает вам вызывать его таким образом:

process("a not defined constant value");

У вас будет ошибка только во время выполнения и только в том случае, если вы будете одновременно проверять переданное значение.

При использовании enum проверки не требуются, поскольку клиент может передать только значение enum в параметре enum.

Например, здесь два значения, определенные в классе enum (поэтому постоянные из коробки):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

Здесь метод, который ожидает иметь одно из этих значений enum в качестве параметра:

public void process(MyEnum myEnum){
    ...    
}

Вы можете вызвать его следующим образом:

process(MyEnum.ONE_CONSTANT);

или

process(MyEnum.ANOTHER_CONSTANT);

Но компиляция никогда не позволит вам вызвать его таким образом:

process("a not defined constant value");

Где мы должны объявлять константы?

Если ваше приложение содержит единственный существующий класс, который обладает специфической и сильной функциональной связностью с постоянными значениями, 1) и 2) кажутся более интуитивными.
Как правило, это облегчает использование констант, если они объявлены в главном классе, который ими манипулирует, или у которого есть имя, и очень естественно догадываться, что мы найдем его внутри.

Например, в библиотеке JDK экспоненциальные значения и значения констант pi объявляются в классе, который объявляет не только объявления констант (java.lang.Math).

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

Клиенты, использующие математические функции, часто полагаются на класс Math. Таким образом, они могут легко найти константы и могут также вспомнить, где E и PI определены очень естественным образом.

Если ваше приложение не содержит существующего класса, который имеет очень специфическую и сильную функциональную сплоченность с постоянными значениями, варианты 1 и 2 вариантов выглядят более интуитивно.
Как правило, это не облегчает использование констант, если они объявлены в одном классе, который ими манипулирует, в то время как у нас есть также 3 или 4 других класса, которые манипулируют ими так же, как и ни один из этих классов не кажется более естественным, чем другие. постоянные значения хоста.
Здесь определение пользовательского класса для хранения только постоянных значений имеет смысл.
Например, в библиотеке JDK перечисление java.util.concurrent.TimeUnit не объявлено в определенном классе, поскольку на самом деле не существует одного и только одного конкретного класса JDK, который представляется наиболее интуитивным для его хранения:

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

Многие классы, объявленные в java.util.concurrent, используют их: BlockingQueue, ArrayBlockingQueue<E>, CompletableFuture, ExecutorService, ... и на самом деле ни один из них не кажется более подходящим для хранения перечисления.

28
задан Peter Mortensen 4 March 2018 в 22:26
поделиться

3 ответа

Проблема заключается в том, что свойство Font формы или элемента управления определяет размер шрифта в точках. Это измерение, которое влияет на высоту букв при изменении настройки DPI. Одна точка составляет 1/72 дюйма. DPI по умолчанию, 96 точек на дюйм и размер шрифта 9 точек, дает букву высотой 9/72 x 96 = 12 пикселей.

Когда пользователь увеличивает настройку DPI, скажем, до 120 DPI (125%), тогда буква становится 9/72 x 120 = 15 пикселей в высоту. Если вы не позволите элементу управления увеличиваться, текст больше не будет помещаться в элемент управления. Очень некрасиво смотреть.

Свойство Form.AutoScaleMode решает эту проблему. Он проверяет, в каком размере была разработана форма, и сравнивает ее с DPI на компьютере, на котором она работает. И изменяет размеры и перемещает элементы управления, чтобы такого рода отсечение не происходило. Очень полезно, оно полностью автоматическое без необходимости что-либо с этим делать.

Типичная проблема - бит «перемещается» в предыдущем абзаце. Если вы присваиваете элементам управления собственный размер шрифта вместо того, чтобы наследовать размер формы, или если автоматическое расположение формы не кошерное, тогда элементы управления могут оказаться в неправильном месте, разрушая организованный вид формы.

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

Самый простой способ отладить проблему с макетом, избегая необходимости постоянного изменения размера DPI, - это временно вставить этот код в класс формы:

    protected override void OnLoad(EventArgs e) {
        this.Font = new Font(this.Font.FontFamily, this.Font.SizeInPoints * 125 / 96);
        base.OnLoad(e);
    }
18
ответ дан 28 November 2019 в 03:03
поделиться

Нет. GDI и Windows Forms зависят от разрешения. Наилучшим вариантом является создание макетов таким образом, чтобы они соответствующим образом масштабировались при изменении размера окна. Это также позволяет корректно работать с масштабированием размера шрифта, так как макеты будут корректироваться по мере необходимости.

Это, между прочим, одно из больших улучшений в WPF - оно разработано, чтобы быть независимым от разрешения.

2
ответ дан 28 November 2019 в 03:03
поделиться

Идти против желаний пользователя, как это не то, что MS охотно приспосабливается.

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

2
ответ дан 28 November 2019 в 03:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: