Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Type conversion to DWord(s) 2

Status
Not open for further replies.

djjd47130

Programmer
Nov 1, 2010
480
US
Some API functions which I'm calling require some DWORD parameters. Some of those parameters allow multiple values, such as...

Code:
CONST_ONE or CONST_TWO or CONST_THREE

I'm trying to wrap this into a component with some properties, such as...

Code:
type
  TCon = (cOne, cTwo, cThree);
  TCons = set of TCon;
  ...
procedure DoSomething;
var
  C: TCons;
begin
  ...
  C:= [cOne, cThree];
  ...
end;

and somehow, that needs to be converted to...

Code:
CONST_ONE or CONST_THREE

Any ideas?


JD Solutions
 
Don't see what's the point here.
constants are there for a reason, no need to add some sets into the mix.

what you can do (although pointless):

Code:
const
 CONST_ONE = 1;
 CONST_TWO = 2;
 CONST_THREE = 4;
 CONST_ONE_OR_THREE = CONST_ONE or CONST_THREE

meh, don't do it

/Daddy


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Agreed. Constants should be self documenting, whereas your approach will likely obfuscate the code.
 
Yes you're making it more complicated than it needs to be. You'd have to have code to explicitly make the conversion (eg a long string of if statements) if you were to proceed with this.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
You're missing the whole point. I'm building a Component. The properties of this component will show in the Object Inspector. Such a property is like the Font Style, or the Anchors of a control. This is the same thing, it will be an expanding property with a number of true/false values. I can't do that with constants, only with Sets.

JD Solutions
 
I'll be a little more specific with what I'm doing...

This component I'm building will be listing various resources/devices (otherwise computers) on the network. There are two API functions for this:

Code:
{$EXTERNALSYM WNetOpenEnum}
function WNetOpenEnum(dwScope, dwType, dwUsage: DWORD;
  lpNetResource: PNetResource; var lphEnum: THandle): DWORD; stdcall;

{$EXTERNALSYM WNetEnumResource}
function WNetEnumResource(hEnum: THandle; var lpcCount: DWORD;
  lpBuffer: Pointer; var lpBufferSize: DWORD): DWORD; stdcall;

for example, WNetOpenEnum can have multiple values for dwType and dwUsage.

I already made functions which convert this, but I can't avoid having one *false* value in the set of DWord's...

Code:
function NetResourceTypesToDWord(Types: TNetResourceTypes): DWORD;
begin
  if nrAny in Types then
    Result:= Result or RESOURCETYPE_ANY;
  if nrDisk in Types then
    Result:= Result or RESOURCETYPE_DISK;
  if nrPrint in Types then
    Result:= Result or RESOURCETYPE_PRINT;
  if nrReserved in Types then
    Result:= Result or RESOURCETYPE_RESERVED;
end;

function NetUsagesToDWord(Usages: TNetUsages): DWORD;
begin
  if ruConnectable in Usages then
    Result:= Result or RESOURCEUSAGE_CONNECTABLE;
  if ruContainer in Usages then
    Result:= Result or RESOURCEUSAGE_CONTAINER;
  if ruNoLocalDevice in Usages then
    Result:= Result or RESOURCEUSAGE_NOLOCALDEVICE;
  if ruSibling in Usages then
    Result:= Result or RESOURCEUSAGE_SIBLING;
  if ruAttached in Usages then
    Result:= Result or RESOURCEUSAGE_ATTACHED;
  if ruAll in Usages then
    Result:= Result or RESOURCEUSAGE_ALL;
  if ruReserved in Usages then
    Result:= Result or RESOURCEUSAGE_RESERVED;
end;

function NetDisplayTypesToDWord(Types: TNetDisplayTypes): DWORD;   
begin
  if ndGeneric in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_GENERIC;
  if ndDomain in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_DOMAIN;
  if ndServer in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_SERVER;
  if ndShare in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_SHARE;
  if ndFile in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_FILE;
  if ndGroup in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_GROUP;
  if ndNetwork in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_NETWORK;
  if ndRoot in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_ROOT;
  if ndShareAdmin in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_SHAREADMIN;
  if ndDirectory in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_DIRECTORY;
  if ndTree in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_TREE;
  if ndNDSContainer in Types then
    Result:= Result or RESOURCEDISPLAYTYPE_NDSCONTAINER;
