diff options
Diffstat (limited to 'app/wlib/mswlib/mswbutt.c')
-rw-r--r-- | app/wlib/mswlib/mswbutt.c | 341 |
1 files changed, 193 insertions, 148 deletions
diff --git a/app/wlib/mswlib/mswbutt.c b/app/wlib/mswlib/mswbutt.c index 16f31c1..be72257 100644 --- a/app/wlib/mswlib/mswbutt.c +++ b/app/wlib/mswlib/mswbutt.c @@ -17,17 +17,24 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <windows.h> #include <string.h> -#include <malloc.h> #include <stdlib.h> #include <commdlg.h> #include <math.h> #include "mswint.h" -int kludge12 = 0; + +/** Macros for button repeat timers */ +#define REPEAT_STAGE0_DELAY 500 +#define REPEAT_STAGE1_DELAY 150 +#define REPEAT_STAGE2_DELAY 75 +#define STOP_TIMER (-1) +#define INITIAL_WAIT (0) +#define SLOW_REPEATS (1) +#define FAST_REPEATS (2) /* ***************************************************************************** @@ -40,25 +47,29 @@ int kludge12 = 0; static XWNDPROC oldButtProc = NULL; struct wButton_t { - WOBJ_COMMON - wButtonCallBack_p action; - wBool_t busy; - wBool_t selected; - wIcon_p icon; - }; + WOBJ_COMMON + wButtonCallBack_p action; + wBool_t busy; + wBool_t selected; + wIcon_p icon; + UINT_PTR timer_id; + int timer_count; + int timer_state; +}; void mswButtPush( - wControl_p b ) + wControl_p b ) { - if ( ((wButton_p)b)->action ) + if ( ((wButton_p)b)->action ) { ((wButton_p)b)->action( ((wButton_p)b)->data ); + } } /** * Paint function for toolbar buttons - * + * * \param hButtDc IN valid device context * \param bm IN bitmap to add to button * \param selected IN selected state of button @@ -66,27 +77,25 @@ void mswButtPush( */ static void drawButton( - HDC hButtDc, - wIcon_p bm, - BOOL_T selected, - BOOL_T disabled ) + HDC hButtDc, + wIcon_p bm, + BOOL_T selected, + BOOL_T disabled ) { HGDIOBJ oldBrush, newBrush; HPEN oldPen, newPen; RECT rect; COLORREF color1, color2; - POS_T offw=5, offh=5; - TRIVERTEX vert[2] ; - GRADIENT_RECT gRect; + wWinPix_t offw=5, offh=5; COLORREF colL; COLORREF colD; COLORREF colF; #define LEFT (0) -#define RIGHT (LONG)ceil(bm->w*scaleIcon+10) +#define RIGHT (bm->w+9) #define TOP (0) -#define BOTTOM (LONG)ceil(bm->h*scaleIcon+10) +#define BOTTOM (bm->h+9) /* get the lightest and the darkest color to use */ colL = GetSysColor( COLOR_BTNHIGHLIGHT ); @@ -106,8 +115,7 @@ static void drawButton( DeleteObject( SelectObject( hButtDc, oldBrush ) ); /* disabled button remain flat */ - if( !disabled ) - { + if( !disabled ) { /* select colors for the gradient */ if( selected ) { color1 = colD; @@ -117,67 +125,27 @@ static void drawButton( color2 = colD; } -#define GRADIENT_WIDTH 6 - - /* - first draw the top gradient - this always ends in the button face color - starting color depends on button state (selected or not) - */ - vert [0] .x = LEFT; - vert [0] .y = TOP; - vert [0] .Red = GetRValue( color1 )* 256; - vert [0] .Green = GetGValue( color1 )* 256; - vert [0] .Blue = GetBValue( color1 )* 256; - vert [0] .Alpha = 0x0000; - vert [1] .x = RIGHT; - vert [1] .y = TOP + GRADIENT_WIDTH; - vert [1] .Red = GetRValue( colF )* 256; - vert [1] .Green = GetGValue( colF )* 256; - vert [1] .Blue = GetBValue( colF )* 256; - vert [1] .Alpha = 0x0000; - - gRect.UpperLeft = 0; - gRect.LowerRight = 1; - - GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); - - /* - now draw the bottom gradient - this always starts with the button face color - ending color depends on button state (selected or not) - */ - vert [0] .x = LEFT; - vert [0] .y = BOTTOM - GRADIENT_WIDTH; - vert [0] .Red = GetRValue( colF )* 256; - vert [0] .Green = GetGValue( colF )* 256; - vert [0] .Blue = GetBValue( colF )* 256; - vert [0] .Alpha = 0x0000; - vert [1] .x = RIGHT; - vert [1] .y = BOTTOM; - vert [1] .Red = GetRValue( color2 )* 256; - vert [1] .Green = GetGValue( color2 )* 256; - vert [1] .Blue = GetBValue( color2 )* 256; - vert [1] .Alpha = 0x0000; - gRect.UpperLeft = 0; - gRect.LowerRight = 1; - GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); + /* draw delimiting lines in shadow color */ + newPen = CreatePen( PS_SOLID, 0, color1 ); + oldPen = SelectObject( hButtDc, newPen ); + + MoveTo( hButtDc, RIGHT-1, TOP ); + LineTo( hButtDc, LEFT, TOP ); + LineTo( hButtDc, LEFT, BOTTOM ); + DeleteObject( SelectObject( hButtDc, oldPen ) ); + newPen = CreatePen( PS_SOLID, 0, color2 ); + oldPen = SelectObject( hButtDc, newPen ); + + MoveTo( hButtDc, RIGHT, TOP+1 ); + LineTo( hButtDc, RIGHT, BOTTOM ); + LineTo( hButtDc, LEFT, BOTTOM ); + DeleteObject( SelectObject( hButtDc, oldPen ) ); } - /* draw delimiting lines in shadow color */ - newPen = CreatePen( PS_SOLID, 0, colD ); - oldPen = SelectObject( hButtDc, newPen ); - - MoveTo( hButtDc, LEFT, TOP ); - LineTo( hButtDc, LEFT, BOTTOM ); - MoveTo( hButtDc, RIGHT, TOP ); - LineTo( hButtDc, RIGHT, BOTTOM ); - - DeleteObject( SelectObject( hButtDc, oldPen ) ); - color2 = GetSysColor( COLOR_BTNSHADOW ); - color1 = RGB( bm->colormap[ 1 ].rgbRed, bm->colormap[ 1 ].rgbGreen, bm->colormap[ 1 ].rgbBlue ); + color1 = RGB( bm->colormap[ 1 ].rgbRed, bm->colormap[ 1 ].rgbGreen, + bm->colormap[ 1 ].rgbBlue ); if (selected) { offw++; offh++; @@ -187,37 +155,46 @@ static void drawButton( static void buttDrawIcon( - wButton_p b, - HDC butt_hDc ) + wButton_p b, + HDC butt_hDc ) { - wIcon_p bm = b->icon; - POS_T offw=5, offh=5; + wIcon_p bm = b->icon; + wWinPix_t offw=5, offh=5; - if (b->selected || b->busy) { - offw++; offh++; - } else if ( (b->option & BO_DISABLED) != 0 ) { - ; - } else { - ; - } - drawButton( butt_hDc, bm, b->selected || b->busy, (b->option & BO_DISABLED) != 0 ); + if (b->selected || b->busy) { + offw++; offh++; + } else if ( (b->option & BO_DISABLED) != 0 ) { + ; + } else { + ; + } + drawButton( butt_hDc, bm, b->selected + || b->busy, (b->option & BO_DISABLED) != 0 ); } void wButtonSetBusy( - wButton_p b, - int value ) + wButton_p b, + int value) { b->busy = value; - if (!value) + if (!value) { b->selected = FALSE; - /*SendMessage( b->hWnd, BM_SETSTATE, (WPARAM)value, 0L );*/ - InvalidateRgn( b->hWnd, NULL, FALSE ); + } + + // in case a timer is associated with the button, kill it + if (b->timer_id) { + KillTimer(b->hWnd, b->timer_id); + b->timer_id = 0; + b->timer_state = STOP_TIMER; + } + + InvalidateRgn(b->hWnd, NULL, FALSE); } void wButtonSetLabel( - wButton_p b, - const char * label ) + wButton_p b, + const char * label ) { if ((b->option&BO_ICON) == 0) { /*b->labelStr = label;*/ @@ -227,9 +204,64 @@ void wButtonSetLabel( } InvalidateRgn( b->hWnd, NULL, FALSE ); } - -static LRESULT buttPush( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) +/** + * Button timer: handle timer events for buttons. These are used for + * auto-repeating presses. Three phases used are + * - initial delay before repetitions begin + * - slow repeats for a few cycles + * - fast repeats therafter + * - stop timer + * + * \param hWnd Handle of the window, unused + * \param message The message, unused + * \param timer The timer id is the wlib widget . + * \param timepast The timepast, unused + */ + +void CALLBACK buttTimer(HWND hWnd, UINT message, UINT_PTR timer, + DWORD timepast) +{ + wButton_p b = (wButton_p)timer; + if (b->timer_id == 0) { + b->timer_state = STOP_TIMER; + return ; + } + + /* Autorepeat state machine */ + switch (b->timer_state) { + case INITIAL_WAIT: + b->timer_state = SLOW_REPEATS; + b->timer_count = 0; + KillTimer(hWnd, (UINT_PTR)b); + SetTimer(hWnd, (UINT_PTR)b, REPEAT_STAGE1_DELAY, buttTimer); + break; + case SLOW_REPEATS: /* Enable slow auto-repeat */ + if (b->timer_count++ > 10) { + /* Start fast auto-repeat */ + b->timer_state = FAST_REPEATS; + KillTimer(hWnd, (UINT_PTR)b); + SetTimer(hWnd, (UINT_PTR)b, REPEAT_STAGE2_DELAY, buttTimer); + } + break; + case FAST_REPEATS: + break; + case STOP_TIMER: + default: + KillTimer(hWnd, (UINT_PTR)b); + b->timer_id = 0; + return; + break; + } + if (b->action) { + b->action(b->data); + } + return; +} + + +static LRESULT buttPush( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, + LPARAM lParam ) { wButton_p bb = (wButton_p)b; DRAWITEMSTRUCT * di = (DRAWITEMSTRUCT *)lParam; @@ -240,19 +272,20 @@ static LRESULT buttPush( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, L case WM_COMMAND: if (bb->action /*&& !bb->busy*/) { bb->action( bb->data ); - return 0L; + return (LRESULT)0; } break; case WM_MEASUREITEM: { MEASUREITEMSTRUCT * mi = (MEASUREITEMSTRUCT *)lParam; - if (bb->type != B_BUTTON || (bb->option & BO_ICON) == 0) + if (bb->type != B_BUTTON || (bb->option & BO_ICON) == 0) { break; + } mi->CtlType = ODT_BUTTON; - mi->CtlID = wParam; - mi->itemWidth = (UINT)ceil(bb->w*scaleIcon); - mi->itemHeight = (UINT)ceil(bb->h*scaleIcon); - } return 0L; + mi->CtlID = (UINT)wParam; + mi->itemWidth = (UINT)bb->w; + mi->itemHeight = (UINT)bb->h; + } return (LRESULT)0; case WM_DRAWITEM: if (bb->type == B_BUTTON && (bb->option & BO_ICON) != 0) { @@ -261,33 +294,29 @@ static LRESULT buttPush( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, L bb->selected = selected; InvalidateRgn( bb->hWnd, NULL, FALSE ); } - return TRUE; + return (LRESULT)TRUE; } break; - } return DefWindowProc( hWnd, message, wParam, lParam ); } static void buttDone( - wControl_p b ) + wControl_p b ) { free(b); } LRESULT CALLBACK pushButt( - HWND hWnd, - UINT message, - UINT wParam, - LONG lParam ) + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam ) { /* Catch <Return> and cause focus to leave control */ -#ifdef WIN32 - long inx = GetWindowLong( hWnd, GWL_ID ); -#else - short inx = GetWindowWord( hWnd, GWW_ID ); -#endif + + wIndex_t inx = (wIndex_t)GetWindowLongPtr( hWnd, GWL_ID ); wButton_p b = (wButton_p)mswMapIndex( inx ); PAINTSTRUCT ps; @@ -297,7 +326,7 @@ LRESULT CALLBACK pushButt( BeginPaint( hWnd, &ps ); buttDrawIcon( (wButton_p)b, ps.hdc ); EndPaint( hWnd, &ps ); - return 1L; + return (LRESULT)1; } break; case WM_CHAR: @@ -308,41 +337,55 @@ LRESULT CALLBACK pushButt( case 0x09: /*SetFocus( ((wControl_p)(b->parent))->hWnd );*/ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR, - wParam, lParam ); + wParam, lParam ); /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND, inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/ - return 0L; + return (LONG_PTR)0; } } break; case WM_KILLFOCUS: - if ( b ) + if ( b ) { InvalidateRect( b->hWnd, NULL, TRUE ); - return 0L; + } + return (LRESULT)0; + break; + case WM_LBUTTONDOWN: + if (b->option&BO_REPEAT) { + SetTimer(hWnd, (UINT_PTR)b,REPEAT_STAGE0_DELAY,buttTimer); + b->timer_state = INITIAL_WAIT; + b->timer_id = (UINT_PTR)b; + } break; case WM_LBUTTONUP: /* don't know why but this solves a problem with color selection */ Sleep( 0 ); + if (b->timer_id) { + KillTimer(hWnd, (UINT_PTR)b); + } + b->timer_id = 0; + b->timer_state = STOP_TIMER; break; } return CallWindowProc( oldButtProc, hWnd, message, wParam, lParam ); } static callBacks_t buttonCallBacks = { - mswRepaintLabel, - buttDone, - buttPush }; + mswRepaintLabel, + buttDone, + buttPush +}; wButton_p wButtonCreate( - wWin_p parent, - POS_T x, - POS_T y, - const char * helpStr, - const char * labelStr, - long option, - wPos_t width, - wButtonCallBack_p action, - void * data ) + wWin_p parent, + wWinPix_t x, + wWinPix_t y, + const char * helpStr, + const char * labelStr, + long option, + wWinPix_t width, + wButtonCallBack_p action, + void * data ) { wButton_p b; RECT rect; @@ -352,8 +395,9 @@ wButton_p wButtonCreate( HDC hDc; wIcon_p bm; - if (width <= 0) + if (width <= 0) { width = 80; + } if ((option&BO_ICON) == 0) { labelStr = mswStrdup( labelStr ); } else { @@ -366,20 +410,21 @@ wButton_p wButtonCreate( b->selected = 0; mswComputePos( (wControl_p)b, x, y ); if (b->option&BO_ICON) { - width = (wPos_t)ceil(bm->w*scaleIcon)+10; - h = (int)ceil(bm->h*scaleIcon)+10; + width = (wWinPix_t)(bm->w+10); + h = bm->h+10; b->icon = bm; } else { - width = (wPos_t)(width*mswScale); + width = (wWinPix_t)(width*mswScale); } style = ((b->option&BO_ICON)? BS_OWNERDRAW : BS_PUSHBUTTON) | - WS_CHILD | WS_VISIBLE | - mswGetBaseStyle(parent); - if ((b->option&BB_DEFAULT) != 0) + WS_CHILD | WS_VISIBLE | + mswGetBaseStyle(parent); + if ((b->option&BB_DEFAULT) != 0) { style |= BS_DEFPUSHBUTTON; + } b->hWnd = CreateWindow( "BUTTON", labelStr, style, b->x, b->y, - /*CW_USEDEFAULT, CW_USEDEFAULT,*/ width, h, - ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); + /*CW_USEDEFAULT, CW_USEDEFAULT,*/ width, h, + ((wControl_p)parent)->hWnd, (HMENU)(UINT_PTR)index, mswHInst, NULL ); if (b->hWnd == NULL) { mswFail("CreateWindow(BUTTON)"); return b; @@ -393,16 +438,16 @@ wButton_p wButtonCreate( mswCallBacks[B_BUTTON] = &buttonCallBacks; mswChainFocus( (wControl_p)b ); - oldButtProc = (WNDPROC) SetWindowLongPtr(b->hWnd, GWL_WNDPROC, (LONG_PTR)&pushButt); + oldButtProc = (WNDPROC)SetWindowLongPtr(b->hWnd, GWLP_WNDPROC, + (LONG_PTR)&pushButt); if (mswPalette) { hDc = GetDC( b->hWnd ); SelectPalette( hDc, mswPalette, 0 ); RealizePalette( hDc ); ReleaseDC( b->hWnd, hDc ); } - if ( !mswThickFont ) - SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L ); + SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, (LPARAM)0 ); InvalidateRect(b->hWnd, &rect, TRUE); |