Проблема с настройкой

#c #winapi

#c #winapi

Вопрос:

Кто-нибудь может сказать мне, почему следующий код не работает? Я не получаю никаких ошибок компилятора.

 short value = 10;
SetProp(hCtl, "value", (short*) value);
  

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

1. Что вы имеете в виду под «не работает»? Чего вы ожидаете, что произойдет? Что же происходит на самом деле?

2. Ничего не происходит. Когда я проверяю значение с помощью GetProp(hCtl, "value") , оно возвращает 0.

3. Слепки почти всегда бывают неправильными. Когда я вижу слепок, мой первый импульс — удалить его. Без приведения компьютер жалуется … поэтому увеличьте уровень предупреждений вашего компилятора и обращайте внимание на предупреждения .

4. @pmg, в данном случае ты прав — неверен актерский состав операции. @Midas — вы , вероятно , захотите прочитать документацию для SetProp() … предполагается, что этот третий параметр должен быть a HANDLE .

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 .