#Help with zigwin32 SetWindowTextW - GetWindowTextW

1 messages · Page 1 of 1 (latest)

narrow sun
#

How get text value from a text field and pass to title of a form window?

The code below shows that I am confused with how var lptStringValue: [*:0]u16 works. Explanation from a Java Developer's perspective (with a few knowledge on pointers) would be greatly appreciated. And I also don't know how to print the lpStringValue for debugging.

    var lpStringValue: [*:0]u16 = undefined;

    _ = win32.GetWindowTextW(txtMessage, @ptrCast(&lpStringValue), 10);

    // std.debug.print("{s}", .{lpStringValue});

    _ = win32.SetWindowTextW(hwnd, lpStringValue);

    // _ = win32.MessageBoxW(hwnd, lpStringValue, L("Message It"), win32.MB_OK);

Signatures:

// TODO: this type is limited to platform 'windows5.0'
pub extern "user32" fn GetWindowTextW(
    hWnd: ?HWND,
    lpString: [*:0]u16,
    nMaxCount: i32,
) callconv(@import("std").os.windows.WINAPI) i32;

...

// TODO: this type is limited to platform 'windows5.0'
pub extern "user32" fn SetWindowTextW(
    hWnd: ?HWND,
    lpString: ?[*:0]const u16,
) callconv(@import("std").os.windows.WINAPI) BOOL;

smoky lion
#

So to start with you’re initialising pointer types to undefined
Closest Java thing would be creating a null array (but undefined is more scary!)
So you’re telling the windows function that it should copy the string to a nonsense buffer that doesn’t exist

#

What you need to do is actually create a buffer for the string to be copied to
You can do this by making an undefined [N:0]u16, where N is the upper limit of characters
And then passing in a reference and the length N+1 to getwindowtext

#

This will give you a zero terminated buffer of the string

#

Now, generally zig code prefers slices and UTF-8
Over the 0-terminated UTF-16 pointer that windows has effectively given you
So you’ll want to covert before printing

narrow sun
#

Thank you @smoky lion for those important and very helpful notes. I can now understand it more clearly. Basically, in my head I'm mixing array and slices but they are totally different. They're related but different in a way that slices are struct of pointer to many items and a length. I converted the code above like you mentioned:

// Array - As far as I understood the elements will be in stack.
var arrayOfUndefined = [_]u16{
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
    undefined,
};

// Create a slice from array with sentinel of null (:0)
var lpStringValue = arrayOfUndefined[0.. :0];

// Win32 API calls
_ = win32.GetWindowTextW(txtMessage, lpStringValue, lpStringValue.len);
_ = win32.SetWindowTextW(hwnd, lpStringValue);

// Printing unicode UTF16's
var cU16: u16 = undefined;
for (lpStringValue) |c| {
    cU16 = c;
    std.debug.print("{u}", .{cU16});
}

If I'm not mistaken, I think this can be further converted into using allocator.allocSentinel instead of using compile time array.

I highly recommend these references for anyone trying to do the same thing:
https://zig.news/david_vanderson/beginner-s-notes-on-slices-arrays-strings-5b67

Now, there's a special line there cU16 = c in the printing block. If I directly do this std.debug.print("{u}", .{c}) the UI crashes at runtime and I wonder why?

Zig NEWS

Originally published at https://github.com/david-vanderson/zig-notes Zig's arrays and slices were...

smoky lion
#

fyi you can do = undefined on the whole array

#

Also by slicing lpStringValue with a :0, you’re asserting that the buffer is followed by a 0
However, this is not the case! For this you should create your array with :0

narrow sun
#

So the conversion to slice with :0 won't automatically add 0 at the end of slice?

smoky lion
#

No, you’re asserting that the buffer represented by the slice is followed by a zero
(i.e. it needs to already be there)

narrow sun
#

Nice! Thank you 🙂

narrow sun
#

Does zig build run bypass the sentinel check?