added some development tools
[windows-sources.git] / developer / VSSDK / VisualStudioIntegration / Common / Source / CSharp / Shell100 / DialogContainerWithToolbar.cs
blob23c7d202e796a23e5ad3b5ef4f287ab8edad2106
1 //------------------------------------------------------------------------------
2 // <copyright file="WindowPane.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
7 using System;
8 using Microsoft.VisualStudio.OLE.Interop;
9 using Microsoft.VisualStudio.Shell.Interop;
10 using System.ComponentModel;
11 using System.ComponentModel.Design;
12 using System.Windows.Forms;
13 using System.Security.Permissions;
15 using IDropTarget = Microsoft.VisualStudio.OLE.Interop.IDropTarget;
16 using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
17 using IServiceProvider = System.IServiceProvider;
18 using IMessageFilter = System.Windows.Forms.IMessageFilter;
20 namespace Microsoft.VisualStudio.Shell {
22 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar"]/*' />
23 /// <devdoc>
24 /// This class is the base class for forms that need to be displayed as modal dialogs inside VisualStudio.
25 /// </devdoc>
26 [CLSCompliant(false)]
27 public class DialogContainerWithToolbar : Form,
28 IVsToolWindowToolbar,
29 IServiceProvider,
30 IMessageFilter
32 /// <devdoc>
33 /// This class is used to change the control contained by the form to a
34 /// IVsWindowPane. This is expecially needed if the control is a form,
35 /// because WinForms will not allow us to make it child of another form.
36 /// </devdoc>
37 private class WindowPaneAdapter : WindowPane
39 private Control control;
40 private DialogContainerWithToolbar container;
41 private IntPtr paneHwnd;
43 private int left;
44 private int top;
45 private int height;
46 private int width;
48 public WindowPaneAdapter(DialogContainerWithToolbar container, Control control) :
49 base ((IServiceProvider)container)
51 this.container = container;
52 this.paneHwnd = IntPtr.Zero;
53 this.control = control;
56 protected override void Dispose(bool disposing)
58 if (disposing)
60 if (null != control)
62 control.Dispose();
63 control = null;
65 paneHwnd = IntPtr.Zero;
67 base.Dispose(disposing);
70 public IntPtr Handle
72 get { return paneHwnd; }
75 public void Focus()
77 control.Focus();
80 // Create the pane at the specific coordinates.
81 public void Create(int left, int top, int height, int width)
83 // Check if the pane was created before.
84 if (IntPtr.Zero != paneHwnd)
85 throw new InvalidOperationException();
87 // Create the object.
88 NativeMethods.ThrowOnFailure(
89 ((IVsWindowPane)this).CreatePaneWindow(container.Handle, left, top, width, height, out paneHwnd));
91 // Store the coordinates
92 this.left = left;
93 this.top = top;
94 this.height = height;
95 this.width = width;
98 // Returns the IWin32Window interface (used to access the handle of the control)
99 public override IWin32Window Window
101 get { return (IWin32Window)control; }
104 // Move the the pane to the specific coordinates.
105 public void Move(int left, int top, int height, int width)
107 if (IntPtr.Zero == Handle)
108 return;
110 bool result = UnsafeNativeMethods.SetWindowPos(
111 Handle,
112 IntPtr.Zero,
113 left,
114 top,
115 width,
116 height,
117 NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
119 if ( !result)
120 throw new Exception();
122 this.left = left;
123 this.top = top;
124 this.height = height;
125 this.width = width;
128 public int Left
130 get { return left; }
133 public int Top
135 get { return top; }
138 public int Height
140 get { return height; }
143 public int Width
145 get { return width; }
149 private class ShowDialogContainer : Container
151 private IServiceProvider provider;
152 public ShowDialogContainer(IServiceProvider sp)
154 provider = sp;
157 protected override object GetService(Type serviceType)
159 if (provider != null)
161 object service = provider.GetService(serviceType);
162 if (null != service)
163 return service;
165 return base.GetService(serviceType);
169 // Variables to handle the contained control
170 private WindowPaneAdapter containedForm;
171 private System.Drawing.Size controlSize;
173 // Toolbar handling
174 private IVsToolWindowToolbarHost toolbarHost;
175 private RECT toolbarRect;
176 private CommandID toolbarCommandId;
177 private VSTWT_LOCATION toolbarLocation;
178 private IDropTarget toolbarDropTarget;
180 // Services
181 private IServiceProvider provider;
182 private OleMenuCommandService commandService;
183 private uint commandTargetCookie;
185 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.DialogContainerWithToolbar"]/*' />
186 /// <devdoc>
187 /// Constructor of the DialogContainerWithToolbar. This constructor allow the caller to set a IServiceProvider,
188 /// the conatined control and an additional IOleCommandTarget implementation that will be chained to the one
189 /// implemented by OleMenuCommandTarget.
190 /// </devdoc>
191 public DialogContainerWithToolbar(IServiceProvider sp, Control contained, IOleCommandTarget parentCommandTarget)
193 if (null == contained)
194 throw new ArgumentNullException("contained");
196 if (null == sp)
197 throw new ArgumentNullException("sp");
199 PrivateInit(sp, contained, parentCommandTarget);
202 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.DialogContainerWithToolbar1"]/*' />
203 /// <devdoc>
204 /// Constructor of the DialogContainerWithToolbar. This constructor allow the caller to set a IServiceProvider and
205 /// the conatined control.
206 /// </devdoc>
207 public DialogContainerWithToolbar(IServiceProvider sp, Control contained)
209 if (null == contained)
210 throw new ArgumentNullException("contained");
212 if (null == sp)
213 throw new ArgumentNullException("sp");
215 IOleCommandTarget parentTarget = contained as IOleCommandTarget;
216 PrivateInit(sp, contained, parentTarget);
219 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.DialogContainerWithToolbar2"]/*' />
220 /// <devdoc>
221 /// Constructor of the DialogContainerWithToolbar. This constructor allow the caller to set a IServiceProvider.
222 /// </devdoc>
223 public DialogContainerWithToolbar(IServiceProvider sp)
225 if (null == sp)
226 throw new ArgumentNullException("sp");
228 PrivateInit(sp, null, null);
231 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.DialogContainerWithToolbar3"]/*' />
232 /// <devdoc>
233 /// Constructor of the DialogContainerWithToolbar.
234 /// </devdoc>
235 public DialogContainerWithToolbar()
237 PrivateInit(null, null, null);
240 private void RegisterCommandTarget()
242 if (null == provider)
243 throw new InvalidOperationException();
245 IVsRegisterPriorityCommandTarget registerCommandTarget = (IVsRegisterPriorityCommandTarget)provider.GetService(typeof(SVsRegisterPriorityCommandTarget));
246 if (null != registerCommandTarget)
247 NativeMethods.ThrowOnFailure(
248 registerCommandTarget.RegisterPriorityCommandTarget(
250 (IOleCommandTarget)commandService,
251 out commandTargetCookie));
254 private void PrivateInit(IServiceProvider sp, Control contained, IOleCommandTarget parentTarget)
256 provider = sp;
258 commandTargetCookie = 0;
259 if (null == parentTarget)
261 commandService = new OleMenuCommandService(sp);
263 else
265 commandService = new OleMenuCommandService(sp, parentTarget);
267 if (null != sp)
269 // Now we have to register the IOleCommandTarget implemented by the OleCommandService
270 // as a priority command target, so it will be called by the shell.
271 RegisterCommandTarget();
274 // Set the defaults for the toolbar (empty toolbar placed at the top)
275 toolbarRect.left = 0;
276 toolbarRect.top = 0;
277 toolbarRect.right = 0;
278 toolbarRect.bottom = 0;
279 toolbarCommandId = null;
280 toolbarLocation = VSTWT_LOCATION.VSTWT_TOP;
282 if (null == contained)
284 containedForm = null;
286 else
288 controlSize = contained.ClientSize;
289 containedForm = new WindowPaneAdapter(this, contained);
290 this.Site = contained.Site;
291 Form innerForm = contained as Form;
292 if (null != innerForm)
294 // If the contained control is a form, then copy some
295 // of its property to this one.
296 this.AcceptButton = innerForm.AcceptButton;
297 this.AccessibleDefaultActionDescription = innerForm.AccessibleDefaultActionDescription;
298 this.AccessibleDescription = innerForm.AccessibleDescription;
299 this.AccessibleName = innerForm.AccessibleName;
300 this.AccessibleRole = innerForm.AccessibleRole;
301 this.AllowDrop = innerForm.AllowDrop;
302 this.AllowTransparency = innerForm.AllowTransparency;
303 this.AutoScaleDimensions = innerForm.AutoScaleDimensions;
304 this.AutoScaleMode = innerForm.AutoScaleMode;
305 this.AutoScroll = innerForm.AutoScroll;
306 this.AutoScrollMargin = innerForm.AutoScrollMargin;
307 this.AutoScrollMinSize = innerForm.AutoScrollMinSize;
308 this.AutoScrollPosition = innerForm.AutoScrollPosition;
309 this.BindingContext = innerForm.BindingContext;
310 this.Bounds = innerForm.Bounds;
311 this.CancelButton = innerForm.CancelButton;
312 this.ContextMenu = innerForm.ContextMenu;
313 this.ControlBox = innerForm.ControlBox;
314 this.Cursor = innerForm.Cursor;
315 this.DesktopBounds = innerForm.DesktopBounds;
316 this.DesktopLocation = innerForm.DesktopLocation;
317 this.Font = innerForm.Font;
318 this.FormBorderStyle = innerForm.FormBorderStyle;
319 this.Icon = innerForm.Icon;
320 this.IsAccessible = innerForm.IsAccessible;
321 this.MaximizeBox = innerForm.MaximizeBox;
322 this.MaximumSize = innerForm.MaximumSize;
323 this.Menu = innerForm.Menu;
324 this.MinimizeBox = innerForm.MinimizeBox;
325 this.MinimumSize = innerForm.MinimumSize;
326 this.Opacity = innerForm.Opacity;
327 this.Region = innerForm.Region;
328 this.RightToLeft = innerForm.RightToLeft;
329 this.ShowInTaskbar = innerForm.ShowInTaskbar;
330 this.SizeGripStyle = innerForm.SizeGripStyle;
331 this.StartPosition = innerForm.StartPosition;
332 this.Text = innerForm.Text;
333 this.TopLevel = innerForm.TopLevel;
334 this.TopMost = innerForm.TopMost;
335 this.TransparencyKey = innerForm.TransparencyKey;
338 // At the end of the copy we have to set the properties that we want
339 // to enforse (right now only the HelpButton on the command bar).
340 this.HelpButton = true;
342 // Set the callbacks for the events that this default implementation will handle.
343 this.Load += new EventHandler(FormLoad);
344 this.Closing += new System.ComponentModel.CancelEventHandler(OnClosing);
347 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.SetSite"]/*' />
348 /// <devdoc>
349 /// Set the site for this window.
350 /// </devdoc>
351 public void SetSite(IServiceProvider sp)
353 if (null != provider)
354 throw new InvalidOperationException();
356 provider = sp;
357 RegisterCommandTarget();
360 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.Dispose"]/*' />
361 /// <devdoc>
362 /// </devdoc>
363 protected override void Dispose(bool disposing)
365 if (disposing)
367 // Make sure that all the resources are closed.
368 OnClosing(this, new System.ComponentModel.CancelEventArgs());
370 base.Dispose(disposing);
373 private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
375 // Close the toolbar host.
376 if (null != toolbarHost)
378 toolbarHost.Close(0);
379 toolbarHost = null;
381 // Close and dispose the main pane.
382 if (null != containedForm)
384 ((IVsWindowPane)containedForm).ClosePane();
385 containedForm = null;
387 // Check if we are still registered as priority command target
388 if ( (0 != commandTargetCookie) && (null != provider) )
390 IVsRegisterPriorityCommandTarget registerCommandTarget = GetService(typeof(SVsRegisterPriorityCommandTarget)) as IVsRegisterPriorityCommandTarget;
391 if (null != registerCommandTarget)
392 registerCommandTarget.UnregisterPriorityCommandTarget(commandTargetCookie);
393 commandTargetCookie = 0;
395 if (null != e)
396 e.Cancel = false;
399 object IServiceProvider.GetService(System.Type serviceType)
401 if ( serviceType.IsEquivalentTo(typeof(IVsToolWindowToolbar)) )
402 return this;
404 if ( serviceType.IsEquivalentTo(typeof(IOleCommandTarget)) )
405 return commandService;
407 if ( (serviceType.IsEquivalentTo(typeof(IVsToolWindowToolbarHost))) && (null != ToolbarHost) )
408 return ToolbarHost;
410 return provider.GetService(serviceType);
413 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.ToolbarID"]/*' />
414 /// <devdoc>
415 /// Gets or Sets the CommandID of the toolbar contained in this dialog.
416 /// </devdoc>
417 public CommandID ToolbarID
419 get { return toolbarCommandId; }
420 set { toolbarCommandId = value; }
423 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.ToolbarLocation"]/*' />
424 /// <devdoc>
425 /// Location of the toolbar (Top, left, right ot bottom).
426 /// </devdoc>
427 public VSTWT_LOCATION ToolbarLocation
429 get { return toolbarLocation; }
430 set { toolbarLocation = value; }
433 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.ToolbarDropTarget"]/*' />
434 /// <summary>
435 /// If the toolwindow has a ToolBar, allows intercepting drag and drop operations on the toolbar.
436 /// Otherwise this is null
437 /// </summary>
438 public IDropTarget ToolbarDropTarget
440 get { return toolbarDropTarget; }
441 set { toolbarDropTarget = value; }
444 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.ToolbarHost"]/*' />
445 /// <devdoc>
446 /// Gets the IVsToolWindowToolbarHost interface for this window.
447 /// </devdoc>
448 public IVsToolWindowToolbarHost ToolbarHost
452 // Check if there is a cached pointer to the interface.
453 if (null != toolbarHost)
454 return toolbarHost;
456 // If no cached version exist, we have to get a new one
457 // from the UIShell service.
458 IVsUIShell uiShell = (IVsUIShell)provider.GetService(typeof(SVsUIShell));
459 NativeMethods.ThrowOnFailure(
460 uiShell.SetupToolbar(Handle, (IVsToolWindowToolbar)this, out toolbarHost));
461 return toolbarHost;
465 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.CommandService"]/*' />
466 /// <devdoc>
467 /// Returns the command service used to check the status or execute
468 /// the toolbar's commands.
469 /// </devdoc>
470 public IMenuCommandService CommandService
472 get { return commandService as IMenuCommandService; }
475 int IVsToolWindowToolbar.GetBorder(RECT[] rect)
477 // Check that the parameter is correct.
478 if ((null == rect) || (rect.Length != 1))
479 throw new ArgumentException("rect");
481 // Return the client area of this form.
482 rect[0].left = 0;
483 rect[0].top = 0;
484 rect[0].right = this.ClientSize.Width;
485 rect[0].bottom = this.ClientSize.Height;
487 return NativeMethods.S_OK;
490 int IVsToolWindowToolbar.SetBorderSpace(RECT[] rect)
492 // Check input parameter.
493 if ((null == rect) || (rect.Length != 1))
494 throw new ArgumentException("rect");
496 // Store the toolbar informations and resize the main pane to leave room
497 // for the commandbar.
498 toolbarRect = rect[0];
499 ResizePane();
501 return NativeMethods.S_OK;
504 [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
505 bool IMessageFilter.PreFilterMessage(ref Message m)
507 if (null != ToolbarHost)
509 int lResult;
510 int hr = ToolbarHost.ProcessMouseActivationModal(m.HWnd,(uint)m.Msg, (uint)m.WParam, (int)m.LParam, out lResult);
511 // Check for errors.
512 if ( NativeMethods.Failed(hr) )
513 return false;
514 // ProcessMouseActivationModal returns S_FALSE to stop the message processing, but this
515 // function have to return true in this case.
516 return (hr==NativeMethods.S_FALSE);
519 return false;
522 /// <include file='doc\DialogContainerWithToolbar.uex' path='docs/doc[@for="DialogContainerWithToolbar.ShowDialog"]/*' />
523 /// <devdoc>
524 /// Show this window as modal dialog.
525 /// </devdoc>
526 public new DialogResult ShowDialog()
528 // if we don't have a service provider we can not show the dialog correctly
529 if (null == provider)
530 throw new InvalidOperationException();
532 DialogResult result;
533 IMessageFilter filter = this as IMessageFilter;
535 // Make sure that there is non visual containment for this form
536 ShowDialogContainer dialogContainer = null;
537 if (this.Site == null)
539 dialogContainer = new ShowDialogContainer((IServiceProvider)this);
540 dialogContainer.Add(this);
545 // This form needs to install its message filter in order to
546 // let the toolbar process the mouse events.
547 Application.AddMessageFilter(filter);
549 // Show the modal dialog
550 result = base.ShowDialog();
552 finally
554 if (dialogContainer != null)
555 dialogContainer.Remove(this);
556 Application.RemoveMessageFilter(filter);
559 return result;
562 private void ResizePane()
564 // Get the size of the window.
565 System.Drawing.Size mySize = this.ClientSize;
567 // toolbarRect is not a real rectangle, it store the space that we have
568 // to free at the left, top, right and bottom of this form for the toolbar.
569 // So we have to move the main pane out of the way.
570 int x = toolbarRect.left;
571 int y = toolbarRect.top;
572 int width = mySize.Width - toolbarRect.left - toolbarRect.right;
573 int height = mySize.Height - toolbarRect.top - toolbarRect.bottom;
575 containedForm.Move(x, y, height, width);
578 private void ResizeForm(object sender, EventArgs e)
580 ResizePane();
581 if (ToolbarHost != null)
582 ToolbarHost.BorderChanged();
585 private void FormLoad(object sender, EventArgs e)
587 if (this.DesignMode)
588 return;
590 if (null == containedForm)
592 // Handle the case that the class was constructed with the parameterless
593 // constructor, so no container control is created.
594 // In this case we have to create a new control that will contain all the
595 // controls contained by this form and use it to create the window pane.
596 Control paneControl = new UserControl();
597 while (this.Controls.Count > 0)
599 Control ctl = this.Controls[0];
600 ctl.Parent = paneControl;
602 containedForm = new WindowPaneAdapter(this, paneControl);
603 controlSize = this.ClientSize;
606 System.Drawing.Size mySize = this.ClientSize;
608 // Check if this window has a toolbar.
609 if (null != toolbarCommandId)
611 Guid toolbarCommandSet = toolbarCommandId.Guid;
612 IVsToolWindowToolbarHost2 toolBarHost2 = (IVsToolWindowToolbarHost2)ToolbarHost;
613 NativeMethods.ThrowOnFailure(
614 toolBarHost2.AddToolbar2(toolbarLocation, ref toolbarCommandSet, (uint)toolbarCommandId.ID, toolbarDropTarget));
615 NativeMethods.ThrowOnFailure(ToolbarHost.Show(0));
616 NativeMethods.ThrowOnFailure(ToolbarHost.ForceUpdateUI());
619 // Now we have to resize the form to make room for the toolbar.
620 mySize.Width = controlSize.Width + toolbarRect.left + toolbarRect.right;
621 mySize.Height = controlSize.Height + toolbarRect.top + toolbarRect.bottom;
622 this.ClientSize = mySize;
624 // Find the coordinate of the main pane.
625 int x = toolbarRect.left;
626 int y = toolbarRect.top;
627 int width = mySize.Width - toolbarRect.left - toolbarRect.right;
628 int height = mySize.Height - toolbarRect.top - toolbarRect.bottom;
630 // Make sure that the pane is created.
631 containedForm.Create(x, y, height, width);
632 // Set the focus to the control
633 containedForm.Focus();
635 // Install the handler for the resize.
636 this.Resize += new EventHandler(ResizeForm);