#include #include #include #include #include #include #include "i18n.h" #include "mswint.h" /* ***************************************************************************** * * Choice Boxes * ***************************************************************************** */ int CHOICE_HEIGHT=(17); int CHOICE_MIN_WIDTH=25; static XWNDPROC oldChoiceItemProc = NULL; static XWNDPROC newChoiceItemProc; typedef struct { WOBJ_COMMON wChoice_p owner; } wChoiceItem_t, * wChoiceItem_p; struct wChoice_t { WOBJ_COMMON const char * * labels; wChoiceItem_p *buttList; long *valueP; long oldVal; wChoiceCallBack_p action; HWND hBorder; }; static FARPROC oldChoiceProc; void wRadioSetValue( wChoice_p bc, long val ) { const char ** labels; long cnt; wChoiceItem_p * butts; butts = (wChoiceItem_p*)bc->buttList; for (labels = bc->labels, cnt=0; *labels; labels++, cnt++, butts++ ) SendMessage( (*butts)->hWnd, BM_SETCHECK, (val==cnt)?1:0, 0L ); bc->oldVal = val; if (bc->valueP) *bc->valueP = val; } long wRadioGetValue( wChoice_p bc ) { return bc->oldVal; } void wToggleSetValue( wChoice_p bc, long val ) { const char ** labels; long cnt; wChoiceItem_p * butts; butts = (wChoiceItem_p*)bc->buttList; for (labels = bc->labels, cnt=0; *labels; labels++, cnt++, butts++ ) SendMessage( (*butts)->hWnd, BM_SETCHECK, (val & (1L<oldVal = val; if (bc->valueP) *bc->valueP = val; } long wToggleGetValue( wChoice_p bc ) { return bc->oldVal; } static void choiceSetBusy( wControl_p b, BOOL_T busy) { wChoiceItem_p * butts; wChoice_p bc = (wChoice_p)b; for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ ) EnableWindow( (*butts)->hWnd, !(BOOL)busy ); } static void choiceShow( wControl_p b, BOOL_T show) { wChoice_p bc = (wChoice_p)b; wChoiceItem_p * butts; if ((bc->option & BC_NOBORDER)==0) ShowWindow( bc->hBorder, show?SW_SHOW:SW_HIDE ); for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ ) ShowWindow( (*butts)->hWnd, show?SW_SHOW:SW_HIDE ); } static void choiceSetPos( wControl_p b, wPos_t x, wPos_t y ) { wChoice_p bc = (wChoice_p)b; wChoiceItem_p * butts; wPos_t dx, dy; dx = x - bc->x; dy = y - bc->y; if ((bc->option & BC_NOBORDER)==0) SetWindowPos( bc->hBorder, HWND_TOP, x, y, CW_USEDEFAULT, CW_USEDEFAULT, SWP_NOSIZE|SWP_NOZORDER ); for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ ) { SetWindowPos( (*butts)->hWnd, HWND_TOP, (*butts)->x+=dx, (*butts)->y+=dy, CW_USEDEFAULT, CW_USEDEFAULT, SWP_NOSIZE|SWP_NOZORDER ); } bc->x = x; bc->y = y; } long FAR PASCAL _export pushChoiceItem( HWND hWnd, UINT message, UINT wParam, LONG lParam ) { /* Catch and cause focus to leave control */ #ifdef WIN32 long inx = GetWindowLong( hWnd, GWL_ID ); #else short inx = GetWindowWord( hWnd, GWW_ID ); #endif wControl_p b = mswMapIndex( inx ); switch (message) { case WM_CHAR: if ( b != NULL) { switch( wParam ) { 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 0L; } } break; } return CallWindowProc( oldChoiceItemProc, hWnd, message, wParam, lParam ); } LRESULT choiceItemProc( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { wChoiceItem_p me = (wChoiceItem_p)b, *rest; wChoice_p bc; int num; switch( message ) { case WM_COMMAND: switch (WCMD_PARAM_NOTF) { case BN_CLICKED: bc = me->owner; num = -1; for (rest = (wChoiceItem_p*)bc->buttList; *rest; rest++ ) { switch (bc->type) { case B_TOGGLE: num = rest-(wChoiceItem_p*)bc->buttList; if (*rest == me) { bc->oldVal ^= (1L<hWnd, BM_SETCHECK, (bc->oldVal & (1L<hWnd, BM_SETCHECK, 0, 0L ); } else { bc->oldVal = rest-(wChoiceItem_p*)bc->buttList; SendMessage( (*rest)->hWnd, BM_SETCHECK, 1, 0L ); } break; } } if (bc->valueP) *bc->valueP = bc->oldVal; if (bc->action) bc->action( bc->oldVal, bc->data ); break; } break; } return DefWindowProc( hWnd, message, wParam, lParam ); } static callBacks_t choiceCallBacks = { mswRepaintLabel, NULL, NULL, choiceSetBusy, choiceShow, choiceSetPos }; static callBacks_t choiceItemCallBacks = { NULL, NULL, choiceItemProc }; /** * Creates choice buttons. This function is used to create a group of * radio buttons and checkboxes. * * \param type IN type of button * \param parent IN parent window * \param x, y IN position of group * \param helpStr IN index string to find help * \param labelStr IN label for group * \param option IN ? * \param labels IN labels for individual choices * \param valueP OUT pointer for return value * \param action IN ? * \param data IN ? * \return created choice button group */ static wChoice_p choiceCreate( wType_e type, wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, const char **labels, long *valueP, wChoiceCallBack_p action, void *data ) { wChoice_p b; const char ** lp; int cnt; wChoiceItem_p * butts; int ppx, ppy; int bs; HDC hDc; HWND hButt; int lab_l; DWORD dw; int w, maxW; int pw, ph; int index; char * helpStrCopy; HFONT hFont; b = mswAlloc( parent, type, mswStrdup(labelStr), sizeof *b, data, &index ); mswComputePos( (wControl_p)b, x, y ); b->option = option; b->valueP = valueP; b->action = action; b->labels = labels; b->labelY += 6; ppx = b->x; ppy = b->y; switch (b->type) { case B_TOGGLE: bs = BS_CHECKBOX; break; case B_RADIO: bs = BS_RADIOBUTTON; break; } for (lp = b->labels,cnt=0; *lp; lp++,cnt++ ); butts = (wChoiceItem_p*)malloc( (cnt+1) * sizeof *butts ); b->buttList = butts; b->oldVal = (b->valueP?*b->valueP:0); ph = pw = 2; maxW = 0; if (helpStr) helpStrCopy = mswStrdup( helpStr ); for (lp = b->labels, cnt=0; *lp; lp++, cnt++, butts++ ) { *butts = (wChoiceItem_p)mswAlloc( parent, B_CHOICEITEM, mswStrdup(_((char *)*lp)), sizeof( wChoiceItem_t ), data, &index ); (*butts)->owner = b; (*butts)->hWnd = hButt = CreateWindow( "BUTTON", (*butts)->labelStr, bs | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), b->x+pw, b->y+ph, 80, CHOICE_HEIGHT, ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); if ( hButt == (HWND)0 ) { mswFail( "choiceCreate button" ); return b; } (*butts)->x = b->x+pw; (*butts)->y = b->y+ph; if (b->hWnd == 0) b->hWnd = (*butts)->hWnd; (*butts)->helpStr = helpStrCopy; hDc = GetDC( hButt ); lab_l = strlen((*butts)->labelStr); if (!mswThickFont) {hFont = SelectObject( hDc, mswLabelFont );} dw = GetTextExtent( hDc, (char *)((*butts)->labelStr), lab_l ); if (!mswThickFont) {SelectObject( hDc, hFont );} w = LOWORD(dw) + CHOICE_MIN_WIDTH; if (w > maxW) maxW = w; SetBkMode( hDc, TRANSPARENT ); ReleaseDC( hButt, hDc ); if (b->option & BC_HORZ) { pw += w; } else { ph += CHOICE_HEIGHT; } if (!SetWindowPos( hButt, HWND_TOP, 0, 0, w, CHOICE_HEIGHT, SWP_NOMOVE|SWP_NOZORDER)) { mswFail("Create CHOICE: SetWindowPos"); } mswChainFocus( (wControl_p)*butts ); newChoiceItemProc = MakeProcInstance( (XWNDPROC)pushChoiceItem, mswHInst ); oldChoiceItemProc = (XWNDPROC)GetWindowLong( (*butts)->hWnd, GWL_WNDPROC ); SetWindowLong( (*butts)->hWnd, GWL_WNDPROC, (LONG)newChoiceItemProc ); if ( !mswThickFont ) SendMessage( (*butts)->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L ); } *butts = NULL; switch (b->type) { case B_TOGGLE: wToggleSetValue( b, (b->valueP?*b->valueP:0L) ); break; case B_RADIO: wRadioSetValue( b, (b->valueP?*b->valueP:0L) ); break; } if (b->option & BC_HORZ) { ph = CHOICE_HEIGHT; } else { pw = maxW; } pw += 4; ph += 4; b->w = pw; b->h = ph; #define FRAME_STYLE SS_ETCHEDFRAME if ((b->option & BC_NOBORDER)==0) { b->hBorder = CreateWindow( "STATIC", NULL, WS_CHILD | WS_VISIBLE | FRAME_STYLE, b->x, b->y, pw, ph, ((wControl_p)parent)->hWnd, 0, mswHInst, NULL ); } mswAddButton( (wControl_p)b, TRUE, helpStr ); mswCallBacks[ B_CHOICEITEM ] = &choiceItemCallBacks; mswCallBacks[ type ] = &choiceCallBacks; return b; } wChoice_p wRadioCreate( wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, const char **labels, long *valueP, wChoiceCallBack_p action, void *data ) { return choiceCreate( B_RADIO, parent, x, y, helpStr, labelStr, option, labels, valueP, action, data ); } wChoice_p wToggleCreate( wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, const char **labels, long *valueP, wChoiceCallBack_p action, void *data ) { return choiceCreate( B_TOGGLE, parent, x, y, helpStr, labelStr, option, labels, valueP, action, data ); }