cebasso
asked on
how to simplify this
Hello,
Shift: TShiftState;
TShiftState = set of (ssShift, ssAlt, ssCtrl,
ssLeft, ssRight, ssMiddle, ssDouble);
Ok, but its not compatible with others languages like C++
So i need to make it compatible in my Param, like
TMyParam = packed record
kbShift: DWORD;
end;
I'm doing in this way...
if ssShift in Shift then
kbShift := Integer(ssShift);
if ssAlt in Shift then
kbShift := kbShift or Integer(ssAlt);
if ssCtrl in Shift then
kbShift := kbShift or Integer(ssCtrl);
//for each type i need to do it, but maybe a loop can do this?
...
So i can call the reverse way like
if ssCtrl in kbShift then
...
But, i think there is a better way to do that... i tried to loop but no success
kbShift := -1;
for i := Low(TShiftState) to High(TShiftState) do
if (TShiftState(i) in Shift) then
kbShift := kbShift or TShiftState(i);
...
not work! hehe
Some idea?
Regards,
Carlos
Shift: TShiftState;
TShiftState = set of (ssShift, ssAlt, ssCtrl,
ssLeft, ssRight, ssMiddle, ssDouble);
Ok, but its not compatible with others languages like C++
So i need to make it compatible in my Param, like
TMyParam = packed record
kbShift: DWORD;
end;
I'm doing in this way...
if ssShift in Shift then
kbShift := Integer(ssShift);
if ssAlt in Shift then
kbShift := kbShift or Integer(ssAlt);
if ssCtrl in Shift then
kbShift := kbShift or Integer(ssCtrl);
//for each type i need to do it, but maybe a loop can do this?
...
So i can call the reverse way like
if ssCtrl in kbShift then
...
But, i think there is a better way to do that... i tried to loop but no success
kbShift := -1;
for i := Low(TShiftState) to High(TShiftState) do
if (TShiftState(i) in Shift) then
kbShift := kbShift or TShiftState(i);
...
not work! hehe
Some idea?
Regards,
Carlos
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
PierreC is right about the virtual key codes bitmask. For this specific topic you'd better stick to windows constants, and his way is the only way to do that correctly.
Now, you just hinted an approach that might be useful for other needs, that is : how to translate a set into a numeric value for use in other languages
Here is how to do so
the principle will work for all kind of sets, with one limitation : no more than 32 possible values for the set elements (64 when Delphi will allow for 64bits compiling).
but you'll need specific translator functions for each kind
Now, you just hinted an approach that might be useful for other needs, that is : how to translate a set into a numeric value for use in other languages
Here is how to do so
the principle will work for all kind of sets, with one limitation : no more than 32 possible values for the set elements (64 when Delphi will allow for 64bits compiling).
but you'll need specific translator functions for each kind
Type
TMyEnumType=(ev1,ev2,ev3,ev4);
TMyEnumSet=Set of TMyEnumType;
function EnumSetToNumeric(es:TMyEnumSet):Cardinal;
Var
ev:TMyEnumType;
begin
Result:=0;
for ev:=Low(TMyEnumType) to High(TMyEnumType) do
if ev in es
Then Result:=Result Or (1 SHL Integer(ev));
// The trick here is to use the binary SHIFT operator
// to translate 0=>1 , 1=>2 , 2=>4 etc...
end;
function NumericToEnumSet(Num:Cardinal):TMyEnumSet;
Var
ev:TMyEnumType;
begin
Result:=[];
for ev:=Low(TMyEnumType) to High(TMyEnumType) do
if (Num And (1 SHL Integer(ev)))>0
Then Result:=Result+[ev];
end;
// this is just to format a value in binary string representation
function IntToBin ( value: Cardinal; digits: integer ): string;
begin
result := StringOfChar ( '0', digits ) ;
while value > 0 do begin
if ( value and 1 ) = 1 then result [ digits ] := '1';
dec ( digits ) ;
value := value shr 1;
end;
end;
// Demo :
ShowMessage(
IntToBin( EnumSetToNumeric([ev2,ev4]) ,
Integer(High(TMyEnumType))+1 // calculate the maximum significant bits
)
);
Hi cebasso,
see if the following code helps you:
var
kbShift: DWORD;
ss: TShiftState;
procedure TForm1.Edit1KeyDown(Sender : TObject; var Key: Word;
Shift: TShiftState);
begin
{ Copy ShiftState Bits to kbShift }
CopyMemory(@kbShift, @Shift, SizeOf(Shift));
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
{ Copy kbShift bits to ss (TShiftState} }
CopyMemory(@ss, @kbShift, SizeOf(ss));
end;
procedure TForm1.Button2Click(Sender : TObject);
begin
{ Test against ss }
if ssCtrl in ss then
showmessage('Control');
end;
see if the following code helps you:
var
kbShift: DWORD;
ss: TShiftState;
procedure TForm1.Edit1KeyDown(Sender
Shift: TShiftState);
begin
{ Copy ShiftState Bits to kbShift }
CopyMemory(@kbShift, @Shift, SizeOf(Shift));
end;
procedure TForm1.Button1Click(Sender
begin
{ Copy kbShift bits to ss (TShiftState} }
CopyMemory(@ss, @kbShift, SizeOf(ss));
end;
procedure TForm1.Button2Click(Sender
begin
{ Test against ss }
if ssCtrl in ss then
showmessage('Control');
end;
Try this:
kbShift:=PByte(@Shift)^
Regards,
Joan-Ramon
kbShift:=PByte(@Shift)^
Regards,
Joan-Ramon
See tha link.
http://delphi.about.com/od/delphitips2007/qt/for_in_set.htm