创建单独的 MFC GUI 线程,不能移动/调整大小/最大化 CWnd

Posted

技术标签:

【中文标题】创建单独的 MFC GUI 线程,不能移动/调整大小/最大化 CWnd【英文标题】:Creating separate MFC GUI thread, can't move/resize/maximize CWnd 【发布时间】:2016-04-26 08:20:40 【问题描述】:

我正在创建一个CWinThread,它将拥有自己的 GUI。当我在该线程上创建 CWnd 时,它会显示,但我无法移动窗口。我确信消息泵正在运行,因为我可以从另一个线程执行MoveWindow,并且窗口会移动。

UIThread.h

#pragma once

class CUIThread : public CWinThread

public:
    DECLARE_DYNCREATE(CUIThread)
    CUIThread();

    // Attributes
public:
    HWND hwnd;
    // Operations
public:
    void KillThread();

    // Overrides
    // ClassWizard generated virtual function overrides
    //AFX_VIRTUAL(CGDIThread)
    //AFX_VIRTUAL

    // Implementation
public:
    virtual ~CUIThread();

protected:
    virtual BOOL InitInstance();

    // Generated message map functions
    //AFX_MSG(CUIThread)
    // NOTE - the ClassWizard will add and remove member functions here.
    //AFX_MSG

    DECLARE_MESSAGE_MAP()
;

UIThread.cpp

#include "stdafx.h"
#include "UIThread.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CUIThread

IMPLEMENT_DYNCREATE(CUIThread, CWinThread)

BEGIN_MESSAGE_MAP(CUIThread, CWinThread)
    //AFX_MSG_MAP(CUIThread)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //AFX_MSG_MAP
END_MESSAGE_MAP()

CUIThread::CUIThread() : hwnd(NULL)

    m_bAutoDelete = FALSE;


BOOL CUIThread::InitInstance()

    this->m_pMainWnd = new CWnd;
    m_pMainWnd->Create(_T("STATIC"), _T("Hi"), WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        CRect(0, 0, 500, 500), CWnd::GetDesktopWindow(), 1234);

    this->hwnd = m_pMainWnd->GetSafeHwnd();

    return TRUE;


CUIThread::~CUIThread()




void CUIThread::KillThread()

    // Note: this function is called in the context of 
    // other threads, not the thread itself.
    this->PostThreadMessage(WM_QUIT, 0, 0);

    // allow thread to run at higher priority during 
    // kill process
    SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
    WaitForSingleObject(m_hThread, INFINITE);

main.cpp

...
CUIThread* pUIThread = static_cast< CUIThread*>(AfxBeginThread(RUNTIME_CLASS(CUIThread)));
getchar();
MoveWindow(pUIThread->hwnd, 100, 100, 500, 500, true); // works
getchar();
CloseWindow(pUIThread->hwnd); // works
getchar();
pUIThread->KillThread(); // works
delete pUIThread;
getchar();
...

我可以看到窗口,但我无法移动/最大化/调整它。

【问题讨论】:

您需要了解消息循环/消息泵的概念。你不能天真地使用getchar()。我在这里没有看到任何消息。 你的设计是错误的。任何 Windows 应用程序 (Win32/MFC) 中都应该只有一个 GUI 线程。打电话给getchar() 有什么意义? @MichaelWalz 请查看msdn.microsoft.com/de-de/library/b807sta6.aspx 并检查运行链接。 CWinThread 提供了一个默认的消息泵。 @AndrewKomiagin 我同意这个设计过于复杂,只需要一个主 GUI 线程,但你能否详细说明为什么这个设计不能工作?在我看来,Paul 创建了一个控制台应用程序并想要添加一个 GUI。关于getchar:它是在主线程中调用的。所以在我看来完全合法:它阻塞了主线程,但额外的 UI 线程应该正在运行。 我必须管理自己的线程,因为我有一个多线程/线程安全的 API,它有辅助弹出窗口,我不想被实现的线程泵处理。 【参考方案1】:

我相信您以错误的方式创建窗口。您正在创建一个以桌面为父窗口的子窗口。这应该有效:

LPCSTR strClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE);
VERIFY(m_pMainWnd->CreateEx(0, strClass, _T("title"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CRect(0, 0, 500, 500), NULL, 0));

【讨论】:

就是这样!小心解释为什么我不能使用CWnd::GetDesktopWindow()。如果我的窗口不需要用户交互,它可以安全使用吗? 子窗口没有标题栏,用户不能移动。*** Windows 可以。

以上是关于创建单独的 MFC GUI 线程,不能移动/调整大小/最大化 CWnd的主要内容,如果未能解决你的问题,请参考以下文章

使用 VS6 C++ GUI 编辑器、MFC 以屏幕(像素)为单位调整全屏窗口大小?

MFC执行线程问题

MFC:从另一个线程访问 GUI?

MFC中静态文本框获取鼠标移动到按钮上的消息

MFC主线程等待另一个线程结束

未调用 MFC 的 CWinThread::PostThreadMessage 处理程序