Just checked more natural way of handling enums with explicit values (still based on ghost properties):
[pascal]unit Unit1_test;

interface

uses
Classes, Controls, StdCtrls, DesignEditors, DesignIntf;

type
TEnum1 = (xxx, yyy, zzz, rrr=5);

TTestComponent = class(TButton)
private
FEnumProp: TEnum1;
procedure SetEnumProp(const Value: TEnum1);
function GetGhost: Cardinal;
procedure SetGhost(const Value: Cardinal);
/////
property aaa_EnumProp: TEnum1 read FEnumProp write SetEnumProp;
published
property aaa_Ghost: Cardinal read GetGhost write SetGhost;
end;

TTestProperty = class(TEnumProperty)
public
function GetAttributes: TPropertyAttributes; override;
function GetValue: string; override;
procedure GetValues(Proc: TGetStrProc); override;
procedure SetValue(const Value: string); override;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterPropertyEditor(TypeInfo(Cardinal), TTestComponent, 'aaa_Ghost', TTestProperty);
RegisterComponents('Visual', [TTestComponent]);
end;


function TTestComponent.GetGhost: Cardinal;
begin
Result:= Cardinal(FEnumProp);
end;

procedure TTestComponent.SetGhost(const Value: Cardinal);
begin
FEnumProp:= TEnum1(value);
end;

procedure TTestComponent.SetEnumProp(const Value: TEnum1);
begin
FEnumProp := Value;
end;

{ TTestProperty }

function TTestProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paMultiSelect, paValueList, paRevertable];
end;

function TTestProperty.GetValue: string;
begin
case GetOrdValue of
0: Result := 'Value1';
1: Result := 'Value2';
2: Result := 'Value3';
end;
end;

procedure TTestProperty.GetValues(Proc: TGetStrProc);
begin
Proc('Value1');
Proc('Value2');
Proc('Value3');
end;

procedure TTestProperty.SetValue(const Value: string);
begin
if Length(Value) < 6 then SetOrdValue(0)
else
case Value[6] of
'1': SetOrdValue(0);
'2': SetOrdValue(1);
'3': SetOrdValue(2);
end;
end;

end.[/pascal]

[Edit by BlueCat - Please use the new [ pascal ] tags instead of [ code ], thankyou ]