Обновить

Комментарии 10

А просто заменить Edit на Static?

Да, вы правы. Так буквы при печати не появляются. К сожалению слово STATIC длиннее и хуже жмется, но да - если хочется перфекционизма, это отличный шаг. Тем более - места теперь много. Я просто оставил то, что было изначально в коде.

Добавил в исходный код ваш вариант, для тех, кто будет читать.

Раньше всё это можно было искать в MSDN, а теперь приходится у чатботов, потому что нет больше подробного MSDN, остались куцые страницы.

Так вот, когда сел проверять, оказалось, что то ли SDK поменяли, то ли железного дурака заглючило, но в моём SDK (10.0.28000.0) WC_STATIC задан через суффикс W, а тот ведёт на L"Static", не на макрос. И значение константы 0x8003 тоже ошибочное. С ним окно не создаётся, а GetLastError() возвращает 1407 (Cannot find window class.)

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

Было:

слово STATIC длиннее и хуже жмется

Передавайте вместо указателя на строку с оконным классом однословное целое (WORD). Из-за того, что второе слово нулевое, винды понимают, что это не настоящий указатель на строку. А то, что это одно слово, может быть, как-то поможет оптимизации.

WC_STATIC из <windows.h> определён как MAKEINTATOM(0x8003), а MAKEINTATOM как #define MAKEINTATOM(i) ((LPCTSTR)(((WORD)(i)))).

Так же и работа с ординалами, о которых вы пишете, устроена, насколько я помню. (Помню не очень уверенно). GetProcAddress тоже запросто кушает под видом lpsz просто число из нижнего диапазона.

А можно ссылку на эту информацию? Потому что я по документации какие-то другие числа вижу.

Я дополнил ответ выше, а ниже написал правильное значение: 0xC01A. Надо было, конечно, наоборот: сначала досконально разобраться, а уже потом писать.

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

Вот такой код на Windows 11:

HWND hStatic = ::CreateWindow(
		MAKEINTATOM(0xC01A),
		NULL,
		WS_CHILD | WS_VISIBLE | SS_RIGHT,
		0,
		0,
		200,
		24,
		m_hWnd,
		nullptr,
		GetModuleHandleW(NULL),
		NULL
	);

DWORD dwError = ::GetLastError();

работает и даёт нам натуральный Static с SS_RIGHT (для контроля). Проверено Spy++.

Число 0xC01A подобрал методом тыка.

Забавно, что я когда я стал разбираться, откуда чатбот взял неправильные константы), то набрёл на вот этот багрепорт на WINE: https://bugs.winehq.org/show_bug.cgi?id=49195

Оказывается, это освящённая временем техника демосценеров: не использовать литералы для оконных классов.

Я нашел что на самом деле это 0xC019 - так что да - с этой константой оно сработало - но, к сожалению, все равно стало на 3 байта больше. Хотя и сама строка "EDIT" удалилась. Но в исходник я тоже добавлю.

Как я написал выше, число 0xC01A я подобрал методом тыка. Мне попалась таблица, где было указано, что Static это 0xC019. Я попробовал, но по факту создался Edit. Не только Spy++ его показал, но ещё и текст в него можно было вводить. Тогда я уменьшил значение на единицу и получил Button. Уменьшил ещё на единицу и получил 1407/Cannot find window class. Тогда я увеличил значение на единицу (до 0xC01A) и получил, наконец, Static.

А почему на три байта больше? Если в коде будет два байта константы вместо шести байт строкового литерала.

Не знаю - это вопросы к Crinkler. Вы можете сами попробовать - заменить и скомпилировать. Возможно он попал в какой-то локальный минимум, возможно еще что-то. Вариант, впрочем, рабочий.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации