SPIN_DLL.C

Go to the documentation of this file.
00001 /* file SPIN_DLL.C DLL to do SPIN buttons */
00002 
00003 #include <windows.h>
00004 
00005 #pragma warning( disable : 4312)
00006 
00007 #include "spin_dll.h"
00008 
00009 #if __SC__
00010 #pragma ZTC align 1
00011 #endif
00012 
00013 #define CBWNDEXTRA            (16)
00014 #define GWL_RANGE             (0)
00015 #define GWL_CRNTVALUE         (4)
00016 #define GWL_TRIANGLEPRESSED   (8)
00017 #define GWL_EDITCTRL          (12)
00018 
00019 #define SPNM_SCROLLVALUE      (WM_USER + 500)
00020 
00021    // Time delay between scrolling events in milliseconds.
00022 #define TIME_DELAY            (150)
00023 
00024 typedef enum { TP_NONE, TP_UP, TP_DOWN } TRIANGLEPRESSED;
00025 
00026 char _szControlName[] = "Spin";
00027 
00028 ATOM  RegisterControlClass (HINSTANCE hInstance);
00029 LRESULT CALLBACK SpinWndFn
00030    (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
00031 
00032 /*** Window's Dynamic-Link Library Initialization Routines ******/
00033 
00034 #if __WATCOMC__
00035 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00036 #elif __BCC__
00037 int APIENTRY DllEntryPoint(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00038 #else
00039 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00040 #endif
00041   static BOOL unregister=TRUE;
00042   switch (dwReason) {
00043     case DLL_PROCESS_ATTACH: {
00044 //      MessageBox (GetFocus(),"Spin","Process attaching",MB_OK|MB_SYSTEMMODAL);
00045       if(!RegisterControlClass(hDLL)){
00046         unregister=FALSE;
00047       }
00048       break;
00049     }
00050     case DLL_PROCESS_DETACH:
00051       if(unregister)UnregisterClass(_szControlName, hDLL);
00052 //      MessageBox (GetFocus(),"Spin","Process detaching",MB_OK|MB_SYSTEMMODAL);
00053       break;
00054   }
00055   return (int)TRUE;
00056 }
00057 
00058 #if __SC__
00059 #pragma startaddress(DllMain)
00060 #endif
00061 
00062 /****************************************************************/
00063 
00064 ATOM  RegisterControlClass (HINSTANCE hInstance) {
00065    WNDCLASS wc;
00066    wc.style         = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
00067    wc.lpfnWndProc   = (WNDPROC)SpinWndFn;
00068    wc.cbClsExtra    = 0;
00069    wc.cbWndExtra    = CBWNDEXTRA;
00070    wc.hInstance     = hInstance;
00071    wc.hIcon         = (HICON) NULL;
00072    wc.hCursor       = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
00073    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
00074    wc.lpszMenuName  = NULL;
00075    wc.lpszClassName = _szControlName;
00076    return(RegisterClass(&wc));
00077 }
00078 
00079 static LRESULT  NotifyParent
00080            (HWND hWndControl, WORD wNotifyCode) {
00081    LRESULT lResult;
00082    lResult = SendMessage(GetParent(hWndControl), WM_COMMAND,
00083              MAKELPARAM((WORD)GetWindowLong(hWndControl,GWL_ID),wNotifyCode),
00084              (LPARAM)hWndControl);
00085    return(lResult);
00086 }
00087 
00088 #if 0
00089 //  old function //
00090 LRESULT CALLBACK SpinWndFn(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
00091    HWND hEdit;
00092    LRESULT lResult = 0;
00093    HDC hDC;
00094    POINT pt;
00095    RECT rc,rc1;
00096    PAINTSTRUCT ps;
00097    int i, nCrntVal, nNewVal, x, y;
00098    TRIANGLEPRESSED TrianglePressed, OldTrianglePressed;
00099    DWORD dwEventTime, dwRange;
00100    BOOL fWrap;
00101    switch (uMsg) {
00102       case WM_GETDLGCODE:
00103          lResult = DLGC_STATIC;
00104          break;
00105       case WM_ENABLE:
00106          InvalidateRect(hWnd, NULL, FALSE);
00107          break;
00108       case WM_CREATE:
00109          SendMessage(hWnd, SPNM_SETRANGE, 0, MAKELPARAM(0, 0));
00110          SendMessage(hWnd, SPNM_SETEDITCTRL,0,(LPARAM)NULL);
00111          SendMessage(hWnd, SPNM_SETCRNTVALUE, 0, 0);
00112          break;
00113       case WM_PAINT:
00114          hDC = BeginPaint(hWnd, &ps);
00115          GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00116          x = rc.right / 2;
00117          y = rc.bottom / 2;
00118          MoveToEx(hDC, 0, y, NULL);           // Draw middle separator bar
00119          LineTo(hDC, rc.right, y);
00120          // Draw rectangle round control
00121          SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
00122          Rectangle(hDC,0,0,rc.right+1,rc.bottom);
00123          SelectObject(hDC, GetStockObject(BLACK_BRUSH));
00124          MoveToEx(hDC, x, 2, NULL);
00125          LineTo(hDC, rc.right - 2, y - 2);
00126          LineTo(hDC, 2, y - 2);
00127          LineTo(hDC, x, 2);
00128          FloodFill(hDC, x, y - 3, RGB(0, 0, 0));
00129          MoveToEx(hDC, 2, y + 2, NULL);
00130          LineTo(hDC, rc.right - 2, y + 2);
00131          LineTo(hDC, x, rc.bottom - 2);
00132          LineTo(hDC, 2, y + 2);
00133          FloodFill(hDC, x, y + 3, RGB(0, 0, 0));
00134          EndPaint(hWnd, &ps);
00135          break;
00136       case WM_LBUTTONDOWN:
00137          // first if attached to edit control get the integer value
00138          // and check that itis in range
00139          if((hEdit=(HWND)GetWindowLong(hWnd, GWL_EDITCTRL)) != NULL){
00140            char str[32];
00141            dwRange = SendMessage(hWnd, SPNM_GETRANGE, 0, 0l);
00142            nCrntVal=(int)SendMessage(hWnd,SPNM_GETCRNTVALUE,0,0l);
00143            i=(int)SendMessage(hEdit,WM_GETTEXT,(WPARAM)32,(LPARAM)str);
00144            if(i > 0){
00145              nNewVal=atoi(str);
00146              if (nNewVal > (int)HIWORD(dwRange))nNewVal=(int)HIWORD(dwRange);
00147              if (nNewVal < (int)LOWORD(dwRange))nNewVal=(int)LOWORD(dwRange);
00148            }
00149            else nNewVal=nCrntVal;
00150            SendMessage(hWnd, SPNM_SETCRNTVALUE, nNewVal, 0l);
00151          }
00152          GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00153          if ((int) HIWORD(lParam) < rc.bottom / 2) {  // Up arrow
00154             TrianglePressed = TP_UP;
00155             rc.bottom /= 2;
00156          } else {
00157             TrianglePressed = TP_DOWN;
00158             rc.top = rc.bottom / 2;
00159          }
00160          SetWindowLong(hWnd, GWL_TRIANGLEPRESSED, TrianglePressed);
00161          hDC = GetDC(hWnd);
00162          CopyRect(&rc1,&rc); rc1.left+= 1; rc1.top += 1; rc1.bottom -= 1;
00163          InvertRect(hDC, &rc1);
00164          ReleaseDC(hWnd, hDC);
00165          SetCapture(hWnd);
00166          dwEventTime = GetTickCount() - TIME_DELAY;
00167          do {
00168             if (dwEventTime > GetTickCount()) continue;
00169             SendMessage(hWnd, SPNM_SCROLLVALUE, 0, 0l);
00170             dwEventTime = GetTickCount() + TIME_DELAY;
00171          } while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
00172          ReleaseCapture();
00173          InvalidateRect(hWnd, NULL, TRUE);
00174          break;
00175       case SPNM_SCROLLVALUE:
00176          GetCursorPos(&pt);
00177          ScreenToClient(hWnd, &pt);
00178          GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00179          if (!PtInRect(&rc, pt)) break;
00180          nNewVal = (int)SendMessage(hWnd, SPNM_GETCRNTVALUE, 0, 0l);
00181          nCrntVal = nNewVal;
00182          dwRange = SendMessage(hWnd, SPNM_GETRANGE, 0, 0l);
00183          fWrap = (BOOL)(GetWindowLong(hWnd, GWL_STYLE) & SPNS_WRAP);
00184          OldTrianglePressed = (TRIANGLEPRESSED)
00185             GetWindowLong(hWnd, GWL_TRIANGLEPRESSED);
00186          // Determine which triangle the mouse is now over
00187          TrianglePressed = (pt.y < rc.bottom / 2)
00188             ? TP_UP : TP_DOWN;
00189          // If the user has switched triangles, invert the entire
00190          // rectangle. This restores the half that was inverted in
00191          // the WM_LBUTTONDOWN message and inverts the new half.
00192          if (OldTrianglePressed != TrianglePressed) {
00193             hDC = GetDC(hWnd);
00194             CopyRect(&rc1,&rc); rc1.left+= 1; rc1.top += 1; rc1.bottom -= 1;
00195             InvertRect(hDC, &rc1);
00196             ReleaseDC(hWnd, hDC);
00197          }
00198          if (TrianglePressed == TP_UP) {
00199             // If value is not at top of range, increment it.
00200             if ((int) HIWORD(dwRange) > nCrntVal) nNewVal++;
00201             else {
00202                // If value at top of range and the "wrap" flag
00203                // is set, set value to the bottom of the range.
00204                if (fWrap) nNewVal = (int) LOWORD(dwRange);
00205             }
00206          }
00207          else {
00208             // If value is not at bottom of range, decrement it.
00209             if ((int) LOWORD(dwRange) < nCrntVal) nNewVal--;
00210             else {
00211                // If value at bottom of range and the "wrap" flag
00212                // is set, set the value to the top of the range.
00213                if (fWrap) nNewVal = (int) HIWORD(dwRange);
00214             }
00215          }
00216          // If the value has been changed, set the new value.
00217          if (nNewVal != nCrntVal)
00218             SendMessage(hWnd, SPNM_SETCRNTVALUE, nNewVal, 0l);
00219          // Set the new triangle pressed for the next call to here
00220          SetWindowLong(hWnd,
00221             GWL_TRIANGLEPRESSED, TrianglePressed);
00222          break;
00223       case SPNM_SETRANGE:
00224          SetWindowLong(hWnd, GWL_RANGE, lParam);
00225          break;
00226       case SPNM_GETRANGE:
00227          lResult = GetWindowLong(hWnd, GWL_RANGE);
00228          break;
00229       case SPNM_SETCRNTVALUE:
00230          SetWindowLong(hWnd, GWL_CRNTVALUE, wParam);
00231          if((hEdit=(HWND)GetWindowLong(hWnd, GWL_EDITCTRL)) != NULL){
00232            char str[16];
00233            sprintf(str,"%ld",wParam);
00234            SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)str);
00235            InvalidateRect(hEdit,NULL,TRUE);
00236            UpdateWindow(hEdit);
00237          }
00238          NotifyParent(hWnd, SPNN_VALUECHANGE);
00239          break;
00240       case SPNM_GETCRNTVALUE:
00241          lResult = (LRESULT) GetWindowLong(hWnd, GWL_CRNTVALUE);
00242          break;
00243       case SPNM_SETEDITCTRL:
00244          SetWindowLong(hWnd, GWL_EDITCTRL, lParam);
00245          break;
00246       default:
00247          lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
00248          break;
00249    }
00250    return(lResult);
00251 }
00252 // end of old function //
00253 #endif
00254 
00255 static void DrawSpinUp(HDC dc, LPRECT lpr){
00256  HBRUSH hbr;
00257  int width,height;
00258  width  = lpr->right - lpr->left;
00259  height = lpr->bottom - lpr->top;
00260  hbr = SelectObject (dc, CreateSolidBrush (GetSysColor (COLOR_BTNFACE)));
00261  PatBlt(dc,lpr->left,lpr->top, width, height, PATCOPY);
00262  DeleteObject (SelectObject (dc, hbr));
00263  PatBlt(dc,lpr->left,lpr->top, 1, height - 1, WHITENESS);
00264  PatBlt(dc,lpr->left,lpr->top, width - 1, 1, WHITENESS);
00265  hbr = SelectObject (dc, CreateSolidBrush (GetSysColor (COLOR_BTNSHADOW)));
00266  PatBlt(dc,lpr->right - 1, lpr->top, 1, height, PATCOPY);
00267  PatBlt(dc,lpr->left, lpr->bottom - 1, width, 1, PATCOPY);
00268  DeleteObject (SelectObject (dc, hbr));
00269 }
00270 
00271 static void DrawSpinDn(HDC dc, LPRECT lpr){
00272  HBRUSH hbr;
00273  int width, height;
00274  width  = lpr->right - lpr->left;
00275  height = lpr->bottom - lpr->top;
00276  hbr = SelectObject(dc,CreateSolidBrush (GetSysColor (COLOR_BTNFACE)));
00277  PatBlt(dc,lpr->left,lpr->top,width, height, PATCOPY);
00278  DeleteObject (SelectObject (dc, hbr));
00279  hbr=SelectObject(dc,CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT)));
00280  PatBlt(dc,lpr->right,lpr->top, 1, height, PATCOPY);
00281  PatBlt(dc,lpr->left,lpr->bottom, width, 1, PATCOPY);
00282  DeleteObject(SelectObject(dc,CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW))));
00283  PatBlt(dc,lpr->left,lpr->top, 1, height, PATCOPY);
00284  PatBlt(dc,lpr->left,lpr->top, width, 1, PATCOPY);
00285  DeleteObject(SelectObject (dc, hbr));
00286 }
00287 
00288 static void DrawSpinArrow(HDC hDC,int x,int y,int ud){
00289  int i,k;
00290  for(i=0;i<5;i++){
00291    if(ud > 0)k=y+i;
00292    else      k=y+4-i;
00293    MoveToEx(hDC,x-i,k,NULL); LineTo(hDC,x+i+1,k);
00294  }
00295 }
00296 
00297 static void DrawSpinButtons(HWND hWnd, HDC hDCin, int id){
00298  HDC hDC;
00299  RECT rc,rc1;
00300  int x,y,yi;
00301  if(hDCin == NULL)hDC = GetDC(hWnd);
00302  else             hDC = hDCin;
00303  GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00304  rc1.left=1; rc1.top=1; rc1.right=rc.right; rc1.bottom=rc.bottom/2;
00305  if(id > 0)DrawSpinDn(hDC,&rc1);
00306  else      DrawSpinUp(hDC,&rc1);
00307  rc1.top=rc.bottom/2+1; rc1.bottom=rc.bottom;
00308  if(id < 0)DrawSpinDn(hDC,&rc1);
00309  else      DrawSpinUp(hDC,&rc1);
00310  x = rc.right / 2;
00311  y = rc.bottom / 2;
00312  SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
00313  Rectangle(hDC,0,0,rc.right+1,rc.bottom);
00314  MoveToEx(hDC, 0, y, NULL);
00315  LineTo(hDC, rc.right, y);
00316  if(id > 0)yi=1; else yi=0;
00317  DrawSpinArrow(hDC,x+yi,(rc.bottom/2-5)/2+yi, 1);
00318  if(id < 0)yi=1; else yi=0;
00319  DrawSpinArrow(hDC,x+yi,y+1+(rc.bottom/2-5)/2+yi,-1);
00320  if(hDCin == NULL)ReleaseDC(hWnd, hDC);
00321 }
00322 
00323 LRESULT CALLBACK SpinWndFn(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
00324    HWND hEdit;
00325    LRESULT lResult = 0;
00326    HDC hDC;
00327    POINT pt;
00328    RECT rc,rc1;
00329    PAINTSTRUCT ps;
00330    int i, nCrntVal, nNewVal, x, y;
00331    TRIANGLEPRESSED TrianglePressed, OldTrianglePressed;
00332    DWORD dwEventTime, dwRange;
00333    BOOL fWrap;
00334    switch (uMsg) {
00335       case WM_GETDLGCODE:
00336          lResult = DLGC_STATIC;
00337          break;
00338       case WM_ENABLE:
00339          InvalidateRect(hWnd, NULL, FALSE);
00340          break;
00341       case WM_CREATE:
00342          SendMessage(hWnd, SPNM_SETRANGE, 0, MAKELPARAM(0, 0));
00343          SendMessage(hWnd, SPNM_SETEDITCTRL,0,(LPARAM)NULL);
00344          SendMessage(hWnd, SPNM_SETCRNTVALUE, 0, 0);
00345          break;
00346       case WM_PAINT:
00347          hDC = BeginPaint(hWnd, &ps);
00348          DrawSpinButtons(hWnd,hDC,0);
00349          EndPaint(hWnd, &ps);
00350          break;
00351       case WM_LBUTTONDOWN:
00352          if((hEdit=(HWND)GetWindowLong(hWnd, GWL_EDITCTRL)) != NULL){
00353            char str[32];
00354            dwRange = SendMessage(hWnd, SPNM_GETRANGE, 0, 0l);
00355            nCrntVal=(int)SendMessage(hWnd,SPNM_GETCRNTVALUE,0,0l);
00356            i=(int)SendMessage(hEdit,WM_GETTEXT,(WPARAM)32,(LPARAM)str);
00357            if(i > 0){
00358              nNewVal=atoi(str);
00359              if (nNewVal > (int)HIWORD(dwRange))nNewVal=(int)HIWORD(dwRange);
00360              if (nNewVal < (int)LOWORD(dwRange))nNewVal=(int)LOWORD(dwRange);
00361            }
00362            else nNewVal=nCrntVal;
00363            SendMessage(hWnd, SPNM_SETCRNTVALUE, nNewVal, 0l);
00364          }
00365          GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00366          if((int) HIWORD(lParam) < rc.bottom / 2) {  // Up arrow
00367            TrianglePressed = TP_UP;
00368            DrawSpinButtons(hWnd,NULL,1);
00369 //           rc.bottom /= 2;
00370          }
00371          else{
00372            TrianglePressed = TP_DOWN;
00373            DrawSpinButtons(hWnd,NULL,-1);
00374 //           rc.top = rc.bottom / 2;
00375          }
00376          SetWindowLong(hWnd, GWL_TRIANGLEPRESSED, TrianglePressed);
00377 //         hDC = GetDC(hWnd);
00378 //         CopyRect(&rc1,&rc); rc1.left+= 1; rc1.top += 1; rc1.bottom -= 1;
00379 //         InvertRect(hDC, &rc1);
00380 //         ReleaseDC(hWnd, hDC);
00381          SetCapture(hWnd);
00382          dwEventTime = GetTickCount() - TIME_DELAY;
00383          do {
00384            if(dwEventTime > GetTickCount()) continue;
00385            SendMessage(hWnd, SPNM_SCROLLVALUE, 0, 0l);
00386            dwEventTime = GetTickCount() + TIME_DELAY;
00387          } while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
00388          ReleaseCapture();
00389          InvalidateRect(hWnd, NULL, TRUE);
00390          break;
00391       case SPNM_SCROLLVALUE:
00392          GetCursorPos(&pt);
00393          ScreenToClient(hWnd, &pt);
00394          GetClientRect(hWnd, &rc); rc.right=rc.bottom/2;
00395          if (!PtInRect(&rc, pt)) break;
00396          nNewVal = (int)SendMessage(hWnd, SPNM_GETCRNTVALUE, 0, 0l);
00397          nCrntVal = nNewVal;
00398          dwRange = SendMessage(hWnd, SPNM_GETRANGE, 0, 0l);
00399          fWrap = (BOOL)(GetWindowLong(hWnd, GWL_STYLE) & SPNS_WRAP);
00400          OldTrianglePressed = (TRIANGLEPRESSED)
00401             GetWindowLong(hWnd, GWL_TRIANGLEPRESSED);
00402          TrianglePressed = (pt.y < rc.bottom / 2)
00403             ? TP_UP : TP_DOWN;
00404          if(OldTrianglePressed != TrianglePressed) {
00405             if(TrianglePressed == TP_UP)DrawSpinButtons(hWnd,NULL, 1);
00406             else                        DrawSpinButtons(hWnd,NULL,-1);
00407 //            hDC = GetDC(hWnd);
00408 //            CopyRect(&rc1,&rc); rc1.left+= 1; rc1.top += 1; rc1.bottom -= 1;
00409 //            InvertRect(hDC, &rc1);
00410 //            ReleaseDC(hWnd, hDC);
00411          }
00412          if(TrianglePressed == TP_UP) {
00413            if((int) HIWORD(dwRange) > nCrntVal) nNewVal++;
00414            else {
00415             if(fWrap)nNewVal = (int) LOWORD(dwRange);
00416            }
00417          }
00418          else{
00419            if((int) LOWORD(dwRange) < nCrntVal) nNewVal--;
00420            else {
00421              if(fWrap) nNewVal = (int) HIWORD(dwRange);
00422            }
00423          }
00424          if(nNewVal != nCrntVal)
00425             SendMessage(hWnd,SPNM_SETCRNTVALUE,nNewVal,0l);
00426          SetWindowLong(hWnd,GWL_TRIANGLEPRESSED,TrianglePressed);
00427          break;
00428       case SPNM_SETRANGE:
00429          SetWindowLong(hWnd, GWL_RANGE, lParam);
00430          break;
00431       case SPNM_GETRANGE:
00432          lResult = GetWindowLong(hWnd, GWL_RANGE);
00433          break;
00434       case SPNM_SETCRNTVALUE:
00435          SetWindowLong(hWnd, GWL_CRNTVALUE, wParam);
00436          if((hEdit=(HWND)GetWindowLong(hWnd, GWL_EDITCTRL)) != NULL){
00437            char str[16];
00438            sprintf(str,"%ld",wParam);
00439            SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)str);
00440            InvalidateRect(hEdit,NULL,TRUE);
00441            UpdateWindow(hEdit);
00442          }
00443          NotifyParent(hWnd, SPNN_VALUECHANGE);
00444          break;
00445       case SPNM_GETCRNTVALUE:
00446          lResult = (LRESULT) GetWindowLong(hWnd, GWL_CRNTVALUE);
00447          break;
00448       case SPNM_SETEDITCTRL:
00449          SetWindowLong(hWnd, GWL_EDITCTRL, lParam);
00450          break;
00451       default:
00452          lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
00453          break;
00454    }
00455    return(lResult);
00456 }

Generated on Sun Apr 27 14:20:09 2014 for OpenFX by  doxygen 1.5.6