adamdruppe / arsd

This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo.
http://arsd-official.dpldocs.info/arsd.html
530 stars 127 forks source link

Minigui: Program exited with code -1073741819 #274

Closed andre2007 closed 1 year ago

andre2007 commented 3 years ago

While opening the main window, I want another window on top be opened which queries for some paramters needed for the main window. This could be e.g. login credentials or a loading indicator.

My implementation looks like this

/+ dub.sdl:
    name "application"
    dependency "arsd-official:minigui" version="9.1.2"
    versions "custom_widgets"
+/

import arsd.minigui;

class AppMainWindow: MainWindow
{
    this()
    {
        super("Monitor");
        auto tenantWindow = new TenantWindow(this);
        tenantWindow.show();
    }
}

class TenantWindow: Window
{   
    this(Widget parent)
    {
        super(parent);
    }
}

void main()
{
    new AppMainWindow().loop();
}

It fails with Program exited with code -1073741819.

In addition there is a second issue. Without versions "custom_widgets" it fails with error:

AppData\Local\dub\packages\arsd-official-9.1.2\arsd-official\minigui.d(3101,26): Error: undefined identifier TBS_REVERSED

adamdruppe commented 3 years ago

I don't think it supports a window being a child of another window like that (I'm not sure why I even allowed the parent in the constructor there because I have never used it); windows are assumed to be top level here.

but I'll look into it soon.

adamdruppe commented 3 years ago

but you don't have TBS_REVERSED ??? that's just weird it has been in druntime for 5+ years, versioned for windows XP and up but it sets that by default for a long time too

    TBS_REVERSED = 0x0200
adamdruppe commented 3 years ago

Ok, that constructor is necessary for pop up menus so I can't remove it... but it is also inappropriate for what you're trying to do...

so it should just be super(), not super(parent). I might just make it private since it is super problematic.

What you're intending to do here is to set what Windows calls a "window owner" and... idk how I want to expose that.... I'd suggest just not doing it right now.

andre2007 commented 3 years ago

Thanks a lot Adam. I just noticed, the system I tested, has a rather old dmd (2.089). That was the reason for the TBS_REVERSED issue.

andre2007 commented 3 years ago

@adamdruppe

Is there a way to set TenantWindow to blocking?

There main window should be blocked until TenantWindow is closed. I tried also base class Dialog, without luck.

adamdruppe commented 3 years ago

On Mon, Feb 01, 2021 at 04:10:11AM -0800, andre2007 wrote:

Is there a way to set TenantWindow to blocking?

No, I don't believe in modal dialogs so I don't support it at all. Few things drive me more nuts than an annoying popup that makes my clicks do nothing.

I think you can do it with a couple other function calls though... but what is your purpose with this? There might be a better design.

andre2007 commented 3 years ago

My main window should show data for a specific tenant. While the application starts, I want to show the user a list of available tenants (in a dedicated window), the user select the tenant he want to work with, and the main window shows only the data of this specific tenant.

Of course I could add a tenant drop down to the main window, for changing the tenant, but this UI workflow I not really like for this specific case.

adamdruppe commented 3 years ago

On Mon, Feb 01, 2021 at 05:49:35AM -0800, andre2007 wrote:

My main window should show data for a specific tenant. While the application starts, I want to show the user a list of available tenants (in a dedicated window), the user select the tenant he want to work with, and the main window shows only the data of this specific tenant.

OK, a few other ideas would be

1) hide the main window when the picker window is up, then show it when it is done.

2) (my preference) keep the window operational and have the tenant change based on an async thing. So in your picker window, when the option changes, reload the info in the main window but still keep it operating. Then you could just show/hide the tenant window too when you don't need it and it allows switching easily.

3) Call the win API function to disable the parent, which I think is what the modal dialog thing does anyway though it doesn't do the blinking a real modal dialog does (I think that's because of the owner window not being set but I don't remember the function for that.)

But this UFCS function:

void enabled(Widget w, bool e) {
        import core.sys.windows.windows;
        if(w.hwnd)
                EnableWindow(w.hwnd, e);

        foreach(child; w.children)
                child.enabled = e;
}

Then you can do like

yourwindow.enabled = false;

to grey it out and

yourwindow.enabled = true;

to turn it back on.

andre2007 commented 3 years ago

The enabled Property I really miss in minigui. If possible, could you add it in future?

It is not that easy to add it on my side, because hwnd is only available with version win32_widgets. But this version cannot be used together with version custom_widgets which I need for the list box. A lot syntax errors are thrown when both versions are used together.

Hiding the main window seems also not work. I call this.hide() in the constructor of the main window just before calling the tenant window, but the main window is still shown.

adamdruppe commented 3 years ago

On Mon, Feb 01, 2021 at 11:09:06PM -0800, andre2007 wrote:

The enabled Property I really miss in minigui. If possible, could you add it in future?

yeah.

It is not that easy to add it on my side, because hwnd is only available with version win32_widgets. But this version cannot be used together with version custom_widgets which I need for the list box.

the list box is in win32 now, I added it over the weekend on master.

But yeah the custom widgets don't support disabling. I'm not sure if I even will add it there.

Hiding the main window seems also not work. I call this.hide() in the constructor of the main window just before calling the tenant window, but the main window is still shown.

oooh that's cuz mainwindow.loop shows it since that's what you want 99% of the time.

you could always do tenantwindow.loop instead. The loop function being on a window is really just a historical accident, it all forwards to a static method on another object anyway in the end.

adamdruppe commented 3 years ago

So I was just reading some of the docs on this and part of the confusion is shared by the Windows api - parent and owner are not the same thing but are set by the same function param just depending on a separate flag.

My API forwards the param but not the flag which is why we can't get quite the right thing here. Still not modal but like it would at least set the relationship.

I'll be pushing some new stuff probably later this week, I'm doing drag and drop first though.

adamdruppe commented 3 years ago

I'm starting to make some changes about this and a website gave me an idea I kinda like : inline modals. Instead of popping up a new top-level window that disables the bottom one, it just goes inside the original window.

Think about how they tend to work on websites. I'm still not quite in love but I think I like it more. Would you agree?

andre2007 commented 3 years ago

Inline modals although sounds like an interesting concept and for some scenarios really useful. In general I think the developer/ ui designer should have the choice between a blocking window and other concepts like inline modals. There are use cases where blocking windows would make more sense from an user designer perspective and other use cases where not.

andre2007 commented 1 year ago

Issue is solved for me.