mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-23 05:35:34 +08:00
added modified ProgressDialog from Ookii.Dialogs.
This commit is contained in:
parent
310c3cee4c
commit
cd5a820c48
@ -3,7 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:w="clr-namespace:Rnd.Windows"
|
||||
Title="{Binding Title}" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
ResizeMode="NoResize" SizeToContent="WidthAndHeight"
|
||||
ResizeMode="NoResize" SizeToContent="WidthAndHeight" ShowActivated="True"
|
||||
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBox x:Name="ErrorText" Text="{Binding Text}" IsReadOnly="True" Background="Transparent" BorderThickness="0" Margin="10"/>
|
||||
|
@ -95,9 +95,6 @@
|
||||
<HintPath>..\packages\NAudio.1.8.0\lib\net35\NAudio.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Ookii.Dialogs.Wpf">
|
||||
<HintPath>..\packages\Ookii.Dialogs.1.0\lib\net35\Ookii.Dialogs.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Controls.Input.Toolkit">
|
||||
@ -158,6 +155,10 @@
|
||||
<Compile Include="ListViewEx.cs" />
|
||||
<Compile Include="ModalWindow.cs" />
|
||||
<Compile Include="NAudio.cs" />
|
||||
<Compile Include="ProgressDialog\IProgressDialog.cs" />
|
||||
<Compile Include="ProgressDialog\ProgressDialog.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Shell.cs" />
|
||||
<Compile Include="Strings\guiStrings.Designer.cs">
|
||||
|
@ -34,7 +34,6 @@ using System.Diagnostics;
|
||||
using GameRes;
|
||||
using GARbro.GUI.Strings;
|
||||
using GARbro.GUI.Properties;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GARbro.GUI
|
||||
|
@ -34,7 +34,6 @@ using System.Windows.Input;
|
||||
using GameRes;
|
||||
using GARbro.GUI.Strings;
|
||||
using GARbro.GUI.Properties;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
|
@ -33,7 +33,6 @@ using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using GameRes;
|
||||
using GARbro.GUI.Strings;
|
||||
using GARbro.GUI.Properties;
|
||||
@ -114,6 +113,7 @@ namespace GARbro.GUI
|
||||
private bool m_skip_audio = false;
|
||||
private bool m_adjust_image_offset = false;
|
||||
private bool m_convert_audio;
|
||||
private bool m_ignore_errors;
|
||||
private ImageFormat m_image_format;
|
||||
private int m_extract_count;
|
||||
private int m_skip_count;
|
||||
@ -284,7 +284,7 @@ namespace GARbro.GUI
|
||||
var arc = m_fs.Source;
|
||||
int total = file_list.Count();
|
||||
int progress_count = 0;
|
||||
bool ignore_errors = false;
|
||||
m_ignore_errors = false;
|
||||
foreach (var entry in file_list)
|
||||
{
|
||||
if (m_progress_dialog.CancellationPending)
|
||||
@ -303,54 +303,18 @@ namespace GARbro.GUI
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
if (!ignore_errors)
|
||||
if (!m_ignore_errors)
|
||||
{
|
||||
IntPtr progress_handle = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
var error_text = string.Format ("{0}\n{1}\n{2}", "Failed to extract file",
|
||||
entry.Name, X.Message);
|
||||
bool dialog_result = false;
|
||||
m_main.Dispatcher.Invoke (() => {
|
||||
progress_handle = HideProgressDialog();
|
||||
var dialog = new FileErrorDialog ("File extraction error", error_text);
|
||||
dialog.Owner = m_main;
|
||||
dialog_result = dialog.ShowDialog() ?? false;
|
||||
ignore_errors = dialog.IgnoreErrors.IsChecked ?? false;
|
||||
});
|
||||
if (!dialog_result)
|
||||
break;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (progress_handle != IntPtr.Zero)
|
||||
ShowWindow (progress_handle, SW_SHOW);
|
||||
}
|
||||
var error_text = string.Format ("{0}\n{1}\n{2}", "Failed to extract file",
|
||||
entry.Name, X.Message);
|
||||
if (!m_main.Dispatcher.Invoke (() => ShowErrorDialog (error_text)))
|
||||
break;
|
||||
}
|
||||
++m_skip_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int SW_HIDE = 0;
|
||||
const int SW_SHOW = 5;
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr FindWindowEx (IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
||||
[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool ShowWindow (IntPtr hWnd, int nCmdShow);
|
||||
|
||||
IntPtr HideProgressDialog ()
|
||||
{
|
||||
// i just want to temporarily hide progress dialog when error window pops up, or at least force it
|
||||
// to background so it can't be interacted with until error dialog is resolved. Unfortunately
|
||||
// it's impossible with Ookii.Dialogs implementation aside from ugly hacks like this one.
|
||||
var found = FindWindowEx (IntPtr.Zero, IntPtr.Zero, null, m_progress_dialog.WindowTitle);
|
||||
if (IntPtr.Zero != found)
|
||||
ShowWindow (found, SW_HIDE);
|
||||
return found;
|
||||
}
|
||||
|
||||
void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format)
|
||||
{
|
||||
using (var decoder = arc.OpenImage (entry))
|
||||
@ -450,6 +414,31 @@ namespace GARbro.GUI
|
||||
throw new IOException ("File aready exists");
|
||||
}
|
||||
|
||||
bool ShowErrorDialog (string error_text)
|
||||
{
|
||||
var dialog = new FileErrorDialog ("File extraction error", error_text);
|
||||
var progress_dialog_hwnd = m_progress_dialog.GetWindowHandle();
|
||||
if (progress_dialog_hwnd != IntPtr.Zero)
|
||||
{
|
||||
var native_dialog = new WindowInteropHelper (dialog);
|
||||
native_dialog.Owner = progress_dialog_hwnd;
|
||||
NativeMethods.EnableWindow (progress_dialog_hwnd, false);
|
||||
EventHandler on_closed = null;
|
||||
on_closed = (s, e) => {
|
||||
NativeMethods.EnableWindow (progress_dialog_hwnd, true);
|
||||
dialog.Closed -= on_closed;
|
||||
};
|
||||
dialog.Closed += on_closed;
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog.Owner = m_main;
|
||||
}
|
||||
bool dialog_result = dialog.ShowDialog() ?? false;
|
||||
m_ignore_errors = dialog.IgnoreErrors.IsChecked ?? false;
|
||||
return dialog_result;
|
||||
}
|
||||
|
||||
void OnExtractComplete (object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
m_extract_in_progress = false;
|
||||
|
116
GUI/ProgressDialog/IProgressDialog.cs
Normal file
116
GUI/ProgressDialog/IProgressDialog.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GARbro.GUI.Interop
|
||||
{
|
||||
[ComImport, Guid ("F8383852-FCD3-11d1-A6B9-006097DF5BD4")]
|
||||
internal class ProgressDialogRCW
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport, Guid ("EBBC7C04-315E-11d2-B62F-006097DF5BD4"), CoClass (typeof(ProgressDialogRCW))]
|
||||
internal interface ProgressDialog : IProgressDialog
|
||||
{
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum ProgressDialogFlags : uint
|
||||
{
|
||||
Normal = 0x00000000,
|
||||
Modal = 0x00000001,
|
||||
AutoTime = 0x00000002,
|
||||
NoTime = 0x00000004,
|
||||
NoMinimize = 0x00000008,
|
||||
NoProgressBar = 0x00000010,
|
||||
MarqueeProgress = 0x00000020,
|
||||
NoCancel = 0x00000040
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum ProgressTimerAction : uint
|
||||
{
|
||||
Reset = 0x00000001,
|
||||
Pause = 0x00000002,
|
||||
Resume = 0x00000003
|
||||
}
|
||||
|
||||
[ComImport, Guid ("EBBC7C04-315E-11d2-B62F-006097DF5BD4"), InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IProgressDialog
|
||||
{
|
||||
|
||||
[PreserveSig]
|
||||
void StartProgressDialog(
|
||||
IntPtr hwndParent,
|
||||
[MarshalAs(UnmanagedType.IUnknown)]
|
||||
object punkEnableModless,
|
||||
ProgressDialogFlags dwFlags,
|
||||
IntPtr pvResevered
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
void StopProgressDialog();
|
||||
|
||||
[PreserveSig]
|
||||
void SetTitle(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string pwzTitle
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
void SetAnimation(
|
||||
IntPtr hInstAnimation,
|
||||
ushort idAnimation
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
bool HasUserCancelled();
|
||||
|
||||
[PreserveSig]
|
||||
void SetProgress(
|
||||
uint dwCompleted,
|
||||
uint dwTotal
|
||||
);
|
||||
[PreserveSig]
|
||||
void SetProgress64(
|
||||
ulong ullCompleted,
|
||||
ulong ullTotal
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
void SetLine(
|
||||
uint dwLineNum,
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string pwzString,
|
||||
[MarshalAs(UnmanagedType.VariantBool)]
|
||||
bool fCompactPath,
|
||||
IntPtr pvResevered
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
void SetCancelMsg(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string pwzCancelMsg,
|
||||
object pvResevered
|
||||
);
|
||||
|
||||
[PreserveSig]
|
||||
void Timer(
|
||||
ProgressTimerAction dwTimerAction,
|
||||
object pvResevered
|
||||
);
|
||||
}
|
||||
|
||||
[ComImport, Guid ("00000114-0000-0000-C000-000000000046"), InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IOleWindow
|
||||
{
|
||||
[PreserveSig]
|
||||
void GetWindow (out IntPtr phwnd);
|
||||
|
||||
[PreserveSig]
|
||||
void ContextSensitiveHelp ([MarshalAs(UnmanagedType.Bool)] bool fEnterMode);
|
||||
}
|
||||
}
|
713
GUI/ProgressDialog/ProgressDialog.cs
Normal file
713
GUI/ProgressDialog/ProgressDialog.cs
Normal file
@ -0,0 +1,713 @@
|
||||
// Modified ProgressDialog from Ookii.Dialogs
|
||||
//
|
||||
// Copyright © Sven Groot (Ookii.org) 2009
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1) Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// 3) Neither the name of the ORGANIZATION nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
public class ProgressDialog : Component
|
||||
{
|
||||
private class ProgressChangedData
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public string Description { get; set; }
|
||||
public object UserState { get; set; }
|
||||
}
|
||||
|
||||
private string _windowTitle;
|
||||
private string _text;
|
||||
private string _description;
|
||||
private Interop.IProgressDialog _dialog;
|
||||
private string _cancellationText;
|
||||
private bool _useCompactPathsForText;
|
||||
private bool _useCompactPathsForDescription;
|
||||
private bool _cancellationPending;
|
||||
private BackgroundWorker _backgroundWorker;
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the dialog is displayed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use this event to perform the operation that the dialog is showing the progress for.
|
||||
/// This event will be raised on a different thread than the UI thread.
|
||||
/// </remarks>
|
||||
public event DoWorkEventHandler DoWork;
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the operation completes.
|
||||
/// </summary>
|
||||
public event RunWorkerCompletedEventHandler RunWorkerCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when <see cref="ReportProgress(int,string,string,object)"/> is called.
|
||||
/// </summary>
|
||||
public event ProgressChangedEventHandler ProgressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProgressDialog"/> class.
|
||||
/// </summary>
|
||||
public ProgressDialog ()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ProgressBarStyle = ProgressBarStyle.ProgressBar;
|
||||
ShowCancelButton = true;
|
||||
MinimizeBox = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text in the progress dialog's title bar.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The text in the progress dialog's title bar. The default value is an empty string.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property must be set before <see cref="ShowDialog()"/> or <see cref="Show()"/> is called. Changing property has
|
||||
/// no effect while the dialog is being displayed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Localizable(true), Category("Appearance"), Description("The text in the progress dialog's title bar."), DefaultValue("")]
|
||||
public string WindowTitle
|
||||
{
|
||||
get { return _windowTitle ?? string.Empty; }
|
||||
set { _windowTitle = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a short description of the operation being carried out.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A short description of the operation being carried. The default value is an empty string.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the primary message to the user.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This property can be changed while the dialog is running, but may only be changed from the thread which
|
||||
/// created the progress dialog. The recommended method to change this value while the dialog is running
|
||||
/// is to use the <see cref="ReportProgress(int,string,string)"/> method.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Localizable(true), Category("Appearance"), Description("A short description of the operation being carried out.")]
|
||||
public string Text
|
||||
{
|
||||
get { return _text ?? string.Empty; }
|
||||
set
|
||||
{
|
||||
_text = value;
|
||||
if (_dialog != null)
|
||||
_dialog.SetLine (1, Text, UseCompactPathsForText, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether path strings in the <see cref="Text"/> property should be compacted if
|
||||
/// they are too large to fit on one line.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> to compact path strings if they are too large to fit on one line; otherwise,
|
||||
/// <see langword="false"/>. The default value is <see langword="false"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <note>
|
||||
/// This property requires Windows Vista or later. On older versions of Windows, it has no effect.
|
||||
/// </note>
|
||||
/// <para>
|
||||
/// This property can be changed while the dialog is running, but may only be changed from the thread which
|
||||
/// created the progress dialog.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Behavior"), Description("Indicates whether path strings in the Text property should be compacted if they are too large to fit on one line."), DefaultValue(false)]
|
||||
public bool UseCompactPathsForText
|
||||
{
|
||||
get { return _useCompactPathsForText; }
|
||||
set
|
||||
{
|
||||
_useCompactPathsForText = value;
|
||||
if (_dialog != null)
|
||||
_dialog.SetLine (1, Text, _useCompactPathsForText, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets additional details about the operation being carried out.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Additional details about the operation being carried out. The default value is an empty string.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This text is used to provide additional details beyond the <see cref="Text"/> property.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property can be changed while the dialog is running, but may only be changed from the thread which
|
||||
/// created the progress dialog. The recommended method to change this value while the dialog is running
|
||||
/// is to use the <see cref="ReportProgress(int,string,string)"/> method.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Localizable(true), Category("Appearance"), Description("Additional details about the operation being carried out."), DefaultValue("")]
|
||||
public string Description
|
||||
{
|
||||
get { return _description ?? string.Empty; }
|
||||
set
|
||||
{
|
||||
_description = value;
|
||||
if (_dialog != null)
|
||||
_dialog.SetLine (2, Description, UseCompactPathsForDescription, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether path strings in the <see cref="Description"/> property should be compacted if
|
||||
/// they are too large to fit on one line.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> to compact path strings if they are too large to fit on one line; otherwise,
|
||||
/// <see langword="false"/>. The default value is <see langword="false"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <note>
|
||||
/// This property requires Windows Vista or later. On older versions of Windows, it has no effect.
|
||||
/// </note>
|
||||
/// <para>
|
||||
/// This property can be changed while the dialog is running, but may only be changed from the thread which
|
||||
/// created the progress dialog.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Behavior"), Description("Indicates whether path strings in the Description property should be compacted if they are too large to fit on one line."), DefaultValue(false)]
|
||||
public bool UseCompactPathsForDescription
|
||||
{
|
||||
get { return _useCompactPathsForDescription; }
|
||||
set
|
||||
{
|
||||
_useCompactPathsForDescription = value;
|
||||
if( _dialog != null )
|
||||
_dialog.SetLine(2, Description, UseCompactPathsForDescription, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text that will be shown after the Cancel button is pressed.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The text that will be shown after the Cancel button is pressed.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property must be set before <see cref="ShowDialog()"/> or <see cref="Show()"/> is called. Changing property has
|
||||
/// no effect while the dialog is being displayed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Localizable(true), Category("Appearance"), Description("The text that will be shown after the Cancel button is pressed."), DefaultValue("")]
|
||||
public string CancellationText
|
||||
{
|
||||
get { return _cancellationText ?? string.Empty; }
|
||||
set { _cancellationText = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether an estimate of the remaining time will be shown.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if an estimate of remaining time will be shown; otherwise, <see langword="false"/>. The
|
||||
/// default value is <see langword="false"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property must be set before <see cref="ShowDialog()"/> or <see cref="Show()"/> is called. Changing property has
|
||||
/// no effect while the dialog is being displayed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Appearance"), Description("Indicates whether an estimate of the remaining time will be shown."), DefaultValue(false)]
|
||||
public bool ShowTimeRemaining { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the dialog has a cancel button.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if the dialog has a cancel button; otherwise, <see langword="false"/>. The default
|
||||
/// value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <note>
|
||||
/// This property requires Windows Vista or later; on older versions of Windows, the cancel button will always
|
||||
/// be displayed.
|
||||
/// </note>
|
||||
/// <para>
|
||||
/// The event handler for the <see cref="DoWork"/> event must periodically check the value of the
|
||||
/// <see cref="CancellationPending"/> property to see if the operation has been cancelled if this
|
||||
/// property is <see langword="true"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Setting this property to <see langword="false"/> is not recommended unless absolutely necessary.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Appearance"), Description("Indicates whether the dialog has a cancel button. Do not set to false unless absolutely necessary."), DefaultValue(true)]
|
||||
public bool ShowCancelButton { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the progress dialog has a minimize button.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if the dialog has a minimize button; otherwise, <see langword="false"/>. The default
|
||||
/// value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <note>
|
||||
/// This property has no effect on modal dialogs (which do not have a minimize button). It only applies
|
||||
/// to modeless dialogs shown by using the <see cref="Show()"/> method.
|
||||
/// </note>
|
||||
/// <para>
|
||||
/// This property must be set before <see cref="Show()"/> is called. Changing property has
|
||||
/// no effect while the dialog is being displayed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Window Style"), Description("Indicates whether the progress dialog has a minimize button."), DefaultValue(true)]
|
||||
public bool MinimizeBox { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the user has requested cancellation of the operation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the user has cancelled the progress dialog; otherwise, <see langword="false" />. The default is <see langword="false" />.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The event handler for the <see cref="DoWork"/> event must periodically check this property and abort the operation
|
||||
/// if it returns <see langword="true"/>.
|
||||
/// </remarks>
|
||||
[Browsable(false)]
|
||||
public bool CancellationPending
|
||||
{
|
||||
get
|
||||
{
|
||||
_backgroundWorker.ReportProgress (-1); // Call with an out-of-range percentage will update the value of
|
||||
// _cancellationPending but do nothing else.
|
||||
return _cancellationPending;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether a regular or marquee style progress bar should be used.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// One of the values of <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle"/>.
|
||||
/// The default value is <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.ProgressBar"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <note>
|
||||
/// Operating systems older than Windows Vista do not support marquee progress bars on the progress dialog. On those operating systems, the
|
||||
/// progress bar will be hidden completely if this property is <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.MarqueeProgressBar"/>.
|
||||
/// </note>
|
||||
/// <para>
|
||||
/// When this property is set to <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.ProgressBar" />, use the <see cref="ReportProgress(int)"/> method to set
|
||||
/// the value of the progress bar. When this property is set to <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.MarqueeProgressBar"/>
|
||||
/// you can still use the <see cref="ReportProgress(int,string,string)"/> method to update the text of the dialog,
|
||||
/// but the percentage will be ignored.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This property must be set before <see cref="ShowDialog()"/> or <see cref="Show()"/> is called. Changing property has
|
||||
/// no effect while the dialog is being displayed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Category("Appearance"), Description("Indicates the style of the progress bar."), DefaultValue(ProgressBarStyle.ProgressBar)]
|
||||
public ProgressBarStyle ProgressBarStyle { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the <see cref="ProgressDialog"/> is running an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if the <see cref="ProgressDialog"/> is running an asynchronous operation;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </value>
|
||||
[Browsable(false)]
|
||||
public bool IsBusy
|
||||
{
|
||||
get { return _backgroundWorker.IsBusy; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the progress dialog as a modeless dialog.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This function will not block the parent window and will return immediately.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
|
||||
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
|
||||
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
|
||||
/// the <see cref="DoWork"/> event handler.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void Show ()
|
||||
{
|
||||
Show (null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the progress dialog as a modeless dialog.
|
||||
/// </summary>
|
||||
/// <param name="argument">A parameter for use by the background operation to be executed in the <see cref="DoWork"/> event handler.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This function will not block the parent window and return immediately.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
|
||||
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
|
||||
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
|
||||
/// the <see cref="DoWork"/> event handler.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void Show (object argument)
|
||||
{
|
||||
RunProgressDialog (IntPtr.Zero, argument);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the progress dialog as a modal dialog.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The ShowDialog function for most .Net dialogs will not return until the dialog is closed. However,
|
||||
/// the <see cref="ShowDialog()"/> function for the <see cref="ProgressDialog"/> class will return immediately.
|
||||
/// The parent window will be disabled as with all modal dialogs.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
|
||||
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
|
||||
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
|
||||
/// the <see cref="DoWork"/> event handler.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The progress dialog's window will appear in the taskbar. This behaviour is also contrary to most .Net dialogs,
|
||||
/// but is part of the underlying native progress dialog API so cannot be avoided.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// When possible, it is recommended that you use a modeless dialog using the <see cref="Show()"/> function.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void ShowDialog()
|
||||
{
|
||||
ShowDialog (null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the progress dialog as a modal dialog.
|
||||
/// </summary>
|
||||
/// <param name="owner">The window that owns the dialog.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The ShowDialog function for most .Net dialogs will not return until the dialog is closed. However,
|
||||
/// the <see cref="ShowDialog()"/> function for the <see cref="ProgressDialog"/> class will return immediately.
|
||||
/// The parent window will be disabled as with all modal dialogs.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
|
||||
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
|
||||
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
|
||||
/// the <see cref="DoWork"/> event handler.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The progress dialog's window will appear in the taskbar. This behaviour is also contrary to most .Net dialogs,
|
||||
/// but is part of the underlying native progress dialog API so cannot be avoided.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// When possible, it is recommended that you use a modeless dialog using the <see cref="Show()"/> function.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void ShowDialog (Window owner)
|
||||
{
|
||||
ShowDialog (owner, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the progress dialog as a modal dialog.
|
||||
/// </summary>
|
||||
/// <param name="owner">The window that owns the dialog.</param>
|
||||
/// <param name="argument">A parameter for use by the background operation to be executed in the <see cref="DoWork"/> event handler.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The ShowDialog function for most .Net dialogs will not return until the dialog is closed. However,
|
||||
/// the <see cref="ShowDialog()"/> function for the <see cref="ProgressDialog"/> class will return immediately.
|
||||
/// The parent window will be disabled as with all modal dialogs.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
|
||||
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
|
||||
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
|
||||
/// the <see cref="DoWork"/> event handler.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The progress dialog's window will appear in the taskbar. This behaviour is also contrary to most .Net dialogs,
|
||||
/// but is part of the underlying native progress dialog API so cannot be avoided.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// When possible, it is recommended that you use a modeless dialog using the <see cref="Show()"/> function.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void ShowDialog (Window owner, object argument)
|
||||
{
|
||||
RunProgressDialog (owner == null ? NativeMethods.GetActiveWindow() : new WindowInteropHelper(owner).Handle, argument);
|
||||
}
|
||||
|
||||
const int SW_HIDE = 0;
|
||||
const int SW_SHOW = 5;
|
||||
|
||||
public void Hide ()
|
||||
{
|
||||
if (null == _dialog)
|
||||
return;
|
||||
var hwnd = GetWindowHandle();
|
||||
if (hwnd != IntPtr.Zero)
|
||||
NativeMethods.ShowWindow (hwnd, SW_HIDE);
|
||||
}
|
||||
|
||||
public void Restore ()
|
||||
{
|
||||
if (null == _dialog)
|
||||
return;
|
||||
var hwnd = GetWindowHandle();
|
||||
if (hwnd != IntPtr.Zero)
|
||||
NativeMethods.ShowWindow (hwnd, SW_SHOW);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get win32 handle of the progress dialog window.
|
||||
/// </summary>
|
||||
public IntPtr GetWindowHandle ()
|
||||
{
|
||||
var ole = _dialog as Interop.IOleWindow;
|
||||
if (null == ole)
|
||||
return IntPtr.Zero;
|
||||
IntPtr hwnd;
|
||||
ole.GetWindow (out hwnd);
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the dialog's progress bar.
|
||||
/// </summary>
|
||||
/// <param name="percentProgress">The percentage, from 0 to 100, of the operation that is complete.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Call this method from the <see cref="DoWork"/> event handler if you want to report progress.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This method has no effect is <see cref="ProgressBarStyle"/> is <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.MarqueeProgressBar"/>
|
||||
/// or <see cref="Ookii.Dialogs.Wpf.ProgressBarStyle.None"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="percentProgress"/> is out of range.</exception>
|
||||
/// <exception cref="InvalidOperationException">The progress dialog is not currently being displayed.</exception>
|
||||
public void ReportProgress (int percentProgress)
|
||||
{
|
||||
ReportProgress (percentProgress, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the dialog's progress bar.
|
||||
/// </summary>
|
||||
/// <param name="percentProgress">The percentage, from 0 to 100, of the operation that is complete.</param>
|
||||
/// <param name="text">The new value of the progress dialog's primary text message, or <see langword="null"/> to leave the value unchanged.</param>
|
||||
/// <param name="description">The new value of the progress dialog's additional description message, or <see langword="null"/> to leave the value unchanged.</param>
|
||||
/// <remarks>Call this method from the <see cref="DoWork"/> event handler if you want to report progress.</remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="percentProgress"/> is out of range.</exception>
|
||||
/// <exception cref="InvalidOperationException">The progress dialog is not currently being displayed.</exception>
|
||||
public void ReportProgress (int percentProgress, string text, string description)
|
||||
{
|
||||
ReportProgress (percentProgress, text, description, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the dialog's progress bar.
|
||||
/// </summary>
|
||||
/// <param name="percentProgress">The percentage, from 0 to 100, of the operation that is complete.</param>
|
||||
/// <param name="text">The new value of the progress dialog's primary text message, or <see langword="null"/> to leave the value unchanged.</param>
|
||||
/// <param name="description">The new value of the progress dialog's additional description message, or <see langword="null"/> to leave the value unchanged.</param>
|
||||
/// <param name="userState">A state object that will be passed to the <see cref="ProgressChanged"/> event handler.</param>
|
||||
/// <remarks>Call this method from the <see cref="DoWork"/> event handler if you want to report progress.</remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="percentProgress"/> is out of range.</exception>
|
||||
/// <exception cref="InvalidOperationException">The progress dialog is not currently being displayed.</exception>
|
||||
public void ReportProgress (int percentProgress, string text, string description, object userState)
|
||||
{
|
||||
if (percentProgress < 0 || percentProgress > 100)
|
||||
throw new ArgumentOutOfRangeException ("percentProgress");
|
||||
if (_dialog == null)
|
||||
throw new InvalidOperationException ("The progress dialog is not shown.");
|
||||
_backgroundWorker.ReportProgress (percentProgress, new ProgressChangedData { Text = text, Description = description, UserState = userState });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="DoWork"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="DoWorkEventArgs"/> containing data for the event.</param>
|
||||
protected virtual void OnDoWork (DoWorkEventArgs e)
|
||||
{
|
||||
var handler = DoWork;
|
||||
if (handler != null)
|
||||
handler (this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="RunWorkerCompleted"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="EventArgs"/> containing data for the event.</param>
|
||||
protected virtual void OnRunWorkerCompleted (RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var handler = RunWorkerCompleted;
|
||||
if (handler != null)
|
||||
handler (this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="ProgressChanged"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="ProgressChangedEventArgs"/> containing data for the event.</param>
|
||||
protected virtual void OnProgressChanged (ProgressChangedEventArgs e)
|
||||
{
|
||||
var handler = ProgressChanged;
|
||||
if (handler != null)
|
||||
handler (this, e);
|
||||
}
|
||||
|
||||
private void RunProgressDialog (IntPtr owner, object argument)
|
||||
{
|
||||
if (_backgroundWorker.IsBusy)
|
||||
throw new InvalidOperationException ("The progress dialog is already running.");
|
||||
|
||||
_cancellationPending = false;
|
||||
_dialog = new Interop.ProgressDialog();
|
||||
_dialog.SetTitle (WindowTitle);
|
||||
|
||||
if (CancellationText.Length > 0)
|
||||
_dialog.SetCancelMsg (CancellationText, null);
|
||||
_dialog.SetLine (1, Text, UseCompactPathsForText, IntPtr.Zero);
|
||||
_dialog.SetLine (2, Description, UseCompactPathsForDescription, IntPtr.Zero);
|
||||
|
||||
var flags = Interop.ProgressDialogFlags.Normal;
|
||||
if (owner != IntPtr.Zero)
|
||||
flags |= Interop.ProgressDialogFlags.Modal;
|
||||
switch (ProgressBarStyle)
|
||||
{
|
||||
case ProgressBarStyle.None:
|
||||
flags |= Interop.ProgressDialogFlags.NoProgressBar;
|
||||
break;
|
||||
case ProgressBarStyle.MarqueeProgressBar:
|
||||
if (NativeMethods.IsWindowsVistaOrLater)
|
||||
flags |= Interop.ProgressDialogFlags.MarqueeProgress;
|
||||
else
|
||||
flags |= Interop.ProgressDialogFlags.NoProgressBar; // Older than Vista doesn't support marquee.
|
||||
break;
|
||||
}
|
||||
if( ShowTimeRemaining )
|
||||
flags |= Interop.ProgressDialogFlags.AutoTime;
|
||||
if( !ShowCancelButton )
|
||||
flags |= Interop.ProgressDialogFlags.NoCancel;
|
||||
if( !MinimizeBox )
|
||||
flags |= Interop.ProgressDialogFlags.NoMinimize;
|
||||
|
||||
_dialog.StartProgressDialog (owner, null, flags, IntPtr.Zero);
|
||||
_backgroundWorker.RunWorkerAsync (argument);
|
||||
}
|
||||
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
_backgroundWorker = new BackgroundWorker();
|
||||
_backgroundWorker.WorkerReportsProgress = true;
|
||||
_backgroundWorker.WorkerSupportsCancellation = true;
|
||||
_backgroundWorker.DoWork += new DoWorkEventHandler (_backgroundWorker_DoWork);
|
||||
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler (_backgroundWorker_RunWorkerCompleted);
|
||||
_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler (_backgroundWorker_ProgressChanged);
|
||||
|
||||
}
|
||||
|
||||
private void _backgroundWorker_DoWork (object sender, DoWorkEventArgs e)
|
||||
{
|
||||
OnDoWork (e);
|
||||
}
|
||||
|
||||
private void _backgroundWorker_RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
_dialog.StopProgressDialog();
|
||||
Marshal.ReleaseComObject (_dialog);
|
||||
_dialog = null;
|
||||
|
||||
OnRunWorkerCompleted (new RunWorkerCompletedEventArgs((!e.Cancelled && e.Error == null) ? e.Result : null, e.Error, e.Cancelled));
|
||||
}
|
||||
|
||||
private void _backgroundWorker_ProgressChanged (object sender, ProgressChangedEventArgs e)
|
||||
{
|
||||
_cancellationPending = _dialog.HasUserCancelled();
|
||||
// ReportProgress doesn't allow values outside this range. However, CancellationPending will call
|
||||
// BackgroundWorker.ReportProgress directly with a value that is outside this range to update the value of the property.
|
||||
if (e.ProgressPercentage >= 0 && e.ProgressPercentage <= 100)
|
||||
{
|
||||
_dialog.SetProgress ((uint)e.ProgressPercentage, 100);
|
||||
var data = e.UserState as ProgressChangedData;
|
||||
if (data != null)
|
||||
{
|
||||
if (data.Text != null)
|
||||
Text = data.Text;
|
||||
if (data.Description != null)
|
||||
Description = data.Description;
|
||||
OnProgressChanged (new ProgressChangedEventArgs (e.ProgressPercentage, data.UserState));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the type of progress on a task dialog.
|
||||
/// </summary>
|
||||
public enum ProgressBarStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// No progress bar is displayed on the dialog.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// A regular progress bar is displayed on the dialog.
|
||||
/// </summary>
|
||||
ProgressBar,
|
||||
/// <summary>
|
||||
/// A marquee progress bar is displayed on the dialog. Use this value for operations
|
||||
/// that cannot report concrete progress information.
|
||||
/// </summary>
|
||||
MarqueeProgressBar
|
||||
}
|
||||
}
|
@ -35,6 +35,14 @@ namespace GARbro.GUI
|
||||
{
|
||||
internal class NativeMethods
|
||||
{
|
||||
public static bool IsWindowsVistaOrLater
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= new Version (6, 0, 6000);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport ("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern int StrCmpLogicalW (string psz1, string psz2);
|
||||
|
||||
@ -46,6 +54,15 @@ namespace GARbro.GUI
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern int ReleaseDC (IntPtr hWnd, IntPtr hDc);
|
||||
|
||||
[DllImport ("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
internal static extern IntPtr GetActiveWindow();
|
||||
|
||||
[DllImport ("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ShowWindow (IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport ("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool EnableWindow (IntPtr hWnd, bool bEnable);
|
||||
}
|
||||
|
||||
public static class Desktop
|
||||
|
Loading…
Reference in New Issue
Block a user