2016-05-22 23 views
3

Ich benutze die IProgressDialog Schnittstelle wie normal, alles funktioniert in Ordnung, aber der Fortschrittsdialog erscheint nur nach ein paar Sekunden, wenn es entscheidet, dass der Vorgang tatsächlich lang ist. Obwohl dies nirgendwo dokumentiert ist, scheint es ein beabsichtigtes Verhalten zu sein und in vielen Fällen nicht schlecht. In dieser speziellen Anwendung müsste ich sie jedoch sofort anzeigen.IProgressDialog, um sofort zu starten

Ich fand eine single reference auf dem gesamten Wide Web, um dies zu erkennen und einen Workaround vorschlagen. Aber vielleicht, weil es während dieser 9 Jahre durchaus ein paar neue Windows-Versionen waren, scheint es heute nicht zur Arbeit:

IProgressDialog dialog; 
dialog.StartProgressDialog(owner, null, flags, IntPtr.Zero); 
... 
IntPtr DialogHWnd; 
((IOleWindow)dialog).GetWindow(out DialogHWnd); 
SendMessage(DialogHWnd, WM_TIMER, new IntPtr(1), IntPtr.Zero); 

Der Fenstergriff ist OK, überprüfte ich es, kein Fehler vorhanden ist, einfach da ist keine Veränderung im Verhalten. Der Dialog erscheint erst nach einigen Sekunden.

Hat jemand einen Vorschlag, den gleichen Dialog und die gleiche Funktionalität in C# erneut zu erstellen? Natürlich nicht unmöglich, aber der Stockdialog hat neben den Usern auch nette Features wie Animation und Abbruchverhalten.

Antwort

2

Anruf dialog.Timer(PDTIMER_RESUME, null) unmittelbar vor oder nach StartProgressDialog. Hier ist eine minimale Probe:

using System; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 { 

[Flags] 
public enum IPD_Flags: uint { 
    Normal = 0x00000000, 
    Modal = 0x00000001, 
    AutoTime = 0x00000002, 
    NoTime = 0x00000004, 
    NoMinimize = 0x00000008, 
    NoProgressBar = 0x00000010 
} 

[Flags] 
public enum IPDTIMER_Flags: uint { 
    Reset = 0x00000001, 
    Pause = 0x00000002, 
    Resume = 0x00000003 
} 

[ComImport] 
[Guid("F8383852-FCD3-11d1-A6B9-006097DF5BD4")] 
internal class ProgressDialog { 
} 

[ComImport] 
[Guid("EBBC7C04-315E-11d2-B62F-006097DF5BD4")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IProgressDialog { 

    [PreserveSig] 
    void StartProgressDialog(IntPtr hwndParent 
     , [MarshalAs(UnmanagedType.IUnknown)] object punkEnableModless 
     , uint 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(uint dwTimerAction, object pvResevered); 

} 


public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     ProgressDialog progressDialog = new ProgressDialog(); 
     IProgressDialog iProgressDialog = (IProgressDialog)progressDialog; 

     iProgressDialog.Timer((uint) IPDTIMER_Flags.Resume, null); 
     iProgressDialog.StartProgressDialog(this.Handle 
      , null 
      , (uint)(IPD_Flags.Normal | IPD_Flags.NoMinimize) 
      , IntPtr.Zero); 
    } 
} 

}

+0

Die Idee ist sehr schön (ich tatsächlich versucht 'Timer()', aber nicht mit dem Wiederaufnahme-Flag). Aber es ist noch nicht perfekt, fürchte ich. Es funktioniert in diesem einfachen Beispiel von dir, aber in der realen Anwendung, wo ich auch den Fortschrittsbalken handhaben muss, bekomme ich entweder sofort den * oder * richtigen Fortschrittsbalken später. :-) Ich versuche es weiter und melde mich wieder. Vielen Dank. –

+0

OK, habe es gefunden. Der wichtige Punkt war, dass dies kein einfacher Fortschrittsbalken war. Der Fortschrittsdialog animiert den Balken im Hintergrund zwischen den Aufrufen von 'SetProgress()', damit er sich zwischen den angegebenen Werten glatter bewegt, anstatt zu springen. Daher musste ich zusätzlich zu Ihrer Idee jeden 'SetProgress()' -Aufruf wie folgt umschließen: 'dialog.Timer (PDTIMER_PAUSE, null); dialog.SetProgress (...); dialog.Timer (PDTIMER_RESUME, null); ' –

Verwandte Themen