Windows MFC 全局模态 实现

本文由 @lonelyrains 出品,转载请注明出处。 
文章链接: http://blog.csdn.net/lonelyrains/article/details/39159671


windows本身没有提供针对整个桌面全局模态对话框的实现方式,需要自己实现。

两种方法:

1、弹出一个全屏幕透明的对话框,再在它的基础上弹出模态框

2、当鼠标在弹出框外时,禁用键盘、鼠标所有功能


第一种不好的是可能有闪一下的效果,影响体验;而且还要让需要模态的框在它上面,还要考虑到这个窗口的释放。

第二种相对来说较方便,但是需要多一个动态库来实现全局钩子。


笔者只实现了第二种方法。


实现方法:

// 用此函数判断是否在内,以决定是否使能鼠标
BOOL CMFC_MouseMoveTest2Dlg::IsInWindow()
{
	CPoint curPoint;
	::GetCursorPos(&curPoint);
	
	CRect wndRect;
	this->GetWindowRect(wndRect);
	
	if ( curPoint.x < wndRect.right && curPoint.x > wndRect.left && curPoint.y < wndRect.bottom && curPoint.y > wndRect.top )
	{
		return TRUE;
	}
	return FALSE;
}
新建一个定时器,在定时器内调用动态库里的钩子:

void CMFC_MouseMoveTest2Dlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	SetHook(!IsInWindow());
	
	CDialog::OnTimer(nIDEvent);
}
钩子的代码:

#include <windows.h>
#include <stdio.h>
#define MYAPI extern "C" _declspec(dllexport)  //导出函数声明,extern "C"要放在最前面
HHOOK hHook = NULL;

LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam)
{
	if (code >= 0)
		return 1;                              //消息不再传递个下一个HOOK子程,也不会再发送给目的窗口
	else
		return CallNextHookEx(hHook, HC_ACTION, wParam, lParam);
}

MYAPI int SetHook(BOOL bHook)
{
	if( TRUE == bHook )
	{
		if( NULL == hHook)
		{
			hHook = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandleA("G_Hook_Dll.dll"), 0);
			if (NULL == hHook)
			{
				return -1;
			}
		}
	}
	else
	{
		if(hHook)
		{
			if (UnhookWindowsHookEx(hHook) == FALSE)
			{
				return -1;
			}
			else
			{
				hHook = NULL;
			}
		}
	}
	return 0;
}

示例工程源码


你可能感兴趣的:(mfc,钩子,模态)