2409wtl,网浏包装

原文

介绍

本教程帮助你用IE引擎构建一个基于WTL,并使用我编写的处理IWebBrowser2接口包装类的迷你浏览器.

因为知道代码可能很难读,因此本教程帮助你逐步开发一个迷你浏览器.

背景

大部分都与互联网浏览有关.我常用超文本视图使用SDI.

有时,我要用真正的浏览器函数,因此我为IWebBrowser2编写了一个包装器.

包装类可处理在IE中嵌入的窗口.它还可非常简单处理事件沉(如:OnDocumentComplete).

创建新项

首先创建一个新的WTL项.我假设你已安装了WTL文件.在向导的第一页上,选择一个SDI应用,并勾选生成.CPP文件.

在第二页上,按超文本视图更改默认视图.

第一步是编辑stdafx.h.请包括atlmisc.h(会不时使用CString)和atlctrlx.h(CMultiPaneStatusBarCtrl).

还需要注释掉_ATL_DLL定义(不想可执行文件依赖atl.dll)并按5版本更改IE版本.

//更改这些值以使用不同版本
#define WINVER      0x0400
//`#define_WIN32_WINNT0x0400`
#define _WIN32_IE   0x0500
#define _RICHEDIT_VER   0x0100//这是在`ATL7`中`管理`浏览器所必需的
//#define _ATL_DLL#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlcom.h>
#include <atlhost.h>
#include <atlwin.h>
#include <atlctl.h>
#include <atlmisc.h>//..
#include <atlframe.h>
#include <atlctrls.h>
#include <atldlgs.h>
#include <atlctrlw.h>
#include <atlctrlx.h>//..
//`{{AFX_INSERT_LOCATION}}MicrosoftVisualC++`插入在上一行前立即其他声明.

更新视图

视图类中,需要包含browser.h,并从它继承视图类.还需要链接它到消息映射,这样该类可处理多条消息(WM_CREATE,WM_DESTROY).

#include "browser.h"
class CWTLBrowserView : public CWindowImpl<CWTLBrowserView, CAxWindow>,public CWebBrowser2<CWTLBrowserView>//..
{
public:DECLARE_WND_SUPERCLASS(NULL, CAxWindow::GetWndClassName())BOOL PreTranslateMessage(MSG* pMsg);BEGIN_MSG_MAP(CWTLBrowserView)CHAIN_MSG_MAP(CWebBrowser2<CWTLBrowserView>)//..END_MSG_MAP()//处理器原型(如果需要,请取消注释参数):`LRESULTMessageHandler(UINT/*uMsg*/,WPARAM/*wParam*/,LPARAM/*lParam*/,BOOL&/*bHandled*/)LRESULTCommandHandler(WORD/*wNotifyCode*/,WORD/*wID*/,HWND/*hWndCtl*/,BOOL&/*bHandled*/)LRESULTNotifyHandler(int/*idCtrl*/,LPNMHDR/*pnmh*/,BOOL&/*bHandled*/)`
};

创建菜单

要在菜单中添加一些新项.典型的浏览器处理back,forward,home,stop(后退,前进,主页,停止)刷新.在菜单和工具栏添加这些命令.

因为有时禁止使用某些项,因此需要处理它们的UI(不能总是使用后退和前进).首先,要在UI更新映射中(在mainfrm.h中)添加它们.

UPDATE_ELEMENT(ID_VIEW_GOTO_BACK, UPDUI_MENUPOPUP|UPDUI_TOOLBAR)
UPDATE_ELEMENT(ID_VIEW_GOTO_FORWARD, UPDUI_MENUPOPUP|UPDUI_TOOLBAR)

通过OnIdle函数更新它们.

UIEnable(ID_VIEW_GOTO_BACK,m_view.CanBack());
UIEnable(ID_VIEW_GOTO_FORWARD,m_view.CanForward());

CWebBrowser2公开了2个函数(CanBackCanForward),可确定后退和前进动作的状态.

因为默认向导microsoft.com启动,因此需要将按about:blank更改代码,并从正常主页开始.需要更改CMainFrame::OnCreate中的代码.

m_hWndClient = m_view.Create(m_hWnd, rcDefault,_T("about:blank"),WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |WS_HSCROLL | WS_VSCROLL, WS_EX_CLIENTEDGE);
.
.
.
m_view.GoHome();
return 0;

创建地址栏

现在有个工作帧,但仍无法在那里输入URL!为此,创建一个用户可输入URL浏览的地址栏.给主框架添加新的叫m_URL(CEdit)成员变量.

CMainFrame::OnCreate创建并初化它.因为还想地址栏自动补全,因此在编辑控件上使用了SHAutoComplete函数.

CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
AddSimpleReBarBand(hWndCmdBar);
AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
CString szAddress;//<<
szAddress.LoadString(IDS_ADDRESS);
m_URL.Create(m_hWnd,CRect(0,0,0,18),NULL,WS_CHILD|WS_VISIBLE,WS_EX_STATICEDGE);
AddSimpleReBarBand(m_URL,szAddress.GetBuffer(0),TRUE);
m_URL.SetFont(AtlGetDefaultGuiFont());
SHAutoComplete(m_URL,SHACF_URLALL);//>>CreateSimpleStatusBar();

如果试编译项,则在链接文件时会出现错误.出现此错误的原因是SHAutoComplete是从shlwapi.dll导出的.要解决它,需要链接(shlwapi.lib)库.

编译项后,看到新的编辑栏等待输入.但是,嘿!如果试按回车键,浏览器只会一直休息!来修复它!

浏览

因为超文本框架把所有键击转发超文本文档,因此不能只等待WM_CHAR消息.需要在预翻译消息函数中添加一些代码.

需要从地址栏中取WM_CHAR消息并处理VK_RETURN符.

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))return TRUE;if (pMsg->message==WM_CHAR && m_URL==pMsg->hwnd){switch (pMsg->wParam){case VK_RETURN:{CString szURL;int nLength=m_URL.GetWindowTextLength();m_URL.GetWindowText(szURL.GetBuffer(nLength),nLength+1);szURL.ReleaseBuffer();m_view.Navigate(szURL);return TRUE;}}return FALSE;}return m_view.PreTranslateMessage(pMsg);
}

命令

现在,可输入URL并浏览它,来观察浏览器.但仍缺少.不可使用back,forward其他新命令?在主框架类中需要添加它们的函数.

调整UI

测试一下浏览器.试转到http://www.codeproject.com/并点击WTL部分.为什么在地址栏中看不到新位置,要修复它,需要在每次更改位置更新地址栏.

一个好地方是处理视图类中的OnNavigateComplete2.因为需要更新,在主框架类中保存的m_URL,因此在视图类中创建它的新引用,并给构造器传递变量.
现在,可处理消息更新地址栏.

void CWTLBrowserView::OnNavigateComplete2(IDispatch* pDisp, const String& szURL)
{m_URL.SetWindowText(GetLocationURL());
}

另一个有用调整包括进度通知,安全图标状态栏文本.它们都在状态栏上.该推出CMultiPaneStatusBarCtrl!

主框架类中创建一个新变量,并在视图类中创建一个引用.状态栏应包含3个部分:默认文本,安全图标和进度通知.

因为默认文本有唯一的ID(ID_DEFAULT_PANE),因此只需要创建另外两个标识.在"View->ResourceSymbols"菜单中,需要创建新符号:IDR_LOCKIDR_PROGRESS.

创建它们后,可从CMainFrame::OnCreate函数初化新状态栏.

CreateSimpleStatusBar();
m_StatusBar.SubclassWindow(m_hWndStatusBar);
int nPanes[]={ID_DEFAULT_PANE,IDR_LOCK,IDR_PROGRESS};
m_StatusBar.SetPanes(nPanes,sizeof(nPanes)/sizeof(int),false);
m_StatusBar.SetPaneWidth(IDR_LOCK,30);
m_StatusBar.SetPaneWidth(IDR_PROGRESS,50);

