mdiclientcontroller.cs

来自「Fireball.CodeEditor is an source code ed」· CS 代码 · 共 578 行 · 第 1/2 页

CS
578
字号

		[Category("Appearance"), DefaultValue(false)]
		[LocalizedDescription("MdiClientController.StretchImage.Description")]
		public bool StretchImage
		{
			get { return m_stretchImage; }
			set
			{
				m_stretchImage = value;
				if(MdiClient != null)
					MdiClient.Invalidate();
			}
		}

		public void RenewMdiClient()
		{
			// Reinitialize the MdiClient and its properties.
			InitializeMdiClient();
			RefreshProperties();
		}

		[Browsable(false)]
		public event EventHandler Disposed;

		[Browsable(false)]
		public event EventHandler HandleAssigned;

		[Browsable(false)]
		public event EventHandler MdiChildActivate;

		[Browsable(false)]
		public event LayoutEventHandler Layout;

		protected virtual void OnHandleAssigned(EventArgs e)
		{
			// Raise the HandleAssigned event.
			if(HandleAssigned != null)
				HandleAssigned(this, e);
		}

		protected virtual void OnMdiChildActivate(EventArgs e)
		{
			// Raise the MdiChildActivate event
			if (MdiChildActivate != null)
				MdiChildActivate(this, e);
		}

		protected virtual void OnLayout(LayoutEventArgs e)
		{
			// Raise the Layout event
			if (Layout != null)
				Layout(this, e);
		}

		[Category("Appearance")]
		[LocalizedDescription("MdiClientController.Paint.Description")]
		public event PaintEventHandler Paint;

		protected virtual void OnPaint(PaintEventArgs e)
		{
			// Raise the Paint event.
			if(Paint != null)
				Paint(this, e);
		}

		protected override void WndProc(ref Message m)
		{
			switch(m.Msg)
			{
				//Do all painting in WM_PAINT to reduce flicker.
				case (int)Win32.Msgs.WM_ERASEBKGND:
					return;

				case (int)Win32.Msgs.WM_PAINT:

					// This code is influenced by Steve McMahon's article:
					// "Painting in the MDI Client Area".
					// http://vbaccelerator.com/article.asp?id=4306

					// Use Win32 to get a Graphics object.
					Win32.PAINTSTRUCT paintStruct = new Win32.PAINTSTRUCT();
					IntPtr screenHdc = User32.BeginPaint(m.HWnd, ref paintStruct);

					using(Graphics screenGraphics = Graphics.FromHdc(screenHdc)) 
					{
						// Get the area to be updated.
						Rectangle clipRect = paintStruct.rcPaint;

						// Double-buffer by painting everything to an image and
						// then drawing the image.
						int width = (MdiClient.ClientRectangle.Width > 0 ? MdiClient.ClientRectangle.Width : 0);
						int height = (MdiClient.ClientRectangle.Height > 0 ? MdiClient.ClientRectangle.Height : 0);
						if (width > 0 && height > 0)
						{
							using(Image i = new Bitmap(width, height))
							{
								using(Graphics g = Graphics.FromImage(i))
								{
									// This code comes from J Young's article:
									// "Generating missing Paint event for TreeView and ListView".
									// http://www.codeproject.com/cs/miscctrl/genmissingpaintevent.asp

									// Draw base graphics and raise the base Paint event.
									IntPtr hdc = g.GetHdc();
									Message printClientMessage = Message.Create(m.HWnd, (int)Win32.Msgs.WM_PRINTCLIENT, hdc, IntPtr.Zero);  
									DefWndProc(ref printClientMessage);
									g.ReleaseHdc(hdc);

									// Draw the image here.
									if(Image != null)
										DrawImage(g, clipRect);

									// Call our OnPaint here to draw graphics over the
									// original and raise our Paint event.
									OnPaint(new PaintEventArgs(g, clipRect));
								}

								// Now draw all the graphics at once.
								screenGraphics.DrawImage(i, MdiClient.ClientRectangle);
							}
						}
					}

					User32.EndPaint(m.HWnd, ref paintStruct);
					return;
	
				case (int)Win32.Msgs.WM_SIZE:
					// Repaint on every resize.
					MdiClient.Invalidate();
					break;
					

				case (int)Win32.Msgs.WM_NCCALCSIZE:
					// If AutoScroll is set to false, hide the scrollbars when the control
					// calculates its non-client area.
					if(!AutoScroll)
						User32.ShowScrollBar(m.HWnd, (int)Win32.ScrollBars.SB_BOTH, 0 /*false*/);
					break;
			}
		
			base.WndProc(ref m);
		}

		private void ParentFormHandleCreated(object sender, EventArgs e)
		{
			// The form has been created, unwire the event, and initialize the MdiClient.
			this.m_parentForm.HandleCreated -= new EventHandler(ParentFormHandleCreated);
			InitializeMdiClient();
			RefreshProperties();
		}

		private void ParentFormMdiChildActivate(object sender, EventArgs e)
		{
			OnMdiChildActivate(e);
		}

		private void MdiClientLayout(object sender, LayoutEventArgs e)
		{
			OnLayout(e);
		}

		private void MdiClientHandleDestroyed(object sender, EventArgs e)
		{
			// If the MdiClient handle has been released, drop the reference and
			// release the handle.
			if(m_mdiClient != null)
			{
				m_mdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
				m_mdiClient = null;
			}

			ReleaseHandle();
		}

		private void InitializeMdiClient()
		{
			// If the mdiClient has previously been set, unwire events connected
			// to the old MDI.
			if(MdiClient != null)
			{
				MdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
				MdiClient.Layout -= new LayoutEventHandler(MdiClientLayout);
			}

			if(ParentForm == null)
				return;

			// Get the MdiClient from the parent form.
			foreach (Control control in ParentForm.Controls)
			{
				// If the form is an MDI container, it will contain an MdiClient control
				// just as it would any other control.

				m_mdiClient = control as MdiClient;
				if(m_mdiClient == null)
					continue;

				// Assign the MdiClient Handle to the NativeWindow.
				ReleaseHandle();
				AssignHandle(MdiClient.Handle);

				// Raise the HandleAssigned event.
				OnHandleAssigned(EventArgs.Empty);

				// Monitor the MdiClient for when its handle is destroyed.
				MdiClient.HandleDestroyed += new EventHandler(MdiClientHandleDestroyed);
				MdiClient.Layout += new LayoutEventHandler(MdiClientLayout);

				break;
			}
		}

		private void RefreshProperties()
		{
			// Refresh all the properties
			BackColor = m_backColor;
			BorderStyle = m_borderStyle;
			AutoScroll = m_autoScroll;
			Image = m_image;
			ImageAlign = m_imageAlign;
			StretchImage = m_stretchImage;
		}

		private void DrawImage(Graphics g, Rectangle clipRect)
		{
			// Paint the background image.
			if(StretchImage)
				g.DrawImage(this.Image, MdiClient.ClientRectangle);
			else
			{
				// Calculate the location of the image. (Note: this logic could be calculated during sizing
				// instead of during painting to improve performance.)
				Point pt = Point.Empty;
				switch(ImageAlign)
				{
					case ContentAlignment.TopLeft:
						pt = new Point(0, 0);
						break;
					case ContentAlignment.TopCenter:
						pt = new Point((MdiClient.ClientRectangle.Width / 2) - (Image.Width / 2), 0);
						break;
					case ContentAlignment.TopRight:
						pt = new Point(MdiClient.ClientRectangle.Width - Image.Width, 0);
						break;
					case ContentAlignment.MiddleLeft:
						pt = new Point(0, (MdiClient.ClientRectangle.Height / 2) - (Image.Height / 2));
						break;
					case ContentAlignment.MiddleCenter:
						pt = new Point((MdiClient.ClientRectangle.Width / 2) - (Image.Width / 2),
							(MdiClient.ClientRectangle.Height / 2) - (Image.Height / 2));
						break;
					case ContentAlignment.MiddleRight:
						pt = new Point(MdiClient.ClientRectangle.Width - Image.Width,
							(MdiClient.ClientRectangle.Height / 2) - (Image.Height / 2));
						break;
					case ContentAlignment.BottomLeft:
						pt = new Point(0, MdiClient.ClientRectangle.Height - Image.Height);
						break;
					case ContentAlignment.BottomCenter:
						pt = new Point((MdiClient.ClientRectangle.Width / 2) - (Image.Width / 2),
							MdiClient.ClientRectangle.Height - Image.Height);
						break;
					case ContentAlignment.BottomRight:
						pt = new Point(MdiClient.ClientRectangle.Width - Image.Width,
							MdiClient.ClientRectangle.Height - Image.Height);
						break;
				}

				// Paint the image with the calculated coordinates and image size.
				g.DrawImage(Image, new Rectangle(pt, Image.Size));
			}
		}

		private void UpdateStyles()
		{
			// To show style changes, the non-client area must be repainted. Using the
			// control's Invalidate method does not affect the non-client area.
			// Instead use a Win32 call to signal the style has changed.
			User32.SetWindowPos(MdiClient.Handle, IntPtr.Zero, 0, 0, 0, 0,
				Win32.FlagsSetWindowPos.SWP_NOACTIVATE |
				Win32.FlagsSetWindowPos.SWP_NOMOVE |
				Win32.FlagsSetWindowPos.SWP_NOSIZE |
				Win32.FlagsSetWindowPos.SWP_NOZORDER |
				Win32.FlagsSetWindowPos.SWP_NOOWNERZORDER |
				Win32.FlagsSetWindowPos.SWP_FRAMECHANGED);
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?