#include #include #include #include #include #include "mswint.h" /* ***************************************************************************** * * List Boxes * ***************************************************************************** */ static XWNDPROC oldListProc = NULL; static XWNDPROC newListProc; static XWNDPROC oldComboProc = NULL; static XWNDPROC newComboProc; struct wList_t { WOBJ_COMMON int count; int last; long * valueP; wListCallBack_p action; wBool_t editable; int colCnt; wWinPix_t * colWidths; wBool_t * colRightJust; const char * * colTitles; wWinPix_t maxWidth; wWinPix_t scrollPos; HWND hScrollWnd; wWinPix_t scrollH; wWinPix_t dragPos; int dragCol; wWinPix_t dragColWidth; }; typedef struct { void * itemContext; wIcon_p bm; wBool_t selected; } listData; static int LIST_HEIGHT = 19; static int listTitleHeight = 16; void wListClear( wList_p b ) { UINT msg; if (b->type==B_LIST) { msg = LB_RESETCONTENT; } else { msg = CB_RESETCONTENT; } SendMessage( b->hWnd, msg, (WPARAM)0, (LPARAM)0 ); b->last = -1; b->count = 0; } void wListSetSize( wList_p bl, wWinPix_t w, wWinPix_t h ) { int rc; RECT rect; wWinPix_t y; bl->w = w; bl->h = h; y = bl->y; if ( bl->hScrollWnd && bl->maxWidth > bl->w ) { h -= bl->scrollH; } if ( bl->colTitles ) { h -= listTitleHeight; y += listTitleHeight; } rc = SetWindowPos( bl->hWnd, HWND_TOP, 0, 0, w, h, SWP_NOMOVE|SWP_NOZORDER); if ( bl->hScrollWnd ) { if ( bl->maxWidth > bl->w ) { GetClientRect( bl->hWnd, &rect ); rc = SetWindowPos( bl->hScrollWnd, HWND_TOP, bl->x, y+rect.bottom+2, bl->w, bl->scrollH, SWP_NOZORDER); ShowWindow( bl->hScrollWnd, SW_SHOW ); } else { ShowWindow( bl->hScrollWnd, SW_HIDE ); } } } void wListSetIndex( wList_p bl, int index ) { listData * ldp; wListGetCount(bl); if ( index >= bl->count ) { index = bl->count-1; } if ( bl->last == index && index == -1 ) { return; } if ( bl->type==B_LIST && (bl->option&BL_MANY) != 0 ) { if ( bl->last != -1 ) { SendMessage( bl->hWnd, LB_SETSEL, (WPARAM)0, (LPARAM)bl->last ); } if ( index >= 0 ) { SendMessage( bl->hWnd, LB_SETSEL, (WPARAM)1, (LPARAM)index ); } } else { SendMessage( bl->hWnd, bl->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL, (WPARAM)index, (LPARAM)0 ); } if ( bl->last >= 0 ) { ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)bl->last, (LPARAM)0 ); if ( ldp && ldp!=(void*)LB_ERR ) { ldp->selected = FALSE; } } if ( index >= 0 ) { ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)index, (LPARAM)0 ); if ( ldp && ldp!=(void*)LB_ERR ) { ldp->selected = TRUE; } } /*if (b->option&BL_ICON)*/ InvalidateRect( bl->hWnd, NULL, FALSE ); bl->last = index; } wIndex_t wListGetIndex( wList_p b ) { return b->last; } void wListSetActive( wList_p b, int inx, wBool_t active ) { } void wListSetEditable( wList_p b, wBool_t editable ) { b->editable = editable; } void wListSetValue( wList_p bl, const char * val ) { if ( bl->type == B_DROPLIST ) { SendMessage( bl->hWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)val ); bl->last = -1; } } wIndex_t wListFindValue( wList_p bl, const char * val ) { wIndex_t inx; WORD cnt; wListGetCount(bl); for ( inx = 0; inx < bl->count ; inx++ ) { cnt = (int)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETTEXT:CB_GETLBTEXT), (WPARAM)inx, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if ( strcmp( val, mswTmpBuff ) == 0 ) { return inx; } } return -1; } wIndex_t wListGetValues( wList_p bl, char * s, int siz, void * * listContextRef, void * * itemContextRef ) { WORD cnt; WORD msg; WORD inx = bl->last; listData *ldp = NULL; if ( bl->type==B_DROPLIST && bl->last < 0 ) { msg = WM_GETTEXT; inx = sizeof mswTmpBuff; } else { if ( bl->last < 0 ) { goto EMPTY; } if ( bl->type==B_LIST ) { msg = LB_GETTEXT; } else { msg = CB_GETLBTEXT; } } cnt = (int)SendMessage( bl->hWnd, msg, (WPARAM)inx, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (s) { strncpy(s, mswTmpBuff, siz); s[siz-1] = '\0'; } if (bl->last >= 0) { ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)bl->last, (LPARAM)0 ); if ( ldp==(listData*)LB_ERR ) { ldp = NULL; } } else { ldp = NULL; } EMPTY: if (itemContextRef) { *itemContextRef = (ldp?ldp->itemContext:NULL); } if (listContextRef) { *listContextRef = bl->data; } return bl->last; } wBool_t wListSetValues( wList_p b, wIndex_t inx, const char * labelStr, wIcon_p bm, void * itemData ) { listData * ldp; WORD curSel = -1; ldp = (listData*)malloc( sizeof *ldp ); ldp->itemContext = itemData; ldp->bm = bm; ldp->selected = FALSE; if ( (b->option&BL_MANY) == 0 ) curSel = (WORD)SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_GETCURSEL:CB_GETCURSEL, (WPARAM)0, (LPARAM)0 ); SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_DELETESTRING:CB_DELETESTRING, (WPARAM)inx, (LPARAM)0 ); inx = (wIndex_t)SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_INSERTSTRING:CB_INSERTSTRING, (WPARAM)inx, (LPARAM)labelStr ); SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA, (WPARAM)inx, (LPARAM)ldp ); if ( (b->option&BL_MANY) == 0 && curSel == (WORD)inx) SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL, (WPARAM)inx, (LPARAM)0 ); /*if (b->option&BL_ICON)*/ InvalidateRect( b->hWnd, NULL, FALSE ); return TRUE; } void wListDelete( wList_p b, wIndex_t inx ) { SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_DELETESTRING:CB_DELETESTRING, (WPARAM)inx, (LPARAM)0 ); } /** * Select all items in list. * * \param bl IN list handle * \return */ void wListSelectAll( wList_p bl ) { wIndex_t inx; listData *ldp; // mark all items selected SendMessage( bl->hWnd, LB_SETSEL, (WPARAM)TRUE, (LPARAM)-1 ); // and synchronize the internal data structures wListGetCount(bl); for ( inx=0; inxcount; inx++ ) { ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)inx, (LPARAM)0 ); ldp->selected = TRUE; SendMessage( bl->hWnd, (UINT)bl->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA, (WPARAM)inx, (LPARAM)ldp ); } } wIndex_t wListGetCount( wList_p bl ) { bl->count = (int)SendMessage( bl->hWnd, (UINT)bl->type==B_LIST?LB_GETCOUNT:CB_GETCOUNT, (WPARAM)0, (LPARAM)0 ); return bl->count; } void * wListGetItemContext( wList_p bl, wIndex_t inx ) { listData * ldp; wListGetCount(bl); if ( inx < 0 || inx >= bl->count ) { return NULL; } ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)inx, (LPARAM)0 ); return ((ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL); } wBool_t wListGetItemSelected( wList_p bl, wIndex_t inx ) { listData * ldp; wListGetCount(bl); if ( inx < 0 || inx >= bl->count ) { return FALSE; } ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)inx, (LPARAM)0 ); return ((ldp&&ldp!=(void*)LB_ERR)?ldp->selected:FALSE); } wIndex_t wListGetSelectedCount( wList_p bl ) { wIndex_t selcnt, inx; wListGetCount(bl); for ( selcnt=inx=0; inxcount; inx++ ) if ( wListGetItemSelected( bl, inx ) ) { selcnt++; } return selcnt; } wIndex_t wListAddValue( wList_p b, const char * value, wIcon_p bm, void * itemContext ) { int nindex; listData * ldp; ldp = (listData*)malloc( sizeof *ldp ); ldp->itemContext = itemContext; ldp->bm = bm; ldp->selected = FALSE; if ( value == NULL ) { value = ""; } b->count++; nindex = (int)SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_ADDSTRING:CB_ADDSTRING, (WPARAM)0, (LPARAM)value ); if (nindex == 0) { SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL, (WPARAM)nindex, (LPARAM)0 ); b->last = 0; } SendMessage( b->hWnd, (UINT)b->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA, (WPARAM)nindex, (LPARAM)ldp ); return nindex; } int wListGetColumnWidths( wList_p bl, int colCnt, wWinPix_t * colWidths ) { wIndex_t inx; if ( bl->type != B_LIST ) { return 0; } if ( bl->colWidths == NULL ) { return 0; } for ( inx=0; inxcolCnt ) { colWidths[inx] = bl->colWidths[inx]; } else { colWidths[inx] = 0; } } return bl->colCnt; } static void listSetBusy( wControl_p b, BOOL_T busy) { wList_p bl = (wList_p)b; EnableWindow( bl->hWnd, !(BOOL)busy ); if ( bl->hScrollWnd ) { EnableWindow( bl->hScrollWnd, !(BOOL)busy ); } } static void listShow( wControl_p b, BOOL_T show) { wList_p bl = (wList_p)b; ShowWindow( bl->hWnd, show?SW_SHOW:SW_HIDE ); if ( bl->hScrollWnd && bl->maxWidth > bl->w ) { ShowWindow( bl->hScrollWnd, show?SW_SHOW:SW_HIDE ); } #ifdef SHOW_DOES_SETFOCUS if ( show && (bl->option&BO_READONLY)==0 ) { hWnd = SetFocus( bl->hWnd ); } #endif } static void listSetPos( wControl_p b, wWinPix_t x, wWinPix_t y ) { wList_p bl = (wList_p)b; wWinPix_t x1, y1; RECT rect; bl->x = x1 = x; bl->y = y1 = y; if ( bl->colTitles ) { y1 += listTitleHeight; } if (!SetWindowPos( b->hWnd, HWND_TOP, x1, y1, CW_USEDEFAULT, CW_USEDEFAULT, SWP_NOSIZE|SWP_NOZORDER)) { mswFail("listSetPos"); } if ( bl->hScrollWnd && bl->maxWidth > bl->w ) { GetClientRect( bl->hWnd, &rect ); if (!SetWindowPos( bl->hScrollWnd, HWND_TOP, x1, y1+rect.bottom+2, CW_USEDEFAULT, CW_USEDEFAULT, SWP_NOSIZE|SWP_NOZORDER)) { mswFail("listSetPos2"); } } } static void listRepaintLabel( HWND hWnd, wControl_p b ) { wList_p bl = (wList_p)b; HDC hDc; RECT rc; HFONT hFont; HPEN hPen0, hPen1, hPen2, hPen3; HBRUSH hBrush; const char * * title; int inx; int start; wWinPix_t colWidth; mswRepaintLabel( hWnd, b ); if ( bl->colTitles == NULL ) { return; } hDc = GetDC( hWnd ); start = bl->x-bl->scrollPos+2; rc.top = bl->y; rc.bottom = bl->y+listTitleHeight; rc.left = bl->x-1; rc.right = bl->x+bl->w; hBrush = CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) ); FillRect( hDc, &rc, hBrush ); SetBkColor( hDc, GetSysColor( COLOR_BTNFACE ) ); hFont = SelectObject( hDc, mswLabelFont ); hPen1 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNTEXT ) ); hPen2 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNHIGHLIGHT ) ); hPen3 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNSHADOW ) ); hPen0 = SelectObject( hDc, hPen1 ); MoveTo( hDc, rc.left, rc.top ); LineTo( hDc, rc.right, rc.top ); LineTo( hDc, rc.right, rc.bottom ); LineTo( hDc, rc.left, rc.bottom ); LineTo( hDc, rc.left, rc.top ); SelectObject( hDc, hPen2 ); MoveTo( hDc, rc.left+1, rc.bottom-1 ); LineTo( hDc, rc.left+1, rc.top+1 ); LineTo( hDc, rc.right-1, rc.top+1 ); SelectObject( hDc, hPen3 ); MoveTo( hDc, rc.left+2, rc.bottom-1 ); LineTo( hDc, rc.right-1, rc.bottom-1 ); LineTo( hDc, rc.right-1, rc.top+1 ); rc.top += 2; rc.bottom -= 1; for ( inx=0,title=bl->colTitles; inxcolCnt&&*title &&startx+bl->w; inx++ ) { colWidth = bl->colWidths[inx]; if ( start+colWidth >= 3 ) { rc.left = start; if ( rc.left < bl->x+2 ) { rc.left = bl->x+2; } rc.right = start+colWidth; if ( rc.right > bl->x+bl->w-1 ) { rc.right = bl->x+bl->w-1; } ExtTextOut( hDc, start+1, rc.top+0, ETO_CLIPPED|ETO_OPAQUE, &rc, *title, (int)(strlen(*title)), NULL ); if ( start-bl->x >= 3 ) { SelectObject( hDc, hPen1 ); MoveTo( hDc, start-1, rc.top-1 ); LineTo( hDc, start-1, rc.bottom+3 ); SelectObject( hDc, hPen2 ); MoveTo( hDc, start, rc.top ); LineTo( hDc, start, rc.bottom+1 ); SelectObject( hDc, hPen3 ); MoveTo( hDc, start-2, rc.top ); LineTo( hDc, start-2, rc.bottom+1 ); } } title++; start += colWidth; } SelectObject( hDc, hPen0 ); SelectObject( hDc, hFont ); DeleteObject( hBrush ); DeleteObject( hPen1 ); DeleteObject( hPen2 ); DeleteObject( hPen3 ); } #ifdef LATER static void listHandleSelectionState( LPDRAWITEMSTRUCT lpdis, LPRECT rc ) { int oldROP; oldROP = SetROP2( lpdis->hDC, R2_NOT ); Rectangle( lpdis->hDC, rc->left, rc->top, rc->right, rc->bottom ); SetROP2( lpdis->hDC, oldROP ); /*InvertRect( lpdis->hDC, rc );*/ } #endif static void listHandleFocusState( LPDRAWITEMSTRUCT lpdis, LPRECT rc ) { DrawFocusRect( lpdis->hDC, rc ); } LRESULT listProc( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { wList_p bl = (wList_p)b; int cnt, inx, selected; size_t len; listData * ldp; HDC hDc; LPMEASUREITEMSTRUCT lpmis; TEXTMETRIC tm; LPDRAWITEMSTRUCT lpdis; RECT rc, rc1; char * cp0, * cp1; wWinPix_t x; int colWidth; int nPos; HFONT hFont; HPEN hPen; HBRUSH hBrush; WPARAM notification; COLORREF col; if (bl) switch( message ) { case WM_COMMAND: notification = WCMD_PARAM_NOTF; switch (bl->type) { case B_LIST: switch (notification) { case LBN_SELCHANGE: case LBN_DBLCLK: if ( (bl->option&BL_DBLCLICK)!=0 ? notification!=LBN_DBLCLK : notification==LBN_DBLCLK ) { break; } if ( (bl->option&BL_MANY) ) { wListGetCount(bl); for ( inx=0; inxcount; inx++ ) { ldp = (listData*)SendMessage( bl->hWnd, LB_GETITEMDATA, (WPARAM)inx, (LPARAM)0 ); if ( ldp != NULL && ldp != (void*)LB_ERR ) { selected = ((long)SendMessage( bl->hWnd, LB_GETSEL, (WPARAM)inx, (LPARAM)0 ) != 0L ); if ( selected != ldp->selected ) { ldp->selected = selected; if ( selected ) { bl->last = inx; cnt = (int)SendMessage( bl->hWnd, LB_GETTEXT, (WPARAM)bl->last, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; } else { mswTmpBuff[0] = '\0'; } if ( bl->action ) { bl->action( inx, mswTmpBuff, selected?1:2, bl->data, ldp->itemContext ); } if ( selected && bl->valueP ) { *bl->valueP = bl->last; } } } } } else { bl->last = (int)SendMessage( bl->hWnd, LB_GETCURSEL, (WPARAM)0, (LPARAM)0 ); cnt = (int)SendMessage( bl->hWnd, LB_GETTEXT, (WPARAM)bl->last, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (bl->action) { ldp = (listData*)SendMessage( bl->hWnd, LB_GETITEMDATA, (WPARAM)bl->last, (LPARAM)0 ); bl->action( bl->last, mswTmpBuff, 1, bl->data, ((bl->last>=0&&ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL) ); } if (bl->valueP) { *bl->valueP = bl->last; } } break; case LBN_KILLFOCUS: if ( ( bl->option&BL_MANY ) == 0 && bl->last != (int)SendMessage( bl->hWnd, LB_GETCURSEL, (WPARAM)0, (LPARAM)0 ) ) { (void)SendMessage( bl->hWnd, LB_SETCURSEL, (WPARAM)bl->last, (LPARAM)0 ); } break; } break; case B_DROPLIST: case B_COMBOLIST: switch (notification) { case CBN_SELCHANGE: case CBN_DBLCLK: if ( (bl->type == B_DROPLIST) || ( (bl->option&BL_DBLCLICK)!=0 ? notification!=CBN_DBLCLK : notification==CBN_DBLCLK) ) { break; } case CBN_CLOSEUP: bl->last = (int)SendMessage( bl->hWnd, CB_GETCURSEL, (WPARAM)0, (LPARAM)0 ); if (bl->last < 0) { break; } if (bl->action) { cnt = (int)SendMessage( bl->hWnd, CB_GETLBTEXT, (WPARAM)bl->last, (LPARAM)mswTmpBuff ); ldp = (listData*)SendMessage( bl->hWnd, CB_GETITEMDATA, (WPARAM)bl->last, (LPARAM)0 ); mswTmpBuff[cnt] = '\0'; bl->action( bl->last, mswTmpBuff, 1, bl->data, ((bl->last>=0&&ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL) ); } if (bl->valueP) { *bl->valueP = bl->last; } mswAllowBalloonHelp = TRUE; /*SendMessage( bl->bWnd, CB_SETCURSEL, bl->last, 0L );*/ break; case CBN_KILLFOCUS: inx = (int)SendMessage( bl->hWnd, CB_GETCURSEL, (WPARAM)0, (LPARAM)0 ); if ( bl->last != inx ) { (void)SendMessage( bl->hWnd, CB_SETCURSEL, (WPARAM)bl->last, (LPARAM)0 ); } break; case CBN_DROPDOWN: mswAllowBalloonHelp = FALSE; break; case CBN_EDITCHANGE: bl->last = -1; if (bl->action) { cnt = (int)SendMessage( bl->hWnd, WM_GETTEXT, (WPARAM)sizeof mswTmpBuff, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; bl->action( -1, mswTmpBuff, 1, bl->data, NULL ); } break; } break; } break; case WM_MEASUREITEM: lpmis = (LPMEASUREITEMSTRUCT)lParam; hDc = GetDC( hWnd ); if ( bl->type == B_LIST ) { hFont = SelectObject( hDc, mswLabelFont ); } GetTextMetrics( hDc, &tm ); lpmis->itemHeight = tm.tmHeight; if ( bl->type == B_LIST ) { SelectObject( hDc, hFont ); } ReleaseDC( hWnd, hDc ); break; case WM_DRAWITEM: lpdis = (LPDRAWITEMSTRUCT)lParam; if (lpdis->itemID == -1) { listHandleFocusState(lpdis, &lpdis->rcItem); return TRUE; } ldp = (listData*)SendMessage( bl->hWnd, (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), (WPARAM)lpdis->itemID, (LPARAM)0); rc = lpdis->rcItem; if (lpdis->itemAction & (ODA_DRAWENTIRE|ODA_SELECT|ODA_FOCUS)) { if( bl->type == B_LIST ) { hFont = SelectObject( lpdis->hDC, mswLabelFont ); } cnt = (int)SendMessage( lpdis->hwndItem, (bl->type==B_LIST?LB_GETTEXT:CB_GETLBTEXT), (WPARAM)lpdis->itemID, (LPARAM)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if ( lpdis->itemState & ODS_SELECTED ) { SetTextColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) ); SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); } else { SetTextColor( lpdis->hDC, GetSysColor( COLOR_WINDOWTEXT ) ); SetBkColor( lpdis->hDC, GetSysColor( COLOR_WINDOW ) ); } rc1 = rc; rc1.left -= bl->scrollPos; for ( inx=0,cp0=mswTmpBuff; inxcolCnt&&cp0&&rc1.left=bl->colCnt-1 || (cp1=strchr(cp0,'\t')) == NULL ) { len = strlen( cp0 ); cp1=cp0 + len; // JBB, to avoid an MSC error below where cp1 has not been defined. } else { len = cp1-cp0; cp1 ++; } if ( bl->colWidths ) { colWidth = bl->colWidths[inx]; } else { colWidth = rc.right; } if ( inx == 0 && ldp && ldp!=(void*)LB_ERR && ldp->bm ) { if (mswPalette) { SelectPalette( lpdis->hDC, mswPalette, 0 ); cnt = RealizePalette( lpdis->hDC ); } hPen = SelectObject( lpdis->hDC, CreatePen( PS_SOLID, 0, GetSysColor( COLOR_WINDOW ) ) ); hBrush = SelectObject( lpdis->hDC, CreateSolidBrush( GetSysColor( COLOR_WINDOW ) ) ); Rectangle( lpdis->hDC, rc1.left, rc1.top, rc1.right, rc1.bottom ); DeleteObject( SelectObject( lpdis->hDC, hPen ) ); DeleteObject( SelectObject( lpdis->hDC, hBrush ) ); col = RGB( (ldp->bm->colormap[ 1 ]).rgbRed, (ldp->bm->colormap[ 1 ]).rgbGreen, (ldp->bm->colormap[ 1 ]).rgbBlue ); mswDrawIcon( lpdis->hDC, rc1.left+2, rc.top+0, ldp->bm, 0, col, col); rc1.left += ldp->bm->w+6; colWidth -= ldp->bm->w+6; } if ( inx>=bl->colCnt-1 || (rc1.right = rc1.left + colWidth) > rc.right ) { rc1.right = rc.right; } if ( rc1.right > 0 && rc1.left+3 < rc.right ) { ExtTextOut( lpdis->hDC, rc1.left+3, rc1.top+1, ETO_CLIPPED | ETO_OPAQUE, &rc1, (LPSTR)cp0, (int)len, NULL ); } rc1.left = rc1.right; cp0 = cp1; } if ( lpdis->itemState & ODS_SELECTED ) { SetTextColor( lpdis->hDC, GetSysColor( COLOR_WINDOWTEXT ) ); SetBkColor( lpdis->hDC, GetSysColor( COLOR_WINDOW ) ); } if (lpdis->itemState & ODS_FOCUS) { DrawFocusRect( lpdis->hDC, &rc ); } if ( bl->type == B_LIST) { SelectObject( lpdis->hDC, hFont ); } return (LRESULT)TRUE; } break; case WM_HSCROLL: len = ((long)bl->maxWidth)-((long)bl->w); if ( len <= 0 ) { return (LRESULT)0; } switch ( WSCROLL_PARAM_CODE ) { case SB_LEFT: if ( bl->scrollPos == 0 ) { return (LRESULT)0; } bl->scrollPos = 0; break; case SB_LINELEFT: case SB_PAGELEFT: if ( bl->scrollPos == 0 ) { return (LRESULT)0; } for ( inx=colWidth=0; inxcolCnt; inx++ ) { if ( colWidth+bl->colWidths[inx] >= bl->scrollPos ) { bl->scrollPos = colWidth; break; } colWidth += bl->colWidths[inx]; } break; case SB_LINERIGHT: case SB_PAGERIGHT: if ( bl->scrollPos >= len ) { return (LRESULT)0; } for ( inx=colWidth=0; inxcolCnt; inx++ ) { if ( colWidth >= bl->scrollPos ) { bl->scrollPos = colWidth+bl->colWidths[inx]; break; } colWidth += bl->colWidths[inx]; } break; case SB_RIGHT: if ( bl->scrollPos >= len ) { return (LRESULT)0; } bl->scrollPos = (int)len; break; case SB_THUMBTRACK: return (LRESULT)0; case SB_THUMBPOSITION: nPos = (int)WSCROLL_PARAM_NPOS; bl->scrollPos = (int)(len*nPos/100); break; case SB_ENDSCROLL: return (LRESULT)0; } if ( bl->scrollPos > len ) { bl->scrollPos = (int)len; } if ( bl->scrollPos < 0 ) { bl->scrollPos = 0; } nPos = (int)(((long)bl->scrollPos)*100L/len+0.5); SetScrollPos( bl->hScrollWnd, SB_CTL, nPos, TRUE ); InvalidateRect( bl->hWnd, NULL, FALSE ); listRepaintLabel( ((wControl_p)(bl->parent))->hWnd, (wControl_p)bl ); return (LRESULT)0; case WM_LBUTTONDOWN: if ( bl->type != B_LIST ) { break; } if ( bl->colCnt <= 1 ) { break; } x = bl->dragPos = LOWORD(lParam)+bl->scrollPos-4; bl->dragCol = -1; for ( inx=0; inxcolCnt; inx++ ) { x -= bl->colWidths[inx]; if ( x < -5 ) { break; } if ( x <= 0 ) { bl->dragCol = inx; break; } if ( x > bl->colWidths[inx+1] ) { continue; } if ( x <= 10 ) { bl->dragCol = inx; break; } } if ( bl->dragCol >= 0 ) { bl->dragColWidth = bl->colWidths[inx]; } return (LRESULT)0; #ifdef LATER case WM_MOUSEMOVE: if ( (wParam&MK_LBUTTON) == 0 ) { break; } if ( bl->type != B_LIST ) { break; } if ( bl->colCnt <= 1 ) { break; } x = LOWORD(lParam)+bl->scrolPos; for ( inx=0; inxcolCnt; inx++ ) { x -= bl->colWidths[inx]; if ( x <= 0 ) { break; } } return (LRESULT)0; #endif case WM_MOUSEMOVE: if ( (wParam&MK_LBUTTON) == 0 ) { break; } case WM_LBUTTONUP: if ( bl->type != B_LIST ) { break; } if ( bl->colCnt <= 1 ) { break; } if ( bl->dragCol < 0 ) { break; } x = LOWORD(lParam)+bl->scrollPos-4-bl->dragPos; /* WIN32??? */ bl->colWidths[bl->dragCol] = bl->dragColWidth+x; if ( bl->colWidths[bl->dragCol] < 0 ) { bl->colWidths[bl->dragCol] = 0; } for ( bl->maxWidth=inx=0; inxcolCnt; inx++ ) { bl->maxWidth += bl->colWidths[inx]; } if ( bl->maxWidth <= bl->w ) { x = bl->w - bl->maxWidth; bl->colWidths[bl->colCnt-1] += x; bl->maxWidth = bl->w; bl->scrollPos = 0; } else { if ( bl->scrollPos+bl->w > bl->maxWidth ) { bl->scrollPos = bl->maxWidth - bl->w; } } InvalidateRect( bl->hWnd, NULL, FALSE ); listRepaintLabel( ((wControl_p)(bl->parent))->hWnd, (wControl_p)bl ); return (LRESULT)0; } return DefWindowProc( hWnd, message, wParam, lParam ); } LRESULT FAR PASCAL _export pushList( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { /* Catch and cause focus to leave control */ wIndex_t inx = (wIndex_t)GetWindowLongPtr(hWnd, GWL_ID); wControl_p b = mswMapIndex(inx); #ifdef OLDCODE long inx = GetWindowLong( hWnd, GWL_ID ); wControl_p b = mswMapIndex( inx ); #endif switch (message) { case WM_CHAR: if ( b != NULL) { switch( WCMD_PARAM_ID ) { case 0x0D: case 0x1B: case 0x09: SetFocus( ((wControl_p)(b->parent))->hWnd ); SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR, wParam, lParam ); /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND, inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/ return (LRESULT)0; } } break; } return CallWindowProc( oldListProc, hWnd, message, wParam, lParam ); } LRESULT FAR PASCAL _export pushCombo( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { /* Catch and cause focus to leave control */ wIndex_t inx = (wIndex_t)GetWindowLongPtr( hWnd, GWL_ID ); wControl_p b = mswMapIndex( inx ); switch (message) { case WM_CHAR: if ( b != NULL) { switch( WCMD_PARAM_ID ) { case 0x0D: case 0x1B: case 0x09: SetFocus( ((wControl_p)(b->parent))->hWnd ); SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR, wParam, lParam ); /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND, inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/ return (LRESULT)0; } } break; } return CallWindowProc( oldComboProc, hWnd, message, wParam, lParam ); } static callBacks_t listCallBacks = { listRepaintLabel, NULL, listProc, listSetBusy, listShow, listSetPos }; static wList_p listCreate( int typ, const char *className, long style, wWin_p parent, wWinPix_t x, wWinPix_t y, const char * helpStr, const char * labelStr, long option, long number, wWinPix_t width, long *valueP, wListCallBack_p action, void *data, wBool_t addFocus, int *indexR ) { wList_p b; RECT rect; int index; b = (wList_p)mswAlloc( parent, typ, mswStrdup(labelStr), sizeof *b, data, &index ); mswComputePos( (wControl_p)b, x, y ); b->option = option; b->count = 0; b->last = -1; b->valueP = valueP; b->labelY += 4; b->action = action; b->maxWidth = 0; b->scrollPos = 0; b->scrollH = 0; b->dragPos = 0; b->dragCol = -1; b->hWnd = CreateWindow( className, NULL, style | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), b->x, b->y, width, LIST_HEIGHT*(int)number, ((wControl_p)parent)->hWnd, (HMENU)(UINT_PTR)index, mswHInst, NULL ); if (b->hWnd == NULL) { mswFail("CreateWindow(LIST)"); return b; } GetWindowRect( b->hWnd, &rect ); b->w = rect.right - rect.left; b->h = rect.bottom - rect.top; b->colCnt = 1; b->colWidths = NULL; b->colTitles = NULL; mswAddButton( (wControl_p)b, TRUE, helpStr ); mswCallBacks[typ] = &listCallBacks; if (addFocus) { mswChainFocus( (wControl_p)b ); if (b->type == B_LIST) { newListProc = MakeProcInstance((XWNDPROC)pushList, mswHInst); oldListProc = (XWNDPROC)GetWindowLongPtr(b->hWnd, GWLP_WNDPROC); SetWindowLongPtr(b->hWnd, GWLP_WNDPROC, (LONG_PTR)newListProc); #ifdef _OLDCODE oldListProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC); SetWindowLong(b->hWnd, GWL_WNDPROC, (LONG)newListProc); #endif } else { newComboProc = MakeProcInstance((XWNDPROC)pushCombo, mswHInst); oldComboProc = (XWNDPROC)GetWindowLongPtr(b->hWnd, GWLP_WNDPROC); SetWindowLongPtr(b->hWnd, GWLP_WNDPROC, (LONG_PTR)newComboProc); #ifdef _OLDCODE oldComboProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC); SetWindowLong(b->hWnd, GWL_WNDPROC, (LONG)newComboProc); #endif } } if ( indexR ) { *indexR = index; } SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, (LPARAM)0 ); return b; } wList_p wListCreate( wWin_p parent, wWinPix_t x, wWinPix_t y, const char * helpStr, const char * labelStr, long option, long number, wWinPix_t width, int colCnt, wWinPix_t * colWidths, wBool_t * colRightJust, const char * * colTitles, long *valueP, wListCallBack_p action, void *data ) { long bs; wList_p bl; static int dbu = 0; RECT rect; int index; int i; bs = LBS_NOTIFY | WS_VSCROLL | WS_BORDER | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS; if (option & BL_MANY) { bs |= LBS_MULTIPLESEL|LBS_EXTENDEDSEL; } if (option & BL_SORT) { bs |= LBS_SORT; } if ( colCnt > 1 ) { bs |= WS_HSCROLL; } if ( colTitles ) { y += listTitleHeight; number -= 1; } bl = listCreate( B_LIST, "LISTBOX", bs, parent, x, y, helpStr, labelStr, option, number, width, valueP, action, data, TRUE, &index ); if ( colTitles ) { bl->y -= listTitleHeight; bl->h += listTitleHeight; } if ( colCnt > 1 ) { bl->colCnt = colCnt; bl->colWidths = (wWinPix_t*)malloc( colCnt * sizeof *bl->colWidths ); bl->colRightJust = (wBool_t*)malloc( colCnt * sizeof *bl->colRightJust ); bl->colTitles = colTitles; bl->maxWidth = 0; memcpy( bl->colWidths, colWidths, colCnt * sizeof *bl->colWidths ); for ( i=0; icolWidths[i] = colWidths[i]; bl->maxWidth += bl->colWidths[i]; } bl->hScrollWnd = CreateWindow( "ScrollBar", NULL, SBS_HORZ | SBS_BOTTOMALIGN | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), bl->x, bl->y, width, CW_USEDEFAULT, ((wControl_p)parent)->hWnd, (HMENU)(UINT_PTR)index, mswHInst, NULL ); if (bl->hScrollWnd == NULL) { mswFail("CreateWindow(LISTSCROLL)"); } SetScrollRange( bl->hScrollWnd, SB_CTL, 0, 100, TRUE ); GetWindowRect( bl->hScrollWnd, &rect ); bl->scrollH = rect.bottom - rect.top+2; } return bl; } wList_p wDropListCreate( wWin_p parent, wWinPix_t x, wWinPix_t y, const char * helpStr, const char * labelStr, long option, long number, wWinPix_t width, long *valueP, wListCallBack_p action, void *data ) { long bs; if ( (option&BL_EDITABLE) != 0 ) { bs = CBS_DROPDOWN; } else { bs = CBS_DROPDOWNLIST; } bs |= WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS; if (option & BL_SORT) { bs |= CBS_SORT; } return listCreate( B_DROPLIST, "COMBOBOX", bs, parent, x, y, helpStr, labelStr, option, number, width, valueP, action, data, TRUE, NULL ); } wList_p wComboListCreate( wWin_p parent, wWinPix_t x, wWinPix_t y, const char * helpStr, const char * labelStr, long option, long number, wWinPix_t width, long *valueP, wListCallBack_p action, void *data ) { long bs; bs = CBS_SIMPLE | WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS; if (option & BL_SORT) { bs |= CBS_SORT; } return listCreate( B_COMBOLIST, "COMBOBOX", bs, parent, x, y, helpStr, labelStr, option, number, width, valueP, action, data, FALSE, NULL ); }