Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос про SetWindowLong() 
:(
    Опции темы
yngwie19
Дата 2.4.2009, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Всем привет. У меня вопрос по функции SetWindowLong. Скажите, допустим при регистрации класса в структуре wc, конкретно в параметре wc.cbWndExtra, задаю размер 8 (байт), после этого с помощью вышеуказанной функции хочу записать 2 числа по 4 байта (т.е int). При вызове этой функции во втором параметре мы указываем смещение, т.е если мы укажем 0, то запись будет осуществляться с первого байта (т.е 1, 2,3,4 будут заняты), после чего для записи второго int мы указываем уже 4 (т.е начиная с 5-го до 8 включительно память будет занятя). Т.е когда мы указываем смещение, то имеем в виду что со следующего байта будет производится запись, так? 
PM MAIL   Вверх
GremlinProg
Дата 4.4.2009, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



да, так

в SetWindowLong и SetClassLong передается смещение, по которому, в памяти, ассоциируемой с окном, и хранятся пользовательские(и системные) параметры, каждый параметр имеет фиксированный размер, покрывающий двойное слово


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  4.4.2009,  00:39 Найти цитируемый пост)
да, так

в SetWindowLong и SetClassLong передается смещение, по которому, в памяти, ассоциируемой с окном, и хранятся пользовательские(и системные) параметры, каждый параметр имеет фиксированный размер, покрывающий двойное слово 

А почему с 1-го, если я смещение 0 указал?
PM MAIL ICQ   Вверх
GremlinProg
Дата 4.4.2009, 01:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Anikmar @  4.4.2009,  02:51 Найти цитируемый пост)
А почему с 1-го, если я смещение 0 указал?

не понял, Anikmar, ты второй частью вопроса ответил на первую


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  4.4.2009,  01:38 Найти цитируемый пост)
не понял, Anikmar, ты второй частью вопроса ответил на первую 

Богатый русский язык. Что это? Черная смородина. А почему она красная? Потому, что зеленая!

Я думал там какая-то хитрая особенность нумерации - указываешь 0, а берется байт № 1 (а не байт № 0). Вот я и уточнил: если смещение 0, то с нулевого байта нумерация или с 1-го.  smile 

А так, естественно, на человеческом языке по смещению 0 находится самый что ни на есть 1-й байт.

Разобрались, короче.  smile 
PM MAIL ICQ   Вверх
yngwie19
Дата 4.4.2009, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Цитата(GremlinProg @  4.4.2009,  00:39 Найти цитируемый пост)
каждый параметр имеет фиксированный размер, покрывающий двойное слово 

т.е больше чем размер двойного слова в один параметр поместить нельзя?
PM MAIL   Вверх
GremlinProg
Дата 4.4.2009, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(yngwie19 @  4.4.2009,  14:02 Найти цитируемый пост)
т.е больше чем размер двойного слова в один параметр поместить нельзя?

а зачем?
эту память используют обычно только для хранения указателей на объекты окна
ну и некоторые компоненты еще сохраняют там дополнительные флаги внутренних состояний
причем в некоторых случаях есть явные ограничения на размер этой памяти:
Цитата(About Window Classes @ MSDN)

Because extra memory is allocated from the system's local heap, an application should use extra window memory sparingly. With system version 4.0 or later, the RegisterClassEx function fails if the amount of extra window memory requested is greater than 40 bytes. If an application requires more than 40 bytes, it should allocate its own memory and store a pointer to the memory in the extra window memory.


Добавлено через 1 минуту и 50 секунд
аот, Anikmar, кстати  и явный пример, где без преобразования указателя к целому не обойтись


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



 smile ух, злопамятный вы, однако!
Цитата(GremlinProg @  4.4.2009,  12:25 Найти цитируемый пост)
аот, Anikmar, кстати  и явный пример, где без преобразования указателя к целому не обойтись 

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

Именно в таких случаях можно применить проверку (если уж совсем параноиком быть). Когда размер указателя перевалит за 40 байт думаю уже другие системы будут  smile 
if (sizeof(void*) > 40) .... типа платформа для данного компилера точно не подходит.

Например, может быть и такая конструкция, если приспичит - на то это и C++:
Код

char Buff[3000];
void *Pointer;
Pointer = ...
memcpy(Buff,&Pointer,sizeof(Pointer));


PM MAIL ICQ   Вверх
GremlinProg
Дата 4.4.2009, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



нет, это как раз именно тот случай, о котором мы с тобой и рассуждали ))
40 бай тут ни при чем, поскольку для записи их одним махом интерфейса как раз нет
Код

LONG SetWindowLong(          HWND hWnd,
    int nIndex,
    LONG dwNewLong
);

в dwNewLong помещается указатель, как ни крути,
и ни где не предлагается его делить порционально,
значит подразумевается, что он туда именно "влезет"
иначе выходит, что система не совместима с платформой, не так ли?
а если так, то наш параноизм уже удовлетворила виндовс тем фактом,
что приложение запущено из ее недр, инкапсулировав и решив все наши опасения

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


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 4.4.2009, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



и еще один "железный" пример, чтобы отмести уже абсолютно все сомнения:
GWL_WNDPROC - смещение для указателя оконной процедуры
Код

typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);

окно - основной компонент операционки,
если GetWindowLong не возвращает корректный указатель, вследствии разноразмерности LONG и WNDPROC,
то как такая система работает?


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  4.4.2009,  13:28 Найти цитируемый пост)
я не злопамятный, просто подвернулся хороший пример, который разрешает спорную ситуацию,
почему бы его не использовать 

