MFC中控件重叠的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC中控件重叠的问题相关的知识,希望对你有一定的参考价值。

比如,我先建一个列表控制框,再在这个框上面建一个按扭,这个按扭就是按扭1吧,,再在列表框外建一个按扭2, 程序开始运行的时候,让这个按扭1先隐藏, 然后当我点击按扭2时,让按扭1显示, 这时候我点击按扭1时,怎么没反应呢,要怎么样,才能响应到这个按扭1呢? 这些按扭的响应函数我都写了, 可部时,点击按扭1时,怎么鼠标点击消息没响应到它啊,况且我是显示了的!!
我是直接在建按扭时在属性里把visible去掉,然后是showwindow显示,不行,我又改成用showwindow来隐藏,同理再显示时,点击后还是不行啊

参考技术A - -。按钮关联了一个按钮类实例化的对象,通过这个对象->调用方法ShowWindow(SW_SHOW)就能出来了。还有你在列表控制框上是指覆盖在框上了还是啥》如果是覆盖在这个框上有可能会被挡住,还要把控件置顶吧
SetWindowPos
参考技术B 额 ,我正好也在学这个东西。下面是关键的代码,不是全部的,画圆和写字你自己加。这里只是演示“按钮无效”。
void CSDIDrawView::OnCircle()

// TODO: Add your command handler code here
a=1;
// Invalidate(TRUE);



void CSDIDrawView::OnUpdateCircle(CCmdUI* pCmdUI)

// TODO: Add your command update UI handler code here
if(a%2==1) pCmdUI->Enable(FALSE);
else pCmdUI->Enable(TRUE);



void CSDIDrawView::OnText()

// TODO: Add your command handler code here
a=2;
// Invalidate(TRUE);



void CSDIDrawView::OnUpdateText(CCmdUI* pCmdUI)

// TODO: Add your command update UI handler code here
if(a%2==0) pCmdUI->Enable(FALSE);
else pCmdUI->Enable(TRUE);

参考技术C 可能用到的两个函数:

1 ShowWindow()

2 SetWindowPos()

应该是空间叠加层次的问题,可以查阅SetWindowPos(),其中第一个属性设置显示的层次,如&wndTop、&wndTopMost等
参考技术D 按钮BN_CLICKED中添加this->Invaliate();
貌似还要重写一下WM_PAINT消息处理函数
第5个回答  2010-04-02 请问你是使用哪个函数来隐藏按钮的?
showwindow函数应该不会出现这种情况啊!还是你是用了EnableWindow?

在 MFC 应用程序中未调用重叠的 WSARecv() 回调

【中文标题】在 MFC 应用程序中未调用重叠的 WSARecv() 回调【英文标题】:Overlapped WSARecv() Callback Not Being Called in MFC App 【发布时间】:2011-04-30 05:40:30 【问题描述】:

我有一个 COM 组件,用 C++ 和 ATL 实现,它使用重叠的套接字 I/O。与服务器建立连接后,它立即开始对套接字进行重叠读取,代码如下:

// Pass pointer to this instance as hEvent parameter, for use by callback
m_recvOverlapped.hEvent = reinterpret_cast<HANDLE>(this);

int rc = ::WSARecv(m_s, &wsabuf, 1, &m_recvNumberOfBytes, &m_recvFlags, &m_recvOverlapped, RecvCallback);
if (rc == SOCKET_ERROR)

    // If error is WSA_IO_PENDING, then the I/O is still in progress.  Otherwise, something bad happened.
    int error = ::WSAGetLastError();
    if (error != WSA_IO_PENDING)
    
        ReceiveError(error);
    

我有一个看起来像这样的回调函数:

void CALLBACK CMySocket::RecvCallback(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)

CMySocket* socket = reinterpret_cast<CMySocket*>(lpOverlapped->hEvent);
ATLASSERT(socket != 0);
if (!socket)
    return;

socket->ReceiveCompleted(dwError, cbTransferred, lpOverlapped, dwFlags);

此 COM 组件在单元测试中、在命令行应用程序中使用时以及在 .NET GUI 应用程序中使用时(通过 COM 互操作)都可以正常工作。但是,当我在 MFC 应用程序中使用此组件时,RecvCallback 在服务器向其发送数据时永远不会被调用。

WSARecv() 返回SOCKET_ERRORWSAGetLastError() 返回WSA_IO_PENDING,正如异步重叠读取所预期的那样。

当我使用 SysInternals TcpView 应用程序观察正在发生的事情时,它表明客户端正在接收数据。但是回调永远不会被调用。

通过连接的套接字向服务器发送数据可以正常工作。

我在我的 MFC 应用程序的 InitInstance() 方法中调用 CoInitializeEx()WSAStartup()

有什么想法吗?

【问题讨论】:

【参考方案1】:

是的,确实如此。仅当线程进入“alertable”等待状态时才处理 APC - 调用 SleepExWaitForMultipleObjectsExMsgWaitForMultipleObjectsEx 函数。

我想纠正你的一点是,使用OVERLAPPEDhEvent 成员作为“用户”数据的占位符是一个坏主意。因为操作系统会在你的 I/O 完成时尝试设置这个“事件”。

将一些“用户”信息传递给回调路由的常用方法实际上是使用取代OVERLAPPED 的自定义结构,根据需要添加更多成员(又名OVERLAPPED_PLUS)。然后你的回调路由可能会将OVERLAPPED 转换为你的OVERLAPPED_PLUS,在那里你会看到所有的成员。

另外一点:由于您正在编写一个 COM 对象 - 您可能没有能力编写自己的消息循环,因此可能难以保证进入警报等待。

【讨论】:

WSARecv 的文档指出“如果 lpCompletionRoutine 不为 NULL,则 hEvent 参数将被忽略,应用程序可以使用它来将上下文信息传递给完成例程。”【参考方案2】:

好的,我通过搜索有关 WSARecv 的其他 Stack Overflow 问题找到了答案。

来自 Len Holgate 对Win32 Overlapped I/O - Completion routines or WaitForMultipleObjects? 的回答:

。 . .您可以传递一个完成例程,该例程在完成时调用。这称为“alertable I/O”,要求发出 WSARecv() 调用的线程处于“alertable”状态才能调用完成例程。线程可以通过多种方式将自己置于警报状态(调用 SleepEx() 或等待函数的各种 EX 版本等)。 . . .

事实证明,如果我在 MFC 应用程序中启动一个定期调用 SleepEx(0, TRUE) 的计时器,则会调用接收回调。所以问题是调用我的 COM 对象的方法的主 MFC 线程调用WSARecv() 永远不会自行进入警报状态。

因此,我可能需要更改我的 COM 对象的实现,以便它使用 I/O 完成端口而不是回调,或者启动它自己的线程来调用 WSARecv() 并保持自己处于警报状态。

【讨论】:

以上是关于MFC中控件重叠的问题的主要内容,如果未能解决你的问题,请参考以下文章

MFC中TAB控件的编辑

如何在 MFC 对话框中保持控件的 Z 顺序?

MFC(C++):为啥顶部的控件不接收事件?

MFC 控件添加热键

MFC中怎么把2个控件组合在一起,如图:怎么把那个圆和实线这个框组合在一起,可以一起操作

MFC 中关于Edit控件问题