Created
May 8, 2021 21:17
-
-
Save htsign/06a4a3bb2202b844dc4b22a0952c487a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// required: FSharp.Control.AsyncSeq | |
open FSharp.Control | |
open System.Diagnostics | |
open System.Drawing | |
open System.Windows.Forms | |
let inline initCollectionWithCtor< ^a, 'b, 'c when ^a : (member Add : 'b -> 'c)> items collection = | |
let add xs x = (^a : (member Add : 'b -> 'c) (xs, x)) | |
items |> List.fold (fun (xs : 'a) x -> add xs x |> ignore; xs) collection | |
let inline initCollection< ^a, 'b, 'c when ^a : (new : unit -> 'a) and ^a : (member Add : 'b -> 'c)> items = | |
initCollectionWithCtor items (new 'a()) | |
type Form1() as self = | |
inherit Form(Text = "Task Dialog Demos", Size = Size(600, 400)) | |
do | |
let currentButtonCount = ref 0 | |
let addButtonForAction name action = | |
incr currentButtonCount | |
let nextButton = !currentButtonCount | |
let button = | |
new Button( | |
Text = name, | |
Size = Size(180, 33), | |
Location = Point(nextButton / 20 * 200 + 20, nextButton % 20 * 40)) | |
button.Click.Add <| fun _ -> action() | |
self.Controls.Add button | |
addButtonForAction "Confirmation Dialog (3x)" self.ShowSimpleTaskDialog | |
addButtonForAction "Close Document Conformation" self.ShowCloseDocumentTaskDialog | |
addButtonForAction "Minesweeper Difficulty" self.ShowMinesweeperDifficultySelectionTaskDialog | |
addButtonForAction "Auto-Closing Dialog" self.ShowAutoClosingTaskDialog | |
addButtonForAction "Multi-Page Dialog (modeless)" self.ShowMultiPageTaskDialog | |
addButtonForAction "Elevation Required" self.ShowElevatedProcessTaskDialog | |
addButtonForAction "Events Demo" self.ShowEventsDemoTaskDialog | |
member private _.ShowSimpleTaskDialog () = | |
let messageBoxResult = | |
MessageBox.Show( | |
self, | |
text = "Stopping the operation might leave your database in a corrupted state. Are you sure you want to stop?", | |
caption = "Confirmation [Message Box]", | |
buttons = MessageBoxButtons.YesNo, | |
icon = MessageBoxIcon.Warning, | |
defaultButton = MessageBoxDefaultButton.Button2) | |
if messageBoxResult = DialogResult.Yes then | |
printfn "User confirmed to stop the operation." | |
let result = | |
TaskDialog.ShowDialog( | |
self, | |
TaskDialogPage( | |
Text = "Stopping the operation might leave your database in a corrupted state.", | |
Heading = "Are you sure you want to stop?", | |
Caption = "Confirmation (Task Dialog)", | |
Buttons = initCollection [TaskDialogButton.Yes; TaskDialogButton.No], | |
Icon = TaskDialogIcon.Warning, | |
DefaultButton = TaskDialogButton.No)) | |
if result = TaskDialogButton.Yes then | |
printfn "User confirmed to stop the operation." | |
let page = | |
TaskDialogPage( | |
Heading = "Are you sure you want to stop?", | |
Text = "Stopping the operation might leave your database in a corrupted state.", | |
Caption = "Confirmation (Task Dialog)", | |
Icon = TaskDialogIcon.Warning, | |
AllowCancel = true, | |
Verification = TaskDialogVerificationCheckBox "Do not show again", | |
Buttons = initCollection [TaskDialogButton.Yes; TaskDialogButton.No], | |
DefaultButton = TaskDialogButton.No) | |
let resultButton = TaskDialog.ShowDialog(self, page) | |
if resultButton = TaskDialogButton.Yes then | |
printfn (if page.Verification.Checked | |
then "Do not show this confirmation again." | |
else "User confirmed to stop the operation.") | |
member private _.ShowCloseDocumentTaskDialog () = | |
let btnCancel = TaskDialogButton.Cancel | |
let btnSave = TaskDialogButton "&Save" | |
let btnDontSave = TaskDialogButton "Do&n't save" | |
let page = | |
TaskDialogPage( | |
Caption = "My Application", | |
Heading = "Do you want to save changes to Untitled?", | |
Buttons = initCollection [btnCancel; btnSave; btnDontSave]) | |
let result = TaskDialog.ShowDialog(self, page) | |
printfn (if result = btnSave | |
then "Saving" | |
elif result = btnDontSave | |
then "Not saving" | |
else "Canceling") | |
member private _.ShowMinesweeperDifficultySelectionTaskDialog () = | |
let page = | |
TaskDialogPage( | |
Caption = "Minesweeper", | |
Heading = "What level of difficulty do you want to play?", | |
AllowCancel = true, | |
Footnote = TaskDialogFootnote "Note: You can change the difficulty level later by clicking Options on the Game menu.", | |
Buttons = initCollection [ | |
TaskDialogCommandLinkButton("&Beginner", "10 mines, 9 x 9 tile grid", Tag = 10) | |
TaskDialogCommandLinkButton("&Intermediate", "40 mines, 16 x 16 tile grid", Tag = 40) | |
TaskDialogCommandLinkButton("&Advanced", "99 mines, 16 x 30 tile grid", Tag = 99) | |
]) | |
let result = TaskDialog.ShowDialog(self, page) | |
printfn "%s" ( | |
match result.Tag with | |
| :? int as resultingMines -> sprintf "Playing with %d mines..." resultingMines | |
| _ -> "User canceled.") | |
member private _.ShowAutoClosingTaskDialog () = | |
let format = sprintf "Reconnecting in %d seconds..." | |
let remainingTenthSeconds = ref 50 | |
let reconnectButton = TaskDialogButton "&Reconnect now" | |
let cancelButton = TaskDialogButton.Cancel | |
let page = | |
TaskDialogPage( | |
Heading = "Connection lost; reconnecting...", | |
Text = format ((!remainingTenthSeconds + 9) / 10), | |
Icon = new TaskDialogIcon(self.Icon), | |
ProgressBar = TaskDialogProgressBar TaskDialogProgressBarState.Paused, | |
Buttons = initCollection [reconnectButton; cancelButton]) | |
use timer = new Timer(Enabled = true, Interval = 100) | |
timer.Tick.Add <| fun _ -> | |
decr remainingTenthSeconds | |
if !remainingTenthSeconds > 0 then | |
page.Text <- format ((!remainingTenthSeconds + 9) / 10) | |
page.ProgressBar.Value <- 100 - !remainingTenthSeconds * 2 | |
else | |
timer.Enabled <- false | |
reconnectButton.PerformClick() | |
let result = TaskDialog.ShowDialog(self, page) | |
printfn (if result = reconnectButton | |
then "Reconnecting." | |
else "Not reconnecting.") | |
member private _.ShowMultiPageTaskDialog () = | |
let initialButtonYes = TaskDialogButton.Yes | |
initialButtonYes.Enabled <- false | |
initialButtonYes.AllowCloseDialog <- false | |
let initialPage = | |
TaskDialogPage( | |
Caption = "My Application", | |
Heading = "Clean up database?", | |
Text = "Do you really want to do a clean-up?\nThis action is irreversible!", | |
Icon = TaskDialogIcon.ShieldWarningYellowBar, | |
AllowCancel = true, | |
AllowMinimize = true, | |
Verification = TaskDialogVerificationCheckBox "I know what I'm doing", | |
Buttons = initCollection [TaskDialogButton.No; initialButtonYes], | |
DefaultButton = TaskDialogButton.No) | |
let inProgressPage = | |
let inProgressCloseButton = TaskDialogButton.Close | |
inProgressCloseButton.Enabled <- false | |
let invisibleCancelButton = TaskDialogButton.Cancel | |
invisibleCancelButton.Visible <- false | |
invisibleCancelButton.AllowCloseDialog <- false | |
TaskDialogPage( | |
Caption = "My Application", | |
Heading = "Operation in progress...", | |
Text = "Please wait while the operation is in progress.", | |
Icon = TaskDialogIcon.Information, | |
AllowMinimize = true, | |
ProgressBar = TaskDialogProgressBar TaskDialogProgressBarState.Marquee, | |
Expander = TaskDialogExpander("Initializing...", Position = TaskDialogExpanderPosition.AfterFootnote), | |
Buttons = initCollection [inProgressCloseButton; invisibleCancelButton]) | |
let showResultsButton = TaskDialogCommandLinkButton "Show &Results" :> TaskDialogButton | |
let finishedPage = | |
TaskDialogPage( | |
Caption = "My Application", | |
Heading = "Success!", | |
Text = "The operation finished.", | |
Icon = TaskDialogIcon.ShieldSuccessGreenBar, | |
AllowMinimize = true, | |
Buttons = initCollection [TaskDialogButton.Close; showResultsButton]) | |
let checkBox = initialPage.Verification | |
checkBox.CheckedChanged.Add <| fun _ -> | |
initialButtonYes.Enabled <- checkBox.Checked | |
initialButtonYes.Click.Add <| fun _ -> | |
initialPage.Navigate inProgressPage | |
inProgressPage.Created.Add <| fun _ -> | |
let progressBar = inProgressPage.ProgressBar | |
let streamBackgroundOperationProgressAsync () = | |
asyncSeq { | |
do! Async.Sleep 2800 | |
for i in seq { 0 .. 4 .. 100 } do | |
yield i | |
do! Async.Sleep 200 } | |
asyncSeq { | |
for progressValue in streamBackgroundOperationProgressAsync () do | |
if progressBar.State = TaskDialogProgressBarState.Marquee then | |
progressBar.State <- TaskDialogProgressBarState.Normal | |
progressBar.Value <- progressValue | |
inProgressPage.Expander.Text <- sprintf "Progress: %d %%" progressValue | |
inProgressPage.Navigate finishedPage } | |
|> AsyncSeq.iter ignore | |
|> Async.StartImmediate | |
let result = TaskDialog.ShowDialog initialPage | |
if result = showResultsButton then | |
printfn "Showing Results!" | |
member private _.ShowElevatedProcessTaskDialog () = | |
let page = | |
let restartNowButton = TaskDialogCommandLinkButton "&Restart now" :> TaskDialogButton | |
restartNowButton.ShowShieldIcon <- true | |
restartNowButton.Click.Add <| fun _ -> | |
restartNowButton.AllowCloseDialog <- true | |
restartNowButton.Enabled <- false | |
let psi = | |
ProcessStartInfo("cmd.exe", "/k echo Hi, this is an elevated command prompt.", | |
UseShellExecute = true, | |
Verb = "runas") | |
try | |
match Process.Start(psi) with | |
| null -> () | |
| x -> x.Dispose() | |
with | |
| :? System.ComponentModel.Win32Exception as ex when ex.NativeErrorCode = 1223 -> | |
restartNowButton.AllowCloseDialog <- false | |
restartNowButton.Enabled <- true | |
TaskDialogPage( | |
Heading = "Settings saved - Service Restart required", | |
Text = "The service needs to be restarted to apply the changes.", | |
Icon = TaskDialogIcon.ShieldSuccessGreenBar, | |
Buttons = initCollection [TaskDialogButton.Close; restartNowButton]) | |
TaskDialog.ShowDialog(self, page) |> ignore | |
member private _.ShowEventsDemoTaskDialog () = | |
let clicked sender _ = printfn "Button '%O' Click" sender | |
let page1 = | |
let buttonOk = TaskDialogButton.OK | |
let buttonHelp = TaskDialogButton.Help | |
let buttonCancelClose = | |
TaskDialogCommandLinkButton("C&ancel Close", allowCloseDialog = false) :> TaskDialogButton | |
let buttonShowInnerDialog = | |
TaskDialogCommandLinkButton("&Show (modeless) Inner Dialog", "(and don't cancel the Close") :> TaskDialogButton | |
let clickedHandler = System.EventHandler clicked | |
buttonOk.Click.AddHandler clickedHandler | |
buttonHelp.Click.AddHandler clickedHandler | |
buttonCancelClose.Click.AddHandler clickedHandler | |
buttonShowInnerDialog.Click.AddHandler <| System.EventHandler(fun sender e -> | |
clicked sender e | |
TaskDialog.ShowDialog(TaskDialogPage(Text = "Inner Dialog")) |> ignore | |
printfn "(returns) Button '%O' Click" sender) | |
TaskDialogPage( | |
Caption = self.Text, | |
Heading = "Event Demo", | |
Text = "Event Demo...", | |
Buttons = | |
initCollection | |
[ | |
buttonOk | |
buttonHelp | |
buttonCancelClose | |
buttonShowInnerDialog | |
], | |
Expander = TaskDialogExpander("Expander", Position = TaskDialogExpanderPosition.AfterFootnote), | |
Verification = TaskDialogVerificationCheckBox "&CheckBox") | |
let buttonNavigate = TaskDialogCommandLinkButton("&Navigate", allowCloseDialog = false) | |
page1.Buttons.Add buttonNavigate | |
buttonNavigate.Click.AddHandler <| System.EventHandler(fun sender e -> | |
clicked sender e | |
let page2 = TaskDialogPage(Heading = "AfterNavigation.", Buttons = initCollection [TaskDialogButton.Close]) | |
page2.Created.Add <| fun _ -> printfn "Page2 Created" | |
page2.Destroyed.Add <| fun _ -> printfn "Page2 Destoryed" | |
page1.Navigate page2) | |
page1.Created.Add <| fun _ -> printfn "Page1 Created" | |
page1.Destroyed.Add <| fun _ -> printfn "Page1 Destoroyed" | |
page1.HelpRequest.Add <| fun _ -> printfn "Page1 HelpRequest" | |
page1.Expander.ExpandedChanged.Add <| fun _ -> printfn "Expander ExpandedChanged: %b" page1.Expander.Expanded | |
page1.Verification.CheckedChanged.Add <| fun _ -> printfn "CheckBox CheckedChanged: %b" page1.Verification.Checked | |
let radioButton1 = page1.RadioButtons.Add "Radi&oButton 1" | |
let radioButton2 = page1.RadioButtons.Add "RadioB&utton 2" | |
radioButton1.CheckedChanged.Add <| fun _ -> printfn "RadioButton1 CheckedChanged: %b" radioButton1.Checked | |
radioButton2.CheckedChanged.Add <| fun _ -> printfn "RadioButton2 CheckedChanged: %b" radioButton2.Checked | |
let dialogResult = TaskDialog.ShowDialog page1 | |
printfn "---> Dialog Result: %O" dialogResult | |
[<EntryPoint; System.STAThread>] | |
do | |
Application.SetHighDpiMode HighDpiMode.SystemAware |> ignore | |
Application.EnableVisualStyles() | |
Application.Run(new Form1()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment