public virtual void UpdateWindow(Bitmap bitmap, double opacity) { if (bitmap == null) { return; } if (Image.IsCanonicalPixelFormat(bitmap.PixelFormat) && Image.IsAlphaPixelFormat(bitmap.PixelFormat)) { IntPtr zero = IntPtr.Zero; IntPtr dC = NativeMethods.GetDC(IntPtr.Zero); IntPtr hObj = IntPtr.Zero; IntPtr hDC = NativeMethods.CreateCompatibleDC(dC); try { Point pptDst = new Point(base.Left, base.Top); Size psize = new Size(bitmap.Width, bitmap.Height); Struct.BLENDFUNCTION pblend = new Struct.BLENDFUNCTION(); Point pptSrc = new Point(0, 0); hObj = bitmap.GetHbitmap(Color.FromArgb(0)); zero = NativeMethods.SelectObject(hDC, hObj); pblend.BlendOp = 0; pblend.SourceConstantAlpha = (byte)((int)(255.0 * opacity)); pblend.AlphaFormat = 1; pblend.BlendFlags = 0; NativeMethods.UpdateWindow(base.Handle, dC, ref pptDst, ref psize, hDC, ref pptSrc, 0, ref pblend, 2); return; } finally { if (hObj != IntPtr.Zero) { NativeMethods.SelectObject(hDC, zero); NativeMethods.DeleteObject(hObj); } NativeMethods.ReleaseDC(IntPtr.Zero, dC); NativeMethods.DeleteDC(hDC); } } throw new ApplicationException("图片必须是32位带Alhpa通道的图片。"); }
protected void RefreshFakeWnd() { if (m_bIsRefreshing) { return; } if (!NativeMethods.IsWindow(m_FakeWndHandle)) { return; } m_bIsRefreshing = true; POINT ptSrc = new POINT(0, 0); POINT ptWinPos = new POINT(this.Left, this.Top); SIZE szWin = new SIZE(m_BgImg.Width, m_BgImg.Height); byte biAlpha = 0xFF; BLENDFUNCTION stBlend = new BLENDFUNCTION(BlendOp.AC_SRC_OVER, 0, biAlpha, BlendOp.AC_SRC_ALPHA); IntPtr hDC = NativeMethods.GetDC(m_FakeWndHandle); if (hDC == IntPtr.Zero) { m_bIsRefreshing = false; Debug.Assert(false, "GetDC failed."); return; } IntPtr hdcMemory = NativeMethods.CreateCompatibleDC(hDC); int nBytesPerLine = ((m_BgImg.Width * 32 + 31) & (~31)) >> 3; BITMAPINFOHEADER stBmpInfoHeader = new BITMAPINFOHEADER(); stBmpInfoHeader.Init(); stBmpInfoHeader.biWidth = m_BgImg.Width; stBmpInfoHeader.biHeight = m_BgImg.Height; stBmpInfoHeader.biPlanes = 1; stBmpInfoHeader.biBitCount = 32; stBmpInfoHeader.biCompression = CompressionType.BI_RGB; stBmpInfoHeader.biClrUsed = 0; stBmpInfoHeader.biSizeImage = (uint)(nBytesPerLine * m_BgImg.Height); IntPtr pvBits = IntPtr.Zero; IntPtr hbmpMem = NativeMethods.CreateDIBSection(hDC , ref stBmpInfoHeader , DIBColorTableIdentifier.DIB_RGB_COLORS , out pvBits , IntPtr.Zero , 0 ); Debug.Assert(hbmpMem != IntPtr.Zero, "CreateDIBSection failed."); if (hbmpMem != null) { IntPtr hbmpOld = NativeMethods.SelectObject(hdcMemory, hbmpMem); Graphics graphic = Graphics.FromHdcInternal(hdcMemory); graphic.DrawImage(m_BgImg, 0, 0, m_BgImg.Width, m_BgImg.Height); foreach (Control ctrl in this.Controls) { if (!ctrl.Visible) { continue; } using (Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height)) { Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height); ctrl.DrawToBitmap(bmp, rect); graphic.DrawImage(bmp, ctrl.Left, ctrl.Top, ctrl.Width, ctrl.Height); } } GUITHREADINFO stGuiThreadInfo = new GUITHREADINFO(); stGuiThreadInfo.Init(); if (NativeMethods.GetGUIThreadInfo((uint)NativeMethods.GetCurrentThreadId(), ref stGuiThreadInfo)) { if (NativeMethods.IsWindow(stGuiThreadInfo.hwndCaret)) { int height = stGuiThreadInfo.rcCaret.Bottom - stGuiThreadInfo.rcCaret.Top; POINT ptCaret = new POINT(stGuiThreadInfo.rcCaret.Left, stGuiThreadInfo.rcCaret.Top); NativeMethods.ClientToScreen(stGuiThreadInfo.hwndCaret, ref ptCaret); NativeMethods.ScreenToClient(this.Handle, ref ptCaret); graphic.DrawLine(new Pen(new SolidBrush(Color.Black)) , ptCaret.X , ptCaret.Y , ptCaret.X , ptCaret.Y + height ); } } NativeMethods.UpdateLayeredWindow(m_FakeWndHandle , hDC , ref ptWinPos , ref szWin , hdcMemory , ref ptSrc , 0 , ref stBlend , UpdateLayerWindowParameter.ULW_ALPHA ); graphic.Dispose(); NativeMethods.SelectObject(hbmpMem, hbmpOld); NativeMethods.DeleteObject(hbmpMem); } NativeMethods.DeleteDC(hdcMemory); NativeMethods.DeleteDC(hDC); m_bIsRefreshing = false; }