alexying Posted May 26, 2003 Posted May 26, 2003 I try to do something like off-screen drawing. First, I create a bitmap, draw on the bitmap, then use the BitBlt() function to draw it on the panel surface. however, all I got is a rectangle with black color. There might be the way calling BitBlt was not so correct. Can someone help me out? thanks a lot. Alex using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading; using System.Runtime.InteropServices; using System.Timers; namespace TransparentBitmap { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private MyPanel panel; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.panel = new TransparentBitmap.MyPanel(); this.SuspendLayout(); // // panel // this.panel.Name = "panel"; this.panel.Size = new System.Drawing.Size(300, 300); this.panel.TabIndex = 0; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(6, 15); this.ClientSize = new System.Drawing.Size(368, 328); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.panel}); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); this.panel.StartTimer(); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [sTAThread] static void Main() { Form1 form = new Form1(); Application.Run(form); } } //----------------------------------------------------------------// public class MyPanel : System.Windows.Forms.UserControl { private System.Timers.Timer timer; Bitmap myBitmap ; Graphics bitmapGraphics; IntPtr bitmapPtr; public MyPanel() { DrawBitmap(); this.SetStyle(ControlStyles.Opaque, true); this.SetStyle(ControlStyles.UserPaint, true); } [DllImport("gdi32.dll")] public static extern bool BitBlt( IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, long dwRop ); [DllImport("user32.dll")] public static extern IntPtr GetDC( IntPtr hwnd ); public void redraw(Graphics g) { if( this.IsDisposed ) { return; } if( ! g.IsVisibleClipEmpty ) { IntPtr hdcScreen = g.GetHdc(); bitmapPtr = bitmapGraphics.GetHdc(); BitBlt(hdcScreen, 0, 0, 300, 300, bitmapPtr, 0, 0, 0x00CC0020); g.ReleaseHdc(hdcScreen); bitmapGraphics.ReleaseHdc(bitmapPtr); } } protected override void OnPaint(PaintEventArgs e) { redraw(e.Graphics); } protected virtual void TimerOnTick( object obj, ElapsedEventArgs ea)//EventArgs ea) { this.Refresh(); } public void StartTimer() { timer = new System.Timers.Timer(); timer.Interval = 20; timer.Elapsed+=new ElapsedEventHandler(TimerOnTick); timer.Enabled = true; } public void DrawBitmap() { myBitmap = new Bitmap(300,300); bitmapGraphics = Graphics.FromImage(myBitmap); bitmapGraphics.FillRectangle(Brushes.Red,0,0,300,100); bitmapGraphics.FillRectangle(Brushes.Yellow,0,100,300,100); bitmapGraphics.FillRectangle(Brushes.Blue,0,200,300,100); } } } Quote
*Experts* mutant Posted May 26, 2003 *Experts* Posted May 26, 2003 You dont need any BltBit use in GDI+ :) All you need is to set the style in your app: SetStyle(ControlStyles.DoubleBuffer,true); SetStyle(ControlStyles.AllPaintingInWmPaint,true); Then just draw like you would normally. :) More info here: http://ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemWindowsFormsControlStylesClassTopic.htm Quote
alexying Posted May 26, 2003 Author Posted May 26, 2003 hi, mutant, Thank you for the reply. What I try to do is I try to build a grid myself. I don't want to draw grid line and cell content every timr the OnPaint() is called. it is not efficient. So, I draw to the bitmap first. when OnPaint() is called, i just blit the bitmap to the screen. I can use Graphics.DrawImage() to draw the bitmap. But Graphics.DrawImage() is slow, or i can say it is taking up too much CPU power when i try to draw the bitmap 50 times per second. that is why i would like to try out the BitBlt to see if it makes any difference in term of CPU usage. thanks Quote
*Gurus* divil Posted May 26, 2003 *Gurus* Posted May 26, 2003 Hang on, You're saying you don't want to use the OnPaint method (which will draw when needed, the most common method of doing it) because it's efficient, but you're trying to draw it 50 times per second? You should be using DrawImage. You could interop with GDI, but why? .NET uses GDI+. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
alexying Posted May 26, 2003 Author Posted May 26, 2003 sorry for the confusion. I am using OnPaint(), inside OnPaint() i want to call Bitblt to draw a GDI+ bitmap instead of calling DrawImage() to draw it. the grid I am creating will be used for displaying real-time data. so, i need to fresh the grid quite often. Maybe 50 times per second is too much, but, it can happen. Does anyone ever use Bitblt to draw a GDI+ bitmap? thanks Quote
AndreRyan Posted May 27, 2003 Posted May 27, 2003 What's the point just draw DrawImage(Same as BitBlt for GDI+), using GDI would be slower because you would have to get a DC for the GDI+ Bitmap before BitBlt could be used, if you want to continually refresh the pictures just use a loop similar to a game loop to continually redraw the images Quote .Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
alexying Posted May 30, 2003 Author Posted May 30, 2003 hi, i find out how to make GDI+ bitmap work with Bitblt. Thanks, Rehan. http://www.codeproject.com/csharp/flicker_free.asp Try both Bitblt and drawImage. Event with get DC before Bitblt, Bitblt is about 1.5 times faster than drawImage. here is the testing code: 1) for Bitblt long start = System.DateTime.Now.Ticks; for(int j =0; j<100;j++) { IntPtr hdcScreen = g.GetHdc();//GetDC(IntPtr.Zero); //IntPtr hdcSurface = myBitmap2.GetHdc(); bitmap2Ptr = bitmap2Graphics.GetHdc(); BitBlt(hdcScreen, 0, 0, 300, 300, bitmap2Ptr, 0, 0, 0x00CC0020);// g.ReleaseHdc(hdcScreen); bitmap2Graphics.ReleaseHdc(bitmap2Ptr); } //surface.ReleaseHdc(hdcSurface); long TimeTaken = System.DateTime.Now.Ticks - start; System.Console.WriteLine("time "+TimeTaken); 2) for drawImage long start = System.DateTime.Now.Ticks; for(int j =0; j<100;j++) { gg.DrawImage(myBitmap2,destRect,srcRect,GraphicsUnit.Pixel); } //surface.ReleaseHdc(hdcSurface); long TimeTaken = System.DateTime.Now.Ticks - start; System.Console.WriteLine("time "+TimeTaken); On average, Bitblt is 2000000 ticks, drawImage is 5000000 ticks if somebody is interested in the comparison of speeds of GDI+ and GDI, go here http://www.appdevadvisor.co.uk/Readers/Source_Code/main.htm download file: AdaExampleApp.zip Quote
*Gurus* divil Posted May 30, 2003 *Gurus* Posted May 30, 2003 If you don't want to use GDI+, why are you using .NET? Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
alexying Posted May 31, 2003 Author Posted May 31, 2003 i like other things about .net, but not the slowness of GDI+ Quote
*Experts* Volte Posted May 31, 2003 *Experts* Posted May 31, 2003 GDI+ is optimized to be very fast with .NET -- using Win32 API with .NET will almost always be slower than using managed code optimized for .NET. Quote
Leaders snarfblam Posted June 16, 2003 Leaders Posted June 16, 2003 GDI+ might draw lines or text faster, i don't know. As far as raster graphics go, GDI+ is useless. The DrawImage() function is very slow compared to the GDI bitblt. I made a program that drew an image composed of 16x11 tiles, drawing it one tile at a time. With GDI the image essentially appeared in the graphics container. With GDI+ you can see the image being draw from left to right; it is much too slow. The only qualm I have with Visual Studio.net is that they intentionally make it difficult to use the Windows API when it is potentially a useful tool. I might help you Alexying, but your code is a huge and needs to be summarized, and i dont really know much about c# anyways. Quote [sIGPIC]e[/sIGPIC]
aewarnick Posted June 17, 2003 Posted June 17, 2003 I am just curious 1. when you tested, did you put SetStyle(ControlStyles.DoubleBuffer,true); SetStyle(ControlStyles.AllPaintingInWmPaint,true); in your C# constructor? 2. the article did not mention anything about DrawImage being slower. In, fact it reccomended using DrawImage instead of Bitblt. 3. the article also said that DrawImage uses Bitblt already...I don't know if it is completely accurate or not though. Quote C#
*Experts* mutant Posted June 17, 2003 *Experts* Posted June 17, 2003 GDI+ might draw lines or text faster, i don't know. As far as raster graphics go, GDI+ is useless. The DrawImage() function is very slow compared to the GDI bitblt. I made a program that drew an image composed of 16x11 tiles, drawing it one tile at a time. With GDI the image essentially appeared in the graphics container. With GDI+ you can see the image being draw from left to right; it is much too slow. The only qualm I have with Visual Studio.net is that they intentionally make it difficult to use the Windows API when it is potentially a useful tool. I might help you Alexying, but your code is a huge and needs to be summarized, and i dont really know much about c# anyways. DId you turn on DoubleBuffering and things like that? I have been working with both BitBlt and DrawImage and GDI+ does a lot better job. It uses the fastest drawing method available. Quote
AndreRyan Posted June 17, 2003 Posted June 17, 2003 Apparently in Windows XP, Microsoft dumped GDI and replaced it with GDI+, the GDI32.dll only exists for compatibility reasons, so if you use WinXP GDI+ should be faster. Quote .Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.