PDA

View Full Version : Need an interface written



Thantos
11-22-2005, 04:04 PM
I am working on a small project for my family and I want to make a small computer illerate program that they can use to transfer some files inmass to my server. Due to some requirements the normal HTTP method is out and FTP is out for other reasons.
While I can easily write the file transfer part my UI skills are lacking.

What I'm looking for is a small UI window that will allow the user to drag and drop file(s) onto the window and have it populate a list of the files. They should also be able to remove file(s) from the list.

Also there will need to be a field for entering the username and a field for the password. There should also be an option for saving the username and password which would autoload it.

Upon clicking the submit button the program should call a function from a DLL (I'll provide that stuff) and pass the list of files as a std::vector<std::string> and the username and password as a std::string.

If anyone is interested please let me know. Sorry but I have nothing to offer but my gratitude

VirtualAce
11-23-2005, 12:05 AM
I could do it in MFC but I shudder at using std::stirng. MFC CString is much more suited to this and the Serialize() feature of the classes derived from CObject will save these types of objects automatically. CString is derived from CObject and therefore is serializable.

I might be able to cook something up, but I'm rather busy with my tile editor in MFC at the moment. Perhaps we should talk via PM to see if you are interested in 'altering' some of the requirements a bit. Drag and drop is easy enough as well as the vector stuff and the saving passwords, etc. That's all very easy.

But what do you want to drag and drop from?
I could probably do this by using a CWnd and this class:



COleDropTarget Class Members
Construction

COleDropTarget Constructs a COleDropTarget object.


Operations

Register Registers the window as a valid drop target.
Revoke Causes the window to cease being a valid drop target.


Overridables

OnDragEnter Called when the cursor first enters the window.
OnDragLeave Called when the cursor is dragged out of the window.
OnDragOver Called repeatedly when the cursor is dragged over the window.
OnDragScroll Called to determine whether the cursor is dragged into the scroll region of the window.
OnDrop Called when data is dropped into the window, default handler.
OnDropEx Called when data is dropped into the window, initial handler.


COleDropTarget Overview | Base Class Members | Hierarchy Chart

Thantos
11-23-2005, 12:23 AM
But what do you want to drag and drop from?
Regular explorer windows

anonytmouse
11-23-2005, 05:57 AM
I hope you wanted an interface for Windows!

Attached is a Dev-C++ project in a zip file. You will have to rename it from .txt to .zip.

It is a dialog based application. I coded it fairly quickly but it looks pretty good and seems to work well.

anonytmouse
11-23-2005, 05:59 AM
Screenshot

anonytmouse
11-23-2005, 06:06 AM
In case anyone wants to look at the code without going through the effort of download/renaming, I'll post it here.

Resource File:


#include <windows.h>
#include <commctrl.h>
#include "resource.h"


/* Include our manifest which tells Windows to use commctrl version 6
* Equivalent to CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST fileTransfer.exe.manifest
*/
1 24 fileTransfer.exe.manifest

/* Start our dialog definition
*/
IDD_FILE_DIALOG DIALOGEX 20, 20, 434, 284
STYLE DS_FIXEDSYS | DS_SETFONT | DS_MODALFRAME | DS_NOIDLEMSG | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "Transfer Files"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 8, "MS Shell Dlg"
{
CONTROL "", IDD_FILES, "SysListView32", LVS_SHOWSELALWAYS | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VISIBLE, 8, 12, 236, 266

CONTROL "Cancel", IDCANCEL, "BUTTON", BS_DEFPUSHBUTTON | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 345, 264, 40, 14
CONTROL "Upload", IDD_UPLOAD, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 389, 264, 40, 14

CONTROL "Add", IDD_ADDFILE, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 248, 247, 40, 14
CONTROL "Remove", IDD_REMOVEFILE, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 248, 264, 40, 14

CONTROL "Username:", 101, "STATIC", SS_RIGHT | WS_CHILD | WS_VISIBLE, 248, 19, 35, 10
CONTROL "Password:", 102, "STATIC", SS_RIGHT | WS_CHILD | WS_VISIBLE, 248, 33, 35, 10
CONTROL "DROP FILES HERE", 103, "STATIC", SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_CHILD | WS_VISIBLE, 313, 146, 58, 10

CONTROL "", IDD_USERNAME, "EDIT", WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VISIBLE, 287, 18, 142, 10
CONTROL "", IDD_PASSWORD, "EDIT", ES_PASSWORD | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VISIBLE, 287, 33, 142, 10
CONTROL "Remember Username && Password", IDD_SAVEPASSWORD, "BUTTON", BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 306, 47, 123, 14
}

Code:


/* Windows header files */
#define _WIN32_IE 0x0500
#include <windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shlwapi.h>

/* Application header files */
#include "resource.h"

/* C++ header files */
#include <vector>
#include <string>


/* Global variable that holds the location of the settings file. */
TCHAR g_szSettingsFile[MAX_PATH];


/*
* Function to save username and password to the settings.ini file.
*/
VOID SaveUserPassword(LPCTSTR szUsername, LPCTSTR szPassword)
{
WritePrivateProfileString(TEXT("FileTransfer"), TEXT("Username"), szUsername, g_szSettingsFile);
WritePrivateProfileString(TEXT("FileTransfer"), TEXT("Password"), szPassword, g_szSettingsFile);
}


/*
* Function to retore the username and password from the settings.ini file.
*/
VOID RestoreUserPassword(HWND hwnd)
{
TCHAR szUsername[500];
TCHAR szPassword[500];

GetPrivateProfileString(TEXT("FileTransfer"), TEXT("Username"), TEXT(""), szUsername, 500, g_szSettingsFile);
GetPrivateProfileString(TEXT("FileTransfer"), TEXT("Password"), TEXT(""), szPassword, 500, g_szSettingsFile);

SetDlgItemText(hwnd, IDD_USERNAME, szUsername);
SetDlgItemText(hwnd, IDD_PASSWORD, szPassword);

if (szUsername[0] != TEXT('\0') || szPassword[0] != TEXT('\0'))
{
/* If settings were successfully retrieved, check the remember settings box
* so that settings are saved again at upload. */
SendDlgItemMessage(hwnd, IDD_SAVEPASSWORD, BM_SETCHECK, BST_CHECKED, 0);
}
}


/*
* Function to set up the list-view control.
*/
VOID SetupDialog(HWND hwnd)
{
HWND hListView = GetDlgItem(hwnd, IDD_FILES);
LVCOLUMN lvc = { 0 };

lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;

lvc.fmt = LVCFMT_LEFT;
lvc.iSubItem = 0;
lvc.cx = 200;
lvc.pszText = TEXT("Filename");
ListView_InsertColumn(hListView, 0, &lvc);

lvc.fmt = LVCFMT_RIGHT;
lvc.iSubItem = 1;
lvc.cx = 60;
lvc.pszText = TEXT("Size");
ListView_InsertColumn(hListView, 1, &lvc);

lvc.fmt = LVCFMT_LEFT;
lvc.iSubItem = 2;
lvc.cx = 0; /* Hidden by default */
lvc.pszText = TEXT("Path");
ListView_InsertColumn(hListView, 2, &lvc);

/* Size the filename column to be as wide as possible. */
RECT rc; GetClientRect(hListView, &rc);
ListView_SetColumnWidth(hListView, 0, rc.right - 60 - 18);

ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT | LVS_EX_FLATSB | LVS_EX_HEADERDRAGDROP);

/* Restore username & password from settings.ini file. */
RestoreUserPassword(hwnd);

/* Notify Windows that our window can accept dropped files. */
DragAcceptFiles(hwnd, TRUE);
}