还需要给项添加新(IDI_LOCK)图标,并在(m_hSecured)变量中加载它.为了正确更新UI,在UI更新映射中添加一行新行:

UPDATE_ELEMENT(0, UPDUI_STATUSBAR)

视图类中,添加一个新的(m_bSecured)变量和一些代码来处理更新状态栏:

void CWTLBrowserView::OnStatusTextChange(const String& szText)
{m_StatusBar.SetPaneText(ID_DEFAULT_PANE,szText);
}
void CWTLBrowserView::OnProgressChange(long nProgress, long nProgressMax)
{CString szText;if (nProgressMax>0)szText.Format(_T("%d%%"),nProgress*100/nProgressMax);m_StatusBar.SetPaneText(IDR_PROGRESS,szText);
}
void CWTLBrowserView::OnSetSecureLockIcon(long nSecureLockIcon)
{m_bSecured=nSecureLockIcon>0;
}

最后,需要给CMainFrame::OnIdle添加一些代码:

m_StatusBar.SetPaneIcon(IDR_LOCK,m_view.IsSecured()? m_hSecured : NULL);
UIUpdateToolBar();
UIUpdateStatusBar();
return FALSE;

文件命令

要允许浏览器保存和打印文件,需要处理文件消息.要给浏览器发送命令,要用ExecWB函数.要(对UI映射)查询命令状态,可用QueryStatusWB函数.

为了保存/打印,需要添加适当的函数,更新UI更新映射,并在OnIdle函数处理它们的UI.

编辑命令

编辑命令是一个特例.因为可与浏览器地址栏一起使用,因此需要在每次使用这些命令时检查焦点窗口.
首先,在UI更新映射中添加它们,然后通过OnIdle函数处理更新:

if (GetFocus()==m_URL)
{DWORD dwSelection=m_URL.GetSel();BOOL bEnable=HIWORD(dwSelection)!=LOWORD(dwSelection);UIEnable(ID_EDIT_CUT,bEnable);UIEnable(ID_EDIT_COPY,bEnable);if (m_URL.OpenClipboard()){UIEnable(ID_EDIT_PASTE,IsClipboardFormatAvailable(CF_TEXT));CloseClipboard();}elseUIEnable(ID_EDIT_PASTE,FALSE);UIEnable(ID_EDIT_UNDO,m_URL.CanUndo());
}
else
{UIEnable(ID_EDIT_CUT,m_view.QueryStatusWB(OLECMDID_CUT) & OLECMDF_ENABLED);UIEnable(ID_EDIT_COPY,m_view.QueryStatusWB(OLECMDID_COPY) & OLECMDF_ENABLED);UIEnable(ID_EDIT_PASTE,m_view.QueryStatusWB(OLECMDID_PASTE) & OLECMDF_ENABLED);UIEnable(ID_EDIT_UNDO,m_view.QueryStatusWB(OLECMDID_UNDO) & OLECMDF_ENABLED);
}

还需要在执行实际命令区分它们:

LRESULT CMainFrame::OnEditCut(WORD /*`wNotifyCode`*/, WORD /*`wID`*/, HWND /*`hWndCtl`*/, BOOL& /*b已处理*/)
{if (GetFocus()==m_URL)m_URL.Cut();elsem_view.ExecWB(OLECMDID_CUT,OLECMDEXECOPT_DONTPROMPTUSER,NULL,NULL);return 0;
}
LRESULT CMainFrame::OnEditCopy(WORD /*`wNotifyCode`*/, WORD /*`wID`*/, HWND /*`hWndCtl`*/, BOOL& /*b已处理*/)
{if (GetFocus()==m_URL)m_URL.Copy();elsem_view.ExecWB(OLECMDID_COPY,OLECMDEXECOPT_DONTPROMPTUSER,NULL,NULL);return 0;
}
LRESULT CMainFrame::OnEditPaste(WORD /*`wNotifyCode`*/, WORD /*`wID`*/, HWND /*`hWndCtl`*/, BOOL& /*b已处理*/)
{if (GetFocus()==m_URL)m_URL.Paste();elsem_view.ExecWB(OLECMDID_PASTE,OLECMDEXECOPT_DONTPROMPTUSER,NULL,NULL);return 0;
}
LRESULT CMainFrame::OnEditUndo(WORD /*`wNotifyCode`*/, WORD /*`wID`*/, HWND /*`hWndCtl`*/, BOOL& /* b已处理*/)
{if (GetFocus()==m_URL)m_URL.Undo();elsem_view.ExecWB(OLECMDID_UNDO,OLECMDEXECOPT_DONTPROMPTUSER,NULL,NULL);return 0;
}

