在学会了 利用CHtmlView 在MFC对话框上显示网页,并支持JavaScript 和 MFC 之间的互相通信后。 当然就想: 我们为什么不能只用HTML 作为前端界面, 而底层用MFC实现逻辑呢? 这样就完全不需要用到MFC对话框的界面风格了。
本文就讲告诉大家如何实现 用HTML代替MFC的对话框界面。
首先解决的问题为: 如何使MFC对话框完全被HTML界面覆盖?
答案就在窗口风格设置上。
首先我们消除对话框上方的系统菜单栏:ModifyStyle(WS_CAPTION , 0);
这里有必要解释下ModifyStyle函数。
BOOL ModifyStyle(
DWORD dwRemove,
DWORD dwAdd,
UINT nFlags = 0
);
dwRemove指定在样式修改时要移除的窗口样式。 dwAdd 指定在样式修改时要添加的窗口样式。
ModifyStyle(WS_CAPTION , 0);相当于将WS_CAPTION 风格移除。 此风格为:对话框上方的系统菜单栏,包含了对话框的名称、关闭、最大化、最小化等按钮。
我们只需要上述设置,就可以移除整个系统菜单栏。
这里注意到:系统菜单框 会占据 对话框客户区一定区域,具体为宽度 15,高度 20。
而我们的html界面的宽度为962, 高度632, 所以如果在有菜单栏的风格中,要想将html全面显示,则对话框宽度,高度至少应设置为977, 652.
消除系统菜单栏后,再用ModifyStyleEx( WS_EX_DLGMODALFRAME, 0) 消除对话框四边的双边,即上图的红色标记部分。
消除后如图:
这双边去除后,可以看到界面上多余了一部分对话框,这是就需要我们设置对话框框的大小,刚好为html界面大小。
如下图,这样就将html完全覆盖了对话框界面。
但是仅仅这样做时,我们发现在将界面最小化后再次弹出时,界面会出现闪烁。我分析闪烁的根本原因为:MFC对话框要先绘制背景,然后再绘制html,这样就会出现闪烁。
故,利用windows分层窗口( LayeredWindows)来将背景对话框透明化,这样就能避免闪烁了。
具体的步骤如下:
一:设置窗口风格为分层窗口(WS_EX_LAYERED):
有两种方法可以设置窗口属性:
方法一:
ModifyStyleEx(0,WS_EX_LAYERED); //设置窗口扩展风格为:分层窗口
方法二:
SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_LAYERED);
当设置了窗口风格为分层窗口后, 如果你未调用SetLayeredWindowAttributes或UpdateLayeredWindow为其设置透明情况,那么默认将为全透明,不会弹出任何窗口。
二:设置背景透明属性
::SetLayeredWindowAttributes(GetSafeHwnd(),RGB(255, 0, 255), 255,LWA_COLORKEY); //将背景颜色为RGB(255, 0, 255)透明化
或:
this->SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY );//将背景颜色为RGB(255, 0, 255)透明化
三:设置对话框背景颜色
在SetLayeredWindowAttributes中,有一项为设置透明颜色, 表示在绘制对话框背景时,如果为透明颜色,则让其透明。 这就需要我们在背景绘制时,将其绘制为透明颜色,使其透明。
设置对话框背景的方式:
在OnPaint函数中:
voidCMFCHtmlTest1Dlg::OnPaint()
{
if (IsIconic())
{
。。。
}
else
{
CPaintDCdc(this);
RECTrect;
GetClientRect(&rect);
dc.FillSolidRect(&rect,RGB(255, 0, 255)); //设置对话框背景颜色
CDialogEx::OnPaint();
}
}
未透明 和 透明窗口 效果如图:
最终这些设置我都在OnInitDialog()完成:
BOOLCMFCHtmlTest1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
//将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) ==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu*pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu !=NULL)
{
BOOLbNameValid;
CStringstrAboutMenu;
bNameValid =strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon,TRUE); // 设置大图标
SetIcon(m_hIcon,FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
ModifyStyle(WS_CAPTION , 0); //移除对话框 上方的系统菜单栏
ModifyStyleEx(WS_EX_DLGMODALFRAME, 0);//分层窗口,并且不在任务栏里显示,不带双边
SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_LAYERED);
CRectrtDesk;
GetWindowRect(rtDesk);
MoveWindow(rtDesk.left,rtDesk.top,width, height);
this->SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY );
m_HtmlView.CreateFromStatic(IDC_STATIC1,this); //加载html
returnTRUE; // 除非将焦点设置到控件,否则返回 TRUE
}