|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionMy company develops a lot of rich-client applications, and we have forever wanted a nice "slick" way to indicate to the user when an activity is occurring in the background. Rarely do we know how long an operation will take (web services, remoting calls etc.), so we always use to just stick a little barber pole type animation in the top-right corner of the main application window. This was never a perfect solution though because we still had to do all the nasty "locking" of the In recent years, AJAX on the web has actually pioneered some interesting GUI concepts. I've always liked it when web sites pop-up with a central window that turns the background slightly darker and then ask you for some input. Then you type that input in and press an OK button, and then you get a nice little barber pole animation to indicate it has gone off back to the server and is waiting for a reply for the next step (if any). That's basically what this project is about. Bringing that "cool" AJAX-style asynchronous indication behaviour to WinForms. BackgroundThe project consists of several fundamental concepts:
Using the codeTo use the base class, simply modify your Alternatively, if you want better control over things, then you can use Internally, public partial class MyForm : AsyncBaseDialog {
public ModalDlg() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
AsyncProcessDelegate d = delegate() {
//
// Do your long-duration work here
// and remove the placeholder Sleep() below
//
System.Threading.Thread.Sleep(3000);
};
RunAsyncOperation(d);
}
private void button2_Click(object sender, EventArgs e) {
//
// Alternatively if you don't want to use the RunAsyncOperation() wrapper...
// You can use BeginAsyncIndication() and EndAsyncIndication() explicitly.
//
BeginAsyncIndication();
}
}//class
How it worksThe The snapshot of the //
// Get DC of the form...
IntPtr srcDc = GetDC(this.Handle);
//
// Create bitmap to store image of form...
Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
//
// Create a GDI+ context from the created bitmap...
using (Graphics g = Graphics.FromImage(bmp)) {
//
// Copy image of form into bitmap...
IntPtr bmpDc = g.GetHdc();
BitBlt(bmpDc, 0, 0, bmp.Width, bmp.Height, srcDc, 0, 0, 0x00CC0020 /* SRCCOPY */);
//
// Release resources...
ReleaseDC(this.Handle, srcDc);
g.ReleaseHdc(bmpDc);
//
// Blur/grayscale it...
Grayscale(bmp);
//
// Apply translucent overlay... fillBrush has an alpha-channel.
g.FillRectangle(fillBrush, 0, 0, bmp.Width, bmp.Height);
}//using
There were a couple issues I had surrounding the user resizing, maximising, minimising, restoring, or double-clicking the title bar of the protected override void WndProc(ref Message m) {
if (IsAsyncBusy) {
if (m.Msg == 0x112 /* WM_SYSCOMMAND */) {
int w = m.WParam.ToInt32();
if (w == 0xf120 /* SC_RESTORE */ || w == 0xf030
/* SC_MAXIMIZE */ || w == 0xf020
/* SC_MINIMIZE */)
return; // short circuit
} else if (m.Msg == 0xa3 /* WM_NCLBUTTONDBLCLK */)
return; // short circuit
}
base.WndProc(ref m);
}
Thank youThanks for reading and I hope you like the control. If you make any modifications/bug fixes/enhancements to this control, please post in the comments section with your source snippets and/or ideas. History
|
||||||||||||||||||||||