见,wtlbrowser_demo.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/53769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创意无限:五款AI绘画应用,让艺术创作更简单

随着人工智能技术的不断进步&#xff0c;AI绘画已经成为一个不可忽视的现象。在短视频平台上&#xff0c;用户只需轻触屏幕&#xff0c;就能生成风格各异的画作&#xff0c;这种一键生成的特效迅速吸引了大量关注。AI绘画技术的快速发展&#xff0c;不仅让艺术创作变得更加便捷…

国产化数据库挑战及发展趋势

非国产数据库如Oracle、MySQL和MSSQL等在某些领域占据重要地位&#xff0c;但国产数据库的市场份额正在逐步提升&#xff0c;特别是在政策支持和市场需求的双重推动下&#xff0c;国产数据库的替代进程正在加速。 一、国产数据库市场规模 2024年中国数据库市场规模预计为543.1亿…

Python 数学建模——灰色关联度分析

文章目录 介绍原理代码实例 介绍 灰色关联度分析&#xff0c;可以反映两个序列 X ( k ) X(k) X(k) 和 Y ( k ) Y(k) Y(k) 之间的联系&#xff0c;用 r r r 表征。然而&#xff0c; r r r 的绝对大小并没有过多的意义&#xff0c;它的意义只在不同的 r r r 进行比较时体现。…

Java设计模式【命令模式】-行为型

1. 介绍 命令模式&#xff08;Command Pattern&#xff09; 是一种行为型设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而使我们可以用不同的请求对客户端进行参数化&#xff0c;并且支持请求的排队、记录日志以及撤销、重做等功能。命令模式将请求的发送者与…

微信小程序路由跳转之间的区别

navigateTo&#xff1a; 功能描述&#xff1a; navigateTo用于保留当前页面&#xff0c;跳转到应用内的某个页面。但是不能跳到 tabbar 页面。 页面栈变化&#xff1a; 当使用navigateTo进行页面跳转时&#xff0c;当前页面会被推入页面栈中&#xff0c;但不会被销毁&#xff0…

掌握Go语言中的时间与日期操作

Go语言中的时间与日期操作 在编写程序时&#xff0c;处理时间和日期看似是一项无关紧要的任务&#xff0c;但在需要同步多个任务或从文本文件中读取时间时&#xff0c;它的重要性便凸显出来。Go语言中的time包为我们提供了丰富的时间与日期操作功能。本文将详细介绍如何在Go语…

C语言蓝桥杯:语言基础

竞赛常用库函数 最值查询 min_element和max_element在vector(迭代器的使用) nth_element函数的使用 例题lanqiao OJ 497成绩分析 第一种用min_element和max_element函数的写法 第二种用min和max的写法 二分查找 二分查找只能对数组操作 binary_search函数&#xff0c;用于查找…

提升效率必备,掌握这些Shell文本处理技能!

Shell脚本是Linux系统里的一项基本功&#xff0c;就算它的语法看起来有点奇怪&#xff0c;读起来也不是特别顺畅&#xff0c;但在一些情况下&#xff0c;它仍然是最能干的解决办法。学好Shell脚本&#xff0c;不仅让你对Linux系统了解更深&#xff0c;还能让你手快地做好很多日…

python的特性,以及和Java的区别

两者各有各的魅力&#xff0c;像是编程语言界的两个明星选手。咱们先看看Python的几个重要特性&#xff0c;然后来个友好对比&#xff0c;看看Java和Python在哪些方面有“性格差异”吧&#xff01; Python的主要特性 简洁易读&#xff1a; Python最出名的就是它的简洁性&#…