Согласно стандарту С++ указатель может преобразовываться в целое число, если размер целого достаточен для вмещения указателя. При обратном преобразовании указатель должен соответствовать исходному. Это по стандарту. В данном случае предполагается, что указатель влезает в dword. (Интересно, а в висте какой прототип этой функции?)

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

Это в общем-то даже не спор был, а отстаивание точек зрения. Я себя к параноикам не отношу, но стараюсь делать аккуратно что-ли - даже слово не подобрать.



PM MAIL ICQ   Вверх
GremlinProg
Дата 4.4.2009, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Anikmar @  4.4.2009,  15:50 Найти цитируемый пост)
Наш спор был об обратной ситуации: в прототипе требовался void*, а мы туда помещали int

я просто обобщил две функции, в предыдущем посте от GetWindowLong требуется указатель на процедуру окна, а возвращает она LONG -  ситуация в точности повторяется

я тоже не параноик и стараюсь следовать букве закона, если на обратное не причин
два интерфейса GetWindowLong и SetWindowLong - "зеркальные" с этой точки зрения,
поэтому не вижу причин для сомнений


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  4.4.2009,  14:00 Найти цитируемый пост)
я просто обобщил две функции, в предыдущем посте от GetWindowLong требуется указатель на процедуру окна, а возвращает она LONG -  ситуация в точности повторяется

я тоже не параноик и стараюсь следовать букве закона, если на обратное не причин
два интерфейса GetWindowLong и SetWindowLong - "зеркальные" с этой точки зрения,
поэтому не вижу причин для сомнений 


Сомнений у меня нет. То что в win32 рамер указателя 4 байта понятно и ежу.
То, что указатель можно передавать через целое достаточного размера прописано в стандарте и тут никакого противоречия с тем, что я говорил нет. Я не говорил, что указатель нельзя передать через целое - половина виндов на этом построена. Я говорил, что если в прототипе функции указан параметр void* не следует его использовать для передачи целого - в целях обеспечения граммотности кода и избежания возможных проблем. 
PM MAIL ICQ   Вверх
GremlinProg
Дата 4.4.2009, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Anikmar @  4.4.2009,  16:24 Найти цитируемый пост)
Я говорил, что если в прототипе функции указан параметр void* не следует его использовать для передачи целого - в целях обеспечения граммотности кода и избежания возможных проблем. 

об этом и речь, результат прототипа GetWindowLong не имеет тип void* и даже WNDPROC, он целочисленный
получается, ты рекомендуешь майкрософту придерживаться стандарта, который соблюсти невозможно?

Цитата(Anikmar @  4.4.2009,  16:24 Найти цитируемый пост)
Я говорил, что если в прототипе функции указан параметр void* не следует его использовать для передачи целого - в целях обеспечения граммотности кода и избежания возможных проблем. 

поэтому целое и необходимо преобразовать к типу void*, т.е. сделать дополнительное телодвижение (void*)(long), которое заставит программиста подумать: "а не приведет ли это к сбою программы"?

подумал, посмотрел на GetWindowLong и SetWindowLong
и заключил - "не приведет"

потом подумал, "а пойму ли я такой ход через пару дней, когда буду вновь вникать в этот код"?

взвесил все за и против, и принял решение, которое от нас с тобой уже абсолютно не зависит


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 4.4.2009, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  4.4.2009,  14:52 Найти цитируемый пост)
об этом и речь, результат прототипа GetWindowLong не имеет тип void* и даже WNDPROC, он целочисленный
получается, ты рекомендуешь майкрософту придерживаться стандарта, который соблюсти невозможно?

 smile Интересно, а прислушался бы микрософт к моим рекомендациям.

Все дело в том, что много кода написано на С, много написано старого и т.п. Эти функции виндов написаны черт знает в каком году и менять windows.h для совместимости никто естественно не будет.
В качестве поддтверждения моих слов о постепенном отходе от вольных преобразований может послужить появление в стандарте таких штуковин как *_cast. Например наши обсуждаемые преобразования static_cast откажется делать.

Параметр dword, который возвращает функция GetWindowLong не нарушает ни стандарта, ни моей точки зрения. Внутри функции получается каким-то образом указатель и его нужно возвратить. Как можно передать указатель через int в параметрах и это допускается стандартом, так можно его и возвратить через int в качестве возвращаемого значения - и это тоже допускается стандартом. Т.е. через int мы вернули указатель ничего особенного не нарушив, главное, что мы должны быть уверены, что указатель туда поместился. И это допускается стандартом и это документировано в описании функции.

А вот если мы найдем в виндах функцию, которая возвращает void*, а в документации будет сказано, что нужно преобразовать его в int - так как через тип void* специально передано значение int, с которым потом можно работать именно как с int, то тут на лицо баг. (Может и есть такое в виндах - от них всего можно ожидать  smile ).

Если разработчики создали функцию, которая получает в качестве параметра некий указатель, а не целое число - возможно в этом был какой-то смысл. И при дальнейших модификациях данной функции вполне возможно, что по этому указателю будет обращение, либо проверка его на NULL и принятие на базе этой проверки решения. И если старый код вполне работал с такой функцией и в этом указателе передавался како-либо параметр, то при переносе кода в новую версию, где в этой функции этот параметр используется как указатель - то можно получить трудноуловимый баг. Я не говорю конкретно о функции CreateThread. Я говорю о подходе в целом - если есть интерфейс, он документирован и требует указателя без явных оговорок его использования - то не следует рисковать. 

Ну висят какие-то оголенные провода без напряжения и мы на них белье вешаем сушить. 30 лет висят, а на 31 год - возьмут на них и напряжение подадут. Провода ведь. А просто надо было сушить белье не на проводах, а на специальных веревках.


PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0897 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.