Thread: Cancel Button not working

  1. #1
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107

    Cancel Button not working

    I finally got around to finishing the set of functions I was writing for displaying a progress window while CopyFileEx() runs. The only problem is that the cancel button on the window won't work. Well, actually it will work if I display a message box right before I create the window, which I haven't been able to explain yet... Anyway, here is the full code for it, less the headers:
    Code:
    //Include files////////////////////////////////////////////////////////////////////////////
    
    #include "global_definitions.h"
    
    #include <windows.h>
    #include <commctrl.h>
    #include "debug.h"
    #include "memory.h"
    #include "stringio.h"
    #include "window_classes.h"
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    //Function prototypes//////////////////////////////////////////////////////////////////////
    
    void InitProgressWindowClass(void);
    
    int CopyFileProgressEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwCopyFlags, HWND hWndParent, char * title, char * message, BOOL popup, DWORD parentUpdate);
    
    DWORD WINAPI ProgressWindowThread(LPVOID lParam);
    
    INT_PTR CALLBACK ProgressWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    LRESULT ProgressWindow_OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    
    DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData);
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    //Function definitions/////////////////////////////////////////////////////////////////////
    
    void InitProgressWindowClass(void)
    {
    
        WNDCLASSEX wc = {0};
    
    	//Register the progress window class
        wc.cbSize         = sizeof(wc);
        wc.lpszClassName  = "Progress Window";
        wc.hInstance      = GetModuleHandle(NULL);
        wc.lpfnWndProc    = ProgressWindowProc;
        wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground  = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
        wc.cbWndExtra     = sizeof(PROGRESSINFO *);
    
    	RegisterClassEx(&wc);
    
    }
    
    int CopyFileProgressEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwCopyFlags, HWND hWndParent, char * title, char * message, BOOL popup, DWORD parentUpdate)
    {
    
    	PROGRESSINFO * pip = ClearMemAlloc(sizeof(PROGRESSINFO));
    	BOOL error;
    	BOOL cancel = 0;
    	DWORD threadId;
    
    	if(!title)
    		title = "";
    
    	if(!message)
    		message = "";
    
    	pip->title = title;
    	pip->message = message;
    
    	pip->popup = popup;
    
    	pip->cancel = &cancel;
    
    	pip->hWndParent = hWndParent;
    
    	pip->parentUpdate = parentUpdate;
    
    	pip->lastParentUpdate = GetTickCount();
    
    	SetFocus(hWndParent);
    
    	CreateThread(NULL, 0, ProgressWindowThread, pip, 0, &threadId);
    
    	while(!pip->hWndProgress)
    		Sleep(0);
    
    	error = CopyFileEx(lpExistingFileName, lpNewFileName, CopyProgressRoutine, pip, NULL, dwCopyFlags);
    
    	if(!error)
    		return 1;
    	else if(cancel)
    		return 2;
    
    	return 0;
    
    }
    
    DWORD WINAPI ProgressWindowThread(LPVOID lParam)
    {
    
    	MSG msg;
    	DWORD exitCode = 0;
    	PROGRESSINFO * pip = (PROGRESSINFO *) lParam;
    	DWORD dwStyle = (pip->hWndParent != NULL ? WS_CHILD : 0) | WS_VISIBLE;
    	RECT progressCords;
    
    	if(pip->popup)
    	{
    		progressCords.left = GetSystemMetrics(SM_CXSCREEN) / 2 - PROGRESSWINDOW_WIDTH / 2;
    		progressCords.top = GetSystemMetrics(SM_CYSCREEN) / 2 - PROGRESSWINDOW_HEIGHT / 2;
    
    		dwStyle |= WS_POPUPWINDOW;
    	}
    	else
    	{
    		dwStyle |= WS_DLGFRAME;
    
    		GetClientRect(pip->hWndParent, &progressCords);
    
    		progressCords.left = (progressCords.right - progressCords.left) / 2 - PROGRESSWINDOW_WIDTH / 2;
    		progressCords.top = (progressCords.bottom - progressCords.top) / 2 - PROGRESSWINDOW_HEIGHT / 2;
    	}
    
    	pip->hWndProgress = CreateWindowEx(
    		0,
    		"Progress Window",
    		pip->title,
    		dwStyle,
    		progressCords.left,
    		progressCords.top,
    		PROGRESSWINDOW_WIDTH,
    		PROGRESSWINDOW_HEIGHT,
    		pip->hWndParent,
    		NULL,
    		GetModuleHandle(NULL),
    		pip);
    
    	while(GetMessage(&msg, NULL, 0, 0))
    	{ 
    		TranslateMessage(&msg); 
    		DispatchMessage(&msg); 
    	} 
    
    	GetExitCodeThread(GetCurrentThread(), &exitCode);
    
    	ExitThread(exitCode);
    
    	ErrorMessage("Abnormal thread termination", NULL, NULL, MB_ICONEXCLAMATION, 1);
    
    	return FALSE;
    
    }
    
    INT_PTR CALLBACK ProgressWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    
    	switch(uMsg)
    	{
    
    	case WM_CREATE:
    		return ProgressWindow_OnCreate(hWnd, wParam, lParam);
    		break;
    
    	case WM_COMMAND:
    		switch(LOWORD(wParam))
    		{
    
    		case BN_CLICKED:
    			*(((PROGRESSINFO *)(GetWindowLongPtr(hWnd, GWL_USERDATA)))->cancel) = 1;
    			break;
    
    		}
    		break;
    
    	case WM_CLOSE:
    		DestroyWindow(hWnd);
    		break;
    
    	case WM_DESTROY:
    		free((void *) GetWindowLongPtr(hWnd, GWL_USERDATA));
    		break;
    
    	}
    
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    
    }
    
    LRESULT ProgressWindow_OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
    
    	PROGRESSINFO * pip = *(PROGRESSINFO **) lParam;
    	RECT rect;
    
    	SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG) pip);
    
    	GetClientRect(hWnd, &rect);
    
    	pip->progressBar = CreateWindowEx(
    		WS_EX_CLIENTEDGE,
    		PROGRESS_CLASS,
    		NULL,
    		WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
    		rect.left + 2,
    		PROGRESSWINDOW_HEIGHT / 2 - GetSystemMetrics(SM_CYVSCROLL),
    		rect.right - 5,
    		GetSystemMetrics(SM_CYVSCROLL),
    		hWnd,
    		0,
    		GetModuleHandle(NULL),
    		NULL);
    
    	pip->hWndStatic = CreateWindowEx(
    		0,
    		"Static",
    		NULL,
    		WS_CHILD | WS_VISIBLE | SS_CENTER,
    		rect.left + 2,
    		rect.top + 10,
    		rect.right - 5,
    		rect.top + 20,
    		hWnd,
    		0,
    		GetModuleHandle(NULL),
    		NULL);
    
    	SetWindowText(pip->hWndStatic, pip->message);
    
    	pip->hWndCancel = CreateWindowEx(
    		0,
    		"Button",
    		NULL,
    		WS_CHILD | WS_VISIBLE | BS_TEXT | BS_PUSHBUTTON,
    		((rect.right - rect.left) / 2) + rect.left - 30,
    		rect.bottom  - 30,
    		60,
    		24,
    		hWnd,
    		0,
    		GetModuleHandle(NULL),
    		NULL);
    
    	SetWindowText(pip->hWndCancel, "Cancel");
    
    	pip->hWndProgress = hWnd;
    
    	SetFocus(pip->hWndCancel);
    
    	return FALSE;
    
    }
    
    DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
    {
    
    	int i;
    	unsigned __int64 biasBit = 0x8000000000000000;
    	int progressRange;
    	int progressAchieved;
    	PROGRESSINFO * pip = lpData;
    
    	if(!pip->progressBias)
    	{
    		if(!(TotalFileSize.QuadPart & 0xFFFFFFFF80000000))
    			pip->progressBias = 0;
    
    		else  //Untested...
    		{
    			for(i = 33; i; i--)
    			{
    				if(biasBit & TotalFileSize.QuadPart)
    					break;
    
    				biasBit = biasBit>>1;
    			}
    
    			pip->progressBias = 32 - i;
    		}
    	}
    
    	progressRange = (int) (TotalFileSize.QuadPart>>(pip->progressBias + 1));
    
    	progressAchieved = (int) (TotalBytesTransferred.QuadPart>>(pip->progressBias + 1));
    
    	SendMessage(pip->progressBar, (UINT) PBM_SETRANGE32, (WPARAM) 0, (LPARAM) progressRange);
    
    	SendMessage(pip->progressBar, (UINT) PBM_SETPOS, (WPARAM) progressAchieved, (LPARAM) 0);
    
    	if(pip->parentUpdate && pip->lastParentUpdate + pip->parentUpdate < GetTickCount())
    	{
    		UpdateWindow(pip->hWndParent);
    		pip->lastParentUpdate = GetTickCount();
    	}
    
    	if(TotalFileSize.QuadPart == TotalBytesTransferred.QuadPart)  //Not sure if this is gurenteed to always be true the last time and only the last time this funtion is called. If it isn't it could be a bit proboblematic
    	{
    		PostMessage(pip->hWndProgress, WM_CLOSE, 0, 0);
    		return PROGRESS_CONTINUE;
    	}
    
    	if(*pip->cancel)
    	{
    		PostMessage(pip->hWndProgress, WM_CLOSE, 0, 0);
    		return PROGRESS_CANCEL;
    	}
    	else
    		return PROGRESS_CONTINUE;
    
    }
    
    ///////////////////////////////////////////////////////////////////////////////////////////

  2. #2
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107
    Ok, I finally figured it out. Since the CopyFileEx funtion completely hijacks the same thread that is used for message processing of the parent window I set for the function to use, that causes some problems. Well that's easy enough to fix, but I'd still like to know why calling a message box fixes the issue... Heh, isn't multithreading fun .

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    When you call MessageBox, your thread will enter a message loop until the user dismisses the message box.

    gg

  4. #4
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107
    In my case though, the message box is destroyed before CopyFileProgressEx() is called...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. writing text over a deleted button
    By algi in forum Windows Programming
    Replies: 4
    Last Post: 05-02-2005, 11:32 AM
  2. Button coordinates in dialog. Strange ?
    By fizisyen in forum Windows Programming
    Replies: 1
    Last Post: 08-23-2004, 09:29 PM
  3. disabling button in another prog
    By timmygax in forum Windows Programming
    Replies: 11
    Last Post: 10-29-2001, 03:40 PM
  4. Button Identifier Problems!
    By SyntaxBubble in forum Windows Programming
    Replies: 2
    Last Post: 10-16-2001, 05:48 PM
  5. Unselecting a selected button in C++Builder 5
    By Frozen_solid in forum Windows Programming
    Replies: 4
    Last Post: 09-25-2001, 07:57 PM