Puzzle me this, Oh Wise Monks:

The following piece of code gets, changes one character, and sets a window's label using the Wide system calls and UTF16-LE strings.

sub change_text { use bytes; my $s= 'x'x256; $getTextF->Call ($handle, $s, 128); # substr ($s,46,2, "\x22\x21"); #substr ($s,40,2, "\x22\x21"); $setTextF->Call ($handle, $s); $s =~ tr/\0 /.-/; print $s; }
The tr// at the end is to make it print out usefully on an 8-bit console. I can see where the 0's are and that all the chars are properly LE with the ASCII code in the first byte and 0 in the second, and my new 16-bit character is properly aligned.

If I un-comment one of the substr lines, the new character does indeed appear in the window, but the string is truncated! How much is truncated seems to vary with the exact string! Maybe 5 chars in one case. That's even if the substr took place at the very first position.

When dumping my string via print, I can see that it is put together correctly, every byte where it belongs.

So I'm wondering what might be making the system call quit early? Are strings discontiguous in memory and this is now two fragments?

If I Get the text out again, I see that bytes have actually been deleted, and stuff after it moved up, not just truncated by getting the length wrong. The Win32 calls take nul-terminated input, so the Set stops when it sees \0\0 in the buffer. Yet the value of $s is unaltered after I call Set, but Get again implies that Set deleted a few bytes before passing it along to the actual OS call.

Is this strange or what? I'm totally mystified.

Full program follows.

—John

${^WIDE_SYSTEM_CALLS}= 1; use strict; use Win32::GUI; use Win32::API; my $s= "This is a TM symbol =>x"; my $setTextF= new Win32::API:: ('user32.dll', 'SetWindowTextW', ['N',' +P'], 'N') or die; my $getTextF= new Win32::API:: ('user32.dll', 'GetWindowTextW', ['N',' +P','N'], 'N') or die; my $window = Win32::GUI::Window->new ( -width => 400, # Set the width -height => 200, # Set the height -text => "Hello World Title", # Set the title -name => "window1", # Set the name (used for event handlers) ); my $font = Win32::GUI::Font->new ( -size => 20, # Set the size (in points) -name => "Comic Sans MS", # Name of the font ); my $lable = $window->AddLabel( -text => $s, # Set the text in the label -font => $font, # Set the font -foreground => [0, 0, 255], # Set the color of the text -name => 'text1' ); my $handle= $window->{text1}{-handle}; print $handle; $window->Show (); change_text(); sub window1_Terminate { return -1; # Return -1 to end the event loop } sub change_text { use bytes; my $s= 'x'x256; $getTextF->Call ($handle, $s, 128); substr ($s,46,2, "\x22\x21"); #substr ($s,40,2, "\x22\x21"); $setTextF->Call ($handle, $s); $s =~ tr/\0 /.-/; print "$s\n"; $getTextF->Call ($handle, $s, 128); $s =~ tr/\0 /.-/; print $s; }

In reply to Where is my string going in Win32::API ? by John M. Dlugosz

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.