It's my first window program. It simply searches for a specified file in the whole computer.
File Search.h (header file that contains the prototypes of fileSearcher class methods.)
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <queue>
namespace fileSearch
{
class fileSearcher
{
public:
fileSearcher();
~fileSearcher(); //So far, this class doesn't allocate memory on the heap,therefore destructor is empty
void getAllPaths(const TCHAR* fileName,std::queue<TCHAR*> &output);
/*Returns all matching pathes at the current local system. Format:
[A-Z]:\FirstPath\dir1...\fileName
[A-Z]:\SecondPath\dir2...\fileName
...
[A-Z]:\NPath\dirN...\fileName
*/
void findFilesRecursivelly(const TCHAR* curDir,const TCHAR* fileName,std::queue<TCHAR*> &output);
//Searches for the file in the current and in sub-directories. Sets nothingFound=false if the file has been found.
private:
static const int MAX_LOCATIONS = 20000;
bool nothingFound;
void endWithBackslash(TCHAR* string);
};
}
File Search.cpp ( ... definitions)
#ifndef UNICODE
#define UNICODE
#endif
#include "File Search.h"
using namespace fileSearch;
fileSearcher::fileSearcher()
{
nothingFound = true;
}
fileSearcher::~fileSearcher()
{
}
void fileSearcher::getAllPaths(const TCHAR* fileName,std::queue<TCHAR*> &output)
{
TCHAR localDrives[50];
TCHAR currentDrive;
int voluminesChecked=0;
TCHAR searchedVolumine[5];
nothingFound = true;
if(!wcslen(fileName))
{
output.push(TEXT("Invalid search key"));
return;
}
GetLogicalDriveStrings(sizeof(localDrives)/sizeof(TCHAR),localDrives);
//For all drives:
for(int i=0; i < sizeof(localDrives)/sizeof(TCHAR); i++)
{
if(localDrives[i] >= 65 && localDrives[i] <= 90)
{
currentDrive = localDrives[i];
voluminesChecked++;
}
else continue;
searchedVolumine[0] = currentDrive;
searchedVolumine[1] = L':';
searchedVolumine[2] = 0;
findFilesRecursivelly(searchedVolumine,fileName,output);
}
if(nothingFound)
output.push(TEXT("FILE NOT FOUND"));
}
void fileSearcher::findFilesRecursivelly(const TCHAR* curDir,const TCHAR* fileName,std::queue<TCHAR*> &output)
{
HANDLE hFoundFile;
WIN32_FIND_DATA foundFileData;
TCHAR* buffer;
buffer = new TCHAR[MAX_PATH+_MAX_FNAME];
wcscpy(buffer,curDir);
endWithBackslash(buffer);
if(!SetCurrentDirectory(buffer)) return;
//Fetch inside current directory
hFoundFile = FindFirstFileEx(fileName,FINDEX_INFO_LEVELS::FindExInfoBasic,&foundFileData ,FINDEX_SEARCH_OPS::FindExSearchNameMatch,NULL,FIND_FIRST_EX_LARGE_FETCH);
if(hFoundFile != INVALID_HANDLE_VALUE)
{
nothingFound = false;
do
{
buffer = new TCHAR[MAX_PATH+_MAX_FNAME];
wcscpy(buffer,curDir);
endWithBackslash(buffer);
wcscat(buffer,foundFileData.cFileName);
wcscat(buffer,TEXT("\r\n"));
output.push(buffer);
}
while(FindNextFile(hFoundFile,&foundFileData));
}
//Go to the subdirs
hFoundFile = FindFirstFileEx(TEXT("*"),FINDEX_INFO_LEVELS::FindExInfoBasic,&foundFileData ,FINDEX_SEARCH_OPS::FindExSearchLimitToDirectories ,NULL , NULL);
if(hFoundFile != INVALID_HANDLE_VALUE )
{
do
{
if(wcscmp(foundFileData.cFileName,TEXT(".")) && wcscmp(foundFileData.cFileName,TEXT("..")))
{
TCHAR nextDirBuffer[MAX_PATH+_MAX_FNAME]=TEXT("");
wcscpy(nextDirBuffer,curDir);
endWithBackslash(nextDirBuffer); //redundant?
wcscat(nextDirBuffer,foundFileData.cFileName);
findFilesRecursivelly( nextDirBuffer,fileName,output);
}
}
while(FindNextFile(hFoundFile,&foundFileData));
}
}
void fileSearcher::endWithBackslash(TCHAR* string)
{
if(string[wcslen(string)-1] != TEXT('\\')) wcscat(string,TEXT("\\"));
}
main.cpp (simple window interface for the fileSearcher class)
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <queue>
#include "File Search.h"
static HWND textBoxFileName;
static HWND searchButton;
static HWND textBoxOutput;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
using namespace fileSearch;
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR cmdLine,int nCmdShow)
{
TCHAR className[] = L"Main window class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = className;
RegisterClass(&wc);
HWND hMainWindow = CreateWindowEx(WS_EX_CLIENTEDGE,className,L"Path getter",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,600,300,NULL,NULL,hInstance,NULL);
if(hMainWindow == NULL)
return 0;
textBoxFileName = CreateWindowEx(WS_EX_CLIENTEDGE, L"Edit", NULL,WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 10, 10, 300, 21, hMainWindow, NULL, NULL, NULL);
searchButton = CreateWindowEx(WS_EX_CLIENTEDGE,L"Button",L"Search",WS_CHILD | WS_VISIBLE | ES_CENTER, 10, 41,75,30,hMainWindow,NULL,NULL,NULL);
textBoxOutput = CreateWindowEx(WS_EX_CLIENTEDGE,L"Edit",NULL,WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_READONLY ,10,81,500,90,hMainWindow,NULL,NULL,NULL);
ShowWindow(hMainWindow,nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
if((HWND)lParam == searchButton)
{
fileSearcher searcher;
TCHAR key[1000];
std::queue<TCHAR*> buffer;
SetWindowText(textBoxOutput,NULL);
GetWindowText(textBoxFileName,key,1000);
searcher.getAllPaths(key,buffer);
SendMessage(textBoxOutput,EM_LIMITTEXT,WPARAM(0xFFFFF),NULL);
while(!buffer.empty())
{
SendMessage(textBoxOutput,EM_SETSEL,GetWindowTextLength(textBoxOutput),GetWindowTextLength(textBoxOutput));
SendMessage(textBoxOutput,EM_REPLACESEL,FALSE, (LPARAM) buffer.front());
delete [] buffer.front();
buffer.pop();
}
}
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HBRUSH pedzel;
pedzel = CreateSolidBrush(RGB(249,224,75));
FillRect(hdc, &ps.rcPaint, pedzel);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Shortcomings that I've noticed so far:
1) The window freezes during work
2) Only a few queries can be done in a row - a memory after each isn't deallocated from heap (I simply don't know how to fix it).