Solved

I hate pointers

Posted on 2001-07-03
16
444 Views
Last Modified: 2010-04-04
This doesn't compile.  I hate pointers.

This code is my feeble attempt to convert C++ to Delphi.

type COPYD = ^COPYDATASTRUCT;
    COPYDATASTRUCT = record
    dwData: WORD;
    cbData: WORD;
    lpdata: PChar;
end;  

procedure TForm1.Enqueue1Click(Sender: TObject);
var mp3filename: String;
    hwndWinamp : THandle;
    cds: ^COPYD;
begin
 hwndWinamp := FindWindow('Winamp v1.x', nil);
 mp3filename := FList.FileName; // from TFileListBox
 cds.dwData := 100;  // Value of IPC_PLAYFILE
 cds.cbData := length(mp3filename) + 1;
 cds.lpData := PChar(mp3filename);
 SendMessage(hwndwinamp, WM_COPYDATA, NULL, cds);
end;


//================
Original C Code from SDK
typedef struct tagCOPYDATASTRUCT {  // cds  
    DWORD dwData;
    DWORD cbData;
    PVOID lpData;
} COPYDATASTRUCT;


//===============
WinAmp's Example

COPYDATASTRUCT cds;
cds.dwData = IPC_PLAYFILE;
cds.cbData = lstrlen(filename) + 1;
cds.lpData = (void *) filename;
SendMessage(hwnd_winamp, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);



Help me convert this to Delphi please.

           
0
Comment
Question by:d32coder
  • 3
  • 3
  • 3
  • +6
16 Comments
 
LVL 7

Expert Comment

by:Motaz
ID: 6251334
I tried this, but I get invalid variant type conversion at run-time

var mp3filename: String;
   hwndWinamp : THandle;
   cds: COPYD;
begin
  hwndWinamp := FindWindow('Winamp v1.x', nil);
  mp3filename := FList.FileName; // from TFileListBox
  New(CDS);
  cds.dwData := 100;  // Value of IPC_PLAYFILE
  cds.cbData := length(mp3filename) + 1;
  cds.lpData := PChar(mp3filename);
  SendMessage(hwndwinamp, WM_COPYDATA, WPARAM(NULL), LPARAM(cds));
end;
0
 

Expert Comment

by:alshaikh
ID: 6251419
Try this the following code, it compiles ok.



Type
  COPYDATASTRUCT = Record
    dwData : DWord ;
    cbData : DWord ;
    lpData : PChar ;
  End ;

procedure TForm2.Button1Click(Sender: TObject);
var
  mp3filename: String;
  hwndWinamp : THandle;
  cds: COPYDATASTRUCT ;
begin
 hwndWinamp := FindWindow('Winamp v1.x', nil);
 mp3filename := 'C:\test' ; // put your file name here
 cds.dwData := 100;  // Value of IPC_PLAYFILE
 cds.cbData := length(mp3filename) + 1;
 cds.lpData := PChar(mp3filename);
 SendMessage(hwndwinamp, WM_COPYDATA, NULL, LPARAM(@cds));
end;
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 6251436
// Your record is too small.

type
  PCOPYDATASTRUCT = ^COPYDATASTRUCT;
  COPYDATASTRUCT = record
    dwData: DWORD;
    cbData: DWORD;
    lpdata: Pointer;
end;  

// ok
hwndWinamp := FindWindow('Winamp v1.x', nil);
mp3filename := FList.FileName; // from TFileListBox
// ok
cds.dwData := 100;  // Value of IPC_PLAYFILE
// wrong. one extra Byte
cds.cbData := Length(mp3filename);
cds.lpData := PChar(mp3filename);
SendMessage(hwndwinamp, WM_COPYDATA,
  WPARAM(Form1.Handle), // sending window
  LPARAM(@cds));  // address of record
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 6251441
// Oops. Thats it.
cds.cbData := Strlen(PChar(mp3filename))+1;
0
 
LVL 17

Expert Comment

by:inthe
ID: 6251447
hi,
you dont need to define the COPYDATASTRUCT as its already done in windows.pas ;-)

just use
var
foo : TCOPYDATASTRUCT ;


here is example for winamp:


unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);    
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  hwnd_winamp : THANDLE;

 Const WM_WINAMP = WM_USER;
       IPC_PLAYFILE = 100; //ADD FILE TO PLAYLIST
       IPC_DELETE = 101;   //DELETE PLAYLIST
       IPC_STARTPLAY = 102; //START PLAYING

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  hwnd_winamp := FindWindow('Winamp v1.x', nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  cds: TCOPYDATASTRUCT;
  filename : string;
 begin
  cds.dwData:=IPC_PLAYFILE;
  filename:='M:\test.mp3';
  cds.lpData := Pchar(filename);
  cds.cbData := length(filename)+1;
  cds.dwData:=IPC_PLAYFILE;
  SendMessage(hwnd_winamp,WM_COPYDATA,0,Integer(@cds));
  end;

procedure TForm1.Button2Click(Sender: TObject);
begin   //play the file
  SendMessage(hwnd_winamp,WM_WINAMP,0,IPC_STARTPLAY);
end;

end.



Regards Barry
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6251450
I love pointers...   :-)

Hi d32coder,

two things:

(1) The record should be a "packed record".

(2) Your variable cds is a pointer to the COPYDATASTRUCT record. That means, there's no memory allocated for the record yet. The pointer is no record itself, it only wants to point to a record. Local variables are not initialized, they have random values, so in the line where you say "cds.dwData := 100;" in fact this means for Delphi (let's guess cds would have the random value $12345678): The COPYDATASTRUCT record which is located at memory position "$12345678" should be changed, the dwData field of this record should be set to 100. The result is that Delphi tries to write to the random address $12345678. That's quite bad, because this is a random address. The result can be that you overwrite important data, or that an access violation occurs. There are several solutions: (a) You can allocate a record with "New(cds);". In that case space for a new COPYDATASTRUCT record is allocated and cds gets set to the memory position of the newly allocated record. Now all that you do works fine. Don't forget to free the record, when you don't need it anymore (Dispose(cds)). The second solution is what "alshaikh" suggested, namely instead of typing "cds" to be a pointer, you can type it to be a record. The result is almost identical to (a), except that (b) is shorter and faster, faster because no real memory allocation is done, local record are stored on the stack, which is very fast.

BTW, TCopyDataStruct is already defined in "Windows.pas".

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6251455
Hey, Robert's and Barry's comments where not there yet, when I wrote my comment. Hi guys...   :-)
0
 
LVL 17

Expert Comment

by:inthe
ID: 6251456
here also is a unit for winamp you may find useful:
i understand this has been submitted to jedi for tidying up but im not sure if its been done yet ( robert ;-)

unit winamp;

interface
uses Windows, Messages, Dialogs, SysUtils;

type
  TWinampMessageKind = (wmkIPC, wmkCopyData, wmkCommand);

const
  WM_WINAMP_IPC = WM_USER; // used for WM_USER messages
  WM_WINAMP_COPYDATA = WM_COPYDATA; // used for WM_COPYDATA messages
  WM_WINAMP_COMMAND = WM_COMMAND; // used for WM_COMMAND messages

(** WM_WINAMP_IPC messages **)

  IPC_GETVERSION = 0;
    // int version =
SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_GETVERSION);
    //
    // Version will be 0x20yx for winamp 2.yx. versions previous to Winamp
2.0
    // typically (but not always) use 0x1zyx for 1.zx versions. Weird, I
know.


  IPC_DELETE = 101;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_DELETE);
    //
    // You can use IPC_DELETE to clear Winamp's internal playlist.

  IPC_STARTPLAY = 102;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_STARTPLAY);
    //
    // Using IPC_STARTPLAY is like hitting 'Play' in Winamp, mostly.

  IPC_ISPLAYING = 104;
    // int res = SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_ISPLAYING);
    //
    // IPC_ISPLAYING returns the status of playback.
    // If it returns 1, it is playing. if it returns 3, it is paused,
    // if it returns 0, it is not playing.

  IPC_GETOUTPUTTIME = 105;
    // int res =
SendMessage(hwnd_winamp,WM_WINAMP_IPC,mode,IPC_GETOUTPUTTIME);
    //
    // IPC_GETOUTPUTTIME returns the position in milliseconds of the
    // current song (mode = 0), or the song length, in seconds (mode = 1).
    // Returns -1 if not playing or error.

  IPC_JUMPTOTIME = 106;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,ms,IPC_JUMPTOTIME);
    //
    // IPC_JUMPTOTIME sets the position in milliseconds of the
    // current song (approximately).
    // Returns -1 if not playing, 1 on eof, or 0 if successful


  IPC_WRITEPLAYLIST = 120;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_WRITEPLAYLIST);
    //
    // IPC_WRITEPLAYLIST writes the current playlist to
