Как отправить плавающие сообщения в окнах - PullRequest
3 голосов
/ 23 марта 2010

Каков наилучший способ отправки плавающего в сообщении Windows с использованием операторов приведения в соответствие c ++?

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

PostWindowMessage(UINT nMsg, WPARAM wParam, LPARAM lParam)

Что не работает:

  • Использование static_cast<WPARAM>() не работает, так как WPARAMtypedef'ed к UINT_PTR и выполнит преобразование чисел из числа с плавающей точкой в ​​целое число, эффективно обрезая значение с плавающей точкой.
  • Использование reinterpret_cast<WPARAM>() не работает, поскольку оно предназначено для использования с указателями и завершается с ошибкой компиляции.

В данный момент я могу придумать два обходных пути:

  • Использование reinterpret_cast в сочетании с адресом оператора:
    float f = 42.0f;
    ::PostWindowMessage(WM_SOME_MESSAGE, *reinterpret_cast<WPARAM*>(&f), 0);
    
  • Использованиесоюз:
    union { WPARAM wParam, float f };
    f = 42.0f;
    ::PostWindowMessage(WM_SOME_MESSAGE, wParam, 0);
    

Какие из них предпочтительнее?Есть ли другой, более изящный способ сделать это?

Ответы [ 4 ]

3 голосов
/ 23 марта 2010

Используйте reinterpret_cast< WPARAM &>(f). Это приведение не ограничено указателями, оно также работает со ссылками.

2 голосов
/ 23 марта 2010

Вы можете использовать memcpy:

#include <memory.h>
int main() {
    float f = 1.0;
    int n;
    memcpy( &n, &f, sizeof(f) );
}

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

int FloatToInt( float f ) {
    int n;
    assert( sizeof(n) == sizeof(f) );
    memcpy( &n, &f, sizeof(f) );
    return n;
}
0 голосов
/ 23 марта 2010

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

WPARAM wParam = *((UINT*)(&f));

Чтобы преобразовать его обратно, вы делаете наоборот. Выполнение приведения на уровне указателя гарантирует, что компилятор не будет пытаться выполнить «преобразование» за вашей спиной.

float f = *((float*)(&wParam))
0 голосов
/ 23 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...