/*
* Function to get the size of the file as a string in kilobytes.
*/
VOID GetFileSize(LPCTSTR szFile, TCHAR szSize[30])
{
LARGE_INTEGER li = { 0 };
WIN32_FIND_DATA wfd = { 0 };

FindClose(FindFirstFile(szFile, &wfd));
li.HighPart = wfd.nFileSizeHigh;
li.LowPart = wfd.nFileSizeLow;
DWORD size = (li.QuadPart / 1024) + 1;

wsprintf(szSize, TEXT("%u KB"), size);
}


/*
* Adds a file item to our list-view control
*/
VOID AddFileItem(HWND hwnd, LPTSTR szFile)
{
HWND hListView = GetDlgItem(hwnd, IDD_FILES);
LVITEM lv = { 0 };

ListView_InsertItem(hListView, &lv);

/* Add file name in column 0. */
ListView_SetItemText(hListView, 0, 0, PathFindFileName(szFile));

/* Add file size in column 1. */
TCHAR szSize[30];
GetFileSize(szFile, szSize);
ListView_SetItemText(hListView, 0, 1, szSize);

/* Add file path in column 2 (which is hidden by default). */
ListView_SetItemText(hListView, 0, 2, szFile);
}


/*
* Remove a file from the list-view.
*/
VOID RemoveFileItem(HWND hwnd)
{
HWND hListView = GetDlgItem(hwnd, IDD_FILES);

/* Get selected item. */
int item = ListView_GetNextItem(hListView, (WPARAM) -1, LVNI_SELECTED);

/* Delete item. */
ListView_DeleteItem(hListView, item);

/* Focus on the item above so that user can do multiple deletes without
* clicking on a file each time. */
ListView_SetItemState(hListView, item > 0 ? item - 1 : item, LVIS_SELECTED, LVIS_SELECTED);
}


/*
* Show a file selection dialog and add the selected file.
* This could be improved by allowing multiple selections.
*/
VOID AddFileDialog(HWND hwnd)
{
OPENFILENAME of = { 0 };
TCHAR buf[MAX_PATH] = { 0 };

of.lStructSize = sizeof(of);
of.hwndOwner = hwnd;
of.lpstrFile = buf;
of.nMaxFile = MAX_PATH;

if (GetOpenFileName(&of))
{
AddFileItem(hwnd, buf);
}
}


