1. Trang chủ
  2. » Công Nghệ Thông Tin

Apress-Visual CSharp 2010 Recipes A Problem Solution Approach_3 pptx

95 521 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 95
Dung lượng 2,09 MB

Nội dung

CHAPTER 7 ■ WINDOWS FORMS 355 synchronously and BeginInvoke executes the delegate asynchronously. To complete an asynchronous operation initiated using BeginInvoke, you call the Control.EndInvoke method. The BeginInvoke and EndInvoke methods make up a common asynchronous execution pattern known as the Classic Async pattern. The details of this pattern and the options you have available for handling method completion are discussed in recipe 4-2. The Code The following example shows how to update a Windows Forms control from multiple threads. The example uses two timers that fire at differing intervals to change the color of a Button control between red and green. The code shows how to use both an anonymous method and a lambda expression with the Invoke call. Both approaches use System.Action, a delegate type that can encapsulate any method that returns void and takes no arguments. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Apress.VisualCSharpRecipes.Chapter07 { public partial class Recipe07_19 : Form { // Declare timers that change the button color. System.Timers.Timer greenTimer; System.Timers.Timer redTimer; public Recipe07_19() { // Initialization code is designer generated and contained // in a separate file named Recipe07-19.Designer.cs. InitializeComponent(); // Create autoreset timers that fire at varying intervals // to change the color of the button on the form. greenTimer = new System.Timers.Timer(3000); greenTimer.Elapsed += new System.Timers.ElapsedEventHandler(greenTimer_Elapsed); greenTimer.Start(); redTimer = new System.Timers.Timer(5000); redTimer.Elapsed += new System.Timers.ElapsedEventHandler(redTimer_Elapsed); redTimer.Start(); } CHAPTER 7 ■ WINDOWS FORMS 356 void redTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Use an anonymous method to set the button color to red. button1.Invoke((Action)delegate {button1.BackColor = Color.Red;}); } void greenTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Use a lambda expression to set the button color to green. button1.Invoke(new Action(() => button1.BackColor = Color.Green)); } private void button1_Click(object sender, EventArgs e) { Application.Exit(); } [STAThread] public static void Main(string[] args) { Application.Run(new Recipe07_19()); } } } 7-20. Display a Web Page in a Windows-Based Application Problem You want to display a web page and provide web-navigation capabilities within your Windows Forms application. Solution Use the WebBrowser control to display the web page and other standard controls like buttons and text boxes to allow the user to control the operation of the WebBrowser. ■ Caution The WebBrowser control is a managed wrapper around the WebBrowser ActiveX control. This means that you must ensure you annotate the Main method of your Windows application with the STAThread attribute and that you dispose of the WebBrowser control (by calling the WebBrowser.Dispose method) when it is no longer required. CHAPTER 7 ■ WINDOWS FORMS 357 How It Works The WebBrowser control makes it a trivial task to embed highly functional web browser capabilities into your Windows applications. The WebBrowser control is responsible for the display of web pages and maintaining page history, but it does not provide any controls for user interaction. Instead, the WebBrowser control exposes properties and events that you can manipulate programmatically to control the operation of the WebBrowser. This approach makes the WebBrowser control highly flexible and adaptable to most common browsing requirements. Table 7-1 summarizes some of the WebBrowser members related to web navigation that you will find particularly useful. Table 7-1. Commonly Used Members of the WebBrowser Control Member Description Property AllowNavigation Controls whether the WebBrowser can navigate to another page after its initial page has been loaded CanGoBack Indicates whether the WebBrowser currently holds back page history, which would allow the GoBack method to succeed CanGoForward Indicates whether the WebBrowser currently holds forward page history, which would allow the GoForward method to succeed IsBusy Indicates whether the WebBrowser is currently busy downloading a page Url Holds the URL of the currently displayed/downloading page Method GoBack Displays the previous page in the page history GoForward Displays the next page in the page history GoHome Displays the home page of the current user as configured in Windows Navigate Displays the web page at the specified URL Stop Stops the current WebBrowser activity Event DocumentCompleted Signals that the active download has completed and the document is displayed in the WebBrowser CHAPTER 7 ■ WINDOWS FORMS 358 You can also use the WebBrowser.DocumentText property to set (or get) the currently displayed HTML contents of the WebBrowser. To manipulate the contents using the Document Object Model (DOM), get an HtmlDocument instance via the Document property. The Code The following example uses the WebBrowser control to allow users to navigate to a web page whose address is entered into a TextBox. Buttons also allow users to move forward and backward through page history and navigate directly to their personal home page. using System; using System.Windows.Forms; namespace Apress.VisualCSharpRecipes.Chapter07 { public partial class Recipe07_20 : Form { public Recipe07_20() { // Initialization code is designer generated and contained // in a separate file named Recipe07-20.Designer.cs. InitializeComponent(); } private void goButton_Click(object sender, EventArgs e) { // Navigate to the URL specified in the text box. webBrowser1.Navigate(textURL.Text); } private void homeButton_Click(object sender, EventArgs e) { // Navigate to the current user's home page. webBrowser1.GoHome(); } protected override void OnLoad(EventArgs e) { // Call the OnLoad method of the base class to ensure the Load // event is raised correctly. base.OnLoad(e); // Navigate to the Apress home page when the application first // loads. webBrowser1.Navigate("http://www.apress.com"); } CHAPTER 7 ■ WINDOWS FORMS 359 private void backButton_Click(object sender, EventArgs e) { // Go to the previous page in the WebBrowser history. webBrowser1.GoBack(); } private void forwarButton_Click(object sender, EventArgs e) { // Go to the next page in the WebBrowser history. webBrowser1.GoForward(); } // Event handler to perform general interface maintenance once a document // has been loaded into the WebBrowser. private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { // Update the content of the TextBox to reflect the current URL. textURL.Text = webBrowser1.Url.ToString(); // Enable or disable the Back button depending on whether the // WebBrowser has back history. if (webBrowser1.CanGoBack) { backButton.Enabled = true; } else { backButton.Enabled = false; } // Enable or disable the Forward button depending on whether the // WebBrowser has forward history. if (webBrowser1.CanGoForward) { forwarButton.Enabled = true; } else { forwarButton.Enabled = false; } } [STAThread] public static void Main(string[] args) { Application.Run(new Recipe07_20()); } } } CHAPTER 7 ■ WINDOWS FORMS 360 7-21. Display WPF Windows in a Windows Forms Application Problem You need to display a WPF window in a Windows Forms application. Solution Create an instance of the WPF window (System.Windows.Window) you want to display in your Windows Forms code. Call Window.ShowDialog to display a modal window, or call Window.Show to display a modeless window. How It Works The trickiest thing about displaying a WPF window in a Windows Forms application is actually integrating the WPF source code into your project correctly if you are using Visual Studio. There is no option in your Windows Forms project to add a WPF Window when you select Add New Item in Solution Explorer. The easiest way around this is to import an existing WPF Window using the Add Existing option in Solution Explorer. This will set everything up appropriately (adding the necessary assembly references), and you can then edit the WPF Window as you would when creating a WPF application. Alternatively, Visual Studio will allow you to add a new WPF user control to your Windows Forms application. You can use that option and then change the XAML and code-behind as required. Once you have a WPF Window declared, you can reference and instantiate the class the same as you would any other class. Calling Window.ShowDialog will display the window modally, meaning that the user can interact with only that window and must close it before they can interact again with the rest of the application. Calling Window.Show will display a modeless window, allowing the user to interact with the new window as well as the rest of the application. The Code The following example (shown running in Figure 7-13) displays a Windows Form with two buttons. The left button opens and closes a modeless WPF window, and the right button opens a modal window. When the example creates the modeless window, it subscribes an event handler to the Window.Closing event so that the application can update the button state should the user choose to close the window directly instead of using the button. The following code is the code-behind for the main Windows Form: using System; using System.ComponentModel; using System.Windows.Forms; namespace Apress.VisualCSharpRecipes.Chapter07 { public partial class Recipe07_21 : Form { private Window1 modelessWindow; CHAPTER 7 ■ WINDOWS FORMS 361 private CancelEventHandler modelessWindowCloseHandler; public Recipe07_21() { // Initialization code is designer generated and contained // in a separate file named Recipe07-21.Designer.cs. InitializeComponent(); modelessWindowCloseHandler = new CancelEventHandler(Window_Closing); } // Handles the button click event to open and close the modeless // WPF window. private void OpenModeless_Click(object sender, EventArgs e) { if (modelessWindow == null) { modelessWindow = new Window1(); // Add an event handler to get notification when the window // is closing. modelessWindow.Closing += modelessWindowCloseHandler; // Change the button text. btnOpenModeless.Text = "Close Modeless Window"; // Show the Windows Form. modelessWindow.Show(); } else { modelessWindow.Close(); } } // Handles the button click event to open the modal WPF Window. private void OpenModal_Click(object sender, EventArgs e) { // Create and display the modal window. Window1 window = new Window1(); window.ShowDialog(); } // Handles the WPF Window's Closing event for the modeless window. private void Window_Closing(object sender, CancelEventArgs e) { // Remove the event handler reference. modelessWindow.Closing -= modelessWindowCloseHandler; modelessWindow = null; CHAPTER 7 ■ WINDOWS FORMS 362 // Change the button text. btnOpenModeless.Text = "Open Modeless Window"; } } } The following XAML provides the declaration of the WPF Window that is opened when the user clicks either of the buttons on the Windows Forms application: <Window x:Class="Apress.VisualCSharpRecipes.Chapter07.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Recipe07_21" Height="200" Width="300"> <StackPanel Margin="20"> <TextBlock FontSize="20" Text="A WPF Window" TextAlignment="Center"/> <Button Click="btnClose_Click" Content="Close" Margin="50" MaxWidth="50" Name="btnClose" /> </StackPanel> </Window> The following is the code-behind for the WPF Window that allows the user to close the window by clicking the Close button: using System.Windows; using System.Windows.Forms; namespace Apress.VisualCSharpRecipes.Chapter07 { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void btnClose_Click(object sender, RoutedEventArgs e) { this.Close(); } } } CHAPTER 7 ■ WINDOWS FORMS 363 Figure 7-13. Displaying a WPF window from a Windows Forms application 7-22. Display WPF Controls in Windows Forms Problem You need to display WPF user interface elements alongside Windows Forms controls in a Windows Form. Solution Use a System.Windows.Forms.Integration.ElementHost control on your Windows Form, and host the WPF control inside it. How It Works The ElementHost control is a Windows Forms control that allows you to host WPF controls in Windows Forms. The ElementHost control makes integrating WPF controls into your Windows Forms application relatively simple and even provides some limited visual design-time support. The ElementHost can contain a single WPF element that inherits from System.Windows.UIElement. The element can be one of the layout containers discussed in Chapter 17, which allows you to create rich, structured WPF content within the ElementHost control. Often, the WPF element you place in the ElementHost control will be a WPF user control (see Chapter 17), but can also be any common WPF control. To use the ElementHost control in Visual Studio’s graphical design environment, open the toolbox and browse to the WPF Interoperability category. Drag the ElementHost control and drop it on the Windows Form as you would with any other control. Using the ElementHost Tasks window, you can then select any WPF user control currently in your project to place in the ElementHost control (see Figure 7-14). CHAPTER 7 ■ WINDOWS FORMS 364 Figure 7-14. Using ElementHost in Visual Studio If you do not want to use a user control, then you will need to populate the ElementHost control programmatically by assigning the desired WPF element to the Child property of the ElementHost control. The Code The following example demonstrates how to integrate WPF controls into a Windows Forms application. The example (shown in Figure 7-15) uses a simple WPF user control consisting of a System.Windows. Shapes.Ellipse that can change between red and blue color gradients. This EllipseControl is assigned to one ElementHost using the Visual Studio form builder. Another ElementHost is populated programmatically with a System.Windows.Controls.TextBox. A standard Windows Forms button triggers the EllipseControl to change color, and then writes a log entry to the TextBox. Here is the XAML for the WPF user control: <UserControl x:Class="Apress.VisualCSharpRecipes.Chapter07.EllipseControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300"> <Grid x:Name="Grid1"> <Grid.Resources> <RadialGradientBrush x:Key="RedBrush" RadiusX=".8" RadiusY="1" Center="0.5,0.5" GradientOrigin="0.05,0.5"> <GradientStop Color="#ffffff" Offset="0.1" /> <GradientStop Color="#ff0000" Offset="0.5" /> <GradientStop Color="#880000" Offset="0.8" /> </RadialGradientBrush> <RadialGradientBrush x:Key="BlueBrush" RadiusX=".8" RadiusY="1" Center="0.5,0.5" GradientOrigin="0.05,0.5"> <GradientStop Color="#ffffff" Offset="0.1" /> <GradientStop Color="#0000ff" Offset="0.5" /> <GradientStop Color="#000088" Offset="0.8" /> </RadialGradientBrush> </Grid.Resources> [...]... System.Drawing.Drawing2D; namespace Apress.VisualCSharpRecipes.Chapter08 { public partial class EllipseShape : Control { public EllipseShape() { InitializeComponent(); } private GraphicsPath path = null; 379 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING private void RefreshPath() { // Create the GraphicsPath for the shape (in this case // an ellipse that fits inside the full control area) // and apply... System.Drawing namespace • The GraphicsPath.IsVisible method takes a point and returns true if the point is inside the area defined by a closed GraphicsPath Because a GraphicsPath can contain multiple lines, shapes, and figures, this approach is useful if you want to test whether a point is contained inside a nonrectangular region The GraphicsPath class is a member of the System.Drawing.Drawing2D namespace •... create a nonrectangular form or control, you first need to define the shape you want The easiest approach is to use the System.Drawing.Drawing2D.GraphicsPath object, which can accommodate any combination of ellipses, rectangles, closed curves, and even strings You can add shapes to a 376 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING GraphicsPath instance using methods such as AddEllipse, AddRectangle,... Region.IsVisible method takes a point and returns true if the point is inside the area defined by a Region A Region, like the GraphicsPath, can represent a complex nonrectangular shape Region is a member of the System.Drawing namespace The Code The following example shows a form that creates a Rectangle and a GraphicsPath By default, these two shapes are given light-blue backgrounds However, an event handler responds... would lead to more drawing and generate additional flicker as the entire form is repainted using using using using System; System.Drawing; System.Windows.Forms; System.Drawing.Drawing2D; namespace Apress.VisualCSharpRecipes.Chapter08 { public partial class Recipe08_02 : Form { // Define the shapes used on this form private GraphicsPath path; private Rectangle rectangle; // Define the flags that track where... (inPath) { g.FillPath(highlightBrush, path); g.FillRectangle(defaultBrush, rectangle); } else if (inRectangle) { g.FillRectangle(highlightBrush, rectangle); g.FillPath(defaultBrush, path); } else { g.FillPath(defaultBrush, path); g.FillRectangle(defaultBrush, rectangle); } g.DrawPath(Pens.Black, path); g.DrawRectangle(Pens.Black, rectangle); } 374 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING private... information about this topic, refer to the Microsoft Developer Network (MSDN) documentation For an example that demonstrates a nonrectangular control, refer to recipe 8-4 378 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING 8-4 Create a Movable Sprite Problem You need to create a shape the user can manipulate on a form, perhaps by dragging it, resizing it, or otherwise interacting with it Solution Create a. .. } } } } Figure 8-2 shows the application in action 375 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING Figure 8-2 Hit testing with a Rectangle and a GraphicsPath object 8-3 Create an Irregularly Shaped Control Problem You need to create a nonrectangular form or control Solution Create a new System.Drawing.Region object that has the shape you want for the form, and assign it to the Form.Region or Control.Region... 8-4 shows the user about to drag an ellipse Figure 8-4 Dragging custom shape controls on a form 382 CHAPTER 8 ■ GRAPHICS, MULTIMEDIA, AND PRINTING 8-5 Create a Scrollable Image Problem You need to create a scrollable picture with dynamic content Solution Leverage the automatic scroll capabilities of the System.Windows.Forms.Panel control by setting Panel.AutoScroll to true and placing a System.Windows.Forms.PictureBox... and shows an animation of an image alternately growing and shrinking on the page The drawing logic takes place in the Form.Paint event handler, and a timer invalidates the form in a preset interval so that the image can be redrawn The user can choose whether to enable double buffering through a check box on the form Without double buffering, the form flickers noticeably When double buffering is enabled, . reference and instantiate the class the same as you would any other class. Calling Window.ShowDialog will display the window modally, meaning that the user can interact with only that window and. GraphicsPath.IsVisible method takes a point and returns true if the point is inside the area defined by a closed GraphicsPath. Because a GraphicsPath can contain multiple lines, shapes, and. System.Drawing namespace. The Code The following example shows a form that creates a Rectangle and a GraphicsPath. By default, these two shapes are given light-blue backgrounds. However, an event

Ngày đăng: 18/06/2014, 16:20