On Friday, 13 August 2021 at 03:05:22 UTC, Mike Parker wrote:
On Friday, 13 August 2021 at 00:30:59 UTC, Ruby The Roobster wrote:


When I run the program and close the window, the program still runs in background mode. I don't know why this happens nor how to fix it. Does anybody know what's going on?

frame beat me to it, but it may well be that you're getting -1. [The documentation][1] says that a window that has already been destroyed will result in the `hWnd` parameter being invalid, which will cause the function to return -1.


[1]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage#return-value

After rewriting the program, I figured out that the bug was still there. Here is the function that causes it:
```d
public class Entity     {
        package:
                ulong id;
                wchar[] name;
                static ulong nextid;
                Point centre;
                Skeleton skeleton;
        public:
this(ulong id, inout(wchar)[] name,Point centre, Skeleton skeleton) { assert(init == true, "Error: dutils.entity has not been initialized yet. Call dutils.entity.initialize() to initialize the library.");
                        this.id = id;
                        this.name.length = name.length;
                        for(uint i = 0; i < name.length; i++)        {
                                this.name[i] = name[i];
                        }
                        this.nextid = this.id + 1;
                        this.centre = centre;
                        if(!skeleton.init)      {
                                this.skeleton = skeleton;
                        }
                        entitytable.length +=1;
                        entitytable[cast(uint)id] = this;
                }

                ~this() {
                        entitytable.length -= 1;
                        this.nextid -=1;
                        did(cast(uint)this.id);
                }

                debug immutable(char)[] f() @property   {
                        import std.format : format;
return format("ID: %s, Name: %s, NextID: %s, Centre: %s, Skeleton: %s", this.id, this.name, this.nextid, this.centre, this.skeleton);
                }

                ulong Id() @property    {
                        return id;
                }
}
```

Context for this: I am creating a module of my own, and this is a class contained in the module. You will notice that after calling this class' constructor anywhere in a Win32 API program, that the program doesn't close after the window is closed.

Here are the files:

