1 Screenshot
2 Source code
/*
* Progman.cpp
* Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*/
// SOL++2000
// 2000.03.20
// 2009/11/06 Modified to stop the Program Scanner Thread
// 2012/07/26 Updated
#define COMMONCONTROLS_V6
#include <sol\ApplicationView.h>
#include <sol\Thread.h>
#include <sol\PopupView.h>
#include <sol\ListView.h>
#include <sol\ImageList.h>
#include <sol\Stdio.h>
#include <sol/EventObject.h>
#include <sol/SystemMetrics.h>
#include "Resource.h"
#define WM_LISTUP (WM_USER+2000)
// class ProgramScanner
namespace SOL {
class ProgramScanner :public Thread {
private:
ImageList& imageList;
ListView& listView;
bool cancel;
View* application;
String startingDir;
//EventObject eventObj;
HANDLE hEvent;
//private:
// static const UINT WM_SOL_THREAD_CANCEL = (WM_USER+2009);
public:
ProgramScanner(View* parent, ListView& listv, ImageList& image,
const TCHAR* scanDirectory=NULL)
:application(parent),
listView(listv),
imageList(image),
hEvent(NULL)
{
if (scanDirectory) {
startingDir = scanDirectory;
startingDir.removeBackSlash();
} else {
TCHAR windir[MAX_PATH];
GetWindowsDirectory(windir, CountOf(windir));
windir[3] = '\0';
//strcat(windir, _T("Program Files"));
_stprintf_s(&windir[3], CountOf(windir)-3, _T("%s"), _T("Program Files"));
startingDir = windir;
}
}
public:
void run()
{
cancel = false;
find((TCHAR*)startingDir);
}
private:
void dispatchMessage()
{
if (hEvent) {
while (true) {
if (MsgWaitForMultipleObjects(1, &hEvent, FALSE,
INFINITE, QS_ALLINPUT|QS_ALLEVENTS) == WAIT_OBJECT_0+1 ) {
MSG msg;
PeekMessage (&msg,NULL,0,0,PM_REMOVE);
SleepEx(10, TRUE);
TranslateMessage(&msg);
DispatchMessage(&msg);
}else {
break;
}
}
CloseHandle(hEvent);
hEvent = NULL;
} else {
MSG msg;
while(PeekMessage (&msg,NULL,0,0,PM_REMOVE)) {
SleepEx(10, TRUE);
if (msg.message == WM_SOL_THREAD_CANCEL) {
this->cancel = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
private:
void find(TCHAR* dir)
{
String xdir = &dir[1];
if (xdir.startsWithIgnoreCase(_T(":\\$Recycle.Bin"))) {
//2009/11/06 Skip Recyle.Bin folder
return;
}
dispatchMessage();
if (isCancelled()) {
return;
}
WIN32_FIND_DATA data;
TCHAR* buffer = new TCHAR[_MAX_PATH*2];
_stprintf_s(buffer, _MAX_PATH*2, _T("%s\\*"), dir);
HANDLE fFile= ::FindFirstFile(buffer, &data);
application->setText(buffer);
if(fFile != INVALID_HANDLE_VALUE) {
do {
dispatchMessage();
if (isCancelled()) {
break;
}
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (strcmp(_T("."), data.cFileName) != 0 &&
strcmp(_T(".."), data.cFileName) != 0) {
dispatchMessage();
if (isCancelled()) {
break;
}
TCHAR* subDir = new TCHAR[_MAX_PATH*2];
_stprintf_s(subDir, _MAX_PATH*2, _T("%s\\%s"), dir, data.cFileName);
find(subDir);
delete [] subDir;
}
} else {
CharLower(data.cFileName);
//Listup only *.exe files.
const TCHAR* p = strstr(data.cFileName, _T(".exe"));
if (p) {
addToListView(dir, data.cFileName);
}
}
} while(::FindNextFile(fFile, &data));
::FindClose(fFile);
}
delete [] buffer;
}
public:
virtual void doresume()
{
cancel = false;
if (hEvent) {
SetEvent(hEvent);
}
}
public:
virtual void dosuspend()
{
if (hEvent) {
CloseHandle(hEvent);
}
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
public:
void stop()
{
cancel = true;
post(WM_SOL_THREAD_CANCEL, 0, 0);
}
public:
bool isCancelled()
{
return this->cancel;
}
private:
void addToListView(TCHAR* dir, TCHAR* fileName)
{
// Extract an icon.
TCHAR fullpath[_MAX_PATH];
_stprintf_s(fullpath, CountOf(fullpath), _T("%s\\%s"), dir, fileName);
HINSTANCE hInst = GetModuleHandle(NULL);//Application::getInstance();
//Listup only the first icon
HICON hicon = ExtractIcon(hInst, fullpath, 0);
if(hicon) {
LV_ITEM item;
memset(&item, 0, sizeof(LV_ITEM));
// If it has an icon, add it ot the imageList.
item.mask = LVIF_TEXT|LVIF_IMAGE;
int id = imageList.addIcon(hicon);
item.iImage = id;
item.pszText = fullpath; //fileName;
item.cchTextMax = _MAX_PATH;
listView.insertItem(&item);
}
}
};
// ProgramManager
class ProgramManager :public ApplicationView {
private:
//<InnerClass> 2012/07/26
class ProgramListView :public ListView {
public:
void reshape(int x, int y, int w, int h, Boolean redraw=True)
{
ListView::reshape(x, y, w, h, redraw);
SystemMetrics metrics;
setColumnWidth(0, w-metrics.vScrollWidth());
}
};
//</InnerClass>
private:
ProgramScanner* scanner;
ImageList imageList;
ProgramListView listView;
int lastChangedItem;
public:
/**
* Constructor
*/
ProgramManager(Application& applet, const TCHAR* name, Args& args)
:ApplicationView(applet, name, args),
imageList(32, 32, ILC_COLOR24|ILC_MASK, 0, 5)
{
Args ar;
//ar.set(XmNstyle, (ulong)WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_ICON);
ar.set(XmNstyle, (ulong)WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_SORTASCENDING|LVS_REPORT);
listView.create(this, NULL, ar);
listView.setImageList(&imageList, LVSIL_SMALL);
listView.setImageList(&imageList, LVSIL_NORMAL);
ListViewColumn item[1] = {
{_T("Filename"), 0, 600}
} ;
listView.setColumn(item, 1);
// Add the listView to the default LayoutManager.
add(listView);
listView.addCallback(XmNdoubleClickCallback, this,
(Callback)&ProgramManager::launch, NULL);
listView.addCallback(XmNitemChangedCallback, this,
(Callback)&ProgramManager::itemChanged, NULL);
ar.reset();
ar.set(XmNwidth, 300);
ar.set(XmNheight, 50);
lastChangedItem = -1;
// Add a menucallback.
addCallback(XmNmenuCallback, IDM_RESUME, this,
(Callback)&ProgramManager::resume, NULL);
// Add a menucallback.
addCallback(XmNmenuCallback, IDM_SUSPEND, this,
(Callback)&ProgramManager::suspend, NULL);
// Add a menucallback.
addCallback(XmNmenuCallback, IDM_EXIT, this,
(Callback)&ProgramManager::exit, NULL);
addEventHandler(WM_LISTUP, this,
(Handler)&ProgramManager::listup, NULL);
restorePlacement();
scanner = NULL;
post(WM_LISTUP, 0, 0);
}
public:
void exit(Action& action)
{
int rc = MessageBox(NULL, _T("Are you sure you want terminate this program?"), _T("Progman"), MB_ICONQUESTION|MB_OKCANCEL);
if (rc == IDOK) {
stopScanner();
ApplicationView::exit(action);
}
}
public:
~ProgramManager()
{
stopScanner();
if (scanner) {
scanner->kill();
delete scanner;
}
}
public:
void suspend(Action& action)
{
if (scanner) {
scanner->dosuspend();
}
}
private:
void stopScanner()
{
if (scanner) {
scanner->doresume();
scanner->stop();
scanner->kill();
waitForThread(scanner->getHandle());
}
}
public:
void resume(Action& action)
{
if (scanner) {
//Don't call resume mehtod in Thread to avoid a deadlock
//scanner->resume();
scanner->doresume();
}
}
private:
long close(Event& event)
{
stopScanner();
savePlacement();
return defaultProc(event);
}
private:
long listup(Event& event)
{
listView.deleteAllItems();
scanner = new ProgramScanner(this, listView, imageList, _T("C:\\"));
scanner ->start();
return 0L;
}
private:
void launch(Action& action)
{
if(lastChangedItem >= 0) {
TCHAR text[_MAX_PATH];
listView.getItemText(lastChangedItem,
0, text, CountOf(text));
ShellExecute(NULL, _T("open"), text, NULL, NULL, SW_SHOW);
}
}
private:
void itemChanged(Action& action)
{
Event& event = action.getEvent();
NM_LISTVIEW* nmlistv = (NM_LISTVIEW*)event.getLParam();
lastChangedItem = nmlistv->iItem;
if(lastChangedItem >= 0) {
TCHAR text[_MAX_PATH];
listView.getItemText(lastChangedItem,
0, text, CountOf(text));
TCHAR title[_MAX_PATH];
_stprintf_s(title, CountOf(title), _T("ProgramManager - %s "), text);
setText(title);
}
}
};
}
// ProgramManager Main
void Main(int argc, TCHAR** argv)
{
ModuleFileName module(argv[0]);
const TCHAR* name = module.getFileName();
try {
Application applet(name, argc, argv);
Args args;
ProgramManager programManager(applet, name, args);
programManager.realize();
applet.run();
} catch (Exception& ex) {
caught(ex);
} catch (...) {
caught(UnknownException());
}
}
Last modified: 1 Feb 2017
Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.