SOL9 2.0 Class: ComboBox

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

Source code

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


// SOL++2000
// 2000/02/18
// 2001/03/19 Added getPreferredSize method.
// 2001/03/29 Added getControlHeight, setControlHeight methods.
// 2001/03/29 Added static variables itemsListDelim, heightMargin.

// 2009/09/22 Added getString method

#pragma once

#include <sol\Primitive.h>


namespace SOL {

class ComboBox :public Primitive {

private:
    // 2001/03/29 Added CBS_AUTOHSCROLL style
    static const long STYLE = (const long)(WS_TABSTOP|WS_VSCROLL|CBS_NOINTEGRALHEIGHT|CBS_AUTOHSCROLL);

    static const TCHAR itemsListDelim = '\n';

    static const int heightMargin = 2;

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

    static Arg*  styles(int* count=NULL)
    {
        static  Arg _styles[] = {
        {XmNsortItems,          CBS_SORT},
        {XmNdisableNoScroll, CBS_DISABLENOSCROLL},
        {XmNoemConvert,      CBS_OEMCONVERT}
        };
        if (count) {
            *count = XtNumber(_styles);
        }
        return _styles;
    }

public:
    ComboBox():Primitive() { }

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

public:
    ComboBox(View* parent, const TCHAR* name, Args& args)
    :Primitive(parent, name, 
            args.set(styles(), stylesCount())
                .set(XmNpredefined, TRUE)
                .set(XmNstyle, (ulong)STYLE)
                .set(XmNuseDefaultFont, _T("true"))
                .set(XmNclassName, _T("ComboBox")))

    {
        setValues(args);
    }

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

        setValues(args);

        return rc;    
    }

public:
    Arg* getCallbackTable(int* num)
    {
        static Arg table[] = {
        {XmNcloseUpCallback,        CBN_CLOSEUP},
         {XmNdefaultActionCallback,    CBN_DBLCLK},
         {XmNdropDownCallback,        CBN_DROPDOWN},
        {XmNeditChangeCallback,        CBN_EDITCHANGE},
        {XmNeditUpdateCallback,        CBN_EDITUPDATE},
        {XmNerrorSpaceCallback,        (ulong)CBN_ERRSPACE},

        {XmNkillFocusCallback,        CBN_KILLFOCUS},
        {XmNselChangeCallback,        CBN_SELCHANGE},
        {XmNselEndCancelCallback,    CBN_SELENDCANCEL},
        {XmNselEndOkCallback,        CBN_SELENDOK},
        {XmNsetFocusCallback,        CBN_SETFOCUS}
        };

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

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();
            // 2001/03/31
            // Compute the length of string buffer to store all 
            // item-texts separated with a new line .
            for(int n = 0; n< count; n++) {
                buffLen = buffLen + getLBTextLen(n) + 1; //strlen("\n");    
            }     

            TCHAR* list = new TCHAR[buffLen];
            *list      = NULL;
            TCHAR* buff = list;
            for(int i = 0; i< count; i++) {
                int len = getLBTextLen(i);
                getLBText(i, buff);
                buff += len;
            
                if(i < count -1) {
                    *buff = itemsListDelim;
                }
                buff++;
            }
            *buff = Zero;
            *val  = (ulong)list;
        }
    }

public:
    // 2001/03/29
    void ComboBox::setValues(Args& args)
    {    
        ulong v;
        if (!args.get(XmNwidth, &v) ) {
            args.set(XmNwidth, 100);
        }
        if (!args.get(XmNheight, &v) ) {
            args.set(XmNheight, 100);
        }
    

        Primitive::setValues(args);

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

        /*
        */
    
        ulong  val;
        if (args.get(XmNmaxLength, &val))
            limitText((int)val);

        if (args.get(XmNlabelString, &val))
            setText((TCHAR*)val);

        // XmNitems & XmNitemCount;
        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* item = (TCHAR*)val;
            int slen = strlen(item)+1;
            list = new TCHAR[slen];
            strcpy_s(list, slen, item);
        }

        if (list) {
            TCHAR* str = list;
            TCHAR* ptr = list;
            while(*ptr) {
                if(*ptr == itemsListDelim) {    //2001/04/01
                    *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;
        ComboBox::findFiles(attr, pattern);    
    }

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);
    }


