April 19, 2024, 07:39:36 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Combobox as color picker

Started by sapero, March 15, 2007, 02:35:30 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

sapero

Here is an example with custom drawn combo box, that displays color rectangles.
I;ve tried with OnDrawItem but the CBS_OWNERDRAWFIXED style bit crashed the application.
#define IDC_COLORPICKER 1001

CONST COLOR_WINDOW = 5;
CONST COLOR_HIGHLIGHT = 13;
CONST ODS_SELECTED = 1;
CONST WM_DRAWITEM = 0x2B;
CONST GWL_WNDPROC = -4;
import int GetSysColor(int nIndex);
import int CreateSolidBrush(int crColor);
import int DeleteObject(int o);
import int FillRect(int dc,RECT* rc,int brush);
import int SetWindowLongA(int hwnd,int i,int l);
import int GetPropA(int hwnd,string *s);
import int SetPropA(int hwnd,string *s,int p);

struct DRAWITEMSTRUCT {
    int CtlType;
    int CtlID;
    int itemID;
    int itemAction;
    int itemState;
    int hwndItem;
    int hDC;
    RECT rcItem;
    int itemData;
}
// 1. create the combobox with CBS_OWNERDRAWFIXED style
// 2. subclass main window and draw the items inside WM_DRAWITEM
// 3. optionally inside WM_MEASUREITEM change the height of combo box
//  *(MEASUREITEMSTRUCT)lParam.itemHeight


class CMyDlg:CDialog
{
declare virtual OnInitDialog(),int;
declare virtual OnClose(),int;

#define PICKER_NUM_COLORS 20
int colors[PICKER_NUM_COLORS];
int m_wndproc;
}

global sub main()
{
CMyDlg dlg;
dlg.Create(0,0,300,202,0x80CB0880,0,"Combo Color Picker",0);
dlg.AddControl(CTGROUPBOX,"Pick a color",24,20,137,60,0x50000007,0x0,1000);
// combo styles: WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_OWNERDRAWFIXED|CBS_DROPDOWNLIST
dlg.AddControl(CTCOMBOBOX,"",35,35,119,124,0x50200013,0x0,IDC_COLORPICKER);
dlg.DoModal();
}


CMyDlg::OnInitDialog()
{
// actually here is a bug that causes combobox with CBS_OWNERDRAWFIXED style
// to crash the dialog. We need to subclass the dialog to hide this message
SetPropA(m_hwnd, "THIS", this);
m_wndproc = SetWindowLongA(m_hwnd, GWL_WNDPROC, &MySubclassProc);

// fill the color table and add dummy items
CCOmbobox *c = GetControl(IDC_COLORPICKER);
for (int x=0; x<PICKER_NUM_COLORS; x++)
{
colors[x] = RGB(rnd(255),rnd(255),rnd(255));
c->AddString("");
}
}


CMyDlg::OnClose(),int
{
CloseDialog(1);
}


sub MySubclassProc(int hwnd,int msg,int wParam,int lParam),int
{
CMyDlg *pDlg = GetPropA(hwnd, "THIS");
if (!pDlg) return false;
if (msg == WM_DRAWITEM)
{
DRAWITEMSTRUCT* lpdis = *(DRAWITEMSTRUCT)lparam;
if (lpdis->CtlID == IDC_COLORPICKER)
{
// fill while item with white or light blue color
int color = GetSysColor(COLOR_WINDOW + (8*((lpdis->itemState & ODS_SELECTED)==ODS_SELECTED)));
int hbr = CreateSolidBrush(color);
FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
DeleteObject(hbr);

// fill small rectangle with custom color
hbr = CreateSolidBrush(pDlg->colors[lpdis->itemID]);
RECT rc;
rc.left   = lpdis->rcItem.left + 16;
rc.top    = lpdis->rcItem.top + 3;
rc.right  = lpdis->rcItem.right - 3;
rc.bottom = lpdis->rcItem.bottom - 3;

FillRect(lpdis->hDC, &rc, hbr);
DeleteObject(hbr);
return true;
}
}
declare *prevproc(int hwnd,int msg,int wParam,int lParam),int;
prevproc = pDlg->m_wndproc;
return prevproc(hwnd, msg, wParam, lParam);
}

pistol350

Regards,

Peter B.