在某些特殊的應用場合,我們很想要一個類似IE功能的模組,定製自己的功能。
HTML控制項現在向我們張開了懷抱。稍稍奇怪的是,它並不完全支援WAP協議。看來,IE還是做了自己的解析。
首先,我們要註冊一下控制項。把Htmlctrl.h包含進來,調用InitHTMLControl()函數,裡面的參數為應用程式控制代碼。以下代碼在MFC中使用:
VERIFY(InitHTMLControl(AfxGetInstanceHandle()));
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
RECT rect;
GetClientRect(&rect);
m_hHtmlWnd = ::CreateWindow (DISPLAYCLASS,
NULL,
dwStyle,
rect.left,
rect.top,
rect.right,
rect.bottom,
m_hWnd,
0,
::AfxGetInstanceHandle(),
NULL);
::SetWindowLong(m_hHtmlWnd, GWL_ID, 12321);
::SetFocus(m_hHtmlWnd);
::SendMessage(m_hHtmlWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)_T(""));
在這裡,m_hHtmlWnd是某個Dialog的HWND型成員變數。
然後,在Dialog的WindowProc函數中,使用如下方法:
switch(message)
{
case WM_NOTIFY:
{
WCHAR wszURL[1000] = {0};
NM_HTMLVIEW* pnmHTMLView = (NM_HTMLVIEW*)lParam;
switch (pnmHTMLView->hdr.code)
{
case NM_HOTSPOT:
{
OutputDebugString(pnmHTMLView->szTarget);
break;
}
case NM_INLINE_IMAGE:
{
OutputDebugString(TEXT("NM_INLINE_IMAGE\r\n"));
break;
}
case NM_INLINE_SOUND:
{
OutputDebugString(TEXT("NM_INLINE_SOUND\r\n"));
break;
}
case NM_TITLE:
{
OutputDebugString(TEXT("NM_TITLE\r\n"));
break;
}
case NM_META:
{
OutputDebugString(TEXT("NM_META\r\n"));
break;
}
case NM_BASE:
{
OutputDebugString(TEXT("NM_BASE\r\n"));
break;
}
case NM_CONTEXTMENU:
{
OutputDebugString(TEXT("NM_CONTEXTMENU\r\n"));
break;
}
case NM_INLINE_XML:
{
OutputDebugString(TEXT("NM_INLINE_XML\r\n"));
break;
}
case NM_BEFORENAVIGATE:
{
OutputDebugString(TEXT("NM_BEFORENAVIGATE\r\n"));
break;
}
case NM_DOCUMENTCOMPLETE:
{
OutputDebugString(TEXT("NM_DOCUMENTCOMPLETE\r\n"));
break;
}
case NM_NAVIGATECOMPLETE:
{
OutputDebugString(TEXT("NM_NAVIGATECOMPLETE\r\n"));
break;
}
case NM_TITLECHANGE:
{
OutputDebugString(TEXT("NM_TITLECHANGE\r\n"));
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
}
}
在上面的幾個關鍵點,NM_HOTSPOT是使用者點擊了網頁連結,通過訪問pnmHTMLView->szTarget可以得到網頁內容。SendMessage可以將得到的內容賦給控制項,控制項會自己解析網頁元素。如果有圖片連結,將會觸發NM_INLINE_IMAGE動作。此時亦需要通過訪問pnmHTMLView->szTarget來得到圖片。如果得到了圖片的內容,可以使用下面的代碼來顯示:
INLINEIMAGEINFO imageInfo;
imageInfo.dwCookie = pnmHTMLView->dwCookie;
imageInfo.bOwnBitmap = FALSE;
imageInfo.hbm = hBitmap;
BITMAP mInfo;
GetObject(hBitmap, sizeof(BITMAP), (LPBYTE)&mInfo);
imageInfo.iOrigWidth = mInfo.bmWidth;
imageInfo.iOrigHeight = mInfo.bmHeight;
::SendMessage(pnmHTMLView->hdr.hwndFrom, DTM_SETIMAGE, 0, (LPARAM)(INLINEIMAGEINFO*)&imageInfo);
上面代碼中hBitmap為圖片位元影像控制代碼。
我在處理圖片的時候,遇到的問題是。使用SHLoadImageFile函數後,需使用DeleteObject函數釋放控制代碼記憶體。否則將有記憶體泄露。MSDN沒有提及這一現象。
如果未得到圖片內容,想在網頁相應的位置顯示一個叉,DTM_SETIMAGE參數應改為DTM_IMAGEFAIL。
值得注意的是,如果我們處理了NM_HOTSPOT或NM_INLINE_IMAGE訊息,需要返回TURE或FALSE,不然控制項本身會再處理一遍。
關於 NM_HTMLVIEW 結構體
typedef struct tagNM_HTMLVIEW {
NMHDR hdr;
LPSTR szTarget;
LPSTR szData;
DWORD dwCookie;
} NM_HTMLVIEW;
函數中的第一個參數是一個NMHDR類型的結構體
NMHDR Structure
Contains information about a notification message.
Syntax
|
typedef struct tagNMHDR { HWND hwndFrom; UINT_PTR idFrom; UINT code; } NMHDR; |
Members
-
hwndFrom
-
A window handle to the control sending the message.
-
idFrom
-
An identifier of the control sending the message.
-
code
-
A notification code. This member can be one of the common notification codes (see Notifications under General Control Reference), or it can be a control-specific notification code.