entity.d:
```d
module dutils.entity;

debug { package import core.sys.windows.winuser; } //For MessageBoxA in debug messages...

public struct Skeleton  {
                public Face[] faces;
                package bool init = false;
                public this(Face[] faces)       {
                        this.faces.length = faces.length;
                        for(uint i = 0; i < faces.length; i++)       {
                                this.faces[i] = faces[i];
                        }
                }
                package this(bool init) {
                        this.init = init;
                }
                public void opAssign(Skeleton rhs)      {
                        this.faces.length = rhs.faces.length;
                        for(uint i; i < rhs.faces.length; i++)       {
                                this.faces[i] = rhs.faces[i];
                        }
                        this.init = rhs.init;
                }
}

public struct Face      {
        Point[] points;
        Point centre;
        void opAssign(Face rhs) {
                this.points.length = rhs.points.length;
                for(uint i = 0; i < rhs.points.length; i++)  {
                        this.points[i] = rhs.points[i];
                }
                this.centre = rhs.centre;
        }
}

public struct Point     {
        real x;
        real y;
        real z;
        void opAssign(Point rhs)        {
                this.x = rhs.x;
                this.y = rhs.y;
                this.z = rhs.z;
        }
}

public class Entity     {
        package:
                ulong id;
                wchar[] name;
                static ulong nextid;
                Point centre;
                Skeleton skeleton;
        public:
this(ulong id, inout(wchar)[] name,Point centre, Skeleton skeleton) { assert(init == true, "Error: dutils.entity has not been initialized yet. Call dutils.entity.initialize() to initialize the library.");
                        this.id = id;
                        this.name.length = name.length;
                        for(uint i = 0; i < name.length; i++)        {
                                this.name[i] = name[i];
                        }
                        this.nextid = this.id + 1;
                        this.centre = centre;
                        if(!skeleton.init)      {
                                this.skeleton = skeleton;
                        }
                        entitytable.length +=1;
                        entitytable[cast(uint)id] = this;
                }

                ~this() {
                        entitytable.length -= 1;
                        this.nextid -=1;
                        did(cast(uint)this.id);
                }

                debug immutable(char)[] f() @property   {
                        import std.format : format;
return format("ID: %s, Name: %s, NextID: %s, Centre: %s, Skeleton: %s", this.id, this.name, this.nextid, this.centre, this.skeleton);
                }

                ulong Id() @property    {
                        return id;
                }
}

public class ImmobileEntity : Entity { //Same as Entity, but with a different constructor...
        public:
                this(inout(wchar)[] name, Point centre, Skeleton skeleton)
                        in      {
assert(skeleton.init == false, "Error: Member Skeleton.init must always be set to false.");
                        }
                        do      {
                                super(this.nextid, name, centre, skeleton);
                        }
}

public class MobileEntity : Entity { //Same as entity, but has a move feature(and a speed in miliseconds per whole number moved)...
        package:
                uint speed;
        public:
this(inout(wchar)[] name, Point centre, Skeleton skeleton, uint speed)
                        in      {
assert(skeleton.init == false, "Error: Member Skeleton.init must always be set to false.");
                        }
                        do      {
                                super(this.nextid, name, centre, skeleton);
                                this.speed = speed;
                        }

void move(Point newpos) { //Distance between one point and another
                        import core.thread;
                        import core.math : sqrt;
real temp = sqrt(((newpos.x - this.centre.x)^^2) + ((newpos.y - this.centre.y)^^2) + ((newpos.z - this.centre.z)^^2));
                        temp *= speed;
                        uint time = cast(uint) temp;
                        Thread.sleep(dur!("msecs")(time));
                        this.centre = newpos;
                }
}
package bool init;
package Entity entity;
public Entity[] entitytable;

public void initialize()        {
        entitytable.length = 0;
        init = true;
entity = new Entity(0, "BaseEntityInitialized@id0"w, Point(0,0,0), Skeleton(true));
}

public void terminate() {
        for(uint i = 0; i < entitytable.length; i++) {
                destroy(entitytable[i]);
        }
        entitytable.length = 0;
}

package void did(uint currid)   {
        for(uint i = currid; i < entitytable.length; i++)    {
                entitytable[i].id -=1;
        }
}
debug   {
        public void DebugInfo() { //Debug messages...
                for(uint i = 0; i < entitytable.length; i++) {
MessageBoxA(null,cast(const(char)*)entitytable[i].f,"Test", MB_ICONINFORMATION | MB_OK);
                }
        }
}
```
test.d
```d
import core.sys.windows.windef;
import core.runtime;
import core.sys.windows.wingdi;
import core.sys.windows.winuser;
import entity;
bool exit = false;
extern(Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
        int ret;
        try     {
                Runtime.initialize();
                ret = prog(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
                Runtime.terminate();
        }
        catch(Throwable o)      {
                MessageBoxA(null, "Error","Error", MB_OK | MB_ICONERROR);
        }
        debug MessageBoxA(null, "HERE!", "HERE!", MB_OK);
        return ret;
}

int prog(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) {
        WNDCLASSW wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = &WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = cast(HBRUSH)GetStockObject(GRAY_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = cast(const(wchar)*)"Test"w;
        if(!RegisterClassW(&wndclass))      {
                throw new Exception("F");
        }
HWND hwnd = CreateWindowW(cast(const(wchar)*)"Test"w, cast(const(wchar)*)"Test Program"w, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 900, 900, NULL, NULL, hInstance, NULL);
        ShowWindow(hwnd, CmdShow);
        UpdateWindow(hwnd);
        MSG msg;
        while((GetMessage(&msg,NULL,0,0)))  {
                if(exit)        {
                        break;
                }
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                debug MessageBoxA(null, "HERE!", "HERE!", MB_OK);
        }
        return msg.wParam;
}

extern(Windows)
LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) nothrow {
        switch(msg)     {
                case WM_CREATE:
                        try     {
                                entity.initialize();
                                Skeleton pyrskel;
                                Face[4] pyrfaces;
                                Point[3][2] pyrpoints;
                                pyrpoints[0][0] = Point(0, 0, 1);
                                pyrpoints[0][1] = Point(-1, 0, -1);
                                pyrpoints[0][2] = Point(1, 0, -1);
                                pyrpoints[1][0] = Point(0, 0.75, -0.5);
                                pyrpoints[1][1] = Point(-1, 0, 0.5);
                                pyrpoints[1][2] = Point(1, 0, -0.5);
                                for(uint i = 0;i < 3;i++)    {
                                        pyrfaces[i].points.length = 3;
                                        for(uint j = 0;j < 3;j++)    {
                                                pyrfaces[i].points[j] = 
pyrpoints[1][j];
                                        }
                                }
                                for(uint i = 0;i < 3;i++)    {
                                        pyrfaces[3].points.length = 3;
                                        pyrfaces[3].points[i] = pyrpoints[0][i];
                                }
                                pyrskel = Skeleton(pyrfaces);
auto Pyramid = new Entity(entitytable[0].Id+1,"Pyramid"w, Point(0,0,0), pyrskel);
                        }
                        catch(Throwable e)      {
                                MessageBoxA(hwnd,"ERROR", "ERROR", MB_OK | 
MB_ICONERROR);
                                PostQuitMessage(1);
                        }
                        return 0;
                        break;
                case WM_CLOSE:
                        try     {
                                entity.terminate();
                                DestroyWindow(hwnd);
                        }
                        catch(Throwable e)      {
                                MessageBoxA(hwnd, "ERROR", "ERROR", MB_OK | 
MB_ICONERROR);
                        }
                        DestroyWindow(hwnd);
                        exit = true;
                        break;
                case WM_DESTROY:
                        exit = true;
                        PostQuitMessage(0);
                        break;
                default:
                return DefWindowProc(hwnd,msg,wparam,lparam);
        }
                return 0;
}
```
Sorry for the inconvenience and longness of this post.

P.S: The issue isn't GetMessage(), I can confirm that.

Reply via email to