// 2001/03/19
public:
    void getPreferredSize(Dimension& d)
    {
        int w, h;
        getSize(w, h);

        LONG style   = getWindowLong(GWL_STYLE);
        if ((style & CBS_DROPDOWN) ||
            (style & CBS_DROPDOWNLIST )) {
            h = getControlHeight() + heightMargin;
        }
        d.set(w, h);
    }


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

    const TCHAR*    defaultCallbackName() { 
        return XmNdefaultActionCallback; 
    }

    int     deleteString(int indx) {
            return (int)send(CB_DELETESTRING, indx, 0L);
    }
    int        dir(int attr, const TCHAR* string) {
            return (int)send(CB_DIR, attr, (LPARAM)string);
    }

    int        findString(int indx, TCHAR* string) {
            return (int)send(CB_FINDSTRING, indx, (LPARAM)string);
    }
    int        findStringExact(int indx, TCHAR* string) {
            return (int)send(CB_FINDSTRINGEXACT, indx, (LPARAM)string);
    }
    
//    Arg*    getCallbackTable(int* num);

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

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

    int        getDroppedControlRect(RECT* rect) {
            return (int)send(CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)rect);
    }

    int        getDroppedState() {
            return (int)send(CB_GETDROPPEDSTATE, 0, 0L);
    }

    long    getEditSel() {
            return send(CB_GETEDITSEL, 0, 0L);
    }

    int        getExtendedUI() {
            return (int)send(CB_GETEXTENDEDUI, 0, 0L);
    }

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

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

    // 2001/03/29
    int     getControlHeight() {
            //Return the height of the edit control(or static-text) portion of the combo box.
            return (int)send(CB_GETITEMHEIGHT, -1, 0L);
    }

    bool    getString(int indx, String& string)
    {
        bool rc = false;
        int len = getLBTextLen(indx);

        if (len >0) {
            TCHAR* buffer = new TCHAR[len+1];
            memset(buffer, (TCHAR)0, len+1);
            if (getLBText(indx, buffer)) {

                string.shallowCopy(buffer);
                rc = true;
            }
        }
        return rc;
    }

    int        getLBText(int indx, TCHAR* buffer) {
            return (int)send(CB_GETLBTEXT, indx, (LPARAM)buffer);
    }

    int        getLBTextLen(int indx) {
            return (int)send(CB_GETLBTEXTLEN, indx, 0L);
    }

//    void    getValues(Args& args);

    int     insertString(int indx, TCHAR* string) {
            return (int)send(CB_INSERTSTRING, indx, (LPARAM)string);
    }
    int        limitText(int len) {
            return (int)send(CB_LIMITTEXT, len, 0L);
    }
    void    resetContent() {
            send(CB_RESETCONTENT, 0, 0L);
    }
    int        selectString(int indx, TCHAR* string) {
            return (int)send(CB_SELECTSTRING, indx, (LPARAM)string);
    }
    int        setCurSel(int indx) {
            return (int)send(CB_SETCURSEL, indx, 0L);
    }
    int        setEditSel(int start, int end) {
            return (int)send(CB_SETEDITSEL, 0, MAKELONG(start, end));
    }
    int        setExtendedUI(int flag) {
            return (int)send(CB_SETEXTENDEDUI, flag, 0L);
    }
    int        setItemData(int indx, LONG data) {
            return (int)send(CB_SETITEMDATA, indx, data);
    }
    int        setItemHeight(int indx, int height) {
            return (int)send(CB_SETITEMHEIGHT, indx, (LPARAM)height);
    }
    int     setControlHeight(int height) {
            return (int)send(CB_SETITEMHEIGHT, -1, (LPARAM)height);
    }

//    void    setValues(Args& args);    

    void    showDropDown(int showCmd) {
            send(CB_SHOWDROPDOWN, showCmd, 0L);
    }

    long     getLocale() {
            return send(CB_GETLOCALE, 0, 0L);
    }
    long     setLocale(long localeId) {
             return send(CB_SETLOCALE, (WPARAM)localeId, 0L);
    }

    // 2001/03/19
//    void    getPreferredSize(Dimension& d);

};

}


Last modified: 1 Feb 2012

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