如何在自定义Windows桌面(HDESK)上显示QDialog

发布于 2025-02-07 08:19:21 字数 2370 浏览 4 评论 0原文

解决方案

在几次测试和社区的良好潜在客户之后,我现在可以确认必须在创建qapplication之前应用setThreadDesktop 。这是允许QT在新桌面中显示Qwidgets的唯一方法。

但是,switchdesktop可以在qapplication之前或之后调用,只要在创建qapplication之前已调用setThreadDesktop,就没关系。

感谢大家!我希望这个话题对他人有用。

问题

我正在使用Windows上的QT项目,我需要使用API​​来创建自定义桌面( hdesk ),例如 createSktop opendesktop and switchdesktop 。在这个新桌面上,我需要显示一个qdialog(使用 exec show 取决于我的需求),但是qdialog并未在新桌面上显示,而是在“默认”上显示“ 一。

我的代码看起来像这样:

/* Starting the QApplication from the main function */
QApplication qApp;
qApp.exec();
/* [...] An HEVENT is fired or a Win32 COM call is made telling me than i need to display the QDialog */
/* Creating the new desktop and switching to it */
HDESK hNewDesktop=NULL;

hNewDesktop=CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
SwitchDesktop(hNewDesktop);

/* Creating the QDialog and showing it */
QDialog *pqdlgMyDialog=NULL;

pqdlgMyDialog=new QDialog(NULL);
pqdlgMyDialog.show(); // or .exec() depending on the my needs

这样做,创建并显示带有黑色背景的新桌面,但qdialog显示在默认桌面上(我们启动Windows时看到的一个)。

我必须尝试将父母设置为我的Qdialog做这样的事情,但也行不通:

QWindow *pqwParentWindow=NULL;
QWidget *pwqParentWidget=NULL;
HWND hwndParentWindow=NULL;

hwndParentWindow=GetTopWindow(NULL); // I have also tried GetDesktopWindow, FindWindowEx etc.
pqwParentWindow=QWindow::fromWinId((WId)hwndParentWindow);
pwqParentWidget=QWidget::createWindowContainer(pqwParentWindow);
[...]
QDialog *pqdlgMyDialog=NULL;
pqdlgMyDialog=new QDialog(pwqParentWidget);
pqdlgMyDialog.show(); // or .exec() depending on the my needs

如果有人有想法,我愿意尝试一切! 我已经阅读了QT文档和MSDN的大量阅读,寻找诸如“ Qapplication链接到桌面”之类的东西,但没有成功...

Solution

After several tests and good leads from the community, I can now confirm that it is mandatory to apply SetThreadDesktop before creating the QApplication. This is the only way to allow Qt to display QWidgets in the new desktop.

However, SwitchDesktop can be called before or after the QApplication, it doesn't matter as long as SetThreadDesktop has been called before the creation of the QApplication.

Thanks to all of you! I hope this topic will be useful for other people.

Problem

I'm working on a Qt project on Windows where i need to create a custom desktop (HDESK) using API such as CreateDesktop, OpenDesktop and SwitchDesktop. On this new Desktop, i need to show a QDialog (using exec or show depending on my needs) but the QDialog is not displayed on the new desktop but on the "default" one.

My code looks something like this :

/* Starting the QApplication from the main function */
QApplication qApp;
qApp.exec();
/* [...] An HEVENT is fired or a Win32 COM call is made telling me than i need to display the QDialog */
/* Creating the new desktop and switching to it */
HDESK hNewDesktop=NULL;

hNewDesktop=CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
SwitchDesktop(hNewDesktop);

/* Creating the QDialog and showing it */
QDialog *pqdlgMyDialog=NULL;

pqdlgMyDialog=new QDialog(NULL);
pqdlgMyDialog.show(); // or .exec() depending on the my needs

Doing this, create and display a new desktop with a black background but the QDialog is displayed on the default desktop (the one we see when we start Windows).

I have to tried to set a parent to my QDialog doing something like this but it does not work either :

QWindow *pqwParentWindow=NULL;
QWidget *pwqParentWidget=NULL;
HWND hwndParentWindow=NULL;

hwndParentWindow=GetTopWindow(NULL); // I have also tried GetDesktopWindow, FindWindowEx etc.
pqwParentWindow=QWindow::fromWinId((WId)hwndParentWindow);
pwqParentWidget=QWidget::createWindowContainer(pqwParentWindow);
[...]
QDialog *pqdlgMyDialog=NULL;
pqdlgMyDialog=new QDialog(pwqParentWidget);
pqdlgMyDialog.show(); // or .exec() depending on the my needs

If someone has an idea, i'm willing to try everything !
I have done a lot of reading of Qt Documentation and MSDN, looking for stuff such as "Is a QApplication linked to a desktop" but without success...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

闻呓 2025-02-14 08:19:21

HWND与螺纹绑定,带有HWND的线程与台式机绑在一起。

如果调用线程在其当前桌面上有任何窗口或挂钩,则SetThreadDesktop函数将失败(除非HDESKTOP参数是当前桌面的句柄)。

我不知道Qapplication是否会创建一个隐藏的窗口,或者您是否在那里有另一个HWND,但是很容易证明SetThreadDesktop如果线程上已经有一个窗口:

HDESK g_hNew;

DWORD CALLBACK TrySwitch(LPVOID Param)
{
    if (Param)
    {
        CreateWindow(L"EDIT", L"Existing window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
    }
    if (SetThreadDesktop(g_hNew))
    {
        SwitchDesktop(g_hNew);
        CreateWindow(L"EDIT", L"New window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
    }
    Sleep(3333);
    return 0;
}

void Example()
{
    HDESK hIn = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, false, DESKTOP_SWITCHDESKTOP);
    g_hNew = CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
    WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) TRUE, 0, NULL), 3333); // Leaks thread handle and I don't care
    WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) FALSE, 0, NULL), 3333); // Leaks thread handle and I don't care
    SwitchDesktop(hIn);
    CloseDesktop(hIn);
    CloseDesktop(g_hNew);
} 

HWNDs are tied to threads and threads with HWNDs are tied to desktops.

The SetThreadDesktop function will fail if the calling thread has any windows or hooks on its current desktop (unless the hDesktop parameter is a handle to the current desktop).

I don't know if QApplication creates a hidden window or if you have another HWND there but it is easy to demonstrate that SetThreadDesktop will fail if there is already a window on the thread:

HDESK g_hNew;

DWORD CALLBACK TrySwitch(LPVOID Param)
{
    if (Param)
    {
        CreateWindow(L"EDIT", L"Existing window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
    }
    if (SetThreadDesktop(g_hNew))
    {
        SwitchDesktop(g_hNew);
        CreateWindow(L"EDIT", L"New window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
    }
    Sleep(3333);
    return 0;
}

void Example()
{
    HDESK hIn = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, false, DESKTOP_SWITCHDESKTOP);
    g_hNew = CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
    WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) TRUE, 0, NULL), 3333); // Leaks thread handle and I don't care
    WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) FALSE, 0, NULL), 3333); // Leaks thread handle and I don't care
    SwitchDesktop(hIn);
    CloseDesktop(hIn);
    CloseDesktop(g_hNew);
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文