/*
* Deal with files that have been dropped on our window.
*/
VOID HandleDroppedFiles(HWND hwnd, HDROP hDrop)
{
UINT count = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

for (int i = 0; i < count; i++)
{
TCHAR buf[MAX_PATH];
DragQueryFile(hDrop, i, buf, MAX_PATH);

/* Reject directories, remove if you wish to handle directories. */
if ((GetFileAttributes(buf) & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
AddFileItem(hwnd, buf);
}
}

DragFinish(hDrop);
}


/*
* Your function starts here.
* Note: I think using a std::string to hold filenames may cause troubles. Even if you don't use
* unicode characters when naming filenames, they often appear in file names downloaded from the
* web, email, etc.
*/
void ThantosDoUpload(std::vector<std::string>& files, std::string user, std::string password)
{


/* DEBUG CODE:
*
for (int i = 0; i < files.size(); i++)
{
MessageBox(NULL, files[i].c_str(), NULL, 0);
}

MessageBox(NULL, user.c_str(), password.c_str(), 0);
*
* END DEBUG CODE */
}



/*
* Upload button pressed. Save settings, if required, retrieve
* info in specified format and pass to Thantos function.
*/
VOID DoUpload(HWND hwnd)
{
HWND hListView = GetDlgItem(hwnd, IDD_FILES);
int count = ListView_GetItemCount(hListView);

if (count == 0)
{
/* No files have been added. Show a message and return. */
MessageBox(hwnd, TEXT("No files have been selected. Please add some files and try again."),
TEXT("No Files Selected"), MB_ICONWARNING);
return;
}

/* Hide the dialog box while we process the files. */
ShowWindow(hwnd, SW_HIDE);

/* Retrieve the username and password from the dialog. */
TCHAR szUsername[500];
TCHAR szPassword[500];
BOOL fSavePassword = SendDlgItemMessage(hwnd, IDD_SAVEPASSWORD, BM_GETCHECK, 0, 0);
GetDlgItemText(hwnd, IDD_USERNAME, szUsername, 500);
GetDlgItemText(hwnd, IDD_PASSWORD, szPassword, 500);

if (fSavePassword)
{
/* Save the username and password to settings.ini. */
SaveUserPassword(szUsername, szPassword);
}
else
{
/* Delete file so that old username and password are not remembered. */
DeleteFile(g_szSettingsFile);
}

/* Retrieve file paths from the list-view and add to vector of strings. */
std::vector<std::string> files;

for (int i = 0; i < count; i++)
{
TCHAR path[MAX_PATH];
ListView_GetItemText(hListView, i, 2, path, MAX_PATH);
files.push_back(std::string(path));
}

/* Transfer info to Thantos' function */
ThantosDoUpload(files, std::string(szUsername), std::string(szPassword));

/* Destroy dialog */
EndDialog(hwnd, 0);
}


/*
* Dialog window procedure.
*/
INT_PTR CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
SetupDialog(hwnd);
}
break;

case WM_COMMAND:
{
int idControl = LOWORD(wParam);
int command = HIWORD(wParam);

if (idControl == IDCANCEL && command == BN_CLICKED)
{
EndDialog(hwnd, 0);
}
else if (idControl == IDD_ADDFILE && command == BN_CLICKED)
{
AddFileDialog(hwnd);
}
else if (idControl == IDD_REMOVEFILE && command == BN_CLICKED)
{
RemoveFileItem(hwnd);
}
else if (idControl == IDD_UPLOAD && command == BN_CLICKED)
{
DoUpload(hwnd);
}
}
break;

case WM_DROPFILES:
{
HandleDroppedFiles(hwnd, (HDROP) wParam);
}
break;

default:
{
return FALSE;
}
break;
}

return TRUE;
}


/*
* Entry function.
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE reserved, LPSTR lpCmdLine, int nCmdShow)
{
InitCommonControls();

/* Get the location of the settings.ini file and create directory, if required.
* The usual settings location is:
* Documents and Settings\User\Application Data\FileTransfer\settings.ini
*/
SHGetSpecialFolderPath(NULL, g_szSettingsFile, CSIDL_APPDATA, FALSE);
PathAppend(g_szSettingsFile, TEXT("FileTransfer"));
CreateDirectory(g_szSettingsFile, NULL);
PathAppend(g_szSettingsFile, TEXT("settings.ini"));

/* Create our modal dialog. */
DialogBox(hInstance, MAKEINTRESOURCE(IDD_FILE_DIALOG), NULL, DialogProc);

return 0;
}

Thantos
11-23-2005, 07:24 AM
Looks very good anonytmouse. Thanks :)

VirtualAce
11-23-2005, 12:26 PM
How do you use those cool XP buttons in MFC? I have to use the crappy old boxy ones. Does it have to be in pure Win32 in order to use them.

In other words, are the MFC classes using the deprecated functions to create the buttons hence their 'old' appearance.

Never mind: http://www.developer.com/net/asp/article.php/3101831

Gotta love google.

Thantos
11-23-2005, 06:26 PM
anonytmouse I haven't had a chance to test it but does the filename include the full path?

anonytmouse
11-23-2005, 11:15 PM
anonytmouse I haven't had a chance to test it but does the filename include the full path?
Yes, the vector includes complete paths.

Thantos
11-23-2005, 11:19 PM
Thankee, started looking at it a couple hours ago. Really nice job.