Re: getting Win32 Messagebox to work

2018-10-26 Thread Adam D. Ruppe via Digitalmars-d-learn

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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn

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

2018-10-26 Thread Adam D. Ruppe via Digitalmars-d-learn

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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn

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

2018-10-26 Thread Adam D. Ruppe via Digitalmars-d-learn

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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn

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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn
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

2018-10-26 Thread Adam D. Ruppe via Digitalmars-d-learn
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

2018-10-26 Thread rikki cattermole via Digitalmars-d-learn

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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn
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

2018-10-26 Thread Mark Moorhen via Digitalmars-d-learn

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

2018-10-26 Thread rikki cattermole via Digitalmars-d-learn

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

2018-10-26 Thread Nicholas Wilson via Digitalmars-d-learn

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

2018-10-26 Thread drug via Digitalmars-d-learn

25.10.2018 23:34, Michelle Long пишет:

Ignores spaces: <-

Doesn't: <

Concatenates results: <~



Thank you for sharing your results!