[comp.windows.ms.programmer] Problem with the WSPrintF function

<F0O@psuvm.psu.edu> (06/05/91)

Hi netters!

   I'm new to Windows programming and I was trying to modify the
STEP3.PAS example program that comes with TPW.  I was changing the
WMLButtonDown method.  The original routine looks like this:

Procedure TMyWindow.WMLButtonDown(Var Msg:TMessage);
VAR
  DC: HDC;
  S: array[0..9] of char;
BEGIN
  WVSPrintF(S, '(%d,%d)', Msg.LParam);
  DC := GetDC(HWindow);
  TextOut(DC, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
  ReleaseDC(HWindow, DC);
END;

   This of course works fine, but I modified the code in the following
way so I could print some text instead of a number:

Procedure TMyWindow.WMLButtonDown(Var TextString: PChar);
VAR
  DC: HDC;
  S: PChar;
BEGIN
  WVSPrintF(S, '%s', TextString);
  DC := GetDC(HWindow);
  TextOut(DC, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
  ReleaseDC(HWindow, DC);
END;

   When Windows hits the WVSPrintF statement, I get a UAE.  By running
in the debugger, the UAE is reported as exception code 13, a memory
addressing error.
   The problem must be that I'm not using PChar correctly, although
the on-line help states all parameters of WVSPrintF are of type PChar
and the manual shows examples of where you can put a text string into
a variable of type PChar.
   If someone can tell me what I'm doing wrong, I'd greatly appreciate
it!

                                                      [Tim]

dsampson@x102a.harris-atd.com (sampson david 58163) (06/06/91)

In article <91156.084930F0O@psuvm.psu.edu> F0O@psuvm.psu.edu writes:

      I'm new to Windows programming and I was trying to modify the
   STEP3.PAS example program that comes with TPW.  I was changing the
   WMLButtonDown method.  The original routine looks like this:

   Procedure TMyWindow.WMLButtonDown(Var Msg:TMessage);
   VAR
     DC: HDC;
     S: array[0..9] of char;
   BEGIN
     WVSPrintF(S, '(%d,%d)', Msg.LParam);
     DC := GetDC(HWindow);
     TextOut(DC, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
     ReleaseDC(HWindow, DC);
   END;

      This of course works fine, but I modified the code in the following
   way so I could print some text instead of a number:

   Procedure TMyWindow.WMLButtonDown(Var TextString: PChar);
   VAR
     DC: HDC;
     S: PChar;
   BEGIN
     WVSPrintF(S, '%s', TextString);
     DC := GetDC(HWindow);
     TextOut(DC, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
     ReleaseDC(HWindow, DC);
   END;

      When Windows hits the WVSPrintF statement, I get a UAE.  By running
   in the debugger, the UAE is reported as exception code 13, a memory
   addressing error.


Hey -- I'll bet it crashes real good.  The problem is with your
variable S.  Notice in the Borland example they've declared it as an
array of characters.  You declared it as a pointer to a character.
The difference between these two declarations is that in Borland's the
ARRAY statement also ALLOCATES the space that will hold the string.

All you have done is declared a pointer.  You haven't allocated any
space to actually hold the string contents.

Look at it this way. If you declare a pointer to char, the compiler
allocates enough space to just hold the address that the pointer
points to (i.e. where the string is located).  If you were to add a
line just after that declaring an integer X, then the compiler will
(more than likely) take the very next 2 bytes to use for the integer
X.  If you thought that the string started in the byte after your
pointer, you're wrong.

What you need to do is ALLOCATE the storage space for the string.  You
can do this with the NEW operator in TP. 

S := New (Char ....      I forget the exact syntax..... you have to
                         tell it how many bytes to allocate 

This statement (in proper form) will allocated the space for the
string contents, return the starting address of that space, and
assign it to your variable S.

David

--

                                          A new world record
                                          in the javalin throw
                                                
    /                                          /
   /                                          I
-------------------------------------------------


David Sampson                                         Harris Corporation
dsampson@x102a.ess.harris.com                   Gov't Aerospace Systems Divison
uunet!x102a!dsampson                                  Melbourne, Florida

-------------------------------------------------------------------------------

press@venice.SEDD.TRW.COM (Barry Press) (06/06/91)

In article <DSAMPSON.91Jun5152408@x102a.harris-atd.com> dsampson@x102a.harris-atd.com (sampson david 58163) writes:
>In article <91156.084930F0O@psuvm.psu.edu> F0O@psuvm.psu.edu writes:
>      This of course works fine, but I modified the code in the following
>   way so I could print some text instead of a number:
>
>     WVSPrintF(S, '%s', TextString);

Although I can't speak from detailed TPW experience, I can tell you that what
you did would likely fail in C because wsprintf and wvsprintf require
pointers to strings to be cast to FAR pointers.  Passing in a near pointer
(which the compiler can't check due to the variable number of args)
is a sure-fire UAE.

-- 
Barry Press                                 Internet: press@venice.sedd.trw.com

bobsc@microsoft.UUCP (Bob SCHMIDT) (06/07/91)

In article <91156.084930F0O@psuvm.psu.edu> F0O@psuvm.psu.edu writes:

    [editted for brevity]

%% Procedure TMyWindow.WMLButtonDown(Var TextString: PChar);
%% VAR
%%   S: PChar;
%% BEGIN
%%   WVSPrintF(S, '%s', TextString);
%% END;
%% 
%%    When Windows hits the WVSPrintF statement, I get a UAE.  By running
%% in the debugger, the UAE is reported as exception code 13, a memory
%% addressing error.

Tim --

I may totally off-base here (after all, I work for Microsoft, and this
is about a Borland product ;-), but it looks like you have no storage
reserved for your string buffer.  I'm guessing that type 'PChar' is pointer
to a character (or character array).  Try defining your buffer to be

    var S : array[0..N] of char; {where N is big enough to avoid UAEs!}

If 'S' is a pointer to an array, then I'd think 'new(S)' (or the Borland
variant) should work also.

...Hope this helps!