使用程序方式获取与处理MySQL表数据

8.1  执行多条语句获取 MySQL 表数据 8.1.1  MySQL 中的常量 8.1.2  MySQL 中的变量 1&#xff0e;用户变量 用户可以在表达式中使用自己定义的变量&#xff0c;这样的变量称为用户变量。 用户变量在使用前必须定义和初始化&#xff0c;如果使用没有初始化的变量&#x…

Python判断两张图片的相似度

在Python中&#xff0c;判断两张以numpy的ndarray格式存储的图片的相似度&#xff0c;通常可以通过多种方法来实现&#xff0c;包括但不限于直方图比较、像素差比较、结构相似性指数&#xff08;SSIM&#xff09;、特征匹配等。以下是一些常见方法的简要介绍和示例代码。 1. 像…

TypeScript系列:续篇 - 对象类型(含数组、元数组、函数)

在 TypeScript 中&#xff0c;对象类型用于定义对象的形状&#xff08;shape&#xff09;&#xff0c;即对象包含哪些属性以及这些属性的类型。 对象类型可以是具体的&#xff0c;也可以是抽象的&#xff0c;用于类型检查和类型推断。 对象类型的最基本形式&#xff1a;接口&…

数据库视图和索引

参考链接&#xff1a; 数据库的视图和索引的概念和区别_索引和视图的区别-CSDN博客 MySQL 数据库--索引&#xff08;理论详解及实例演示&#xff09;_数据库索引-CSDN博客 1.视图 视图是从一个或多个表中导出来的表&#xff0c;是一种不是一种真正存在的概念。这样&#xf…

CUDA int128相乘是怎么实现的

CUDA int128相乘是怎么实现的 一.指令对应关系1.cuda C代码2.PTX代码[二个int64]3.SASS指令[多个u32] 二.复现过程 CUDA int128相乘是怎么实现的 一.指令对应关系 1.cuda C代码 clock_t t0clock64(); __prof_trigger(0); int128_t r4r2*r3; //二个int128_t相加 __prof_trig…

Android Glide:让图片加载从未如此简单

在 Android 开发中,图片加载一直是一个关键环节。无论是从网络还是本地加载图片,都需要考虑到性能、内存管理和用户体验等多个方面。而在这方面,Glide 成为了众多开发者的首选库之一。本文将带你深入了解 Glide 的强大之处,并介绍如何在项目中快速集成和使用 Glide。 为什…

外包干了三年,快要废了。。。

先简单说一下自己的情况&#xff0c;普通本科&#xff0c;在外包干了3年多的功能测试&#xff0c;这几年因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不能够在这样蹉跎下去了&#xff0c;长时间呆在一个舒适的环境真的会…

算法刷题:300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

300. 最长递增子序列 1.dp定义&#xff1a;dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度 2.递推公式&#xff1a;if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1); 注意这里不是要dp[i] 与 dp[j] 1进行比较&#xff0c;而是我们要取dp[j] 1的最大值…

JAVA 的excel数据批量导入解析 现在都用什么API工具 Apache POI 、EasyExcel 、easypoi有什么区别

&#x1f4dd;个人主页&#x1f339;&#xff1a;个人主页 ⏩收录专栏⏪&#xff1a;SpringBoot &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339;&#xff0c;让我们共同进步&#xff01; 在Java中&#xff0c;处理Excel数据批量导入解析时&#xff0c;常…

高空抛物检测算法的应用场景解析

高空抛物事件频发&#xff0c;对公众安全构成严重威胁。无论是居民区还是商业中心&#xff0c;从高层建筑中丢弃物品都可能导致人员伤亡和财产损失。传统的监控手段多以事后追溯为主&#xff0c;无法在事发时及时预警和干预。为应对这一难题&#xff0c;视觉分析技术的发展为高…

全国历年高考真题2008-2024

目录 分享链接&#xff1a; ⬇️⬇️⬇️ 点击下载