<winampdir>\\Winamp.m3u,
    // and returns the current playlist position.
    // Kinda obsoleted by some of the 2.x new stuff, but still good for when
    // using a front-end (instead of a plug-in)

  IPC_SETPLAYLISTPOS = 121;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,position,IPC_SETPLAYLISTPOS)
    //
    // IPC_SETPLAYLISTPOS sets the playlsit position to 'position'.

  IPC_SETVOLUME = 122;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,volume,IPC_SETVOLUME);
    //
    // IPC_SETVOLUME sets the volume of Winamp (from 0-255).

  IPC_SETPANNING = 123;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,panning,IPC_SETPANNING);
    //
    // IPC_SETPANNING sets the panning of Winamp (from 0 (left) to 255
(right)).

  IPC_GETLISTLENGTH = 124;
    // int length =
SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_GETLISTLENGTH);
    //
    // IPC_GETLISTLENGTH returns the length of the current playlist, in
    // tracks.

  IPC_SETSKIN = 200;
    // only usable from plug-ins (not external apps)
    //
SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)"skinname",IPC_SETSKIN);
    //
    // IPC_SETSKIN sets the current skin to "skinname". Note that skinname
    // can be the name of a skin, a skin .zip file, with or without path.
    // If path isn't specified, the default search path is the winamp skins
    // directory.

  IPC_GETSKIN = 201;
    // only usable from plug-ins (not external apps)
    //
SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN);
    //
    // IPC_GETSKIN puts the directory where skin bitmaps can be found
    // into  skinname_buffer.
    // skinname_buffer must be MAX_PATH characters in length.
    // When using a .zip'd skin file, it'll return a temporary directory
    // where the ZIP was decompressed.

  IPC_EXECPLUG = 202;
    // only usable from plug-ins (not external apps)
    //
SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG);
    //
    // IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM.
    // the format of this string can be:
    // "vis_whatever.dll"
    // "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir)
    // "C:\\dir\\vis_whatever.dll,1"

  IPC_GETPLAYLISTFILE = 211;
    // only usable from plug-ins (not external apps)
    // char
*name=SendMessage(hwnd_winamp,WM_WINAMP_IPC,index,IPC_GETPLAYLISTFILE);
    //
    // IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].
    // returns a pointer to it. returns NULL on error.

  IPC_GETPLAYLISTTITLE = 212;
    // only usable from plug-ins (not external apps)
    // char
*name=SendMessage(hwnd_winamp,WM_WINAMP_IPC,index,IPC_GETPLAYLISTTITLE);
    //
    // IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index].
    // returns a pointer to it. returns NULL on error.

  IPC_GETLISTPOS = 125;
    // int pos=SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_GETLISTPOS);
    //
    // IPC_GETLISTPOS returns the playlist position. A lot like
IPC_WRITEPLAYLIST
    // only faster since it doesn't have to write out the list. Heh, silly
me.

  IPC_GETINFO = 126;
    // int inf=SendMessage(hwnd_winamp,WM_WINAMP_IPC,mode,IPC_GETINFO);
    //
    // IPC_GETINFO returns info about the current playing song. The value
    // it returns depends on the value of 'mode'.
    // Mode      Meaning
    // ------------------
    // 0         Samplerate (i.e. 44100)
    // 1         Bitrate  (i.e. 128)
    // 2         Channels (i.e. 2)

  IPC_GETEQDATA = 127;
    // int data=SendMessage(hwnd_winamp,WM_WINAMP_IPC,pos,IPC_GETEQDATA);
    //
    // IPC_GETEQDATA queries the status of the EQ.
    // The value returned depends on what 'pos' is set to:
    // Value      Meaning
    // ------------------
    // 0-9        The 10 bands of EQ data. 0-63 (+20db - -20db)
    // 10         The preamp value. 0-63 (+20db - -20db)
    // 11         Enabled. zero if disabled, nonzero if enabled.
    // 12         Autoload. zero if disabled, nonzero if enabled.

  IPC_SETEQDATA = 128;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,pos,IPC_GETEQDATA);
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,value,IPC_SETEQDATA);
    //
    // IPC_SETEQDATA sets the value of the last position retrieved
    // by IPC_GETEQDATA.
  IPC_ADDBOOKMARK = 129;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)file,IPC_ADDBOOKMARK);
    //
    // IPC_ADDBOOKMARK will add the specified file to the Winamp bookmark
list.

  IPC_RESTARTWINAMP = 135;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_RESTARTWINAMP);
    //
    // IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :)

  IPC_MBOPEN = 241;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_MBOPEN);
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)url,IPC_MBOPEN);
    //
    // IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it
will open the Minibrowser window.

  IPC_INETAVAILABLE = 242;
    // val=SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_INETAVAILABLE);
    //
    // IPC_INETAVAILABLE will return 1 if the Internet connection is
available for Winamp.

  IPC_UPDTITLE = 243;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_UPDTITLE);
    //
    // IPC_UPDTITLE will ask Winamp to update the informations about the
current title.

  IPC_CHANGECURRENTFILE = 245;
    //
SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE);
    //
    // IPC_CHANGECURRENTFILE will set the current playlist item.

  IPC_GETMBURL = 246;
    // char buffer[4096]; // Urls can be VERY long
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)buffer,IPC_GETMBURL);
    //
    // IPC_GETMBURL will retrieve the current Minibrowser URL into buffer.

  IPC_REFRESHPLCACHE = 247;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_REFRESHPLCACHE);
    //
    // IPC_REFRESHPLCACHE will flush the playlist cache buffer.

  IPC_MBBLOCK = 248;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,value,IPC_MBBLOCK);
    //
    // IPC_MBBLOCK will block the Minibrowser from updates if value is set
to 1

  IPC_MBOPENREAL = 249;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,(WPARAM)url,IPC_MBOPENREAL);
    //
    // IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works
even if
    // IPC_MBBLOCK has been set to 1

  IPC_GET_SHUFFLE = 250;
    // val=SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_GET_SHUFFLE);
    //
    // IPC_GET_SHUFFLE returns the status of the Shuffle option (1 if set)

  IPC_GET_REPEAT = 251;
    // val=SendMessage(hwnd_winamp,WM_WINAMP_IPC,0,IPC_GET_REPEAT);
    //
    // IPC_GET_REPEAT returns the status of the Repeat option (1 if set)

  IPC_SET_SHUFFLE = 252;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,value,IPC_SET_SHUFFLE);
    //
    // IPC_SET_SHUFFLE sets the status of the Shuffle option (1 to turn it
on)

  IPC_SET_REPEAT = 253;
    // SendMessage(hwnd_winamp,WM_WINAMP_IPC,value,IPC_SET_REPEAT);
    //
    // IPC_SET_REPEAT sets the status of the Repeat option (1 to turn it on)

(** WM_WINAMP_COPYDATA messages **)

  IPC_PLAYFILE = 100;
    //
WinampCopyData(hwnd_winamp,IPC_PLAYFILE,PChar('file.mp3'),Length('file.mp3')
);
    //
    // This will play the file "file.mp3".


  IPC_CHDIR = 103;
    // WinampCopyData(hwnd_winamp,IPC_CHDIR,PChar('c:\\download'),
Length('c:\\download'));
    //
    // This will make Winamp change to the directory C:\\download


(** WM_WINAMP_COMMAND messages **)

  WINAMP_OPTIONS_EQ     =          40036; // toggles the EQ window
  WINAMP_OPTIONS_PLEDIT =          40040; // toggles the playlist window
  WINAMP_VOLUMEUP       =          40058; // turns the volume up a little
  WINAMP_VOLUMEDOWN     =          40059; // turns the volume down a little
  WINAMP_FFWD5S         =          40060; // fast forwards 5 seconds
  WINAMP_REW5S          =          40061; // rewinds 5 seconds

  // the following are the five main control buttons, with optionally shift
  // or control pressed (for the exact functions of each, just try it out)
  WINAMP_BUTTON1        =          40044;
  WINAMP_BUTTON2        =          40045;
  WINAMP_BUTTON3        =          40046;
  WINAMP_BUTTON4        =          40047;
  WINAMP_BUTTON5        =          40048;
  WINAMP_BUTTON1_SHIFT  =          40144;
  WINAMP_BUTTON2_SHIFT  =          40145;
  WINAMP_BUTTON3_SHIFT  =          40146;
  WINAMP_BUTTON4_SHIFT  =          40147;
  WINAMP_BUTTON5_SHIFT  =          40148;
  WINAMP_BUTTON1_CTRL   =          40154;
  WINAMP_BUTTON2_CTRL   =          40155;
  WINAMP_BUTTON3_CTRL   =          40156;
  WINAMP_BUTTON4_CTRL   =          40157;
  WINAMP_BUTTON5_CTRL   =          40158;

  WINAMP_FILE_PLAY      =          40029; // pops up the load file(s) box
  WINAMP_OPTIONS_PREFS  =          40012; // pops up the preferences
  WINAMP_OPTIONS_AOT    =          40019; // toggles always on top
  WINAMP_HELP_ABOUT     =          40041; // pops up the about box :)


function GetWinampWindow: HWND;

function WinampMessage(WinampWindow: HWND; Kind: TWinampMessageKind; Msg:
DWORD; Data: Variant): LRESULT;

implementation

function GetWinampWindow: HWND;
begin
  // always uses 'Winamp v1.x' for compatibility between versions
  Result := FindWindow('Winamp v1.x', nil);
end;

function WinampMessage(WinampWindow: HWND; Kind: TWinampMessageKind; Msg:
DWORD; Data: Variant): LRESULT;

    function WinampIPC(Param: WPARAM): LRESULT;
    begin
      Result := SendMessage(WinampWindow, WM_WINAMP_IPC, Param, Msg);
    end;

    function WinampCopyData(s: string): LRESULT;
    var cds: TCopyDataStruct;
    begin
      cds.dwData := Msg;
      cds.lpData := PChar(s);
      cds.cbData := Length(s);
      Result := SendMessage(WinampWindow, WM_WINAMP_COPYDATA, 0,
LPARAM(@cds));
    end;

    function WinampCommand: LRESULT;
    begin
      Result := SendMessage(WinampWindow, WM_WINAMP_COMMAND, Msg, 0);
    end;

begin
  Result := 0;
  case Kind of
    wmkIPC:
      Result := WinampIPC(Data);
    wmkCopyData:
      Result := WinampCopyData(VarToStr(Data));
    wmkCommand:
      Result := WinampCommand;
  end;
end;

end.

0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 17

Expert Comment

by:inthe
ID: 6251459
hello mate,
your pointer love is sadistic madshi ;-)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6251463
:-)   I would stop programming at once if I would have to work with VB, no true pointer support there...   (-:
0
 
LVL 11

Accepted Solution

by:
robert_marquardt earned 200 total points
ID: 6251530
Lets try to make a working version.
type
  PCOPYDATASTRUCT = ^COPYDATASTRUCT;
  COPYDATASTRUCT = record
    dwData: DWORD;
    cbData: DWORD;
    lpdata: Pointer;
  end;  

procedure TForm1.Enqueue1Click(Sender: TObject);
var
  mp3filename: string;
  hwndWinamp : HWND;
  cds: COPYDATASTRUCT;
begin
  hwndWinamp := FindWindow('Winamp v1.x', nil);
  mp3filename := FList.FileName; // from TFileListBox
  cds.dwData := 100;  // Value of IPC_PLAYFILE
  cds.cbData := StrLen(PChar(mp3filename)) + 1;
  cds.lpData := PChar(mp3filename);
  SendMessage(hwndWinamp, WM_COPYDATA,
    WPARAM(Form1.Handle), LPARAM(@cds));
end;
0
 
LVL 7

Expert Comment

by:Motaz
ID: 6251961
Hey d32coder,
I forget to tell you some thing, as Madshi said, "I LOVE POINTERS" very much.:)

Motaz
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6252116
There's no point in programming without pointers... :-))
0
 
LVL 5

Expert Comment

by:scrapdog
ID: 6252202
The name of the sports teams at my university was the "Pointers".

IMHO

In C and vanilla Pascal, pointers are straightforward and unambiguous, and can be used without much thought.  Maybe I'm a bit naive, but in Delphi/Object Pascal, I do find pointers to be somewhat confusing sometimes.  It seems that there is a lot of magical implicit things going on with them that are not present in C or Pascal.  Sometimes, where you would instinctively dereference a pointer, it turns out that Delphi already did it for you.

I have suffered many headaches working with PChar and its ilk.  Maybe I should post some more questions here. =)

This is not to say that Delphi doesn't rule.


Madshi, I too share your undying love for VB. =)
0
 

Author Comment

by:d32coder
ID: 6252578
Wow, wonderful responses!

Madshi, Your decription of pointers is the best I've seen yet.  Thank you.

Tough decision on giving the points, everyone is very helpful.

I'll give the points to Robert.  His sample specifically addressed my procedure and worked beautifully.

Regards,
Don

PS I deleted the typedef, didn't know it was already in Windows.pas.



0
 
LVL 4

Expert Comment

by:Neutron
ID: 6252595
"Oh, those glorious pointers,
 That grow in a list or a tree,
 What usefull thing a programmer,
 Could do without thee"
           William Shakespointer ;o)

What about Java references (no real pointer support)?
Does that put Java in the same basket with VB?

Greetings,
    Ntr:)
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now