Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi SETs unterschiedlicher Grösse kombinieren (https://www.delphipraxis.net/153720-sets-unterschiedlicher-groesse-kombinieren.html)

ralfiii 13. Aug 2010 15:04

Delphi-Version: 2010

SETs unterschiedlicher Grösse kombinieren
 
Ich hab ein Problem eine Komponente so hinzubasteln, dass sie unter D2007 und D2010 funktioniert.

In Delphi2007 lief folgender Code problemlos:
Delphi-Quellcode:
type TSx_ShiftKeys=set of (skShift, skAlt, skCtrl); // subset of TShiftState
procedure SetZoomShift(const V:TSx_ShiftKeys);
var fZoomShift: TShiftState;
begin
     fZoomShift:=[ssLeft]+TShiftState(V);
     ...
In Delphi2010 funktioniert's nicht mehr, da TShiftState ein paar Zustände dazugekriegt hat und jetzt 2 Byte gross ist.

Wie könnt ich das vernünftig lösen?
Das Set brauch ich wieder, damit die Komponente im Design-mode vernünftig konfigurierbar ist.

So eine Lösung
Delphi-Quellcode:
     fZoomShift:=[ssLeft];
     w:=word(fZoomShift) or byte(v);
     fZoomShift:=TShiftState(w);
kommt mir völlig behindert vor - und ich müsst erst wieder ein define + Alternativcode herumwickeln damit alles auch unter D2007 läuft.

Danke!
Ralf

uligerhardt 13. Aug 2010 15:54

AW: SETs unterschiedlicher Grösse kombinieren
 
Ich würde es wie folgt machen:
Delphi-Quellcode:
type
  TSx_ShiftKey = (skShift, skAlt, skCtrl);
  TSx_ShiftKeys = set of TSx_ShiftKey;

function Sx_ShiftKeysToShiftState(const V: TSx_ShiftKeys): TShiftState;
var
  sk: TSx_ShiftKey;
begin
  Result := [];
  for sk in V do
  begin
    case sk of
      skShift:
        Include(Result, ssShift);
      skAlt:
        Include(Result, ssAlt);
      skCtrl:
        Include(Result, ssCtrl);
    end;
  end;
end;

procedure SetZoomShift(const V: TSx_ShiftKeys);
var
  fZoomShift: TShiftState;
begin
  fZoomShift := Sx_ShiftKeysToShiftState(V);
  Include(fZoomShift, ssLeft);
end;
Noch schöner wäre statt des
Delphi-Quellcode:
case
ein konstantes Zuordnungsarray, aber da die VCL-Schreiberlinge ungeschickterweise den Elementtyp von TShiftState (wie du den von TSx_ShiftKeys :P) namenlos gelassen haben, geht das nicht (zumindest ohne Casterei).

Hawkeye219 13. Aug 2010 19:02

AW: SETs unterschiedlicher Grösse kombinieren
 
Hallo,
Zitat:

Zitat von uligerhardt (Beitrag 1041971)
Noch schöner wäre statt des
Delphi-Quellcode:
case
ein konstantes Zuordnungsarray, aber da die VCL-Schreiberlinge ungeschickterweise den Elementtyp von TShiftState (wie du den von TSx_ShiftKeys :P) namenlos gelassen haben, geht das nicht (zumindest ohne Casterei).

Na, dann geben wir dem Wunschkind doch einen Namen:
Delphi-Quellcode:
type
  TSx_ShiftKey = (skShift, skAlt, skCtrl);
  TSx_ShiftKeys = set of TSx_ShiftKey;

  TSomeShiftKey = ssShift..ssCtrl;
  TSomeShiftKeys = set of TSomeShiftKey;

function Sx_ShiftKeysToShiftState (const V: TSx_ShiftKeys): TShiftState;
const
  Map: array [TSx_ShiftKey] of TSomeShiftKey = (ssShift, ssAlt, ssCtrl);
var
  sk: TSx_ShiftKey;
begin
  Result := [];
  for sk in V do
    Include (Result, Map[sk]);
end;

procedure SetZoomShift(const V: TSx_ShiftKeys);
var
  fZoomShift: TShiftState;
begin
  fZoomShift := Sx_ShiftKeysToShiftState(V);
  Include(fZoomShift, ssLeft);
end;
Wenn du TSomeShiftKeys schon bei der Definition der Eigenschaft verwendest anstatt neue Bezeichner für die Werte des (eingeschränkten) Aufzählungstypen einzuführen, könnte die Routine SetZoomShift so aussehen:
Delphi-Quellcode:
procedure SetZoomShift (const V: TSomeShiftKeys);
var
  fZoomShift: TShiftState;
begin
  fZoomShift := V + [ssLeft];
end;
Gruß Hawkeye

uligerhardt 13. Aug 2010 19:19

AW: SETs unterschiedlicher Grösse kombinieren
 
Zitat:

Zitat von Hawkeye219 (Beitrag 1042029)
Na, dann geben wir dem Wunschkind doch einen Namen:
Delphi-Quellcode:
  TSomeShiftKey = ssShift..ssCtrl;
  TSomeShiftKeys = set of TSomeShiftKey;

Gute Idee.:thumb:

Zitat:

Zitat von Hawkeye219 (Beitrag 1042029)
Delphi-Quellcode:
procedure SetZoomShift (const V: TSomeShiftKeys);
var
  fZoomShift: TShiftState;
begin
  fZoomShift := V + [ssLeft];
end;

Noch bessere Idee.:mrgreen:

himitsu 13. Aug 2010 19:28

AW: SETs unterschiedlicher Grösse kombinieren
 
Wie wäre es damit?
Delphi-Quellcode:
type
  TZoomShiftKeys = type TShiftState;
Und dann eventuell noch sowas.
Delphi-Quellcode:
const
  AllowedZoomKeys = [ssShift..ssCtrl];

ralfiii 16. Aug 2010 08:41

AW: SETs unterschiedlicher Grösse kombinieren
 
Zitat:

Zitat von Hawkeye219 (Beitrag 1042029)
Na, dann geben wir dem Wunschkind doch einen Namen:
<Snip>

Super! Sieht gut aus, danke!!!

Zitat:

Wenn du TSomeShiftKeys schon bei der Definition der Eigenschaft verwendest anstatt neue Bezeichner für die Werte des (eingeschränkten) Aufzählungstypen einzuführen, könnte die Routine SetZoomShift so aussehen:<Snip>
Dafür ist's leider zu spät, dann müsst ich alle dfm's neu reinladen und die Werte neu setzen.


Eine fragwürdige Alternative hab ich am WE noch gebastelt:

Delphi-Quellcode:
{$IF Compilerversion<=18.5}  // Bei D2007 hat's noch funktioniert
type TSx_ShiftKeys=set of (skShift, skAlt, skCtrl);
{$ELSE}
type TSx_ShiftKeys=set of (skShift, skAlt, skCtrl,
                           _sk_IgnoreMe = (sizeof(TShiftState)*8)-1 ); // to make set same size as TShiftKey
{$IFEND}

ralfiii 4. Okt 2010 11:04

AW: SETs unterschiedlicher Grösse kombinieren
 
Zitat:

Zitat von ralfiii (Beitrag 1042465)
Eine fragwürdige Alternative hab ich am WE noch gebastelt:

Die fragwürdige Alternative bringt unter Delphi2010 den Objektinspektor zum Crashen, ich hab also Hawkeyes 2ten Vorschlag umgesetzt - die dfm's mit Search&replace auszubessern war doch sinnvoller...


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz