Каково различие между CreateWnd и CreateWindowHandle?

Быстрый ответ ...

С Swift 2.0 вы можете использовать #available в if или guard для защиты кода, который должен запускаться только в определенных системах.

if #available(iOS 9, *) {} В Objective-C вам нужно проверить версию системы и выполнить сравнение.

[[NSProcessInfo processInfo] operatingSystemVersion] в iOS 8 и выше.

Начиная с Xcode 9 :

if (@available(iOS 9, *)) {}

Полный ответ ...

В Objective-C и Swift в редких случаях лучше избегайте использования версии операционной системы в качестве индикатора возможностей устройства или ОС. Обычно существует более надежный метод проверки доступности конкретной функции или класса.

Проверка наличия API-интерфейсов:

Например, вы можете проверить, есть ли UIPopoverController доступный на текущем устройстве с помощью NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

Для слабосвязанных классов, можно безопасно сразу передать сообщение классу. Примечательно, что это работает для фреймворков, которые явно не связаны как «Обязательно». Для отсутствующих классов выражение оценивается как nil, если не выполняется условие:

if ([LAContext class]) {
    // Do something
}

Некоторые классы, такие как CLLocationManager и UIDevice, предоставляют методы проверки возможностей устройства:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Проверка наличия символов:

Очень часто вы должны проверить наличие константы. Это появилось в iOS 8 с введением UIApplicationOpenSettingsURLString, который использовался для загрузки настроек приложения через -openURL:. Значение не существовало до iOS 8. Передача nil в этот API приведет к сбою, поэтому сначала вы должны убедиться в наличии константы:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

Сравнение с версией операционной системы:

Предположим, вы столкнулись с относительно редкой необходимостью проверить версию операционной системы. Для проектов, ориентированных на iOS 8 и выше, NSProcessInfo включает метод сравнения версий с меньшей вероятностью ошибки:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Проекты, ориентированные на более старые системы, могут использовать systemVersion в UIDevice. Apple использует его в своем образном коде GLSprite .

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

Если по какой-либо причине вы решите, что systemVersion - это то, что вы хотите, обязательно обработайте его как строку или вы рискуете усечь номер версии исправления (например, 3.1.2 -> 3.1).

23
задан Rob Kennedy 24 February 2009 в 18:19
поделиться

4 ответа

До сих пор большинство ответов здесь находится в значительной степени на метке, и Вы преуспели бы для учета их совета. Однако существует немного больше к этой истории. К Вашему конкретному вопросу о том, когда Вы переопределили бы один или другой, я попытаюсь вещи ореховой скорлупы немного.

CreateParams ();

В целом, большую часть времени все, что действительно необходимо сделать, должно переопределить CreateParams (). Если все, что Вы хотите сделать, должно разделить на подклассы (помните разделение на подклассы "стиля Windows?" Посмотрите оригинальную работу Petzold над программированием Windows), существующий класс управления, и оберните его в управлении VCL, Вы делаете это от CreateParams. Можно также управлять тем, какие биты стиля установлены и другие различные параметры. Мы сделали процесс из создания "подкласса" очень легким. Просто назовите CreateSubClass () от Вашего CreateParams () методом. Посмотрите базовые средства управления VCL для примера, такие как TCheckBox или TButton.

CreateWnd ();

Вы переопределили бы этого, если необходимо сделать немного больше с дескриптором окна, как только он создается. Например, если Вы имеете контроль, который является некоторым списком, деревом, или иначе требует конфигурации постсоздания, Вы сделали бы это здесь. Назовите наследованный CreateWnd, и когда он возвращается (Вы знаете, что у Вас есть допустимый дескриптор, если Вы возвращаетесь из CreateWnd, потому что он повысит исключение, если что-то спуталось), просто примените свое дополнительное волшебство. Общий сценарий должен взять данные, которые кэшируются в экземпляре список TStrings, и на самом деле переместите его в базовое управление окном. TListBox является классическим примером этого.

CreateWindowHandle ();

я должен был пойти, обновляют мою память на этом, но кажется, что это, каждый редко, если когда-либо, переопределен. В нескольких случаях в самом VCL кажется, что это используется для работы вокруг определенной версии Windows и причуд локали с некоторыми средствами управления, такими как TEdit и TMemo. Другое больше ясного случая находится в самом TCustomForm. В этом случае это там для поддержки старого MDI (интерфейс mutli-документа) модель. В этом случае дети MDI не могут быть созданы с помощью нормального CreateWindowEx () API, необходимо отправить сообщение в родительский кадр MDI для фактического создания дескриптора. Так единственная причина для сверхъязя этот метод - то, если фактический процесс создания дескриптора сделан через средство, полностью отличающееся, чем старый проверенный CreateWindowEx ().

я действительно замечал, что Ваш вопрос просто спрашивал о процессе создания, но существуют соответствующие методы, которые переопределяются в некоторых случаях и для разрушения дескриптора и для "вуду", который иногда окружает воссоздание дескриптора. Но это другие темы, которые должны быть затронуты отдельно:-).

40
ответ дан Uli Gerhardt 29 November 2019 в 01:43
поделиться

CreateWnd сначала называет CreateParams, затем называет CreateWindowHandle с помощью созданного Params. Обычно Вы переопределите CreateWnd и CreateParams, а не CreateWindowHandle.

я надеюсь, что это помогает!

4
ответ дан Tim Sullivan 29 November 2019 в 01:43
поделиться

, Кто делает что:
CreateWnd является генеральным подрядчиком, который создает полностью сформированное окно для WinControl.
Первый, это должно установить необходимые атрибуты для WindowClass путем вызова CreateParams и проверки, что это правильно регистрируется.
Тогда это создало окно на самом деле путем вызова CreateWindowHandle, который возвращает получающийся Дескриптор из ОС.
После этого, у нас есть допустимое окно, которое в состоянии обработать сообщения, и , CreateWnd делает уход финала, корректировку различных визуальных аспектов как размер, шрифт, и т.д.

существует также более поздний шаг, сделанный [1 111] CreateHandle, после того, как CreateWnd закончен, для помощи VCL в управлении его окнами (идентификация, происхождение...).

3
ответ дан François 29 November 2019 в 01:43
поделиться

Я уверен, что окончательный ответ может только прибыть от людей, вовлеченных в создание VCL (Allen?), но по моему скромному мнению виртуальный метод с наименьшим количеством ответственности / который является самым низким в цепочке вызовов, должен быть переопределен. Вот почему я всегда переопределял CreateParams () и CreateWindowHandle () . Это похоже на хорошую подгонку, так как их оба называют CreateWnd () , и оба делают только одну специальную вещь.

В конце это - вероятно, вопрос предпочтения.

0
ответ дан David Heffernan 29 November 2019 в 01:43
поделиться
Другие вопросы по тегам:

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