2409wtl,网浏包装

2024-09-09 06:44
文章标签 包装 2409wtl 网浏

本文主要是介绍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.

这篇关于2409wtl,网浏包装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1150448

相关文章

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

2409wtl,切换视图

原文 介绍 我从一个基于SDI(单文档接口)WTL向导的应用开始,添加了一些从控件继承的窗口和一些对话框窗口(表单视图),然后才发现我必须,使SDI框架动态加载和卸载子窗口. 本文演示了两个可用来完成的技术:在SDI应用中的视图间动态切换.这是我使用的两个. 技术 1技术:第一个方法涉及按需析构和重建视图实例.这更简单,且在不介意析构和重建窗口对象时效果很好. 2:按需创建视图,然后用

C++11,可变参数模板,lambda表达式,包装器

可变参数模板 在C++11中模板也可以接收多个不定参数,就和int printf(const char *format, ...);函数一般模板也可以接收多个参数; // 可变参数模板template<class ...Args>void testArgs(Args... args){}int main(){testArgs(123, 'a', "abc",

2409wtl,打开浏览器

原文 介绍 曾经想在不破坏现有浏览器窗口内容时打开URL:方法如下,只需几秒钟. 1,首先,包含头文件: #include "url.h" 2,然后只需声明一个CURL对象并调用Open方法: CURL url;url.Open(_T("<A href="http://www.codeproject.com/">http://www.codeproject.com/</A>"))

[C++11#47] (四) function包装器 | bind 函数包装器 | 结合使用

目录 一. function包装器 1. 在题解上  2.bind 绑定 1.调整参数顺序 2.对类中函数的包装方法 一. function包装器 function包装器也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。 那么我们来看看,我们为什么需要function呢? ret = func(x);// 上面func可能是什么呢?那么func可能

包装类_Date类_日历类_File类_目录树状结构JAVA063-071

来源:http://www.bjsxt.com/ 1、S01E063_01常用类之基本数据类型的包装类(Wrapper Class) (1)Integer:MIN_VALUE,MAX_VALUE, toHexString(int):转为十六进制数 parseInt(Stirng):把字符串按十进制转为int intValue:转为int longValue:转为long (2)包装类

4、java的基本类型和包装类型

基本类型 Java 中有 8 种基本数据类型,分别为: 6 种数字类型: 4 种整数型:byte、short、int、long2 种浮点型:float、double 1 种字符类型:char1 种布尔型:boolean 包装类型 如上8种基本数据类型都有对应的包装类型,这些包装类型都是不可变的类,它们提供了基本数据类型与对象之间的转换(解决基本数据类型无法直接应用于需要对象的环境中,例如在

包装类及对象池

1、基本数据类型byte、short、int、long、char、boolean的包装类用到了对象池,大小在127以内的从对象池获取; 2、基本数据类型中float、double没有实现对象池技术; 3、java中字符串实现对象池技术; public class Test {public static void main(String[] args) {Integer i1 = 100;In

Java包装类和作用

Java是一门面向对象的语言,对基本类型的处理某些场景需要使用对应的包装类,如collections中的类型变量需要使用包装类,另外为了使用方便Java1.5后增加了基本类型和包装类型之间的自动拆箱和装箱。 另外包装类中提供了一些类型转换的方法。 int不存在null值,一经初始化,就被赋予默认值0. 但Integer是存在null值的,只做初始化而不赋值,那它就是个null。

Java 包装类作用

Java每个基本类型都有对应的包装类型与之对应 因为Java是面向对象 每个包装类型是一个class类 继承Object 可以为null 同时可以调用对应的类型方法,以满足不同需要。 基本类型作为属性如果没有初始化存在默认值,如果你不希望属性有默认值,就要使用对应的包装类型即可。