SOL9 2.0 Sample: Progman

SOL9 2.0 Samples

1 Screenshot


2 Source code

/*
 * Progman.cpp 
 * Copyright (c) 2009 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */



// SOL++2000 
// 2000.03.20
// 2009/11/06 Modified to stop the Program Scanner Thread

#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 "Resource.h"

#define WM_LISTUP    (WM_USER+200)


//  class ProgramScanner 

namespace SOL {

class ProgramScanner :public Thread {
private:
    ImageList&    imageList;
    ListView&    listView;
    bool    cancel;
    View*  application;
private:
    static const UINT WM_SOL_THREAD_CANCEL = (WM_USER+2009);

public:
    ProgramScanner(View* parent, ListView& listv, ImageList& image)
        :application(parent),
        listView(listv),
        imageList(image)
    {
        Args ar;
        ar.set(XmNwidth, 300);
        ar.set(XmNheight, 50);
    }

public:
    void run()
    {
        cancel = false;

        TCHAR path[10];
        TCHAR drive[10];
        DWORD d = ::GetLogicalDrives();

        for(int i = 0; i<26; i++) {
            dispatchMessage();
            Sleep(10);
            if (cancel == true) {
                break;
            }
            if(d & 1) {    
                _stprintf_s(path, SizeOf(path), _T("%c:"), 'A'+i);
                _stprintf_s(drive, SizeOf(drive), _T("%c:\\"), 'A'+i);
                UINT driveType = GetDriveType(drive);
                if (driveType == DRIVE_FIXED) {
                    find(path);
                } 
            }
            d = d >> 1;
        }

    }

private:
    void dispatchMessage()
    {
        MSG msg;

        while(
            PeekMessage (&msg,NULL,0,0,PM_REMOVE)) {
            Sleep(10);

            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 (this->cancel) {
            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();
                //Sleep(10);

                if (this->cancel == true) {
                    break;
                }

                if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                    if (strcmp(_T("."), data.cFileName) != 0 && 
                        strcmp(_T(".."), data.cFileName) != 0) {
                        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:
    void stop()
    {
        cancel = true;

        post(WM_SOL_THREAD_CANCEL, 0, 0);

    }

private:
    void addToListView(TCHAR* dir, TCHAR* fileName)
    {
        // Extract an icon.
        TCHAR fullpath[_MAX_PATH];
        _stprintf_s(fullpath, SizeOf(fullpath), _T("%s\\%s"), dir, fileName);

        HINSTANCE hInst = GetModuleHandle(NULL);//Application::getInstance();

        int number  = (int)ExtractIcon(hInst, fullpath, -1);
    
        for (int i = 0; i<number; i++) {
            dispatchMessage();
            if (cancel) {
                break;
            }
            HICON hicon = ExtractIcon(hInst, fullpath, i);

            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);
    
                //2009/11/06 Only list up the first icon
                break;
            }
        }
    }
};



//   ProgramManager

class ProgramManager :public ApplicationView {
private:

    ProgramScanner* scanner;
    ImageList   imageList;
    ListView    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, 500}
        }    ;
        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);

        scanner = NULL;

        post(WM_LISTUP, 0, 0);

        restorePlacement();
    }

public:
    ~ProgramManager()
    {
        //stopScanner();
        if (scanner) {
            delete scanner;
        }
    }


public:
    void suspend(Action& action)
    {
        if (scanner) {
            //Suspend the Scanner Thread
            scanner->suspend();
        }
    }

private:
    void stopScanner()
    {
        if (scanner) {
            //Do resume the scanner thread, even if it's running.
            scanner->resume();
            scanner->stop();
            scanner->wait();
        }
    }

public:
    void resume(Action& action)
    {
        if (scanner) {
            //Resume the Scanner Thread.
            scanner->resume();
        }
    }

private:
    long close(Event& event)
    {
        stopScanner();

        imageList.clear();
        savePlacement();
        return defaultProc(event);
    }

private:
    long listup(Event& event)
    {
        listView.deleteAllItems();

        scanner = new ProgramScanner(this, listView, imageList);
        scanner ->start();
        return 0L;
    }

private:
    void launch(Action& action)
    {
        if(lastChangedItem >= 0) {    
            TCHAR text[_MAX_PATH];
            listView.getItemText(lastChangedItem, 
                            0, text, SizeOf(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, sizeof(text));
            TCHAR title[_MAX_PATH];
            _stprintf_s(title, SizeOf(title), _T("ProgramManager - %s "), text);
            setText(title);
        }
    }
};

}

// ProgramManager Main
void    Main(int argc, TCHAR** argv)
{
    const String appClass = "ProgramManager";
    try {
        Application applet(appClass, argc, argv);

        Args args;
        ProgramManager programManager(applet, appClass, args);
        programManager.realize();

        applet.run();
    } catch (...) {

    }
}

Last modified: 11 Nov 2009

Copyright (c) 2009 Antillia.com ALL RIGHTS RESERVED.