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: 170Hat 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...