找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1572|回复: 0

[分享] TaskDialog with progress bar

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-6-13 01:20:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
TaskDialog with progress bar                         By Adam Nagy
I found the ShowProgressBar property of TaskDialog, but it's not clear how I could make use of it. Any samples?
Solution
You need to assign a callback function to the TaskDialog that can be called continously so you can do parts of the lengthy process you want to show a progress bar for. Here is a sample that shows how you can do it.
As you can see it from the comments below there are issues with this on 64 bit OS. My colleague Dianne Phillips looked into it and it turned out to be some issue with assigning your own data to the TaskDialog like so:
td.CallbackData = new MyData();
Her modified code circumvents the issue in two ways: either by using a global variable or assigning your data as an IntPtr. Both ways seem to work fine on 64 bit OS as well.
using System;
using Autodesk.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using acApp = Autodesk.AutoCAD.ApplicationServices.Application;

using System.Threading;
using System.Globalization;
using System.Runtime.InteropServices;
using WinForms = System.Windows.Forms;

[assembly: CommandClass(typeof(TaskDialogTest.Commands))]
[assembly: ExtensionApplication(typeof(TaskDialogTest.Module))]

namespace TaskDialogTest
{
  // to make the AutoCAD managed runtime happy
  public class Module : IExtensionApplication
  {
    public void Initialize()
    {
    }
    public void Terminate()
    {
    }
  }

  public class Commands
  {
    public class MyVarOverride : IDisposable
    {
      object oldValue;
      string varName;

      public MyVarOverride(string name, object value)
      {
        varName = name;
        oldValue = acApp.GetSystemVariable(name);
        acApp.SetSystemVariable(name, value);
      }

      public void Dispose()
      {
        acApp.SetSystemVariable(varName, oldValue);
      }
    }

    public class MyData
    {
      public int counter = 0;
      public bool delay = true;

      // since the callback data can be reused, be sure
      // to reset it before invoking the task dialog
      public void Reset()
      {
        counter = 0;
        delay = true;
      }
    }

    #region HELPER METHODS

    // helper method for processing the callback both in the
    // data-member case and the callback argument case
    private bool handleCallback(ActiveTaskDialog taskDialog,
                                TaskDialogCallbackArgs args,
                                MyData callbackData)
    {
      // This gets called continuously until we finished completely
      if (args.Notification == TaskDialogNotification.Timer)
      {
        // To make it longer we do some delay in every second call
        if (callbackData.delay)
        {
          System.Threading.Thread.Sleep(1000);
        }
        else
        {
          callbackData.counter += 10;
          taskDialog.SetProgressBarRange(0, 100);
          taskDialog.SetProgressBarPosition(
              callbackData.counter);

          // This is the main action - adding 100 lines 1 by 1
          Database db = HostApplicationServices.WorkingDatabase;
          Transaction tr = db.TransactionManager.TopTransaction;
          BlockTable bt = (BlockTable)tr.GetObject(
            db.BlockTableId, OpenMode.ForRead);
          BlockTableRecord ms = (BlockTableRecord)tr.GetObject(
            bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
          Line ln = new Line(
            new Point3d(0, callbackData.counter, 0),
            new Point3d(10, callbackData.counter, 0));
          ms.AppendEntity(ln);
          tr.AddNewlyCreatedDBObject(ln, true);

          // To make it appear on the screen - might be a bit costly
          tr.TransactionManager.QueueForGraphicsFlush();
          acApp.DocumentManager.MdiActiveDocument.Editor.Regen();

          // We are finished
          if (callbackData.counter >= 100)
          {
            // We only have a cancel button,
            // so this is what we can press
            taskDialog.ClickButton(
              (int)WinForms.DialogResult.Cancel);
            return true;
          }
        }

        callbackData.delay = !callbackData.delay;
      }
      else if (
        args.Notification == TaskDialogNotification.ButtonClicked)
      {
        // we only have a cancel button
        if (args.ButtonId == (int)WinForms.DialogResult.Cancel)
        {
          return false;
        }
      }

      return true;
    }

    private TaskDialog CreateTaskDialog()
    {
      TaskDialog td = new TaskDialog();
      td.WindowTitle = "Adding lines";
      td.ContentText = "This operation adds 10 lines one at a " +
                      "time and might take a bit of time.";
      td.EnableHyperlinks = true;
      td.ExpandedText = "This operation might be lengthy.";
      td.ExpandFooterArea = true;
      td.AllowDialogCancellation = true;
      td.ShowProgressBar = true;
      td.CallbackTimer = true;
      td.CommonButtons = TaskDialogCommonButtons.Cancel;
      return td;
    }

    #endregion

    #region TASK DIALOG USING CALLBACK DATA ARGUMENT

    /////////////////////////////////////////////////////////////////
    // This sample uses a local instance of the callback data.
    // Since the TaskDialog class needs to convert the callback data
    // to an IntPtr to pass it across the managed-unmanaged divide,
    // be sure to convert it to an IntPtr before passing it off
    // to the TaskDialog instance.
    //
    // This case requires more code than the member-based sample
    // below, but is useful when a callback is shared
    // between multiple task dialogs.
    /////////////////////////////////////////////////////////////////

    // task dialog callback that uses the mpCallbackData argument
    public bool TaskDialogCallback(ActiveTaskDialog taskDialog,
                                    TaskDialogCallbackArgs args,
                                    object mpCallbackData)
    {
      // convert the callback data from an IntPtr to the actual
      // object using GCHandle
      GCHandle callbackDataHandle =
        GCHandle.FromIntPtr((IntPtr)mpCallbackData);
      MyData callbackData = (MyData)callbackDataHandle.Target;

      // use the helper method to do the actual processing
      return handleCallback(taskDialog, args, callbackData);
    }

    [CommandMethod("ShowTaskDialog")]
    public void ShowTaskDialog()
    {
      Database db = HostApplicationServices.WorkingDatabase;
      using (
        Transaction tr = db.TransactionManager.StartTransaction())
      {
        // create the task dialog and initialize the callback method
        TaskDialog td = CreateTaskDialog();
        td.Callback = new TaskDialogCallback(TaskDialogCallback);

        // create the callback data and convert it to an IntPtr
        // using GCHandle
        MyData cbData = new MyData();
        GCHandle cbDataHandle = GCHandle.Alloc(cbData);
        td.CallbackData = GCHandle.ToIntPtr(cbDataHandle);

        // Just to minimize the "Regenerating model" messages
        using (new MyVarOverride("NOMUTT", 1))
        {
          td.Show(Application.MainWindow.Handle);
        }

        // If the dialog was not cancelled before it finished
        // adding the lines then commit transaction
        if (memberCallbackData.counter >= 100)
          tr.Commit();

        // be sure to clean up the gc handle before returning
        cbDataHandle.Free();
      }
    }

    #endregion

    #region TASK DIALOG USING DATA-MEMBER-BASED CALLBACK DATA

    /////////////////////////////////////////////////////////////////
    // This sample uses a data member for the callback data.
    // This avoids having to pass the callback data as an IntPtr.
    /////////////////////////////////////////////////////////////////

    // member-based callback data -
    // used with MemberTaskDialogCallback
    MyData memberCallbackData = new MyData();

    // task dialog callback that uses the callback data member;
    // does not use mpCallbackData
    public bool TaskDialogCallbackUsingMemberData(
      ActiveTaskDialog taskDialog,
      TaskDialogCallbackArgs args,
      object mpCallbackData)
    {
      // use the helper method to do the actual processing
      return handleCallback(taskDialog, args, memberCallbackData);
    }

    [CommandMethod("ShowTaskDialogWithDataMember")]
    public void ShowTaskDialogWithDataMember()
    {
      Database db = HostApplicationServices.WorkingDatabase;
      using (
        Transaction tr = db.TransactionManager.StartTransaction())
      {
        // create the task dialog and initialize the callback method
        TaskDialog td = CreateTaskDialog();
        td.Callback =
          new TaskDialogCallback(TaskDialogCallbackUsingMemberData);

        // make sure the callback data is initialized before
        // invoking the task dialog
        memberCallbackData.Reset();

        // Just to minimize the "Regenerating model" messages
        using (new MyVarOverride("NOMUTT", 1))
        {
          td.Show(Application.MainWindow.Handle);
        }

        // If the dialog was not cancelled before it finished
        // adding the lines then commit transaction
        if (memberCallbackData.counter >= 100)
          tr.Commit();
      }
    }

    #endregion
  }
}


论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-22 12:34 , Processed in 0.380282 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表