获得Win32窗口句柄的更好的方法
2010-06-29 20:42:26 来源:WEB开发网下面我们一步一步来分析实现过程,首先必须获取 IHTMLDocument2 接口:
SPIHTMLDocument2 doc = GetHtmlDocument();
SPIHTMLDocument2 与 CComQIPtr<IHTMLDocument2> 一样是一个指向 IHTMLDocument2 的ATL智能指针,(当今 Windows 编程已进入 COM 时代,作为一名编写 Windows 应用程序的开发人员,如果你使用 COM 技术,但没有用过智能指针,那么这段代码会对你有所裨益),接着,必须创建一个SAFEARRAY,以便存放作为 BSTR 数组唯一元素的 HTML 串,SAFEARRAY是一个 COM 数据结构,其作用是在不同平台之间安全地传递数组数据,ATL提供了 CComBSTR 和 CComSafeArray 两个类,为开发人员在处理 BSTRs 和安全数组时减轻了许多痛苦:
// strHTML is LPCTSTR
CComSafeArray<VARIANT> sar;
sar.Create(1,0);
sar[0] = CComBSTR(strHTML);
如果不借助于 CComSafeArray 和 CComBSTR,而是用下列这些 API 函数来实现相同的处理,如 SafeArrayCreateVector,SafeArrayAccessData, 和 SafeArrayUnaccessData,那么至少还得写10-20行无聊的代码。一旦你上手了智能指针,你会觉得ATL的这些东西用起来真的很爽。
现在有了文档对象以及在安全数组中的内容,接下来便可以打开文档,进行写入操作,关闭文档等等。IHTMLDocument2::write需要 VARIANTS 和 BSTRs 类型的数据,这里ATL又一次显示了它的优势:
LPDISPATCH lpdRet;
doc->open(CComBSTR("text/html"), // MIME type
CComVariant(CComBSTR("_self")), // open in same window
CComVariant(CComBSTR("")), // no features
CComVariant((bool)1), // replace history entry
&lpdRet)); // IDispatch returned
doc->write(sar); // write it
doc->close(); // close
lpdRet->Release();
CHtmlCtrl::SetHTML 非常好用。使用它时有一个技巧:当第一次创建 CHtmlCtrl 时,它没有文档(GetHtmlDocument返回NULL)。所以在调用 CHtmlCtrl::SetHTML 之前,你必须创建一个文档,最简单的方法就是打开一个空文档,就象下面这样:
m_wndView.Navigate(_T("about:blank"));
此外,如果HTML很简单,你可以用 about: 代替 CHtmlCtrl::SetHTML 来得到HTML,如下面的代码:
m_wndView.Navigate(_T("about:<HTML><B>hello, world</B></HTML>"));
针对简单的HTML可以这么做,如果比较复杂的文档则要调用 SetHTML。本文附带的例子程序动态构造了一个包含图像、表格、链接等元素的HTML文档, 该文档列出所有顶层窗口的信息,然后将它们显示出来,如图一所示。
例子程序的参考代码如下:
//////////////////////////////////////
// HtmlApp.cpp
class CMyApp : public CWinApp {
public:
virtual BOOL InitInstance();
protected:
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
} theApp;
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
END_MESSAGE_MAP()
BOOL CMyApp::InitInstance()
{
// Create main frame window (don''t use doc/view stuff)
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
m_pMainWnd = pMainFrame;
return TRUE;
}
//////////////////////////////////////////////////////
// “关于”对话框使用 HTML 控制显示内容.
//
class CAboutDialog : public CDialog {
protected:
CHtmlCtrl m_page; // HTML control
virtual BOOL OnInitDialog();
public:
CAboutDialog() : CDialog(IDD_ABOUTBOX, NULL) { }
DECLARE_DYNAMIC(CAboutDialog)
};
IMPLEMENT_DYNAMIC(CAboutDialog, CDialog)
///////////////////////
// 初始化“关于”对话框
//
BOOL CAboutDialog::OnInitDialog()
{
// cmd map for CHtmlCtrl handles "app:ok"
static HTMLCMDMAP AboutCmds[] = {
{ _T("ok"), IDOK },
{ NULL, 0 },
};
VERIFY(CDialog::OnInitDialog());
VERIFY(m_page.CreateFromStatic(IDC_HTMLVIEW, this)); // create HTML
// ctrl
m_page.SetHideContextMenu(TRUE); // hide context
// menu
m_page.SetCmdMap(AboutCmds); // set command
// table
m_page.LoadFromResource(_T("about.htm")); // load HTML from
// resource
return TRUE;
}
/////////////////////
// 运行“关于”对话框
void CMyApp::OnAppAbout()
{
static CAboutDialog dlg; // static to remember state of hyperlinks
dlg.DoModal(); // run it
}
////////////////////////////////////////////////////////////////
// MainFrm.h
// 典型的主框架处理例程......
class CMainFrame : public CFrameWnd {
public:
CMainFrame(){ }
virtual ~CMainFrame() { }
protected:
CHtmlCtrl m_wndView; // CHtmlCtrl 作为主窗口视图
CStatusBar m_wndStatusBar; // status line
CToolBar m_wndToolBar; // toolbar
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint pos);
// helper to format main window HTML
CString FormatWindowListHTML();
DECLARE_DYNCREATE(CMainFrame)
DECLARE_MESSAGE_MAP()
};
////////////////////////////////////////////////////////////////
// MainFrm.cpp
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
// Commmand map for app: commands in main window HTML.
HTMLCMDMAP MyHtmlCmds[] = {
{ _T("about"), ID_APP_ABOUT },
{ _T("exit"), ID_APP_EXIT },
{ NULL, 0 },
};
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
VERIFY(CFrameWnd::OnCreate(lpCreateStruct)==0);
...
// create/init html control as view
VERIFY(m_wndView.Create(CRect(), this, AFX_IDW_PANE_FIRST));
m_wndView.SetHideContextMenu(TRUE); // 隐藏上下文菜单
m_wndView.SetCmdMap(MyHtmlCmds); // 设置命令
m_wndView.Navigate(_T("about:blank")); // 创建文档
m_wndView.SetHTML(FormatWindowListHTML()); // 设置获取的HTML内容串
SetActiveView(&m_wndView); // 设置MFC活动视图
return 0;
}
///////////////////////////////////////////////////////////////////
// 处理上下文菜单的命令函数,当前该函数只是显示TRACE信息,以示被调用过。
//
void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint pos)
{
TRACE(_T("CMainFrame::OnContextMenu\n"));
}
//////////////////////////////////////////////////////////////////////
// 这个函数创建在主窗口视图中显示的 HTML。
// EnumWindows 回调该函数:如果窗口可见,则将窗口信息添加到 HTML table中。
//
static BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lp)
{
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
if (style & WS_VISIBLE) {
CString& s = *(CString*)lp;
char cname[256];
GetClassName(hwnd, cname, sizeof(cname));
TCHAR text[1024];
GetWindowText(hwnd, text, sizeof(text)/sizeof(text[0]));
CString temp;
temp.Format(_T("<TR><TD>%p </TD><TD>%s</TD><TD>%s</TD></TR>\n"),
hwnd, cname, text);
s += temp;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
// 该函数创建一个文本串,这个串就是要显示在主窗口的 HTML 文档。
CString CMainFrame::FormatWindowListHTML()
{
// start w/top matter
CString html = _T("<HTML><BODY STYLE=\"font-family:Verdana;\" \
link=\"#02B7B7\" vlink=\"#02B7B7\">\n\
<TABLE WIDTH=\"100%\">\n\
<TR><TD VALIGN=top><A target=\"new\" HREF=\"http://www.vckbase.com\"><IMG \
BORDER=0 ALT=\"VCKBASE Online Journal\" SRC=http://www.bianceng.cn/"res://AboutHtml3.exe/mlogo.gif\"></A></TD>\
<TD COLSPAN=2><B>AboutHtml3 例子程序 -- 顶层可见窗口清单</B><BR>\n\
<SMALL><A target=\"new\" \
HREF=\"http://www.vckbase.com\"> VC知识库 </A></SMALL></TD></TR>\n\
<TR><TD><B>窗口句柄(hwnd)</B></TD><TD><B>窗口类名</B></TD><TD WIDTH=75%><B>窗口标题</B>\
</TD><TR>\n");
// enumerate top-level windows to append their info
EnumWindows(MyEnumWindowsProc, (LPARAM)&html);
// append bottom matter. note commands app:about and app:exit
html += _T("</TABLE>\n\
<P><B>[<A HREF=\"app:about\">关于</A>] \
[<A HREF=\"app:exit\">退出</A>]</B>\n\
</BODY>\n\
</HTML>");
return html;
}
更多精彩
赞助商链接