nic@aub.dk wrote:
> It is actually done in a very strange way. The constants are half
> bitwise as DT_TOP and DT_LEFT are defined as zero.
>
> A much smarter way of doing this would had been to define DT_LEFT as 1,
> DT_LEFT as 2 and DT_CENTER as 3, using two bits for the vertical
> alignment - then having DT_TOP as 4, DT_BOTTOM as 8 and DT_VCENTER as
> 12.
This certainly was the initial intent of the C bitfields:
struct flags { unsigned prop1:1, prop2:2, prop3:1 ... };
where the ":n" indicates the number of bits for every field.
Unfortunately all the values then are untyped ordinals, so that it is
possible to assign an value, or even a named constant, to any bitfield
(no type-safety!).
That's why named bitmasks became popular, where only the definitions are
critical (overlapping...), but not (so much) their use.
> Doing this, you are still able to use DT_LEFT or DT_VCENTER, but unable
> to use DT_LEFT or DT_RIGHT (in fact this would return in DT_CENTER).
Right, we still have the problem, that not all values have a predefined
meaning, and that ORing values can result in a different meaning.
In Pascal/Delphi it had been no problem to declare:
type
T1 = (DT_LEFT, DT_RIGHT, DT_CENTER);
...
flags = packed record prop1:T1; prop2:T2... end;
when the compiler would pack the (enumerated) types into as few bits as
required. Unfortunately such dense packing would required very strict
conventions, so that every compiler only could produce the same
inambiguous encoding. And such strict rules are inacceptable to C
coders, so... ;-]
As the last "innovation", newer Windows APIs use structs with individual
fields (of byte size or even more), instead of the old compact bitwise
representation. Unfortunately still without appropriate enum types :-(
DoDi