SetThreadDesktop(old_desk_) liefert 170: "The requested resource is in use"



  • Hallo,

    ich versuche folgendes...

    GetClipCursor(&rect_old_clip);
    GetWindowRect(wnd_, &rect_clip);
    ClipCursor(&rect_clip);
    

    das funktioniert aber nicht. Der Cursor sollte ja das Fenster nicht verlassen. Bei mir macht er das aber nicht.
    Das Programm soll und Vista, Windows 8 und Windows 10 laufen.

    die MSDN sagt dazu

    https://msdn.microsoft.com/de-de/library/ms648383

    The calling process must have WINSTA_WRITEATTRIBUTES access to the window station.

    Ich muss aber doch nicht...

    handle_windowstation = OpenWindowStation("winsta0", false,
                                          WINSTA_ACCESSCLIPBOARD |
                                          WINSTA_ACCESSGLOBALATOMS |
                                          WINSTA_CREATEDESKTOP |
                                          WINSTA_ENUMDESKTOPS |
                                          WINSTA_ENUMERATE |
                                          WINSTA_EXITWINDOWS |
                                          WINSTA_READATTRIBUTES |
                                          WINSTA_READSCREEN |
                                          WINSTA_WRITEATTRIBUTES);
    
    if (handle_windowstation != nullptr){
            SetProcessWindowStation(handle_windowstation);
    }
    

    Kann mir wer helfen, das meine "unsichtbare" Maus das Fenster nicht verlässt?

    Gruß



  • Hallo,

    habe mal ein simples Testprogramm gebaut:

    #include <windows.h>
    #include <stdexcept>
    
    namespace{
        LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM);
    }
    
    class App
    {
    public:
        App(HINSTANCE instance_exe);
        App(const App &) = delete;
        App& operator=(const App &) = delete;
    
    public:
        ~App();
    
    public:
        void Shutdown(bool throw_exceptions = false);
        void SetupMainWindow();
        void CloseMainWindow();
        bool PumpMessages();
    
    private:
        HINSTANCE instance_exe_;
    
        HWINSTA old_winsta_;
        HDESK old_desk_;
    
        HWINSTA winsta_;
        HDESK desk_;
    
        bool shutdown_;
        HWND wnd_;
    };
    
    namespace global{
        App *app {};
    }
    
    App::App(HINSTANCE instance_exe):
        instance_exe_{instance_exe},
    
        old_winsta_ {},
        old_desk_ {},
    
        winsta_ {},
        desk_ {},
    
        shutdown_ {},
    
        wnd_{}
    {
        global::app = this;
    
        old_winsta_ = GetProcessWindowStation();
    
        if(old_winsta_ == nullptr){
            throw std::runtime_error(
                                "GetProcessWindowStation failed :" +
                                std::to_string(GetLastError()));
        }
    
        old_desk_ = GetThreadDesktop(GetCurrentThreadId());
    
        if(old_desk_ == nullptr){
             throw std::runtime_error(
                                "GetThreadDesktop failed :" +
                                std::to_string(GetLastError()));
        }
    
        winsta_ = OpenWindowStation("winsta0", false,
                                      WINSTA_ACCESSCLIPBOARD |
                                      WINSTA_ACCESSGLOBALATOMS |
                                      WINSTA_CREATEDESKTOP |
                                      WINSTA_ENUMDESKTOPS |
                                      WINSTA_ENUMERATE |
                                      WINSTA_EXITWINDOWS |
                                      WINSTA_READATTRIBUTES |
                                      WINSTA_READSCREEN |
                                      WINSTA_WRITEATTRIBUTES);
    
        if(winsta_ == nullptr){
            throw std::runtime_error(
                                "OpenWindowStation (winsta0) failed :" +
                                std::to_string(GetLastError()));
        }
    
        if(!SetProcessWindowStation(winsta_)){
            throw std::runtime_error(
                                "SetProcessWindowStation (winsta0) failed :" +
                                std::to_string(GetLastError()));
        }
    
        HDESK test_desk = GetThreadDesktop(GetCurrentThreadId());
    
        if(test_desk == nullptr){
            throw std::runtime_error(
                                "Test desktop failed :" +
                                std::to_string(GetLastError()));
        }
    
        desk_ = OpenDesktop(
                "default", 0, false,
                DESKTOP_CREATEMENU |
                DESKTOP_SWITCHDESKTOP |
                DESKTOP_READOBJECTS |
                DESKTOP_JOURNALPLAYBACK |
                DESKTOP_JOURNALRECORD |
                DESKTOP_WRITEOBJECTS |
                DESKTOP_CREATEWINDOW |
                READ_CONTROL |
                WRITE_DAC
                 );
    
        if(desk_ == nullptr){
            throw std::runtime_error(
                                "OpenDesktop (default) failed :" +
                                std::to_string(GetLastError()));
        }
    
        if(!SetThreadDesktop(desk_)){
            throw std::runtime_error(
                                "SetThreadDesktop (default) failed :" +
                                std::to_string(GetLastError()));
        }
    }
    
    App::~App()
    {
        if(!shutdown_){
            Shutdown(false);
        }
    
        global::app = nullptr;
    }
    
    void App::CloseMainWindow()
    {
        ClipCursor(nullptr);
        DestroyWindow(wnd_);
    }
    
    void App::Shutdown(bool throw_exceptions)
    {
        if(winsta_)
        {
            if(!SetProcessWindowStation(old_winsta_)){
                if(throw_exceptions){
                    throw std::runtime_error(
                                    "SetProcessWindowStation (reset) failed :" +
                                    std::to_string(GetLastError()));
                }
            }
    
            CloseWindowStation(winsta_);
            winsta_ = nullptr;
        }
    
        if(old_desk_){
            if(!SetThreadDesktop(old_desk_)){
                if(throw_exceptions){
                    throw std::runtime_error(
                                    "SetThreadDesktop (reset) failed :" +
                                    std::to_string(GetLastError()));
                }
            }
    
            CloseDesktop(desk_);
            desk_ = nullptr;
        }
    
        shutdown_ = true;
    }
    
    bool App::PumpMessages()
    {
        MSG msg {};
    
        while(PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE))
        {
            if(GetMessageW(&msg, nullptr, 0, 0) <= 0)
            {
                return false;
            }
    
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    
        return true;
    }
    
    void App::SetupMainWindow()
    {
        static const auto wndclass_name = [&]() -> const wchar_t*
        {
            WNDCLASSEXW wcx {};
    
            wcx.cbSize = sizeof(WNDCLASSEXW);
            wcx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
            wcx.hInstance = instance_exe_;
            wcx.lpfnWndProc = MainWindowProc;
            wcx.lpszClassName = L"MainWindowClass";
            wcx.hbrBackground = static_cast<HBRUSH>(
                                                GetStockObject(WHITE_BRUSH));
            wcx.hIcon = reinterpret_cast<HICON>(
                                            LoadImage(
                                                    nullptr,
                                                    IDI_APPLICATION,
                                                    IMAGE_ICON,
                                                    0,0,
                                                    LR_DEFAULTSIZE | LR_SHARED));
            wcx.hCursor = reinterpret_cast<HCURSOR>(
                                            LoadImage(
                                                    nullptr,
                                                    IDC_ARROW,
                                                    IMAGE_CURSOR,
                                                    0,0,
                                                    LR_DEFAULTSIZE | LR_SHARED));
    
            ATOM result = RegisterClassExW(&wcx);
    
            if(!result){
                throw std::runtime_error("Failed to register main window class");
            }
    
            return wcx.lpszClassName;
        }();
    
        auto wnd = CreateWindowExW(
                                0,
                                wndclass_name,
                                L"test...",
                                WS_OVERLAPPEDWINDOW,
                                0, 0, 640, 480,
                                nullptr,
                                nullptr,
                                instance_exe_,
                                nullptr);
    
        if(!wnd){
            throw std::runtime_error("Failed to create main window");
        }
    
        ShowWindow(wnd, SW_SHOW);
        UpdateWindow(wnd);
    
        RECT r;
        GetWindowRect(wnd, &r);
        ClipCursor( &r );
    
        wnd_ = wnd;
    }
    
    int WINAPI WinMain(
                    HINSTANCE instance_exe,
                    HINSTANCE,
                    LPSTR,
                    int)
    {
        try{
            App app{instance_exe};
    
            app.SetupMainWindow();
    
            while(true)
            {
                if(!app.PumpMessages()){
                    break;
                }
            }
    
            app.Shutdown(true);
        }
        catch(const std::exception &e){
            MessageBoxA(nullptr, e.what(), "", MB_ICONSTOP);
        }
    
        return EXIT_SUCCESS;
    }
    
    namespace{
        LRESULT CALLBACK MainWindowProc(
                                        HWND wnd,
                                        UINT msg,
                                        WPARAM wparam,
                                        LPARAM lparam)
        {
            LRESULT result {};
    
            switch(msg)
            {
            case WM_CLOSE:
                global::app->CloseMainWindow();
                break;
    
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
    
            default:
                result = DefWindowProcW(wnd, msg, wparam, lparam);
                break;
            }
    
            return result;
        }
    }
    

    - App-Konstruktor läuft durch...
    - Fenster wird angezeigt...
    - nix Clipping 😡
    - Shutdown erzeugt denn folgenden Fehler (SetThreadDesktop (reset) failed: 170 🙄

    Hat denn wirklich niemand eine Idee?

    Gruß



  • 😃

    #include <windows.h>
    #include <string>
    #include <stdexcept>
    
    namespace{
        LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM);
    }
    
    class App
    {
    public:
        App(HINSTANCE instance_exe);
        App(const App &) = delete;
        App& operator=(const App &) = delete;
    
    public:
        ~App();
    
    public:
        void Shutdown(bool throw_exceptions = false);
        void SetupMainWindow();
        void CloseMainWindow();
        bool PumpMessages();
    
    private:
        HINSTANCE instance_exe_;
    
        HWINSTA old_winsta_;
        HDESK old_desk_;
    
        HWINSTA winsta_;
        HDESK desk_;
    
        bool shutdown_;
        HWND wnd_;
    
        std::wstring wndclass_name_;
    };
    
    namespace global{
        App *app {};
    }
    
    App::App(HINSTANCE instance_exe):
        instance_exe_{instance_exe},
    
        old_winsta_ {},
        old_desk_ {},
    
        winsta_ {},
        desk_ {},
    
        shutdown_ {},
    
        wnd_{},
    
        wndclass_name_{}
    {
        global::app = this;
    
        old_winsta_ = GetProcessWindowStation();
    
        if(old_winsta_ == nullptr){
            throw std::runtime_error(
                                "GetProcessWindowStation failed :" +
                                std::to_string(GetLastError()));
        }
    
        old_desk_ = GetThreadDesktop(GetCurrentThreadId());
    
        if(old_desk_ == nullptr){
             throw std::runtime_error(
                                "GetThreadDesktop failed :" +
                                std::to_string(GetLastError()));
        }
    
        winsta_ = OpenWindowStation("winsta0", false,
                                      WINSTA_ACCESSCLIPBOARD |
                                      WINSTA_ACCESSGLOBALATOMS |
                                      WINSTA_CREATEDESKTOP |
                                      WINSTA_ENUMDESKTOPS |
                                      WINSTA_ENUMERATE |
                                      WINSTA_EXITWINDOWS |
                                      WINSTA_READATTRIBUTES |
                                      WINSTA_READSCREEN |
                                      WINSTA_WRITEATTRIBUTES);
    
        if(winsta_ == nullptr){
            throw std::runtime_error(
                                "OpenWindowStation (winsta0) failed :" +
                                std::to_string(GetLastError()));
        }
    
        if(!SetProcessWindowStation(winsta_)){
            throw std::runtime_error(
                                "SetProcessWindowStation (winsta0) failed :" +
                                std::to_string(GetLastError()));
        }
    
        HDESK test_desk = GetThreadDesktop(GetCurrentThreadId());
    
        if(test_desk == nullptr){
            throw std::runtime_error(
                                "Test desktop failed :" +
                                std::to_string(GetLastError()));
        }
    
        desk_ = OpenDesktop(
                "default", 0, false,
                DESKTOP_CREATEMENU |
                DESKTOP_SWITCHDESKTOP |
                DESKTOP_READOBJECTS |
                DESKTOP_JOURNALPLAYBACK |
                DESKTOP_JOURNALRECORD |
                DESKTOP_WRITEOBJECTS |
                DESKTOP_CREATEWINDOW |
                READ_CONTROL |
                WRITE_DAC
                 );
    
        if(desk_ == nullptr){
            throw std::runtime_error(
                                "OpenDesktop (default) failed :" +
                                std::to_string(GetLastError()));
        }
    
        if(!SetThreadDesktop(desk_)){
            throw std::runtime_error(
                                "SetThreadDesktop (default) failed :" +
                                std::to_string(GetLastError()));
        }
    }
    
    App::~App()
    {
        if(!shutdown_){
            Shutdown(false);
        }
    
        global::app = nullptr;
    }
    
    void App::CloseMainWindow()
    {
        ClipCursor(nullptr);
    
        DestroyWindow(wnd_);
        UnregisterClassW(wndclass_name_.c_str(), instance_exe_);
    }
    
    void App::Shutdown(bool throw_exceptions)
    {
        if(winsta_)
        {
            if(!SetProcessWindowStation(old_winsta_)){
                if(throw_exceptions){
                    throw std::runtime_error(
                                    "SetProcessWindowStation (reset) failed :" +
                                    std::to_string(GetLastError()));
                }
            }
    
            CloseWindowStation(winsta_);
            winsta_ = nullptr;
        }
    
        if(old_desk_){
            if(!SetThreadDesktop(old_desk_)){
                if(throw_exceptions){
                    throw std::runtime_error(
                                    "SetThreadDesktop (reset) failed :" +
                                    std::to_string(GetLastError()));
                }
            }
    
            CloseDesktop(desk_);
            desk_ = nullptr;
        }
    
        shutdown_ = true;
    }
    
    bool App::PumpMessages()
    {
        MSG msg {};
    
        while(PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE))
        {
            if(GetMessageW(&msg, nullptr, 0, 0) <= 0)
            {
                return false;
            }
    
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    
        return true;
    }
    
    void App::SetupMainWindow()
    {
        static const auto wndclass_name = [&]() -> const wchar_t*
        {
            WNDCLASSEXW wcx {};
    
            wcx.cbSize = sizeof(WNDCLASSEXW);
            wcx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
            wcx.hInstance = instance_exe_;
            wcx.lpfnWndProc = MainWindowProc;
            wcx.lpszClassName = L"MainWindowClass";
            wcx.hbrBackground = static_cast<HBRUSH>(
                                                GetStockObject(WHITE_BRUSH));
            wcx.hIcon = reinterpret_cast<HICON>(
                                            LoadImage(
                                                    nullptr,
                                                    IDI_APPLICATION,
                                                    IMAGE_ICON,
                                                    0,0,
                                                    LR_DEFAULTSIZE | LR_SHARED));
            wcx.hCursor = reinterpret_cast<HCURSOR>(
                                            LoadImage(
                                                    nullptr,
                                                    IDC_ARROW,
                                                    IMAGE_CURSOR,
                                                    0,0,
                                                    LR_DEFAULTSIZE | LR_SHARED));
    
            ATOM result = RegisterClassExW(&wcx);
    
            if(!result){
                throw std::runtime_error("Failed to register main window class");
            }
    
            return wcx.lpszClassName;
        }();
    
        wndclass_name_ = wndclass_name;
    
        ///////////////////////////////////////////
    
        RECT r {};
    
        r.bottom = 480; // height
        r.right = 640; // width
    
        AdjustWindowRect(
                        &r,
                        WS_OVERLAPPEDWINDOW,
                        false);
    
        int width = r.right - r.left;
        int height = r.bottom - r.top;
    
        //////////////////////////////////////////
    
        auto wnd = CreateWindowExW(
                                0,
                                wndclass_name,
                                L"test...",
                                WS_OVERLAPPEDWINDOW,
                                0 , 0, width, height,
                                nullptr,
                                nullptr,
                                instance_exe_,
                                nullptr);
    
        if(!wnd){
            throw std::runtime_error("Failed to create main window");
        }
    
        ShowWindow(wnd, SW_SHOW);
        UpdateWindow(wnd);
    
        GetClientRect(wnd, &r);
    
        ///////////////////////////////////////////
    
        POINT upper_left;
        upper_left.x = r.left;
        upper_left.y = r.top;
    
        POINT lower_right;
        lower_right.x = r.right;
        lower_right.y = r.bottom;
    
        MapWindowPoints(wnd, nullptr, &upper_left, 1);
        MapWindowPoints(wnd, nullptr, &lower_right, 1);
    
        r.left = upper_left.x;
        r.top = upper_left.y;
    
        r.right = lower_right.x;
        r.bottom = lower_right.y;
    
        ///////////////////////////////////////////
    
        ClipCursor(&r);
    
        wnd_ = wnd;
    }
    
    int WINAPI WinMain(
                    HINSTANCE instance_exe,
                    HINSTANCE,
                    LPSTR,
                    int)
    {
        try{
            App app{instance_exe};
    
            app.SetupMainWindow();
    
            while(true)
            {
                if(!app.PumpMessages()){
                    break;
                }
            }
    
            app.Shutdown(true);
        }
        catch(const std::exception &e){
            MessageBoxA(nullptr, e.what(), "", MB_ICONSTOP);
        }
    
        return EXIT_SUCCESS;
    }
    
    namespace{
        LRESULT CALLBACK MainWindowProc(
                                        HWND wnd,
                                        UINT msg,
                                        WPARAM wparam,
                                        LPARAM lparam)
        {
            LRESULT result {};
    
            switch(msg)
            {
            case WM_CLOSE:
                global::app->CloseMainWindow();
                break;
    
            case WM_CHAR:
                {
                    if(wparam == VK_ESCAPE){
                        global::app->CloseMainWindow();
                    }
                }
                break;
    
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
    
            default:
                result = DefWindowProcW(wnd, msg, wparam, lparam);
                break;
            }
    
            return result;
        }
    }
    

    So bleibt man im Fenster des späteren "Graphplotters". Aber das hantieren mit dem Desktop-Zeugs...wow 😮

    Das einzige Problem ist nur der doofe Fehlercode: 170.

    Ich muss irgendein GDI-Zeugs noch aktiv haben...aber ich weiß nicht wo.

    Der Fehler tritt wie schon erwähnt hier auf

    SetThreadDesktop(old_desk_)
    

    Das hat doch sicher schon jemand mal gemacht...bütte, bütte...


Anmelden zum Antworten