UrlDownloadToFile - Mit der Callback Klasse das UI Updaten....



  • Hey,
    ich schaff es einfach nicht mit der Callback Klasse von URLDownloadToFile meine ProgressBar zu updaten, sodass der Fortschritt vom Download angezeigt wird.
    MainForm.h

    #pragma once
    #include <urlmon.h> // URLDowbloadToFile
    #include <WinInet.h> // Delete Cache
    #pragma comment(lib,"urlmon.lib") // URLDowbloadToFile
    #pragma comment(lib, "wininet.lib") // Delete Cache
    
    namespace DownloadProgressBar {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    	using namespace System::Threading;
    	using namespace std;
    
    	/// <summary>
    	/// Zusammenfassung für MainForm
    	/// </summary>
    	public ref class MainForm : public System::Windows::Forms::Form
    	{
    	public:
    		MainForm(void)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~MainForm()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    	private: System::Windows::Forms::ProgressBar^  progressBar;
    
    	private: System::Windows::Forms::Label^  labSizeName;
    	private: System::Windows::Forms::Label^  labSizeNumber;
    
    	private: System::ComponentModel::IContainer^  components;
    	protected:
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->progressBar = (gcnew System::Windows::Forms::ProgressBar());
    			this->labSizeName = (gcnew System::Windows::Forms::Label());
    			this->labSizeNumber = (gcnew System::Windows::Forms::Label());
    			this->SuspendLayout();
    			// 
    			// progressBar
    			// 
    			this->progressBar->Location = System::Drawing::Point(12, 32);
    			this->progressBar->Name = L"progressBar";
    			this->progressBar->Size = System::Drawing::Size(660, 23);
    			this->progressBar->TabIndex = 0;
    			// 
    			// labSizeName
    			// 
    			this->labSizeName->AutoSize = true;
    			this->labSizeName->Location = System::Drawing::Point(12, 65);
    			this->labSizeName->Name = L"labSizeName";
    			this->labSizeName->Size = System::Drawing::Size(56, 13);
    			this->labSizeName->TabIndex = 1;
    			this->labSizeName->Text = L"Data Size:";
    			// 
    			// labSizeNumber
    			// 
    			this->labSizeNumber->AutoSize = true;
    			this->labSizeNumber->Location = System::Drawing::Point(75, 65);
    			this->labSizeNumber->Name = L"labSizeNumber";
    			this->labSizeNumber->Size = System::Drawing::Size(12, 13);
    			this->labSizeNumber->TabIndex = 2;
    			this->labSizeNumber->Text = L"/";
    			// 
    			// MainForm
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(684, 87);
    			this->Controls->Add(this->labSizeNumber);
    			this->Controls->Add(this->labSizeName);
    			this->Controls->Add(this->progressBar);
    			this->Name = L"MainForm";
    			this->Text = L"MainForm";
    			this->Load += gcnew System::EventHandler(this, &MainForm::MainForm_Load);
    			this->ResumeLayout(false);
    			this->PerformLayout();
    
    		}
    		void Download()
    		{
    			DeleteUrlCacheEntryA("http://debian/c++patcher/files/data/data_data");
    			HRESULT hr;
    			//MyCallback pCallback;
    
    			hr = URLDownloadToFileA(NULL, "http://debian/c++patcher/files/data/data_data", "C:\\data", 0, NULL/*&pCallback*/);
    			if (!SUCCEEDED(hr)){ MessageBox::Show("Fehler beim herunterladen der Datei!"); }
    			else { MessageBox::Show("Datei erfolgreich heruntergeladen!"); }
    		}
    #pragma endregion
    	public: System::Void MainForm_Load(System::Object^  sender, System::EventArgs^  e) {
    		Thread^ newThread = gcnew Thread(gcnew ThreadStart(this, &DownloadProgressBar::MainForm::Download));
    		newThread->Start();
    	}
    	};
    }
    

    downloadcallback.h

    #ifndef DownloadCallbackH
    #define DownloadCallbackH
    #include <urlmon.h> // URLDowbloadToFile
    #include <WinInet.h> // Delete Cache
    #include <shlwapi.h> // for StrFormatByteSize()
    #pragma comment(lib,"urlmon.lib") // URLDowbloadToFile
    #pragma comment(lib, "wininet.lib") // Delete Cache
    
    class DownloadCallback : public IBindStatusCallback
    {
    public:
    	DownloadCallback();
    
    	~DownloadCallback();
    
    	// This one is called by URLDownloadToFile
    	// OnProgress Method!
    	STDMETHOD(OnProgress)(
    		/* [in] */ ULONG ulProgress,
    		/* [in] */ ULONG ulProgressMax,
    		/* [in] */ ULONG ulStatusCode,
    		/* [in] */ LPCWSTR wszStatusText);
    
    	// IBindStatusCallback methods.  Note that the only method called by IE
    	// is OnProgress(), so the others just return E_NOTIMPL.
    	STDMETHOD(OnStartBinding)(
    		/* [in] */ DWORD dwReserved,
    		/* [in] */ IBinding __RPC_FAR *pib)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(GetPriority)(
    		/* [out] */ LONG __RPC_FAR *pnPriority)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(OnLowResource)(
    		/* [in] */ DWORD reserved)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(OnStopBinding)(
    		/* [in] */ HRESULT hresult,
    		/* [unique][in] */ LPCWSTR szError)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(GetBindInfo)(
    		/* [out] */ DWORD __RPC_FAR *grfBINDF,
    		/* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(OnDataAvailable)(
    		/* [in] */ DWORD grfBSCF,
    		/* [in] */ DWORD dwSize,
    		/* [in] */ FORMATETC __RPC_FAR *pformatetc,
    		/* [in] */ STGMEDIUM __RPC_FAR *pstgmed)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD(OnObjectAvailable)(
    		/* [in] */ REFIID riid,
    		/* [iid_is][in] */ IUnknown __RPC_FAR *punk)
    	{
    		return E_NOTIMPL;
    	}
    	STDMETHOD_(ULONG, AddRef)()
    	{
    		return 0;
    	}
    	STDMETHOD_(ULONG, Release)()
    	{
    		return 0;
    	}
    	STDMETHOD(QueryInterface)(
    		/* [in] */ REFIID riid,
    		/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
    	{
    		return E_NOTIMPL;
    	}
    };
    #endif
    

    downloadcallback.cpp

    #include "downloadcallback.h"
    #include "MainForm.h"
    
    DownloadCallback::DownloadCallback()
    {
    
    }
    DownloadCallback::~DownloadCallback()
    {
    
    }
    
    HRESULT DownloadCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
    	ULONG ulStatusCode, LPCWSTR wszStatusText)
    {
    	//Hier muss die Progressbar geupdatet werden!!!
    
    	//cout << "Downloaded " << ulProgress << " of " << ulProgressMax << " byte(s), " << " Status Code = " << ulStatusCode << endl;
    
    	return S_OK;
    }
    

    main.cpp

    #include "MainForm.h"
    
    using namespace System;
    using namespace System::Windows::Forms;
    
    [STAThread]
    void main(array<String^>^ arg) {
    	Application::EnableVisualStyles();
    	Application::SetCompatibleTextRenderingDefault(false);
    
    	DownloadProgressBar::MainForm form;
    	Application::Run(%form);
    }
    

    Ich hoffe mir kann einer helfen 😕



  • Benutze doch den WebClient und dessen DownloadProgressChanged Event um den Progress darzustellen anstatt dich mit native/managed Problemen herumzuschlagen - noch besser nimm gleich C#.



  • He, du hast die Frage hier schonmal gestellt:
    https://www.c-plusplus.net/forum/331251



  • Erstmal danke für die schnellen antworten. Ich würde die gerne gelöst haben, falls einer weiß wie es geht. 😕
    Ja es ist ein zweiter Beitrag, ich glaube es war das falsche forum.



  • 1. Falsches Form.
    2. Ungenügende Fehlerbeschreibung.

    Rate mal mit Rosenthal?



  • Es gibt ja auch keine Fehler. Es passiert aber einfach nichts in dem UI.
    Wenn ich die MainForm in der Callback KLasse aufrufe und dann eine Funktion oder das UI verändern möchte passiert nichts.

    #include "downloadcallback.h"
    #include "MainForm.h"
    #include <iostream>
    
    DownloadCallback::DownloadCallback()
    {
    
    }
    DownloadCallback::~DownloadCallback()
    {
    
    }
    
    HRESULT DownloadCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
    	ULONG ulStatusCode, LPCWSTR wszStatusText)
    {
    	//Hier muss die Progressbar geupdatet werden!!!
    	DownloadProgressBar::MainForm main;
    	main.progressBar->Value = 20;
    	//std::cout << "Downloaded " << ulProgress << " of " << ulProgressMax << " byte(s), " << " Status Code = " << ulStatusCode << std::endl;
    
    	return S_OK;
    }
    


  • Du erzeugst ja auch eine neue Instanz Deiner Klasse MainForm im Callback. Du solltest wohl eher auf eine bestehende Instanz zugreifen.

    Mfg Martin



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum C++/CLI mit .NET verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Danke Martin, das ist eine gute Antowrt odch wie greife ich auf eine bestehende Instanz zu?



  • Okay also mein obiger Beitrag hat sich erledigt...
    Wenn ich es so mache -> DownloadProgressBar::MainForm::progressBar->Value = 20; <-
    kann ich es nicht kompilieren.
    Fehler:

    error C2227: Links von "->Value" muss sich ein Zeiger auf Klassen-/Struktur-/Union-/generischen Typ befinden.
    


  • WindowsForms... schrieb:

    Danke Martin, das ist eine gute Antowrt odch wie greife ich auf eine bestehende Instanz zu?

    Spendiere Deiner Callbackklasse einen Zeiger auf Deine MainForm.

    class Callback
    {
       MainForm *myMainForm;
    
       Callback ( MainForm *theMain ) myMainForm (theMain) : {}
    ...
    }
    

    Beim Instanziieren gibst Du den Zeiger mit.

    MainForm::download ()
    {
    myCallback = new Callback ( this );
    ...
    }
    

    In der Callbackfunktion kannst Du dann auf Dein Formular zugreifen

    Callback::onDownload ()
    {
       myMainForm-> progressBar-> value = xxx;
    }
    

    Alles nur Beispiele, die für dich angepasst werden müssen.

    Mfg Martin


Anmelden zum Antworten