0

I'm confused. The LVITEM structure states:

state

Type: UINT

Indicates the item's state, state image, and overlay image. The stateMask member indicates the valid bits of this member.

Bits 0 through 7 of this member contain the item state flags. This can be one or more of the item state values.

So my question is, what are bits 0 through 7 for? They appear not to indicate what is used by the other bits, otherwise the stateMask wouldn't be needed.

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • @KenWhite, Yes, I read that. You state _`state` is used to set multiple values at once._, but that is what `stateMask` is already doing, as stated by your quote of the documentation. – Adrian Feb 12 '18 at 21:14
  • 1
    *Bits 0 through 7 of this member contain the [item state](https://msdn.microsoft.com/en-us/library/windows/desktop/bb774733) flags. This can be one or more of the item state values.* – RbMm Feb 12 '18 at 21:15
  • @RbMm, yes, I read that. So, what is the expected response when setting `state` bits 0-7 to `LVIS_OVERLAYMASK` or `LVIS_STATEIMAGEMASK`? Garbage? – Adrian Feb 12 '18 at 21:19
  • @Adrian, take a look at LVIS_OVERLAYMASK/LVIS_STATEIMAGEMASK values, it's 0x0f00/0xf000. Obviously you can't set first byte to this value. stateMask and state use the same LVIS_* flags. – bunglehead Feb 14 '18 at 05:55

2 Answers2

0

MSDN tells you exactly what the bits in state are:

Bits 0 through 7 of this member contain the item state flags. This can be one or more of the item state values.

Bits 8 through 11 of this member specify the one-based overlay image index. ... To isolate these bits, use the LVIS_OVERLAYMASK mask.

Bits 12 through 15 of this member specify the state image index. To isolate these bits, use the LVIS_STATEIMAGEMASK mask.

It does not make sense to set the bottom bits to LVIS_*MASK, only the other LVIS_* states. stateMask specifies which bits in state are required/valid when you query or set the state.

The bit layout of state and stateMask is the same and if someone hands you a LVITEM you would calculate the valid bits as valid = lvi.state & lvi.stateMask. If the state bits you care about are not set in stateMask you would have to query the listview for those bits.

In the source code for the listview the query code might look something like this:

void ListView::GetItemState(LVITEM&lvi, int idx)
{
  lvi.state = 0;
  if ((lvi.stateMask & LVIS_CUT) && isItemInCutState(idx, lvi)) lvi.state |= LVIS_CUT;
  if ((lvi.stateMask & LVIS_...) && ...
}
Community
  • 1
  • 1
Anders
  • 97,548
  • 12
  • 110
  • 164
  • So, the bits in `state` should only accept values that don't match `LVIS_*MASK`, and the `stateMask` will indicate what bits will be updated in `state`? You state that *"If the bits you care about are not set in stateMask you would have to query the listview for those bits.*" What other way would I query the listview for those bits? Or would I use the same call with different `stateMask`? – Adrian Feb 12 '18 at 21:41
  • The bits you want to query must be set in stateMask. `lvi.stateMask = LVIS_CUT; ListView_...(); isCut = lvi.state & LVIS_CUT;` – Anders Feb 12 '18 at 22:23
0

There are two bits of information you want to communicate: The final value of each flag, and the set of flags you want to adjust. Those are represented by the state and stateMask members, respectively.

The operation performed is:

auto flags = prev_flags & ~( state | stateMask ); // reset flags
     flags = flags      |  ( state & stateMask ); // set flags

An example: Assuming prev_flags is 101 and you wish to reset flag 0, set flag 1, and keep flag 2 unchanged, you'd pass 010 as the state and 011 as the stateMask. Note, that the stateMask denotes 0 for flag 2, to retain its current value.

state & stateMask evaluates to 010.

~( state | stateMask ) evaluates to 101.

flags = prev_flags & ~( state & stateMask ) evaluates to 101 &= 100, i.e. 100

flags | ( state & stateMask ) evaluates to 100 | 010, i.e. 110.

IInspectable
  • 46,945
  • 8
  • 85
  • 181