环境:VS2005 C# XP小弟以webbrowser控件为基础做一个多页面网页流览器,页面切换时会有相对明显的闪烁。经goole,网上找到这么一篇资料:Web Browser控件和CHtmlView有什么具体应用我也不废话了,咱们开门见山吧。通常使用上述两个东西的时候会发现切换的时候有很严重的闪烁。仔细观察你会发现,比方在ChtmlView中,窗口的绘画过程是:先画View的背景,然后在上层画控件(即网页)解决办法很简单,禁止View进行那无用的导致闪烁的绘制背景过程。具体做法 :在派生类里处理WM_ERASEBKGND消息BOOL CMyHtmlView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
// return CHtmlView::OnEraseBkgnd(pDC);
}通过上面的改动以后,你会发现VIEW会跟腾讯的QQ浏览器一样无闪烁:)Web Browser控件的相应做法类似,不再详述于是在Webbrowser控件里重写WndProc方法,截获该消息,但没有效果。重写OnPaintBackground,让它啥也不干,照样没效果。忽然想到Webbrowser不过是对底层axwebbrowser控件的封装,于是改用底层的axwebbrowser,还是重写WndProc和OnPaintBackground,结果令人大失所望,页面切换时闪烁依旧。请问有什么好的办法吗?
{
return TRUE;
// return CHtmlView::OnEraseBkgnd(pDC);
}通过上面的改动以后,你会发现VIEW会跟腾讯的QQ浏览器一样无闪烁:)Web Browser控件的相应做法类似,不再详述于是在Webbrowser控件里重写WndProc方法,截获该消息,但没有效果。重写OnPaintBackground,让它啥也不干,照样没效果。忽然想到Webbrowser不过是对底层axwebbrowser控件的封装,于是改用底层的axwebbrowser,还是重写WndProc和OnPaintBackground,结果令人大失所望,页面切换时闪烁依旧。请问有什么好的办法吗?
构造函数中添加DocumentCompleted事件响应相关代码:
[DllImport("user32.dll")]
protected static extern int GetWindowLong(int hwindow, int unindex);
[DllImport("user32.dll")]
protected static extern int CallWindowProc(int lpPrevWndFunc, int hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
protected static extern int SetWindowLong(int hwindow, int unindex, CallWindowProcDelegate lnewvalue);
public static int oldWindow = 0;
public const int GWL_WNDPROC = -4;
public delegate int CallWindowProcDelegate(int Wnd, int Msg, int WParam, int LParam);
public CallWindowProcDelegate MyCallWindowProc; bool add = false; void ExtendWebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if(add)
{ return; } add = true;
FindWindow fw = new FindWindow(this.Handle, "Internet Explorer_Server");
IntPtr hIE = fw.FoundHandle; if (hIE.ToInt32() != 0)
{
oldWindow = (int)GetWindowLong(hIE.ToInt32(), GWL_WNDPROC);
MyCallWindowProc = new CallWindowProcDelegate(WndProc);
SetWindowLong(hIE.ToInt32(), GWL_WNDPROC, MyCallWindowProc);
}
} private int WndProc(int Wnd, int Msg, int WParam, int LParam)
{
const int WM_ERASEBKGND = 0x14; if (Msg == WM_ERASEBKGND)
{
return 1;
} return CallWindowProc(oldWindow, Wnd, Msg, WParam, LParam);
} /**/
/// <summary>
/// This class is to find the given window's child window accroding to the given child window's name.
/// The useage: FindWindow fw = new FindWindow(wndHandle, "ChildwndClassName"); IntPtr ip = fw.FoundHandle;
/// I adapt the code from Paul DiLascia,who is the MSDN Magazine's writer.
/// The original class is named CFindWnd which is written in C++, and you could get it on Internet.
/// www.pinvoke.net is a great website.It includes almost all the API fuctoin to be used in C#.
/// </summary>
class FindWindow
{
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
//IMPORTANT : LPARAM must be a pointer (InterPtr) in VS2005, otherwise an exception will be thrown
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
//the callback function for the EnumChildWindows
private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); //if found return the handle , otherwise return IntPtr.Zero
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); private string m_classname; // class name to look for private IntPtr m_hWnd; // HWND if found
public IntPtr FoundHandle
{
get { return m_hWnd; }
}
// ctor does the work--just instantiate and go
public FindWindow(IntPtr hwndParent, string classname)
{
m_hWnd = IntPtr.Zero;
m_classname = classname;
FindChildClassHwnd(hwndParent, IntPtr.Zero);
} //EnumChildWindows是API函数,能够遍历主窗口下所有子窗口。不过它的遍历过程是通过
//第二个参数即回调函数与程序员交互的。EnumChildWindows每找到一个窗口。就调用回调
//函数。回调函数如果返回false。遍历就会结束。 /**/
/// <summary>
/// Find the child window, if found m_classname will be assigned
/// </summary>
/// <param name="hwndParent">parent's handle</param>
/// <param name="lParam">the application value, nonuse</param>
/// <returns>found or not found</returns>
//The C++ code is that lParam is the instance of FindWindow class , if found assign the instance's m_hWnd
private bool FindChildClassHwnd(IntPtr hwndParent, IntPtr lParam)
{
EnumWindowProc childProc = new EnumWindowProc(FindChildClassHwnd);
IntPtr hwnd = FindWindowEx(hwndParent, IntPtr.Zero, this.m_classname, string.Empty);
if (hwnd != IntPtr.Zero)
{
this.m_hWnd = hwnd; // found: save it
return false; // stop enumerating
}
EnumChildWindows(hwndParent, childProc, IntPtr.Zero); // recurse redo FindChildClassHwnd
return true;// keep looking
}
}