#include #include #include #include #include #include #include #include "mswint.h" struct wString_t { WOBJ_COMMON char * valueP; wIndex_t valueL; wStringCallBack_p action; }; struct wInteger_t { WOBJ_COMMON long low, high; long * valueP; long oldValue; wIntegerCallBack_p action; }; struct wFloat_t { WOBJ_COMMON double low, high; double * valueP; double oldValue; wFloatCallBack_p action; }; static XWNDPROC oldEditProc = NULL; static XWNDPROC newEditProc; static void triggerString( wControl_p b ); #ifdef LATER static void triggerInteger( wControl_p b ); static void triggerFloat( wControl_p b ); #endif long FAR PASCAL _export pushEdit( 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; case WM_KEYUP: if ( b != NULL) switch (b->type) { case B_STRING: if (((wString_p)b)->action) mswSetTrigger( (wControl_p)b, triggerString ); break; #ifdef LATER case B_INTEGER: if (((wInteger_p)b)->action) mswSetTrigger( (wControl_p)b, triggerInteger ); break; case B_FLOAT: if (((wFloat_p)b)->action) mswSetTrigger( (wControl_p)b, triggerFloat ); break; #endif } break; } return CallWindowProc( oldEditProc, hWnd, message, wParam, lParam ); } /* ***************************************************************************** * * String Boxes * ***************************************************************************** */ void wStringSetValue( wString_p b, const char * arg ) { WORD len = (WORD)strlen( arg ); SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)arg ); #ifdef WIN32 SendMessage( b->hWnd, EM_SETSEL, len, len ); SendMessage( b->hWnd, EM_SCROLLCARET, 0, 0L ); #else SendMessage( b->hWnd, EM_SETSEL, 0, MAKELPARAM(len,len) ); #endif SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); } void wStringSetWidth( wString_p b, wPos_t w ) { int rc; b->w = w; rc = SetWindowPos( b->hWnd, HWND_TOP, 0, 0, b->w, b->h, SWP_NOMOVE|SWP_NOZORDER ); } const char * wStringGetValue( wString_p b ) { static char buff[1024]; SendMessage( b->hWnd, WM_GETTEXT, sizeof buff, (DWORD)buff ); return buff; } static void triggerString( wControl_p b ) { wString_p bs = (wString_p)b; int cnt; if (bs->action) { *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bs->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (bs->valueP) strcpy( bs->valueP, mswTmpBuff ); bs->action( mswTmpBuff, bs->data ); mswSetTrigger( NULL, NULL ); } } LRESULT stringProc( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { wString_p bs = (wString_p)b; int cnt; int modified; switch( message ) { case WM_COMMAND: switch (WCMD_PARAM_NOTF) { case EN_KILLFOCUS: modified = (int)SendMessage( bs->hWnd, (UINT)EM_GETMODIFY, 0, 0L ); if (!modified) break; *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bs->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (bs->valueP) strncpy( bs->valueP, mswTmpBuff, bs->valueL ); if (bs->action) { bs->action( mswTmpBuff, bs->data ); mswSetTrigger( NULL, NULL ); } break; SendMessage( bs->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L ); } break; } return DefWindowProc( hWnd, message, wParam, lParam ); } static callBacks_t stringCallBacks = { mswRepaintLabel, NULL, stringProc }; wString_p wStringCreate( wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, POS_T width, char *valueP, wIndex_t valueL, wStringCallBack_p action, void *data ) { wString_p b; RECT rect; int index; DWORD style = 0; b = (wString_p)mswAlloc( parent, B_STRING, mswStrdup(labelStr), sizeof *b, data, &index ); mswComputePos( (wControl_p)b, x, y ); b->option = option; b->valueP = valueP; b->valueL = valueL; b->labelY += 2; b->action = action; if (option & BO_READONLY) style |= ES_READONLY; #ifdef WIN32 b->hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT", NULL, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style, b->x, b->y, width, mswEditHeight, ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); #else b->hWnd = CreateWindow( "EDIT", NULL, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style, b->x, b->y, width, mswEditHeight, ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); #endif if (b->hWnd == NULL) { mswFail("CreateWindow(STRING)"); return b; } #ifdef CONTROL3D Ctl3dSubclassCtl( b->hWnd); #endif newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst ); oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC ); SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc ); if (b->valueP) { SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)b->valueP ); } SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); if ( !mswThickFont ) SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L ); GetWindowRect( b->hWnd, &rect ); b->w = rect.right - rect.left; b->h = rect.bottom - rect.top; mswAddButton( (wControl_p)b, TRUE, helpStr ); mswCallBacks[B_STRING] = &stringCallBacks; mswChainFocus( (wControl_p)b ); return b; } #ifdef LATER /* ***************************************************************************** * * Integer Value Boxes * ***************************************************************************** */ #define MININT ((long)0x80000000) #define MAXINT ((long)0x7FFFFFFF) void wIntegerSetValue( wInteger_p b, long arg ) { b->oldValue = arg; wsprintf( mswTmpBuff, "%ld", arg ); SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); } long wIntegerGetValue( wInteger_p b ) { return b->oldValue; } static void triggerInteger( wControl_p b ) { wInteger_p bi = (wInteger_p)b; int cnt; long value; char * cp; if (bi->action) { *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bi->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (strcmp( mswTmpBuff, "-" )==0 ) return; value = strtol( mswTmpBuff, &cp, 10 ); if (*cp != '\0' || value < bi->low || value > bi->high ) return; if (bi->oldValue == value) return; if (bi->valueP) *bi->valueP = value; bi->oldValue = value; bi->action( value, bi->data ); } } LRESULT integerProc( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { wInteger_p bi = (wInteger_p)b; int inx; int cnt; long value; char * cp; wBool_t ok; int modified; switch( message ) { case WM_COMMAND: switch (WCMD_PARAM_NOTF) { case EN_KILLFOCUS: ok = TRUE; modified = (int)SendMessage( bi->hWnd, (UINT)EM_GETMODIFY, 0, 0L ); if (!modified) break; *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bi->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (strcmp( mswTmpBuff, "-" )==0 && 0 >= bi->low && 0 <= bi->high ) { value = 0; } else { value = strtol( mswTmpBuff, &cp, 10 ); if (*cp != '\0' || value < bi->low || value > bi->high ) { inx = GetWindowWord( bi->hWnd, GWW_ID ); if (wWinIsVisible(bi->parent)) { PostMessage( ((wControl_p)(bi->parent))->hWnd, WM_NOTVALID, inx, 0L ); return TRUE; } else { if (value < bi->low) value = bi->low; else value = bi->high; sprintf( mswTmpBuff, "%ld", value ); SendMessage( bi->hWnd, (UINT)WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); } } } bi->oldValue = value; if (bi->valueP) *bi->valueP = value; if (bi->action) { bi->action( value, bi->data ); mswSetTrigger( NULL, NULL ); } SendMessage( bi->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L ); } break; case WM_NOTVALID: wsprintf( mswTmpBuff, "Please enter a value between %ld and %ld", bi->low, bi->high ); if (bi->low > MININT && bi->high < MAXINT) sprintf( mswTmpBuff, "Please enter an integer value between %ld and %ld", bi->low, bi->high ); else if (bi->low > MININT) sprintf( mswTmpBuff, "Please enter an integer value greater or equal to %ld", bi->low ); else if (bi->high < MAXINT) sprintf( mswTmpBuff, "Please enter an integer value less or equal to %ld", bi->high ); else strcpy( mswTmpBuff, "Please enter an integer value" ); MessageBox( bi->hWnd, mswTmpBuff, "Invalid entry", MB_OK ); SetFocus( bi->hWnd ); #ifdef WIN32 SendMessage( bi->hWnd, EM_SETSEL, 0, 0x7fff ); SendMessage( bi->hWnd, EM_SCROLLCARET, 0, 0L ); #else SendMessage( bi->hWnd, EM_SETSEL, 0, MAKELONG(0,0x7fff) ); #endif return TRUE; } return DefWindowProc( hWnd, message, wParam, lParam ); } static callBacks_t integerCallBacks = { mswRepaintLabel, NULL, integerProc }; wInteger_p wIntegerCreate( wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, POS_T width, long low, long high, long *valueP, wIntegerCallBack_p action, void *data ) { wInteger_p b; RECT rect; int index; DWORD style = 0; b = mswAlloc( parent, B_INTEGER, mswStrdup(labelStr), sizeof *b, data, &index ); mswComputePos( (wControl_p)b, x, y ); b->option = option; b->low = low; b->high = high; b->valueP = valueP; b->labelY += 2; b->action = action; if (option & BO_READONLY) style |= ES_READONLY; b->hWnd = CreateWindow( "EDIT", NULL, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style, b->x, b->y, width, mswEditHeight, ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); if (b->hWnd == NULL) { mswFail("CreateWindow(INTEGER)"); return b; } #ifdef CONTROL3D Ctl3dSubclassCtl( b->hWnd); #endif newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst ); oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC ); SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc ); if ( !mswThickFont ) SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L ); if (b->valueP) { wsprintf( mswTmpBuff, "%ld", *b->valueP ); SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); b->oldValue = *b->valueP; } else b->oldValue = 0; SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); GetWindowRect( b->hWnd, &rect ); b->w = rect.right - rect.left; b->h = rect.bottom - rect.top; mswAddButton( (wControl_p)b, TRUE, helpStr ); mswCallBacks[ B_INTEGER ] = &integerCallBacks; mswChainFocus( (wControl_p)b ); return b; } /* ***************************************************************************** * * Floating Point Value Boxes * ***************************************************************************** */ #define MINFLT (-1000000) #define MAXFLT (1000000) void wFloatSetValue( wFloat_p b, double arg ) { b->oldValue = arg; sprintf( mswTmpBuff, "%0.3f", arg ); SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); } double wFloatGetValue( wFloat_p b ) { return b->oldValue; } static void triggerFloat( wControl_p b ) { wFloat_p bf = (wFloat_p)b; int cnt; double value; char * cp; if (bf->action) { *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bf->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (strcmp( mswTmpBuff, "-" )==0) return; value = strtod( mswTmpBuff, &cp ); if (*cp != '\0' || value < bf->low || value > bf->high ) return; if (bf->oldValue == value) return; bf->oldValue = value; if (bf->valueP) *bf->valueP = value; bf->action( wFloatGetValue(bf), bf->data ); } } LRESULT floatProc( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { wFloat_p bf = (wFloat_p)b; int inx; int cnt; double value; char * cp; wBool_t ok; int modified; switch( message ) { case WM_COMMAND: switch (HIWORD(lParam)) { case EN_KILLFOCUS: ok = TRUE; modified = (int)SendMessage( bf->hWnd, (UINT)EM_GETMODIFY, 0, 0L ); if (!modified) break; *(WPARAM*)&mswTmpBuff[0] = 78; cnt = (int)SendMessage( bf->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff ); mswTmpBuff[cnt] = '\0'; if (strcmp( mswTmpBuff, "-" )==0 && 0 >= bf->low && 0 <= bf->high ) { value = 0; } else { value = strtod( mswTmpBuff, &cp ); if (*cp != '\0' || value < bf->low || value > bf->high ) { inx = GetWindowWord( bf->hWnd, GWW_ID ); if (wWinIsVisible(bf->parent)) { PostMessage( ((wControl_p)(bf->parent))->hWnd, WM_NOTVALID, inx, 0L ); return TRUE; } else { if (value < bf->low) value = bf->low; else value = bf->high; sprintf( mswTmpBuff, "%0.3f", value ); SendMessage( bf->hWnd, (UINT)WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); } } } bf->oldValue = value; if (bf->valueP) *bf->valueP = value; if (bf->action) { bf->action( value, bf->data ); mswSetTrigger( NULL, NULL ); } SendMessage( bf->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L ); } break; case WM_NOTVALID: if (bf->low > MINFLT && bf->high < MAXFLT) sprintf( mswTmpBuff, "Please enter an float value between %0.3f and %0.3f", bf->low, bf->high ); else if (bf->low > MINFLT) sprintf( mswTmpBuff, "Please enter an float value greater or equal to %0.3f", bf->low ); else if (bf->high < MAXFLT) sprintf( mswTmpBuff, "Please enter an float value less or equal to %0.3f", bf->high ); else strcpy( mswTmpBuff, "Please enter an float value" ); MessageBox( bf->hWnd, mswTmpBuff, "Invalid entry", MB_OK ); SetFocus( bf->hWnd ); #ifdef WIN32 SendMessage( bi->hWnd, EM_SETSEL, 0, 0x7fff ); SendMessage( bi->hWnd, EM_SCROLLCARET, 0, 0L ); #else SendMessage( bi->hWnd, EM_SETSEL, 0, MAKELONG(0,0x7fff) ); #endif return TRUE; } return DefWindowProc( hWnd, message, wParam, lParam ); } static callBacks_t floatCallBacks = { mswRepaintLabel, NULL, floatProc }; wFloat_p wFloatCreate( wWin_p parent, POS_T x, POS_T y, const char * helpStr, const char * labelStr, long option, POS_T width, double low, double high, double *valueP, wFloatCallBack_p action, void *data ) { wFloat_p b; RECT rect; int index; DWORD style = 0; b = mswAlloc( parent, B_FLOAT, mswStrdup(labelStr), sizeof *b, data, &index ); mswComputePos( (wControl_p)b, x, y ); b->option = option; b->low = low; b->high = high; b->valueP = valueP; b->labelY += 2; b->action = action; if (option & BO_READONLY) style |= ES_READONLY; b->hWnd = CreateWindow( "EDIT", NULL, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style, b->x, b->y, width, mswEditHeight, ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); if (b->hWnd == NULL) { mswFail("CreateWindow(FLOAT)"); return b; } #ifdef CONTROL3D Ctl3dSubclassCtl( b->hWnd); #endif newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst ); oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC ); SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc ); if (b->valueP) { b->oldValue = *b->valueP; } else b->oldValue = 0.0; if (b->valueP) sprintf( mswTmpBuff, "%0.3f", *b->valueP ); else strcpy( mswTmpBuff, "0.000" ); if ( !mswThickFont ) SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L ); SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff ); SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L ); GetWindowRect( b->hWnd, &rect ); b->w = rect.right - rect.left; b->h = rect.bottom - rect.top; mswAddButton( (wControl_p)b, TRUE, helpStr ); mswCallBacks[ B_FLOAT ] = &floatCallBacks; mswChainFocus( (wControl_p)b ); return b; } #endif