Like Tree2Likes

Pass parameter to a thread

This is a discussion on Pass parameter to a thread within the Windows Programming forums, part of the Platform Specific Boards category; There are several problems here, not the least of which is that you never call CreateThread() which means that your ...

  1. #16
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    There are several problems here, not the least of which is that you never call CreateThread() which means that your code is simply a subroutine of the main thread... and will block anything else in that thread until it's done.

    Secondly the number of files and their names will have to come from a server someplace... this means you're going to have to poll the server for the next file... then the next, etc... until if finishes... There's going to have to be far more communication than is apparent here.

    You're also going to run into a problem that if you're updating software Windows will not let you overwrite a running program.
    So your update code is going to have to run in a completely separate executable.

    PHP Code:
    get current program version...
    contact server and get number of new files

      
    while files pending
        
    get name of next file
        
    open file in temp folder
        
    download file

    close with server
    confirm accurate downloads
    stop main program
    copy files to program folder
    clean up temp folder
    restart main program 
    I don't see even half of that in your samples.

    For the business of launching a thread...
    This is just "air code" to show you the idea of how it works... don't even think about trying to compile it.

    Code:
    // free running thead
    DWORD WINAPI DoDownload(LPVOID Server)
      { 
         DWORD good = 1;
         INT FileCount;
         CHAR FileName[MAX_PATH];
           
         // get file count from server
         FileCount = ContactServer((PCHAR) Server);  // --- see typecast here...
         if (! FileCount)
           ExitThread(1);  // signal completion if no files
    
         InitializeProgressBar(FileCount)
                  
         while (FileCount)
            { 
               GetNextFilename(FileName);   // get next name from server
               if ( ! Download(FileName) )
                { 
                   CloseServer();
                   CloseProgressBar()
                   ExitThread(0); // signal failure
                 }
               UpdateProgressBar();
               FileCount--; 
            }
          CloseProgressBar();
          ExitThread(1);  // signal done
       }
    
    
    // initiator function
    int GetUpdates( void )  // or as you need it
      {
         // confirm with user
    
         // this launches the free running thread
         hThread = CreateThread(NULL,0,DoDownload,(LPVOID) ServerName,0,NULL);
    
      }
    Last edited by CommonTater; 12-26-2011 at 10:07 PM.

  2. #17
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    Well, that is because I haven't shown my whole source at all. I've shown just 2 functions. You guys leave my no choice, but I hope showing everything will lead to a complete solution.

    Updater.cpp
    Code:
    #include "updater.h"
    
    //---------------------------------------------------------------------------
    HWND hWnd;
    HINSTANCE hInst;
    LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    HWND hwndpb;
    
    HANDLE thread_download;
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    	
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    	InitCommonControlsEx(&InitCtrlEx);
    	
    	// Now create thread for progess bar
    	
    	thread_download = CreateThread( NULL, 0, CheckForUpdate, 0, CREATE_SUSPENDED, NULL);
    	SuspendThread(thread_download);
        
    	DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROLS_DLG),
    	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		hwndpb = CreateWindowEx(0, PROGRESS_CLASS, NULL,
    		               WS_CHILD | WS_VISIBLE | PBS_SMOOTH ,
    			      20, 20, 260, 17,
    			      hWndDlg, (HMENU)IDC_PROGBAR, hInst, NULL);
    			      
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		 case IDUPDATE: 
             {
                
                ResumeThread(thread_download);
                
    			return TRUE;
             }
             break;
    		 case IDCANCEL:
             {
                CloseHandle(thread_download);
                DestroyWindow(hwndpb);
    			EndDialog(hWndDlg, 0);
    			return TRUE;
             }
             break;
    		}
    	}
    
    	return FALSE;
    }
    Updater.h
    Code:
    #include <windows.h>
    #include <commctrl.h>
    
    #include <stdio.h>
    #include <string.h>
    
    #include <curl/curl.h> 
    #include <curl/types.h> 
    #include <curl/easy.h> 
    
    #define IDD_CONTROLS_DLG  100
    #define IDC_PROGBAR       101
    #define IDUPDATE          102
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
    void DownloadFile(char *url, char *outFile);
    void prog_update(void *p, double dltotal, double dlnow, double ult, double uln);
    DWORD WINAPI CheckForUpdate(void *file);
    
    extern HWND hWnd;
    extern HWND hwndpb;
    extern int num_files;
    
    struct Version
    {
           int major;
           int minor;
           int build;
           
           int numFiles;
    };
    
    struct Download
    {
           char name[56];
           char outName[16];
    };
    Resource.rc
    Code:
    #include "updater.h"
    #include <afxres.h>
    
    1 RT_MANIFEST "style.xml"
    
    IDD_CONTROLS_DLG DIALOG 260, 200, 200, 120
    STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "Project DOD Updater"
    FONT 8, "MS Shell Dlg"
    BEGIN
        DEFPUSHBUTTON   "Update", IDUPDATE, 30, 100, 50, 14
        PUSHBUTTON   "Close", IDCANCEL, 120, 100, 50, 14
    END
    Download.cpp
    Code:
    #include "updater.h"
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) 
    {     
          size_t written;     
          written = fwrite(ptr, size, nmemb, stream);     
          return written; 
    } 
    
    void DownloadFile(char *url, char *outFile)
    {
           CURL *curl;     
           FILE *fp;     
           CURLcode res;     
                        
           curl = curl_easy_init();
           if (curl) 
           {         
    
                                  fp = fopen(outFile,"wb");         
                                  curl_easy_setopt(curl, CURLOPT_URL, url);
                                  
                                  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);         
                                  curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                                  
                                  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
                                  curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, prog_update);
                                           
                                  res = curl_easy_perform(curl);
    
                                  curl_easy_cleanup(curl);
                                           
                                  fclose(fp);
           }  
                           
    }
    Thread.cpp
    Code:
    #include "updater.h"
    
    struct Version curVer;
    struct Version version;
    
    FILE *fp;
    
    int num_files;
    
    
    void GetProgVersion(void)
    {
         fp = fopen("version.dat", "rb");
            
         fread(&curVer, sizeof(curVer), 1, fp);
            
         fclose(fp);
    }
    
    int GetUpdate(void) // num_files = GetUpdate();
    {
         DownloadFile("http://website.net/projects/dod/update.dat","update.dat");
         
         struct Download file[version.numFiles];
         
         fp = fopen("update.dat", "rb");
        
         fread(&version, sizeof(version), 1, fp);
         fread(&file, sizeof(file), 1, fp);
        
         fclose(fp);
         
         return(version.numFiles);
    }
    
    void DownloadUpdates(void *file)
    {
         int j;
         
         for(j = 0; j < num_files; j++)
         {
               SendMessage(hwndpb, PBM_SETPOS, 0, 0);
               DownloadFile((struct*)file[j].name, (struct*)file[j].outName); //for reg struct
               //DownloadFile((*file)[j].name, (*file)[j].outName);
         }
    }
    
    void prog_update(void *p, double dltotal, double dlnow, double ult, double uln)
    {
         SendMessage(hwndpb, PBM_SETPOS, (int)dlnow/(int)dltotal*200, 0);
    }
    
    // This creates the second thread to our application which will
    // control the downloading as the progress bar works
    
    DWORD WINAPI CheckForUpdate(void *file)
    {
         GetProgVersion();
         
         num_files = GetUpdate();
          
         SendMessage(hwndpb, PBM_SETRANGE, 0, MAKELPARAM(0, 200 ));
                
         if(version.major > curVer.major || version.minor > curVer.minor || version.build > curVer.build)
         {
                 int ret = MessageBox(hWnd, "An update is available to download.  Would you like to download it?", "Update Available", MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1);
                          
                 if(ret == IDNO)
                         return 2;
                          
                 DownloadUpdates((void*)file);
                 
                 return 0;
         }
         else
                 MessageBox(hWnd, "No updates are available to download.", "No Updates Available", MB_OK | MB_ICONINFORMATION);
    
         return 1;
    }
    There is my entire project contents. I'm downloading files vai libcurl. Firstly, I do call CreateThread() upon initialization. Secondly, I download the update.dat file, which contains the update version, and all the file url's and the outfilenames of all the necessary files for the update (which is dynamic). Thirdly, this is the updater, and I have no plans of updating it. I just need a good updater, so it does not require it to be updated.

  3. #18
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Ok... Creating the thread in suspended mode may not be to your best advantage... Usually when you want a free-running process that is part of your mains but doesn't block it, you don't actually create the thread until you need it, as I did in my example. The thread should live only long enough to do it's job... no longer. That way you can get a result from GetExitCodeThread() to know if it succeeded, failed or is still running... Most multitasking programs hatch and bury threads on a millisecond by millisecond basis, it is rare indeed that creating a thread in suspeneded mode makes any real sense...

    I don't know LibCurl... I usually work with Windows API calls, so I'm not much help to you there.

  4. #19
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    I've tested the libCurl code, and I gurantee it works fine.

    I updated updater.cpp to look like so.
    Code:
    #include "updater.h"
    
    //---------------------------------------------------------------------------
    HWND hWnd;
    HINSTANCE hInst;
    LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    HWND hwndpb;
    
    HANDLE thread_download;
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    	
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    	InitCommonControlsEx(&InitCtrlEx);
        
    	DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROLS_DLG),
    	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		hwndpb = CreateWindowEx(0, PROGRESS_CLASS, NULL,
    		               WS_CHILD | WS_VISIBLE | PBS_SMOOTH ,
    			      20, 20, 260, 17,
    			      hWndDlg, (HMENU)IDC_PROGBAR, hInst, NULL);
    			      
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		 case IDUPDATE: 
             {
                
                // Now create thread for progess bar
    	
    	        thread_download = CreateThread( NULL, 0, CheckForUpdate, 0, 0, NULL);
    	        
    	        DWORD ExitCode;
    	        
    	        if(GetExitCodeThread(thread_download, &ExitCode) != 0)
                       ExitThread(ExitCode);
                
    			return TRUE;
             }
             break;
    		 case IDCANCEL:
             {
                CloseHandle(thread_download);
                DestroyWindow(hwndpb);
    			EndDialog(hWndDlg, 0);
    			return TRUE;
             }
             break;
    		}
    	}
    
    	return FALSE;
    }
    So now I create the thread if the user checks for Updates. If there is no updates available, or the user does not want to update, it kills the thread.

    But what about the typecasting pointer problem for the thread function?

  5. #20
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    I've just looked at the syntax for the CreateThread function again, and something I have overlooked is that I can pass a parameter from the CreateThread function itself. In my code, I have it like so:
    Code:
    thread_download = CreateThread( NULL, 0, CheckForUpdate, 0, 0, NULL);
    I have a 0 after CheckForUpdate, which is an optional parameter spot. Should I be passing the pointer to the structure there as well? Have I set up the pointer correctly for:
    Code:
    struct Download file[version.numFiles];

  6. #21
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    You don't have to kill the thread... it will end naturally when the thread function returns. That's why, in my example, I used ExitThread() instead of return... it's only valid inside the thread function or it's subordinates.

    As for the typecasting issue...

    Code:
    // an example struct
    typedef struct T_THREADDATA
      { char name[128];
         int count; }
      THREADDATA, *pTHREADDATA;  
    
      // a live struct
      THREADDATA data;  
    
    // launching the thread
    CreateThread(NULL,0,ThreadFunc,(PVOID) &data,0,NULL);
    
    // the thread function
    DWORD WINAPI ThreadFunc(PVOID stuff)
      {
         int x;
    
        // this is where you typecast your struct
         printf("%s",((pTHREADDATA) stuff)->name);
    
         x = ((pTHREADDATA) stuff)-> count * 42;
         printf("%d", x);
    
         ExitThread(0);
       }

  7. #22
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    The compiler reads CreateThread first, before the file struct is initialized, and reports that file is not declared. It's essentally right, because I only initialize it in the thread once it's launched.

    Is there a way to copy the data from the structure (remember it's contents could be anything, there could be 2 files, or 6) to a global structure so I won't have to pass the structure as a void pointer.

  8. #23
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    The thing would be to do this in two stages...

    1) launch a first thread to gather the needed information
    2) launch a second thread to download the files

    The way you're doing it... intializing the list within the thread... there's no need to pass anything in, so why would you want to?

    No offense... but it seems to me that you've created a very convoluted process here. Pehaps it would help you to sit down and work it out on paper first... sort of a "step by step" instruction that you can then turn into code.

  9. #24
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    Ok, so I've re-structured my code. Here it is:

    Updater.cpp
    Code:
    #include "updater.h"
    
    //---------------------------------------------------------------------------
    HWND hWnd;
    HINSTANCE hInst;
    LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    HWND hwndpb;
    
    HANDLE gather_info;
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    	
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    	InitCommonControlsEx(&InitCtrlEx);
        
    	DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROLS_DLG),
    	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		hwndpb = CreateWindowEx(0, PROGRESS_CLASS, NULL,
    		               WS_CHILD | WS_VISIBLE | PBS_SMOOTH ,
    			      20, 20, 260, 17,
    			      hWndDlg, (HMENU)IDC_PROGBAR, hInst, NULL);
    			      
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		 case IDUPDATE: 
             {
                
                gather_info = CreateThread( NULL, 0, CheckForUpdate, 0, 0, NULL);
    	
    			return TRUE;
             }
             break;
    		 case IDCANCEL:
             {
                CloseHandle(gather_info);
                CloseHandle(download_updates);
                DestroyWindow(hwndpb);
    			EndDialog(hWndDlg, 0);
    			return TRUE;
             }
             break;
    		}
    	}
    
    	return FALSE;
    }
    Updater.h
    Code:
    #include <windows.h>
    #include <commctrl.h>
    
    #include <stdio.h>
    #include <string.h>
    
    #include <curl/curl.h> 
    #include <curl/types.h> 
    #include <curl/easy.h> 
    
    #define IDD_CONTROLS_DLG  100
    #define IDC_PROGBAR       101
    #define IDUPDATE          102
    
    // Misc
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
    void prog_update(void *p, double dltotal, double dlnow, double ult, double uln);
    
    // Thread
    DWORD WINAPI CheckForUpdate(LPVOID);
    DWORD WINAPI DownloadUpdates(LPVOID);
    
    // Download file
    void DownloadFile(char *url, char *outFile);
    
    // Info
    void GetProgVersion(void);
    int GetUpdate(void);
    
    extern HWND hWnd;
    extern HWND hwndpb;
    extern HANDLE download_updates;
    
    extern int num_files;
    
    extern struct Version curVer;
    extern struct Version version;
    
    struct Version
    {
           int major;
           int minor;
           int build;
           
           int numFiles;
    };
    
    struct FileList
    {
           char name[56];
           char outName[16];
    };
    Download.cpp
    Code:
    #include "updater.h"
    
    void prog_update(void *p, double dltotal, double dlnow, double ult, double uln)
    {
         SendMessage(hwndpb, PBM_SETPOS, (int)dlnow/(int)dltotal*200, 0);
    }
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) 
    {     
          size_t written;     
          written = fwrite(ptr, size, nmemb, stream);     
          return written; 
    } 
    
    void DownloadFile(char *url, char *outFile)
    {
           CURL *curl;     
           FILE *fp;     
           CURLcode res;     
                        
           curl = curl_easy_init();
           if (curl) 
           {         
    
                                  fp = fopen(outFile,"wb");         
                                  curl_easy_setopt(curl, CURLOPT_URL, url);
                                  
                                  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);         
                                  curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                                  
                                  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
                                  curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, prog_update);
                                           
                                  res = curl_easy_perform(curl);
    
                                  curl_easy_cleanup(curl);
                                           
                                  fclose(fp);
           }  
                           
    }
    Thread.cpp (which now ONLY contains thread functions)
    Code:
    #include "updater.h"
    
    // This creates the second thread to our application which will
    // control gather required information
    
    /******Thread 1******/
    
    DWORD WINAPI CheckForUpdate(LPVOID)
    {
         GetProgVersion();
         
         num_files = GetUpdate();
                
         if(version.major > curVer.major || version.minor > curVer.minor || version.build > curVer.build)
         {
                 int ret = MessageBox(hWnd, "An update is available to download.  Would you like to download it?", "Update Available", MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1);
                          
                 if(ret == IDNO)
                         ExitThread(2);
                          
                 download_updates = CreateThread( NULL, 0, DownloadUpdates, 0, 0, NULL);
                 
                 ExitThread(0);
         }
         else
                 MessageBox(hWnd, "No updates are available to download.", "No Updates Available", MB_OK | MB_ICONINFORMATION);
    
         ExitThread(1);
    }
    
    /********Thread 2*********/
    
    /* Thread downloads updates based on struct data*/
    
    DWORD WINAPI DownloadUpdates(LPVOID)
    {
         int j;
         
         SendMessage(hwndpb, PBM_SETRANGE, 0, MAKELPARAM(0, 200 ));
         
         for(j = 0; j < num_files; j++)
         {
               SendMessage(hwndpb, PBM_SETPOS, 0, 0);
    /*
               DownloadFile((pDOWNLOAD)file[j]->name, (pDOWNLOAD)file[j]->outName); 
               //DownloadFile((*file)[j].name, (*file)[j].outName); */
         }
    }
    Info.cpp
    Code:
    #include "updater.h"
    
    FILE *fp;
    
    void GetProgVersion(void)
    {
         fp = fopen("version.dat", "rb");
            
         fread(&curVer, sizeof(curVer), 1, fp);
            
         fclose(fp);
    }
    
    int GetUpdate(void) // num_files = GetUpdate();
    {
         DownloadFile("http://website.net/projects/dod/update.dat","update.dat");
         
         struct FileList file[version.numFiles];
         
         fp = fopen("update.dat", "rb");
        
         fread(&version, sizeof(version), 1, fp);
         fread(&file, sizeof(file), 1, fp);
        
         fclose(fp);
         
         return(version.numFiles);
    }
    The most notable changes I've made is that I have moved some functions around, and created a new source file for the info functions (to make things cleaner). Along with that, I have created a new thread and changed DownloadUpdates to the thread function (so now I only have to pass the parameter to DownloadUpdates, not CheckForUpdates). I still need to work with the structure and DownloadFile so that it downloads the correct files.

    Now, the way I would normally access the structure would be like:
    Code:
         for(j = 0; j < num_files; j++)
         {
               SendMessage(hwndpb, PBM_SETPOS, 0, 0);
    
               DownloadFile(file[j].name, file[j].outName);
         }
    But since I can only pass a void pointer, how would I do that?
    Last edited by binks; 12-27-2011 at 04:08 PM.

  10. #25
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Did you even bother to look at my example in message 21?

    Yes, It was in C but you should have no problem implementing it in C++...

    But I am going to make a little suggestion here... This is all one small thing... maybe 200 lines total...

    Put it all in one source file. Breaking it up the way you have obscures the process and the relationships. You will likely find some of your functions would be better if they were combined... A large part of your problem is that you are breaking things up too finely.

    In your place, I'd have it so the function to get the file list from the server (or whereever it's coming from) and then the loop to download from that list, would all be in one function, now you don't need to pass that struct back and forth... it's in the same scope as your loop.

    In fact, everything except the dialog display and message tosser probably should be a thread single function, in a single source file, with the thread launched directly from the button handler...

    It's not syntax that's the problem... it's your program's structure that is tripping you up.
    Last edited by CommonTater; 12-27-2011 at 06:22 PM.

  11. #26
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    I think your right... I don't even need the pointers because I can just put all that mess into 1 thread function (well, except download file, because that is a generic function I made for any file). I'll get back to you.

  12. #27
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    Everything seems to be working fine now, but I am still not getting full results. I now need to pass a double variable through sendmessage to update the progress bar, but it only allows 32 bit integers, how can I easily fix this?

    Code:
    SendMessage(hwndpb, PBM_SETPOS, (double)dlnow/(double)dltotal*200, 0);
    dlnow and dltotal are double variables, but I get warnings.

    So I change it to this
    Code:
    void prog_update(void *p, double dltotal, double dlnow, double ult, double uln)
    {
         int now = (int)dlnow;
         int total = (int)dltotal;
         
         SendMessage(hwndpb, PBM_SETPOS, (int)now/(int)total*200, 0);
    }
    But it crashes when I hit update. Is that not proper conversion of double to int. (well, an elegant way of doing it)
    Last edited by binks; 12-27-2011 at 08:03 PM.

  13. #28
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by binks View Post
    Everything seems to be working fine now, but I am still not getting full results. I now need to pass a double variable through sendmessage to update the progress bar, but it only allows 32 bit integers, how can I easily fix this?
    That's simple... don't use doubles when you're just counting stuff.
    What's the most out of your mind biggest honking ugly file you're likely to download?
    When's the last time you downloaded a fraction of a byte?

    99.999% of the time a simple unsigned int (DWORD) is perfectly adequate as a download counter... that will handle up to 4gb, for you. If you need to go beyond 4gb use a 64 bit integer (DWORD64, uint64_t or unsigned long long) and divide it by UINT_MAX before passing it to the progress bar function.

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    (Hint: Always do everything with integers --especially money-- unless you have no choice... What Every Computer Scientist Should Know About Floating-Point Arithmetic )

    The progress bar should be scaled to your filesize, or some divisor there of... That way when you call the update routine it knows how far to move the bar.

    Code:
    DWORD FileCount = 0;
    DWORD ThisBlock;
    
    // in your downloader loop
    ThisBlock = GetNextBlock() // where GetNextBlock returns the size of the block
    
    FileCount += ThisBlock;
    UpdateProgressBar(FileCount);
    If the file gets too big (unlikely on an update)
    Code:
    #define MBYTE 1024 * 1024
    
    DWORD64 FileCount = 0;
    DWORD ThisBlock;
    
    // in your downloader loop
    ThisBlock = GetNextBlock() // where GetNextBlock returns the size of the block
    
    FileCount += ThisBlock;
    UpdateProgressBar(FileCount/MBYTE);  // update in megabytes
    Last edited by CommonTater; 12-27-2011 at 10:22 PM.

  14. #29
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    Thanks, I'll try the DWORD64.

  15. #30
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by binks View Post
    Thanks, I'll try the DWORD64.

    You don't actually need a 64 bit variable until you cross the 4 gigabyte line...

    Wow... huge files eh?

Page 2 of 3 FirstFirst 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 11-27-2011, 07:40 PM
  2. Replies: 9
    Last Post: 10-19-2009, 05:46 PM
  3. How pass NULL for a parameter in a function?
    By 6tr6tr in forum C++ Programming
    Replies: 2
    Last Post: 04-02-2008, 02:29 PM
  4. how would i pass on a vector pointer parameter
    By bugmenot in forum C++ Programming
    Replies: 5
    Last Post: 12-16-2005, 02:51 AM
  5. Parameter pass
    By Gades in forum C Programming
    Replies: 28
    Last Post: 11-20-2001, 02:08 PM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21