#c #winapi
#c #winapi
Вопрос:
Кто-нибудь может сказать мне, почему следующий код не работает? Я не получаю никаких ошибок компилятора.
short value = 10;
SetProp(hCtl, "value", (short*) value);
Комментарии:
1. Что вы имеете в виду под «не работает»? Чего вы ожидаете, что произойдет? Что же происходит на самом деле?
2. Ничего не происходит. Когда я проверяю значение с помощью
GetProp(hCtl, "value")
, оно возвращает 0.3. Слепки почти всегда бывают неправильными. Когда я вижу слепок, мой первый импульс — удалить его. Без приведения компьютер жалуется … поэтому увеличьте уровень предупреждений вашего компилятора и обращайте внимание на предупреждения .
4. @pmg, в данном случае ты прав — неверен актерский состав операции. @Midas — вы , вероятно , захотите прочитать документацию для
SetProp()
… предполагается, что этот третий параметр должен быть aHANDLE
.5. @Carl Norum: в этом случае вы, вероятно, не хотите amp;value: SetProp просто принимает значение указателя и сохраняет его вслепую; ему все равно, является ли это вообще реальным значением. Думайте об этом как о dwUserData, но с необычным типом. Проблема с сохранением и значением в этом случае заключается в том, что вы сохраняете адрес переменной, которая (по-видимому) находится в стеке, что впоследствии не принесет вам никакой пользы. Как ни странно (даже по стандартам Win32!), приведение самого значения на самом деле является правильным решением здесь — Get / SetProp, возможно, является единственным Win32 API, где приведение почти всегда правильное. (Смотрите ссылку на MSDN в комментарии выше.)
Ответ №1:
Третий параметр вводится как a HANDLE
, поэтому IMO, чтобы выполнить явный контракт функции, вы должны сохранить свойство как a, HANDLE
выделив HGLOBAL
блок памяти. Однако, как отмечено в комментариях ниже, MSDN утверждает, что можно указать любое значение, и действительно, когда я пытаюсь использовать его в Windows 7…
SetProp(hWnd, _T("TestProp"), (HANDLE)(10)); // or (HANDLE)(short*)(10)
...
(short)GetProp(hWnd, _T("TestProp"));
… Я получаю обратно 10 от GetProp. Я подозреваю, что где-то между вашими SetProp и GetProp происходит одна из двух вещей: (1) значение hWnd отличается — вы проверяете другое окно или (2) проблема с синхронизацией — свойство еще не было установлено или было удалено.
Если вы хотите использовать HGLOBAL
вместо этого для следования определенным типам сигнатуры функции, вы можете следовать этому примеру в MSDN.
Несмотря на то, что a HANDLE
— это просто указатель, это определенный тип данных, который выделяется вызовами в Windows API. У многих вещей есть дескрипторы: иконки, курсоры, файлы, … Если в документации явно не указано иное, чтобы использовать большой двоичный объект данных, такой как a short
когда функция вызывает a HANDLE
, вам нужен дескриптор памяти (an HGLOBAL
).
Приведенный выше пример кода копирует данные в виде строки, но вместо этого вы можете задать его как другой тип данных:
// TODO: Add error handling
hMem = GlobalAlloc(GPTR, sizeof(short));
lpMem = GlobalLock(hMem);
if (lpMem != NULL)
{
*((short*)lpMem) = 10;
GlobalUnlock(hMem);
}
Чтобы прочитать его обратно, когда вы GetProp
хотите получить HANDLE
, вы должны заблокировать его для чтения из памяти:
// TODO: Add error handling
short val;
hMem = (HGLOBAL)GetProp(hwnd, ...);
if (hMem)
{
lpMem = GlobalLock(hMem);
if (lpMem)
{
val = *((short*)lpMem);
}
}
Комментарии:
1. Неверно: хотя на самом деле оно введено как дескриптор, в MSDN указано, что это может быть любое значение: msdn.microsoft.com/en-us/library/ms632594 (v = VS.85).aspx : Свойство window — это любые данные, назначенные окну. Свойство window обычно является дескриптором специфичных для окна данных, но это может быть любое значение.
2. Вы правы. Я только что протестировал это в Windows 7, и вызов
SetProp(hWnd, "PropName", (HANDLE)(short*)(10))
действительно работает. Интересно, может быть, предыдущие версии Windows требовали, чтобы это действительно былоHANDLE
, затем они смягчили это в более поздней версии? Это не работает для операции…3. Также работает и на XP… Это самая старая версия Windows, с которой мне приходилось тестировать.
4. Похоже, что код, который у меня был изначально, действительно сработал. Должно быть, в моем коде была какая-то другая проблема…
Ответ №2:
Я бы создал short
в куче, чтобы она продолжала существовать, или, возможно, сделал бы ее глобальной, что, возможно, вы и сделали. Также приведение для short
адреса должно быть void *
, или HANDLE
.