SOL9 2.0 Class: ListBox

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree 

Source code

/*
 * ListBox.h 
 * Copyright (c) 2011 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// SOL++2000
// 2000.02.18
#pragma once

#include <sol\Primitive.h>


namespace SOL {

class ListBox :public Primitive {
private:
    //2009/11/07 For findAllFiles method
    bool scanning;

private:

    static const long STYLE = (WS_TABSTOP|WS_BORDER|LBS_NOTIFY|WS_HSCROLL|WS_VSCROLL|\
                LBS_NOINTEGRALHEIGHT);

    static const TCHAR itemsListDelim = '\n';

    static int stylesCount()
    {
        int count = 0;
        styles(&count);
        return count;
    }

    static Arg* styles(int* count=NULL)
    {
        static Arg _styles[] = {
        {XmNdisableNoScroll,   LBS_DISABLENOSCROLL},
        {XmNextendedSel,       LBS_EXTENDEDSEL},
        {XmNmultiColumn,       LBS_MULTICOLUMN},
        {XmNmultipleSel,       LBS_MULTIPLESEL},
        {XmNsortItems,         LBS_SORT},
        {XmNuseTabStops,       LBS_USETABSTOPS},
        {XmNwantKeyboardInput, LBS_WANTKEYBOARDINPUT},
        };

        if (count){
            *count = XtNumber(_styles);
        }
        return _styles;
    }


public:
    ListBox():Primitive() { }

public:
    ListBox(View* parent, HWND hwnd)
        :Primitive(parent, hwnd) { }

public:
    ListBox(View* parent, const TCHAR* name, Args& args)
    :Primitive(parent, name, 
            args.set(styles(), stylesCount())
                .set(XmNpredefined, TRUE)
                .set(XmNstyle,     (ulong)STYLE)
                .set(XmNexStyle,   (ulong)WS_EX_CLIENTEDGE)
                .set(XmNuseDefaultFont, _T("true"))
                .set(XmNclassName, _T("ListBox")))
    {
        setValues(args);
    }


public:
    virtual Boolean create(View* parent, const TCHAR* name, Args& args)
    {
        Boolean rc = Primitive::create(parent, name, 
            args.set(styles(), stylesCount())
                .set(XmNpredefined, TRUE)
                .set(XmNstyle,     (ulong)STYLE)
                .set(XmNexStyle,   (ulong)WS_EX_CLIENTEDGE)
                .set(XmNuseDefaultFont, _T("true"))
                .set(XmNclassName, _T("ListBox")));

        setValues(args);

        return rc;
    }

public:
    Arg* getCallbackTable(int* num)
    {
        static Arg table[] = {
        {XmNdefaultActionCallback,     LBN_DBLCLK},
        {XmNerrorSpaceCallback,        (ulong)LBN_ERRSPACE},
        {XmNkillFocusCallback,        LBN_KILLFOCUS},
        {XmNselCancelCallback,        LBN_SELCANCEL},
         {XmNselChangeCallback,        LBN_SELCHANGE},
         {XmNsetFocusCallback,        LBN_SETFOCUS},
         };

        *num = XtNumber(table);
        return table;
    }

public:
    int    getCurText(TCHAR* buffer) 
    {
        if(buffer) {
            *buffer = Zero;
            int indx = getCurSel();
            if(indx != LB_ERR) {
                return getText(indx, buffer);
            }
            else {
                return 0;
            }
        }
        return 0;
    }

public:
    TCHAR* getCurText()
    {
        TCHAR* text = NULL;

        int indx = getCurSel();
        if(indx != LB_ERR) {
            int len = getTextLen(indx);
            text = new TCHAR[len+1];
            getText(indx, text);
        }
        return text;
    }

public:
    void getValues(Args& args)
    {
        Primitive::getValues(args);

        getStyle(args, styles(), stylesCount());

        ulong* val = (ulong*)args.get(XmNitemsList);
        if(val) {
            int buffLen = 0;
            int count  = getCount();
            for(int n = 0; n< count; n++) {
                buffLen = buffLen + getTextLen(n) + 1; //strlen("\n");
            }

            TCHAR* list = new TCHAR[buffLen];
            *list      = NULL;
            TCHAR* buff = list;

            for(int i = 0; i< count; i++) {
                int len = getTextLen(i);
                getText(i, buff);
                buff += len;
                if(i < count -1) {
                    *buff  = itemsListDelim;
                }
                buff++;
            }
            *buff = Zero;

            *val  = (ulong)list;
        }
    }

public:
    void ListBox::setValues(Args& args)
    {
        Primitive::setValues(args);

        updateStyle(args, styles(), stylesCount());

        ulong  val;
        TCHAR** items = NULL;
        int     count = 0;
        if (args.get(XmNitemCount, &val))
            count = (int)val;
        if (args.get(XmNitems, &val))
            items = (TCHAR**)val;
        if (count >0 && items) {
            resetContent();
            for (int i = 0; i<count; i++) {
                addString(items[i]);
            }
        }

        // XmNitemsList

        TCHAR* list = NULL;
        if (args.get(XmNitemsList, &val)) {
            resetContent();
            TCHAR* s = (TCHAR*)val;
            int slen = strlen(s)+1;
            list = new TCHAR[slen];
            strcpy_s(list, slen, s);
        }
        if (list) {
            TCHAR* str = list;
            TCHAR* ptr = list;
            while(*ptr) {
                if(*ptr == itemsListDelim) {
                    *ptr++ = NULL;
                    addString(str);
                    str = ptr;
                }
                else {
                    ptr++;
                }
            }
            if (str)  addString(str);
            if (list) delete list;
        }
    }

public:
    // List up long file names.
    void findFiles(DWORD attr, const TCHAR* pattern)
    {
        WIN32_FIND_DATA data;
        HANDLE hf = ::FindFirstFile(pattern, &data);
        if(hf != INVALID_HANDLE_VALUE) {
            do {
                if(data.dwFileAttributes & attr) {
                    addString((TCHAR*)data.cFileName);
                }            
            } while(::FindNextFile(hf, &data));
            ::FindClose(hf);
        }
    }

public:
    void findFiles(const TCHAR* pattern)
    {
        DWORD attr = FILE_ATTRIBUTE_ARCHIVE|
        FILE_ATTRIBUTE_DIRECTORY|
        FILE_ATTRIBUTE_COMPRESSED|
        FILE_ATTRIBUTE_HIDDEN| 
        FILE_ATTRIBUTE_NORMAL|    
        FILE_ATTRIBUTE_READONLY| 
        FILE_ATTRIBUTE_SYSTEM;
        ListBox::findFiles(attr, pattern);    
    }

private:
    //2009/11/07
    void dispatchMessage()
    {
        MSG msg;
        
        while(
            PeekMessage (&msg,NULL,0,0,PM_REMOVE)) {
            Sleep(10);
            if (msg.message == WM_QUIT) {
                scanning = false;
                //Repost WM_QUIT message to your application message queue.
                PostMessage(NULL, WM_QUIT, 0, 0);
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

public:
    //2009/11/06
    //2009/11/06
    // List up all file name having an extension of ext.
    void findAllFiles(const TCHAR* dir, const TCHAR* ext)
    {
        if (dir == NULL || ext == NULL) {
            return;
        }

        setRedraw(FALSE);
        clear();
        scanning = true;
        
        findAllFilesRecursively(dir, ext);
        scanning = false;
        
        setRedraw(TRUE);
    }

public:
    bool isScanning()
    {
        return scanning;
    }

public:
    void stopScanning()
    {
        scanning = false;
    }

public:
    //2009/11/06
    // List up all file name having an extension of ext.
    void findAllFilesRecursively(const TCHAR* dir, const TCHAR* ext)
    {
        if (scanning == false) {
            return;
        }

        setRedraw(FALSE);

        WIN32_FIND_DATA data;
        TCHAR* path = new TCHAR[MAX_PATH];
        _stprintf_s(path, MAX_PATH, _T("%s\\%s"), dir, _T("*"));
        
        HANDLE hf = ::FindFirstFile(path, &data);
        if(hf != INVALID_HANDLE_VALUE) {
            do {
                dispatchMessage();
                if (scanning == false) {
                    break;
                }
                if (!(strcmp(data.cFileName, _T(".")) == 0 ||
                    strcmp(data.cFileName, _T("..")) == 0)) {
        
                    TCHAR* fullPath = new TCHAR[MAX_PATH];
                    _stprintf_s(fullPath, MAX_PATH, _T("%s\\%s"), dir, data.cFileName);

                    if(String::endsWithIgnoreCase(data.cFileName, ext)) {
                        addString((TCHAR*)fullPath);
                    }
                    // Recursively call findAllFile provided fullPath were a directory
                    if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                        findAllFilesRecursively(fullPath, ext); 
                    }
                    delete [] fullPath;
                }
            } while(::FindNextFile(hf, &data));
            ::FindClose(hf);
        }
        delete [] path;

        setRedraw(TRUE);
    }

public:
    // Find all subdirectories under dir.
    // Give a string such as "c:\\windows"  for dir.
    void findDirectories(const TCHAR* dir)
    {
        TCHAR pattern[_MAX_PATH];
        _stprintf_s(pattern, SizeOf(pattern), _T("%s\\*.*"), dir);
        findFiles(FILE_ATTRIBUTE_DIRECTORY, pattern);
    }

    int     addString(const TCHAR* string) {
            return (int)send(LB_ADDSTRING, 0, (LPARAM)string);
    }

    // 1999.09.23
    void    clear() {
            send(LB_RESETCONTENT, 0, 0L);
    }

    const TCHAR*    defaultCallbackName() { 
        return XmNdefaultActionCallback; 
    }
    
    int     deleteString(int indx) {
            return (int)send(LB_DELETESTRING, indx, 0L);
    }

    int        dir(int attr, const TCHAR* string) {
            return (int)send(LB_DIR, attr, (LPARAM)string);
    }

    int        findString(int indx, const TCHAR* string) {
            return (int)send(LB_FINDSTRING, indx, (LPARAM)string);
    }

    int        findStringExact(int indx, const TCHAR* string) {
            return (int)send(LB_FINDSTRINGEXACT, indx, (LPARAM)string);
    }

    int     getCaretIndex() {
            return (int)send(LB_GETCARETINDEX, 0, 0L);
    }

    int     getCount() {
            return (int)send(LB_GETCOUNT, 0, 0L);
    }

    int        getCurSel() {
            return (int)send(LB_GETCURSEL, 0, 0L);
    }

    int        getHorizontalExtent() {
            return (int)send(LB_GETHORIZONTALEXTENT, 0, 0L);
    }

    long    getItemData(int indx) {
            return send(LB_GETITEMDATA, indx, 0L);
    }

    long    getItemHeight(int indx) {
            return send(LB_GETITEMHEIGHT, indx, 0L);
    }

    int        getItemRect(int indx, LPRECT rect) {
            return (int)send(LB_GETITEMRECT, indx, (LPARAM)rect);
    }

    int        getSel(int indx) {
            return (int)send(LB_GETSEL, indx, 0L);
    }

    int        getSelCount() {
            return (int)send(LB_GETSELCOUNT, 0, 0L);
    }

    int        getSelItems(int max, int array[]) {
            return (int)send(LB_GETSELITEMS, max, (LPARAM)array);
    }

    int     getText(int indx, TCHAR* buffer) {
            return (int)send(LB_GETTEXT, indx, (LPARAM)buffer);
    }

    int     getTextLen(int indx) {
            return (int)send(LB_GETTEXTLEN, indx, 0L);
    }

    int        getTopIndex() {
            return (int)send(LB_GETTOPINDEX, 0, 0L);
    }

    int     insertString(int indx, const TCHAR* string) {
            return (int)send(LB_INSERTSTRING, indx, (LPARAM)string);
    }

    void    resetContent() {
            send(LB_RESETCONTENT, 0, 0L);
    }

    int        selectString(int indx, const TCHAR* string) {
            return (int)send(LB_SELECTSTRING, indx, (LPARAM)string);
    }

    int        selItemRange(int sel, int first, int last) {
            return (int)send(LB_SELITEMRANGE, sel, MAKELPARAM(first,last));
    }

    void    setCaretIndex(int indx, int scroll) {
            send(LB_SETCARETINDEX, indx, MAKELPARAM(scroll, 0));
    }

    void    setColumnWidth(int width) {
            send(LB_SETCOLUMNWIDTH, width, 0L);
    }

    int        setCurSel(int indx) {
            return (int)send(LB_SETCURSEL, indx, 0L);
    }

    void    setHorizontalExtent(int width) {
            send(LB_SETHORIZONTALEXTENT, width, 0L);
    }

    int        setItemData(int indx, LPARAM data) {
            return (int)send(LB_SETITEMDATA, indx, data);
    }

    int        setItemHeight(int indx, int height) {
            return (int)send(LB_SETITEMHEIGHT, indx, MAKELPARAM(height,0));
    }

    int        setSel(int sel, int indx) {
            return (int)send(LB_SETSEL, sel, MAKELPARAM(indx, 0));
    }

    int        setTabStops(int num, int pos[]) {
            return (int)send(LB_SETTABSTOPS, num, (LPARAM)pos);
    }

    int        setTopIndex(int indx) {
            return (int)send(LB_SETTOPINDEX, indx, 0L);
    }
//    void    setValues(Args& args);

    int     getAnchorIndex() {
             return (int)send(LB_GETANCHORINDEX, 0, 0L);
    }

    long     getLocale() {
            return send(LB_GETLOCALE, 0, 0L);
    }

    void     setAnchorIndex(int indx) {
             send(LB_SETANCHORINDEX, (WPARAM)indx, 0L);
    }

    long     setLocale(long localeId) {
             return send(LB_SETLOCALE, (WPARAM)localeId, 0L);
    }
};

}



Last modified: 1 Feb 2012

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