Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 15:10:14 UTC, Mark Moorhen wrote: It does compile, but does not run as expected. Any clues? You imported, but never actually called Runtime.initalize(). Just stick that at the top, first thing you do inside WinMain, and it will work. (or use main instead of WinMain!)
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 13:59:17 UTC, Adam D. Ruppe wrote: On Friday, 26 October 2018 at 12:36:42 UTC, Mark Moorhen wrote: Can anyone help me out with this? Yeah, let me make a few general points here: Welcome to the wonderful world of wide strings and D Windows programming! :) Wow, that's a lot of info, but it makes things a lot clearer. I ended up with this: import core.runtime; import std.utf; import core.sys.windows.windows; extern (Windows) void WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { const(wchar*) foo = toUTF16z("hello"w[0 .. 2]); MessageBoxW(null, foo, "hi", 0); } It does compile, but does not run as expected. Any clues?
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 12:36:42 UTC, Mark Moorhen wrote: Can anyone help me out with this? Yeah, let me make a few general points here: * The win32.xxx packages shouldn't be necessary any longer, because they have been merged into the druntime core since those tutorials were written, so instead of `win32.xxx` try `core.sys.windows.xxx`. It should mostly work better, though you might see some differences about stuff like nothrow compared to the examples, but solving those are as simple as tossing `nothrow` on your function too. (It will also have bug fixes, especially relating to 64 bit builds!) Regardless, generally, tossing `import core.sys.windows.windows;` at the top of your file should give you most access to the win32 api. * The Windows API, for any function that works with strings, will have three names: FunctionA, FunctionW, and just Function. MessageBox is one of these. The difference is if they take Ascii or Wide strings. The Ascii versions are inferior to the Wide versions because they do not support non-ascii unicode characters and may get other legacy/limiting behavior (for example, CreateFileA has a filename size limit that CreateFileW does not have), so the Wide ones should be preferred. The naked name is an alias for the W version, unless you build with -version=ANSI (or are using a really old library - like the tutorial copy might be, it is 6 years old lol). * D's string and "hello" literals are UTF-8... which kinda looks like Ascii, but isn't. It will compile to pass them to the A version of the functions, and even work as long as you don't have any multi-byte characters in there. So fine for hello world, but asking for trouble later. Instead, use D's wstring and wchar types and associated "hello"w strings. That w after the quotes means it is a wide string literal. const(wchar)* msg = "hello, world!".ptr; // but beware of this later MessageBoxW(null, msg, "Hi there"w, 0); // note the w there The compiler will take care of wide string conversions for you here. * I said beware because the .ptr trick only works if the string is zero terminated. The Windows API generally works with C-style, zero-terminated strings (unless the documentation for that specific function says differently). D's string *literals* are zero terminated, and the compiler knows it. That's why it allows you to pass "a string literal"w to the function without any casts, .ptr calls, or errors. So that will always work. But D's string *types* are not necessarily zero terminated, which is why passing: wstring foo; MessageBoxW(null, foo, "hi"w, 0); will generate an error: the compiler doesn't know if foo is properly formed. You can shut it up with .ptr... but behold the following: wstring foo = "hello"w[0 .. 2]; MessageBoxW(null, foo.ptr, "hi"w, 0); The [x .. y] operator in D will slice the string or array, returning a reference to just the elements between the two indexes (including the first index, excluding the last). In this case, it'd return the first two elements (btw a string element is not necessarily the same as a character - some characters span multiple elements, even on wide strings. Try an emoji in there, for example. But for English letters, this shortcut works, and I don't want to go TOO deep in this little post.) So, given the slice, you'd expect that MessageBox to say "he", right? Try it though... it will say "hello". Why? Because the zero terminator is still at the same place it was before! And using .ptr will bypass the D length part and just give the raw pointer, which keeps going until it hits that zero ... or if there is no zero, such as if the string was generated by another function like the x ~ y concatenation operator, it will keep going and print gibberish, or until the program crashes. * To solve this, append a zero to the end of the slice before passing it. D's standard library has a function to do this: toUTF16z. import std.utf; const(wchar*) foo = toUTF16z("hello"w[0 .. 2]); // now this foo is safe to pass to the Windows function, and will print "he". Dox: http://dpldocs.info/experimental-docs/std.utf.toUTF16z.html That function will also convert other forms of D strings to wstring for you, if necessary. Note that D's standard library also has a toStringz function that does this, but that only works with plain string - the A version in Windows talk. It is helpful for other C functions you might call, but not ideal for Windows, where toUTF16z shines. Important: before calling the D standard library, you must initialize the D runtime. Which brings me to: * I would suggest avoiding WinMain in D code. Instead, just write an ordinary main() function. If you need hInstance, you can call GetModuleHandle. If you need lpCmdLine, you can call GetCommandLine. hPrevInstance is useless in 32 and 64 bit builds, so you won't need it. nCmdShow is only used in one case: passing it to ShowWind
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 13:20:17 UTC, Adam D. Ruppe wrote: If that doesn't compile without casts, you don't want it to compile - casting is often a mistake; the compiler is trying to tell you something. Now you've mentioned, I also tried: { const(char)* content = "Some random content."; MessageBox(NULL, content , "Window title", 0); } And it compiles like a charm.
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 13:13:07 UTC, Mark Moorhen wrote: But how would you do this without casts? If that doesn't compile without casts, you don't want it to compile - casting is often a mistake; the compiler is trying to tell you something. Let me guess, it is saying something like cannot implicitly cast X of type const(char)* to const(wchar)* ? That difference between char and wchar is very important, and casting it away will not run correctly. Whereas just immutable -> const is an implicit cast and the compiler will do it for you since it will not generate wrong code. But this is why rikki posted MessageBoxA and your code has just MessageBox - it is a way around it (not the best way, but a working way). I'm typing a longer post right now explaining this in more detail.
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 13:04:21 UTC, Adam D. Ruppe wrote: On Friday, 26 October 2018 at 12:56:21 UTC, rikki cattermole wrote: MessageBoxA(null, cast(const(char)*)content.ptr, cast(const(char)*)"Window title".ptr, 0); Get rid of those casts, they are unnecessary. I got to this: string content = "Some random content."; const(char)* content2 = content.ptr; MessageBox(NULL, content2 , "Window title", 0); But how would you do this without casts?
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 12:56:21 UTC, rikki cattermole wrote: On 27/10/2018 1:46 AM, Mark Moorhen wrote: On Friday, 26 October 2018 at 12:39:13 UTC, rikki cattermole wrote: On 27/10/2018 1:36 AM, Mark Moorhen wrote: [...] alias string = immutable(char)[]; A slice (string in this case) is a length + pointer pair. You need to add .ptr on content with a cast to get to const(char)*. Thanks for your quick reply. However when I do: cast(const(char)*) content.ptr; I get a error: HelloMsg.d(9): Error: `cast(const(char)*)cast(immutable(char)*)content` has no effect This should work: string content = "Some random content."; MessageBoxA(null, cast(const(char)*)content.ptr, cast(const(char)*)"Window title".ptr, 0); Thanks again. It does work indeed. Now I'll have to try and get my head around it. But that will work out. eventually...
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 12:56:21 UTC, rikki cattermole wrote: MessageBoxA(null, cast(const(char)*)content.ptr, cast(const(char)*)"Window title".ptr, 0); Get rid of those casts, they are unnecessary.
Re: getting Win32 Messagebox to work
On 27/10/2018 1:46 AM, Mark Moorhen wrote: On Friday, 26 October 2018 at 12:39:13 UTC, rikki cattermole wrote: On 27/10/2018 1:36 AM, Mark Moorhen wrote: [...] alias string = immutable(char)[]; A slice (string in this case) is a length + pointer pair. You need to add .ptr on content with a cast to get to const(char)*. Thanks for your quick reply. However when I do: cast(const(char)*) content.ptr; I get a error: HelloMsg.d(9): Error: `cast(const(char)*)cast(immutable(char)*)content` has no effect This should work: string content = "Some random content."; MessageBoxA(null, cast(const(char)*)content.ptr, cast(const(char)*)"Window title".ptr, 0);
Re: getting Win32 Messagebox to work
On Friday, 26 October 2018 at 12:39:13 UTC, rikki cattermole wrote: On 27/10/2018 1:36 AM, Mark Moorhen wrote: [...] alias string = immutable(char)[]; A slice (string in this case) is a length + pointer pair. You need to add .ptr on content with a cast to get to const(char)*. Thanks for your quick reply. However when I do: cast(const(char)*) content.ptr; I get a error: HelloMsg.d(9): Error: `cast(const(char)*)cast(immutable(char)*)content` has no effect
getting Win32 Messagebox to work
Hi, I've recently started looking into D, and I'm afraid i'm gonna need some support to get me going. I work mostly on Windows, so i've downloaded the examples from "https://github.com/AndrejMitrovic/DWinProgramming";. Only these examples do not work out-of-the-box on my machine (Win10, 64-bit / DMD32 D Compiler v2.082.0) Now I'm trying to pass the content for a Messagebox as a variable like this: import core.runtime; import win32.windef; import win32.winuser; extern (Windows) void WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { string content = "Some random content."; MessageBox(NULL, content , "Window title", 0); } When compiling I get the error: HelloMsg.d(9): Error: function `win32.winuser.MessageBoxA(void*, const(char)*, const(char)*, uint)` is not callable using argument types `(typeof(null), string, string, int)` HelloMsg.d(9):cannot pass argument `content` of type `string` to parameter `const(char)*` Can anyone help me out with this?
Re: getting Win32 Messagebox to work
On 27/10/2018 1:36 AM, Mark Moorhen wrote: Hi, I've recently started looking into D, and I'm afraid i'm gonna need some support to get me going. I work mostly on Windows, so i've downloaded the examples from "https://github.com/AndrejMitrovic/DWinProgramming";. Only these examples do not work out-of-the-box on my machine (Win10, 64-bit / DMD32 D Compiler v2.082.0) Now I'm trying to pass the content for a Messagebox as a variable like this: import core.runtime; import win32.windef; import win32.winuser; extern (Windows) void WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { string content = "Some random content."; MessageBox(NULL, content , "Window title", 0); } When compiling I get the error: HelloMsg.d(9): Error: function `win32.winuser.MessageBoxA(void*, const(char)*, const(char)*, uint)` is not callable using argument types `(typeof(null), string, string, int)` HelloMsg.d(9): cannot pass argument `content` of type `string` to parameter `const(char)*` Can anyone help me out with this? alias string = immutable(char)[]; A slice (string in this case) is a length + pointer pair. You need to add .ptr on content with a cast to get to const(char)*.
Re: Help needed to extend the core.thread
On Friday, 26 October 2018 at 01:58:47 UTC, Heromyth wrote: Maybe it's better to extend core.thread.Thread by inheriting it. Am I right? Thanks! Yes, see the example at https://dlang.org/phobos/core_thread.html#.Thread
Re: Pegged: spaces
25.10.2018 23:34, Michelle Long пишет: Ignores spaces: <- Doesn't: < Concatenates results: <~ Thank you for sharing your results!