00001
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
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
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
00045 if(!RegisterControlClass(hDLL)){
00046 unregister=FALSE;
00047 }
00048 break;
00049 }
00050 case DLL_PROCESS_DETACH:
00051 if(unregister)UnregisterClass(_szControlName, hDLL);
00052
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
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);
00119 LineTo(hDC, rc.right, y);
00120
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
00138
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) {
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
00187 TrianglePressed = (pt.y < rc.bottom / 2)
00188 ? TP_UP : TP_DOWN;
00189
00190
00191
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
00200 if ((int) HIWORD(dwRange) > nCrntVal) nNewVal++;
00201 else {
00202
00203
00204 if (fWrap) nNewVal = (int) LOWORD(dwRange);
00205 }
00206 }
00207 else {
00208
00209 if ((int) LOWORD(dwRange) < nCrntVal) nNewVal--;
00210 else {
00211
00212
00213 if (fWrap) nNewVal = (int) HIWORD(dwRange);
00214 }
00215 }
00216
00217 if (nNewVal != nCrntVal)
00218 SendMessage(hWnd, SPNM_SETCRNTVALUE, nNewVal, 0l);
00219
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
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) {
00367 TrianglePressed = TP_UP;
00368 DrawSpinButtons(hWnd,NULL,1);
00369
00370 }
00371 else{
00372 TrianglePressed = TP_DOWN;
00373 DrawSpinButtons(hWnd,NULL,-1);
00374
00375 }
00376 SetWindowLong(hWnd, GWL_TRIANGLEPRESSED, TrianglePressed);
00377
00378
00379
00380
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
00408
00409
00410
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 }