end;

Like I mentioned, these are properties of this component...

TNetList_Properties.png





JD Solutions
 
ok, Now I understand, thanks.

normally you could get away with:

Code:
 MyDword := LongWord(MySet);

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks whosrdaddy, I'll give that a check. Otherwise, I think I could initialize the result to -1, then check if the result is -1 then directly assign the result to the constant, or if the result is not -1, then add it with 'or'. But, that would make the code 5 times as big as it already is...

Code:
function NetResourceTypesToDWord(Types: TNetResourceTypes): DWORD;
begin
  Result:= DWord(-1);
  if nrAny in Types then begin
    if Result = -1 then
      Result:= RESOURCETYPE_ANY
    else
      Result:= Result or RESOURCETYPE_ANY;
  end;
  if nrDisk in Types then begin
    if Result = -1 then
      Result:= RESOURCETYPE_DISK
    else
      Result:= Result or RESOURCETYPE_DISK;
  end;
end;

Haven't given it a try yet, but it should work. I just hate to put so much code for such a simple task. I hope I can figure out whosrdaddy's suggestion with...

Code:
MyDword := LongWord(MySet);


JD Solutions
 
Result := Longword(Types); ???

no need to write a function for that...

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
But how does it know that nrReserved represents the constant RESOURCETYPE_RESERVED?

This is how I have it defined:
Code:
type
  TNetResourceType = (nrAny, nrDisk, nrPrint, nrReserved);
  TNetResourceTypes = set of TNetResourceType;

And in the Windows unit (at least for Delphi 7) on line #27,478 the constant RESOURCETYPE_RESERVED is declared.

JD Solutions
 
you must build the set the way the constants are defined.

a set uses a 16 bytes, so it can represent 256 bits.

using your example:

Code:
 look in the windows.pas file and search for the constants:

  RESOURCETYPE_ANY = 0;
  RESOURCETYPE_DISK = 1;
  RESOURCETYPE_PRINT = 2;
  RESOURCETYPE_RESERVED = 8;

as you can see these values represent bits
RESOURCETYPE_DISK = bit 0 (2^0)
RESOURCETYPE_PRINT = bit 1 (2^1)
RESOURCETYPE_RESERVED = bit 3 (2^3)

bit 2 is not documented by the API (for some reason)

 
how to implement:
TNetResourceType = (nrDisk, nrPrint, nrReserved=3);
// or (nrDisk, nrPrint, nrDummy1, nrReserved) for delphi versions lower dan 6

nrAny represents 0 so don't need it

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TypInfo;

type
  TNetResourceType = (nrDisk, nrPrint, nrReserved=3);
  TNetResourceTypes = set of TNetResourceType;
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function Set2DWord(AType: PTypeInfo; const ASet): DWord;
begin
 Result := 0;
 case GetTypeData(AType)^.OrdType of
  otSByte, otUByte: Result := Byte(ASet);
  otSWord, otUWord: Result := Word(ASet);
  otSLong, otULong: Result := DWord(ASet);
 end;
end;


procedure TForm1.Button1Click(Sender: TObject);

var MySet : TNetResourceTypes;
begin
 MySet := [nrDisk, nrPrint, nrReserved];
 ShowMessage(InttoStr(Set2DWord(TypeInfo(TNetResourceTypes), MySet)));
end;

end.

play with the code and see if it makes sense to you...

/Daddy


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
adding that nrReserved=3 made me understand better. However, then I saw that function you made Set2DWord and got even more confused, especially with the pointer reference. I will play around with it and hopefully will make it work, thanks.

JD Solutions
 
Bad news, that idea of assigning the values in the declaration won't work. Delphi won't allow using such types as published properties of a component.

I know ActiveX stuff has some way of converting constants to publishable properties. I'll probably wind up investigating that, because when I convert a component to an ActiveX component, it somehow converts those types of properties to something similar.

JD Solutions
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top