Разбиение переменной LPARAM и просмотр групп битов - PullRequest
0 голосов
/ 05 августа 2011

Я знаю, что переменная LPARAM имеет определенные биты (внутри нее), которые идентифицируют информацию, такую ​​как длинные нажатия клавиш и т. Д., Когда я получаю событие WM_KEYDOWN.

Поэтому я пытаюсь разбить LPARAMпеременная и просмотр групп отдельных значений битов и групп битов и этого значения (например, для просмотра 16-го и 24-го битов и значения из этого).

Моя проблема: Iне знаете, как посмотреть отдельные биты и группы битов?Как мне разбить переменную LPARAM и посмотреть на значения битов (распечатывая их в двоичном, шестнадцатеричном и десятичном виде). ​​

Пока что у меня есть это, но работа на уровне битов меня очень смущает, так что яне уверен, действительно ли я смотрю на 24-е, 25-е и 16-е битовые значения в десятичном формате и т. д.

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch(msg)
    {
        case WM_KEYDOWN:
        {
            // I know that a LPARAM variable is a 32 bit(or is it byte?) long variable. How would I look at the
            // 16th bit value? How would I look that the value from the 16th to the 24th bit?
            printf("A: %d, %d, %d\n", lParam >> 24, lParam >> 25, lParam >> 16 );
        }
        break;

Ответы [ 4 ]

3 голосов
/ 06 августа 2011

A намного Более простой способ - объявить собственную структуру.

// information about key
union KeyInfo
{
  // LPARAM
  LPARAM lParam;

  // bit-field
  struct Bits {
    WORD nRepeatCount: 16;
    BYTE nScanCode : 8;
    BYTE nExtended : 1;
    BYTE nReserved : 4;
    BYTE nContext : 1;
    BYTE nPrevious : 1;
    BYTE nTransition : 1;
  };
};

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

РЕДАКТИРОВАТЬ: См. эту ссылку , которая в основном показывает, как сделать то, что я только что сделал.

3 голосов
/ 05 августа 2011

Как правило, вы используете побитовое И для проверки, установлен ли определенный бит:

unsigned int flags;  // some flags

if (flags & 0x01) { } // bit 0 is set
if (flags & 0x02) { } // bit 1 is set
if (flags & 0x04) { } // bit 2 is set
...
if (flags & (1U << n)) { } // bit n is set

Однако не полагайтесь на физические битовые значения.Вместо этого API определяет USEFUL_CONSTANTS, которые описывают значение флагов:

LPARAM flags = ApiFunction();
if (flags & USEFUL_CONSTANT) { } // check if the flag is set

Проверьте документацию API соответствующего сообщения, чтобы узнать, какие значения определены.

Обновление: Я вижу, что в вашем случае вы, возможно, захотите значения , а не просто флаги.Таким образом, чтобы получить значение младших 16 битов, вам нужно просто поразрядно-И значение с соответствующей битовой маской: unsigned int repeat_count = flags & 0xFFFF; Обратите внимание, что 0xFFFF - 1111111111111111 в двоичном формате.

2 голосов
/ 05 августа 2011

LPARAM может содержать значение указателя, это важно для 64-битной совместимости.

Для проверки n-го бита (0 является наименее значимым):

if (lParam & (1 << n)) { /*bit set*/ } else { /* bit not set*/ }

Чтобы извлечь его как 0 или 1:

(lParam >> n) & 1

Чтобы извлечь бит X из позиции Y:

(lParam >> Y) & ((1<<X)-1)

Это работает, сначала смещая байты вниз к наименее значимым местам и создавая маску шириной X бит для их маскировки.

1 голос
/ 05 августа 2011

Самое практичное здесь - использовать Google.Например, если вы Google, "case WM_KEYDOWN" вы найдете пример кода, который показывает, как проверить различные значения, встроенные в LPARAM и WPARAM.Поскольку каждое сообщение имеет свою собственную обработку WPARAM и LPARAM, обычно проще всего посмотреть, как это делают другие люди, и скопировать.MSDN также имеет примеры.Манипулирование набором битов - это целый набор арифметики, поэтому нецелесообразно все это здесь объяснять.

...