Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

732 lines
19 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // KNOB.CPP
  4. //
  5. // Multimedia Knob Control class; helper functions
  6. //
  7. // Copyright (c) Microsoft Corporation 1997
  8. //
  9. // 12/18/97 David Stewart / dstewart
  10. //
  11. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  12. #include "knob.h"
  13. #include "windowsx.h"
  14. #include <TCHAR.H>
  15. #include "resource.h"
  16. #include "dib.h"
  17. #include "math.h"
  18. #include "mmfw.h"
  19. #ifdef UNICODE
  20. #define WC_KNOB L"DES_KnobClass"
  21. #else
  22. #define WC_KNOB "DES_KnobClass"
  23. #endif
  24. //externals
  25. extern HPALETTE hpalMain;
  26. extern int g_nColorMode;
  27. #define LIGHT_OFFSET 9
  28. #define RADIAN_45DEG 0.785398163397448309615
  29. #define RADIAN_90DEG 1.57079632679489661923
  30. #define RADIAN_135DEG 2.356194490192344899999999999925
  31. #define DEGREE_CONVERTER 57.295779513082320876846364344191
  32. #define RADIAN_CONVERTER 0.017453292519943295769222222222222
  33. #define TRACK_TICK 5
  34. #define FAST_TRACK_TICK 1
  35. #define TRACK_DEGREES_PER_TICK 10
  36. #define FLASH_TICK 150
  37. #define KEYBOARD_STEP 3000
  38. //static data members ... these control the Window Class
  39. HINSTANCE CKnob::m_hInst = NULL;
  40. DWORD CKnob::m_dwKnobClassRef = 0;
  41. ATOM CKnob::m_KnobAtom = NULL;
  42. HANDLE CKnob::m_hbmpKnob = NULL;
  43. HANDLE CKnob::m_hbmpKnobTab = NULL;
  44. HANDLE CKnob::m_hbmpLight = NULL;
  45. HANDLE CKnob::m_hbmpLightBright = NULL;
  46. HANDLE CKnob::m_hbmpLightMask = NULL;
  47. int CKnob::m_nLightWidth = 0;
  48. int CKnob::m_nLightHeight = 0;
  49. CKnob* CreateKnob(DWORD dwWindowStyle,
  50. DWORD dwRange,
  51. DWORD dwInitialPosition,
  52. int x,
  53. int y,
  54. int width,
  55. int height,
  56. HWND hwndParent,
  57. int nID,
  58. HINSTANCE hInst)
  59. {
  60. if (CKnob::m_KnobAtom == NULL)
  61. {
  62. CKnob::InitKnobs(hInst);
  63. }
  64. CKnob* pKnob = new CKnob;
  65. //ensure this is a child window
  66. dwWindowStyle = dwWindowStyle|WS_CHILD;
  67. TCHAR szCaption[MAX_PATH];
  68. LoadString(hInst,IDB_TT_VOLUME,szCaption,sizeof(szCaption)/sizeof(TCHAR));
  69. HWND hwnd = CreateWindowEx(0,
  70. WC_KNOB,
  71. szCaption,
  72. dwWindowStyle,
  73. x,
  74. y,
  75. width,
  76. height,
  77. hwndParent,
  78. (HMENU)nID,
  79. hInst,
  80. NULL);
  81. if (hwnd == NULL)
  82. {
  83. //if we can't create the window, nuke it and fail
  84. DWORD dwErr = GetLastError();
  85. delete pKnob;
  86. return NULL;
  87. }
  88. SetWindowLongPtr(hwnd,0,(LONG_PTR)pKnob);
  89. pKnob->m_hwnd = hwnd;
  90. pKnob->m_nID = nID;
  91. pKnob->SetRange(dwRange);
  92. pKnob->SetPosition(dwInitialPosition,FALSE);
  93. return (pKnob);
  94. }
  95. BOOL CKnob::InitKnobs(HINSTANCE hInst)
  96. {
  97. m_hInst = hInst;
  98. if (m_KnobAtom == NULL)
  99. {
  100. WNDCLASSEX wc;
  101. ZeroMemory(&wc,sizeof(wc));
  102. wc.cbSize = sizeof(wc);
  103. wc.lpszClassName = WC_KNOB;
  104. wc.lpfnWndProc = CKnob::KnobProc;
  105. wc.hInstance = hInst;
  106. wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  107. wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MMFW));
  108. wc.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_VOLHAND));
  109. wc.hbrBackground = (HBRUSH)(CTLCOLOR_DLG+1);
  110. wc.cbWndExtra = sizeof(CKnob*);
  111. m_KnobAtom = RegisterClassEx(&wc);
  112. }
  113. int nBitmap = IDB_KNOB;
  114. switch (g_nColorMode)
  115. {
  116. case COLOR_16 : nBitmap = IDB_KNOB_16; break;
  117. case COLOR_HICONTRAST : nBitmap = IDB_KNOB_HI; break;
  118. }
  119. HBITMAP hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  120. CKnob::m_hbmpKnob = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
  121. DeleteObject(hbmpTemp);
  122. nBitmap = IDB_KNOB_TABSTATE;
  123. switch (g_nColorMode)
  124. {
  125. case COLOR_16 : nBitmap = IDB_KNOB_TABSTATE_16; break;
  126. case COLOR_HICONTRAST : nBitmap = IDB_KNOB_TABSTATE_HI; break;
  127. }
  128. hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  129. CKnob::m_hbmpKnobTab = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
  130. DeleteObject(hbmpTemp);
  131. nBitmap = IDB_KNOB_LIGHT_DIM;
  132. switch (g_nColorMode)
  133. {
  134. case COLOR_16 : nBitmap = IDB_KNOB_LIGHT_16; break;
  135. case COLOR_HICONTRAST : nBitmap = IDB_KNOB_LIGHT_16; break;
  136. }
  137. hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  138. CKnob::m_hbmpLight = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
  139. BITMAP bm;
  140. GetObject(hbmpTemp,sizeof(bm),&bm);
  141. CKnob::m_nLightWidth = bm.bmWidth;
  142. CKnob::m_nLightHeight = bm.bmHeight;
  143. DeleteObject(hbmpTemp);
  144. nBitmap = IDB_KNOB_LIGHT;
  145. switch (g_nColorMode)
  146. {
  147. case COLOR_16 : nBitmap = IDB_KNOB_LIGHT_16; break;
  148. case COLOR_HICONTRAST : nBitmap = IDB_KNOB_LIGHT_HI; break;
  149. }
  150. hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  151. CKnob::m_hbmpLightBright = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
  152. DeleteObject(hbmpTemp);
  153. m_hbmpLightMask = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(IDB_KNOB_LIGHTMASK),IMAGE_BITMAP,0,0,LR_MONOCHROME);
  154. return (m_KnobAtom != NULL);
  155. }
  156. void CKnob::UninitKnobs()
  157. {
  158. UnregisterClass(WC_KNOB,m_hInst);
  159. DeleteObject(CKnob::m_hbmpLightMask);
  160. GlobalFree(CKnob::m_hbmpLight);
  161. GlobalFree(CKnob::m_hbmpKnob);
  162. GlobalFree(CKnob::m_hbmpKnobTab);
  163. GlobalFree(CKnob::m_hbmpLightBright);
  164. m_KnobAtom = NULL;
  165. CKnob::m_hbmpLight = NULL;
  166. CKnob::m_hbmpKnob = NULL;
  167. CKnob::m_hbmpKnobTab = NULL;
  168. CKnob::m_hbmpLightMask = NULL;
  169. CKnob::m_hbmpLightBright = NULL;
  170. }
  171. //Given a parent window and a control ID, return the CMButton object
  172. CKnob* GetKnobFromID(HWND hwndParent, int nID)
  173. {
  174. HWND hwnd = GetDlgItem(hwndParent, nID);
  175. return (GetKnobFromHWND(hwnd));
  176. }
  177. //Given the window handle of the button, return the CMButton object
  178. CKnob* GetKnobFromHWND(HWND hwnd)
  179. {
  180. CKnob* pKnob = (CKnob*)GetWindowLongPtr(hwnd, 0);
  181. return (pKnob);
  182. }
  183. CKnob::CKnob()
  184. {
  185. m_dwKnobClassRef++;
  186. m_hwnd = NULL;
  187. m_nID = -1;
  188. m_nLightX = 0;
  189. m_nLightY = 0;
  190. m_dwRange = 100;
  191. m_dwPosition = 0;
  192. m_dwCurPosition = 0;
  193. m_fDim = TRUE;
  194. }
  195. CKnob::~CKnob()
  196. {
  197. m_dwKnobClassRef--;
  198. if (m_dwKnobClassRef==0)
  199. {
  200. UninitKnobs();
  201. }
  202. }
  203. void CALLBACK CKnob::TrackProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  204. {
  205. CKnob* pKnob = (CKnob*)idEvent; //idEvent holds pointer to knob object that created timer
  206. if (pKnob!=NULL)
  207. {
  208. pKnob->OnTimer();
  209. }
  210. }
  211. void CALLBACK CKnob::FlashProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  212. {
  213. CKnob* pKnob = (CKnob*)GetWindowLongPtr(hwnd, 0);
  214. if (pKnob!=NULL)
  215. {
  216. pKnob->OnFlashTimer();
  217. }
  218. }
  219. LRESULT CALLBACK CKnob::KnobProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  220. {
  221. CKnob* pKnob = (CKnob*)GetWindowLongPtr(hwnd, 0);
  222. if (pKnob != NULL)
  223. {
  224. switch (iMsg)
  225. {
  226. case WM_SETFOCUS :
  227. {
  228. SendMessage(GetParent(pKnob->m_hwnd),DM_SETDEFID,pKnob->m_nID,0);
  229. pKnob->m_fDim = FALSE;
  230. InvalidateRect(hwnd,NULL,FALSE);
  231. UpdateWindow(hwnd);
  232. pKnob->m_uFlashTimerID = SetTimer(hwnd,(UINT_PTR)hwnd,FLASH_TICK,(TIMERPROC)CKnob::FlashProc);
  233. }
  234. break;
  235. case WM_KILLFOCUS :
  236. {
  237. KillTimer(hwnd,pKnob->m_uFlashTimerID);
  238. pKnob->m_fDim = TRUE;
  239. InvalidateRect(hwnd,NULL,FALSE);
  240. UpdateWindow(hwnd);
  241. }
  242. break;
  243. case WM_GETDLGCODE :
  244. {
  245. return (DLGC_WANTARROWS);
  246. }
  247. break;
  248. case WM_KEYDOWN :
  249. {
  250. int nVirtKey = (int)wParam;
  251. DWORD dwCurrent = pKnob->GetPosition();
  252. switch (nVirtKey)
  253. {
  254. case VK_LEFT :
  255. case VK_DOWN :
  256. {
  257. if (dwCurrent - KEYBOARD_STEP > 65535)
  258. {
  259. dwCurrent = KEYBOARD_STEP;
  260. }
  261. pKnob->SetPosition(dwCurrent - KEYBOARD_STEP,TRUE);
  262. NMHDR nmhdr;
  263. nmhdr.hwndFrom = pKnob->m_hwnd;
  264. nmhdr.idFrom = pKnob->m_nID;
  265. nmhdr.code = TRUE;
  266. SendMessage(GetParent(pKnob->m_hwnd),WM_NOTIFY,(WPARAM)pKnob->m_nID,(LPARAM)&nmhdr);
  267. }
  268. break;
  269. case VK_RIGHT :
  270. case VK_UP :
  271. {
  272. if (dwCurrent + KEYBOARD_STEP > 65535)
  273. {
  274. dwCurrent = 65535 - KEYBOARD_STEP;
  275. }
  276. pKnob->SetPosition(dwCurrent + KEYBOARD_STEP,TRUE);
  277. NMHDR nmhdr;
  278. nmhdr.hwndFrom = pKnob->m_hwnd;
  279. nmhdr.idFrom = pKnob->m_nID;
  280. nmhdr.code = TRUE;
  281. SendMessage(GetParent(pKnob->m_hwnd),WM_NOTIFY,(WPARAM)pKnob->m_nID,(LPARAM)&nmhdr);
  282. }
  283. break;
  284. default:
  285. {
  286. //not a key we want ... tell our parent about it
  287. SendMessage(GetParent(hwnd),WM_KEYDOWN,wParam,lParam);
  288. }
  289. break;
  290. } //end switch
  291. }
  292. break;
  293. case WM_ERASEBKGND :
  294. {
  295. pKnob->Draw((HDC)wParam);
  296. return TRUE;
  297. }
  298. case WM_PAINT :
  299. {
  300. HDC hdc;
  301. PAINTSTRUCT ps;
  302. hdc = BeginPaint( hwnd, &ps );
  303. pKnob->Draw(hdc);
  304. EndPaint(hwnd,&ps);
  305. return 0;
  306. }
  307. break;
  308. case WM_RBUTTONDOWN :
  309. {
  310. pKnob->m_fFastKnob = TRUE;
  311. pKnob->OnButtonDown(LOWORD(lParam),HIWORD(lParam));
  312. pKnob->OnMouseMove(LOWORD(lParam),HIWORD(lParam));
  313. }
  314. break;
  315. case WM_RBUTTONUP :
  316. {
  317. pKnob->OnButtonUp();
  318. }
  319. break;
  320. case WM_LBUTTONDOWN :
  321. {
  322. pKnob->m_fFastKnob = FALSE;
  323. pKnob->OnButtonDown(LOWORD(lParam),HIWORD(lParam));
  324. pKnob->OnMouseMove(LOWORD(lParam),HIWORD(lParam));
  325. }
  326. break;
  327. case WM_LBUTTONUP :
  328. {
  329. pKnob->OnButtonUp();
  330. }
  331. break;
  332. case WM_MOUSEMOVE :
  333. {
  334. pKnob->OnMouseMove(LOWORD(lParam),HIWORD(lParam));
  335. }
  336. break;
  337. } //end switch
  338. } //end if class pointer assigned
  339. LRESULT lResult = DefWindowProc(hwnd, iMsg, wParam, lParam);
  340. if (iMsg == WM_DESTROY)
  341. {
  342. //auto-delete the knob class
  343. SetWindowLongPtr(hwnd,0,0);
  344. if (pKnob)
  345. {
  346. delete pKnob;
  347. }
  348. pKnob = NULL;
  349. }
  350. return (lResult);
  351. }
  352. void CKnob::OnButtonDown(int x, int y)
  353. {
  354. SetCapture(m_hwnd);
  355. m_fDim = FALSE;
  356. InvalidateRect(m_hwnd,NULL,FALSE);
  357. UpdateWindow(m_hwnd);
  358. m_uFlashTimerID = SetTimer(m_hwnd,(UINT_PTR)m_hwnd,FLASH_TICK,(TIMERPROC)CKnob::FlashProc);
  359. }
  360. void CKnob::OnButtonUp()
  361. {
  362. KillTimer(m_hwnd,m_uTrackTimerID);
  363. KillTimer(m_hwnd,m_uFlashTimerID);
  364. //we want to be sure the light is dim when we're done
  365. if (!m_fDim)
  366. {
  367. m_fDim = TRUE;
  368. InvalidateRect(m_hwnd,NULL,FALSE);
  369. UpdateWindow(m_hwnd);
  370. }
  371. ReleaseCapture();
  372. }
  373. void CKnob::OnFlashTimer()
  374. {
  375. m_fDim = !m_fDim;
  376. InvalidateRect(m_hwnd,NULL,FALSE);
  377. UpdateWindow(m_hwnd);
  378. }
  379. void CKnob::OnTimer()
  380. {
  381. RECT rect;
  382. GetClientRect(m_hwnd,&rect);
  383. int nWidth = rect.right - rect.left;
  384. int radius = (nWidth / 2) - LIGHT_OFFSET;
  385. double degree = ((double)m_dwPosition / m_dwRange) * 270;
  386. degree = degree + 135;
  387. if (abs((int)m_trackdegree-(int)degree) < TRACK_DEGREES_PER_TICK)
  388. {
  389. m_trackdegree = degree;
  390. KillTimer(m_hwnd,m_uTrackTimerID);
  391. }
  392. else
  393. {
  394. if (m_trackdegree > degree)
  395. {
  396. m_trackdegree -= TRACK_DEGREES_PER_TICK;
  397. }
  398. else
  399. {
  400. m_trackdegree += TRACK_DEGREES_PER_TICK;
  401. }
  402. }
  403. double angle = m_trackdegree * RADIAN_CONVERTER;
  404. double fLightX = radius * cos(angle);
  405. double fLightY = radius * sin(angle);
  406. //convert to proper gdi coordinates
  407. m_nLightX = ((int)fLightX) - (m_nLightWidth / 2) + (nWidth / 2);
  408. m_nLightY = ((int)fLightY) - (m_nLightHeight / 2) + (nWidth / 2);
  409. InvalidateRect(m_hwnd,NULL,FALSE);
  410. UpdateWindow(m_hwnd);
  411. degree = m_trackdegree - 135;
  412. if (degree < 0) degree = degree + 360;
  413. double percentage = degree / 270;
  414. m_dwCurPosition = (DWORD)(m_dwRange * percentage);
  415. NMHDR nmhdr;
  416. nmhdr.hwndFrom = m_hwnd;
  417. nmhdr.idFrom = m_nID;
  418. nmhdr.code = TRUE;
  419. SendMessage(GetParent(m_hwnd),WM_NOTIFY,(WPARAM)m_nID,(LPARAM)&nmhdr);
  420. }
  421. BOOL CKnob::ComputeCursor(int deltaX, int deltaY, int maxdist)
  422. {
  423. double distance = sqrt(double((deltaX * deltaX) + (deltaY * deltaY)));
  424. double degrees = -((atan2(deltaX,deltaY) * DEGREE_CONVERTER) - double(180.0));
  425. BOOL fDeadZone = FALSE;
  426. if (distance < double(4))
  427. {
  428. fDeadZone = TRUE;
  429. }
  430. if (distance <= maxdist)
  431. {
  432. SetCursor(LoadCursor(m_hInst, MAKEINTRESOURCE(IDC_VOLHAND)));
  433. }
  434. else
  435. {
  436. int volcur;
  437. if ((degrees < double( 22.5) || degrees > double(337.5)) ||
  438. (degrees > double(157.5) && degrees < double(202.5)))
  439. {
  440. volcur = IDC_VOLHORZ;
  441. }
  442. else if ((degrees > double( 22.5) && degrees < double( 67.5)) ||
  443. (degrees > double(202.5) && degrees < double(247.5)))
  444. {
  445. volcur = IDC_VOLDNEG;
  446. }
  447. else if ((degrees > double( 67.5) && degrees < double(112.5)) ||
  448. (degrees > double(247.5) && degrees < double(292.5)))
  449. {
  450. volcur = IDC_VOLVERT;
  451. }
  452. else
  453. {
  454. volcur = IDC_VOLDPOS;
  455. }
  456. SetCursor(LoadCursor(m_hInst, MAKEINTRESOURCE(volcur)));
  457. }
  458. return fDeadZone;
  459. }
  460. void CKnob::OnMouseMove(int x, int y)
  461. {
  462. if (GetCapture()==m_hwnd)
  463. {
  464. //do the calculations as if 0,0 were the center of the control,
  465. //then translate to gdi coordinates later (0,0 = top left of control in gdi)
  466. RECT rect;
  467. GetClientRect(m_hwnd,&rect);
  468. int nWidth = rect.right - rect.left;
  469. int nHeight = rect.bottom - rect.top;
  470. int maxdist = (nWidth / 2) + 3;
  471. int radius = (nWidth / 2) - LIGHT_OFFSET;
  472. //convert to short to force negative numbers for coordinates
  473. short sx = (short)x;
  474. short sy = (short)y;
  475. int deltaX = sx - (nWidth / 2);
  476. int deltaY = sy - (nHeight / 2);
  477. BOOL fDeadZone = ComputeCursor(deltaX, deltaY, maxdist);
  478. if (!fDeadZone)
  479. {
  480. double angle = atan2(deltaY,deltaX);
  481. double degrees = angle * DEGREE_CONVERTER;
  482. degrees = degrees + 225;
  483. if (degrees < 0) degrees = 0;
  484. if (degrees >= 360)
  485. {
  486. degrees = degrees - 360;
  487. }
  488. if (degrees > 270)
  489. {
  490. return; //block this case
  491. }
  492. double percentage = degrees / 270;
  493. m_dwPosition = (DWORD)(m_dwRange * percentage);
  494. if (m_fFastKnob)
  495. {
  496. m_uTrackTimerID = SetTimer(m_hwnd,(UINT_PTR)this,FAST_TRACK_TICK,(TIMERPROC)CKnob::TrackProc);
  497. }
  498. else
  499. {
  500. m_uTrackTimerID = SetTimer(m_hwnd,(UINT_PTR)this,TRACK_TICK,(TIMERPROC)CKnob::TrackProc);
  501. }
  502. }
  503. }
  504. }
  505. void CKnob::SetPosition(DWORD dwPosition, BOOL fNotify)
  506. {
  507. if (GetCapture()==m_hwnd)
  508. {
  509. //we're in a feedback loop, return immediately
  510. return;
  511. }
  512. m_dwPosition = dwPosition;
  513. m_dwCurPosition = dwPosition;
  514. RECT rect;
  515. GetClientRect(m_hwnd,&rect);
  516. int nWidth = rect.right - rect.left;
  517. int radius = (nWidth / 2) - LIGHT_OFFSET;
  518. double degree = ((double)m_dwPosition / m_dwRange) * 270;
  519. degree = degree + 135;
  520. m_trackdegree = degree; //instantly track when position is set programmatically
  521. double angle = degree * RADIAN_CONVERTER;
  522. double fLightX = radius * cos(angle);
  523. double fLightY = radius * sin(angle);
  524. //convert to proper gdi coordinates
  525. m_nLightX = ((int)fLightX) - (m_nLightWidth / 2) + (nWidth / 2);
  526. m_nLightY = ((int)fLightY) - (m_nLightHeight / 2) + (nWidth / 2);
  527. InvalidateRect(m_hwnd,NULL,FALSE);
  528. UpdateWindow(m_hwnd);
  529. if (fNotify)
  530. {
  531. NMHDR nmhdr;
  532. nmhdr.hwndFrom = m_hwnd;
  533. nmhdr.idFrom = m_nID;
  534. nmhdr.code = FALSE;
  535. SendMessage(GetParent(m_hwnd),WM_NOTIFY,(WPARAM)m_nID,(LPARAM)&nmhdr);
  536. }
  537. }
  538. //kmaskblt -- cuz MaskBlt doesn't work on all platforms. This is all it does anyway.
  539. // uses same params as MaskBlt, ignoring the flags part as dwDummy
  540. void CKnob::KMaskBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSource, int xs, int ys, HBITMAP hMask, int xm, int ym, DWORD dwDummy)
  541. {
  542. HDC hdcMask = CreateCompatibleDC(hdcDest);
  543. HBITMAP holdbmp = (HBITMAP)SelectObject(hdcMask,hMask);
  544. BitBlt(hdcDest, x, y, width, height, hdcSource, xs, ys, SRCINVERT);
  545. BitBlt(hdcDest, x, y, width, height, hdcMask, xm, ym, SRCAND);
  546. BitBlt(hdcDest, x, y, width, height, hdcSource, xs, ys, SRCINVERT);
  547. SelectObject(hdcMask,holdbmp);
  548. DeleteDC(hdcMask);
  549. }
  550. void CKnob::Draw(HDC hdc)
  551. {
  552. RECT rect;
  553. GetClientRect(m_hwnd,&rect);
  554. int nWidth = rect.right - rect.left;
  555. int nHeight = rect.bottom - rect.top;
  556. HPALETTE hpalOld = SelectPalette(hdc,hpalMain,FALSE);
  557. RealizePalette(hdc);
  558. HDC memDC = CreateCompatibleDC(hdc);
  559. HPALETTE hpalmemOld = SelectPalette(memDC,hpalMain,FALSE);
  560. RealizePalette(memDC);
  561. HBITMAP hbmp = CreateCompatibleBitmap(hdc,nWidth,nHeight);
  562. HBITMAP hbmpOld = (HBITMAP)SelectObject(memDC,hbmp);
  563. HDC maskmemDC = CreateCompatibleDC(hdc);
  564. HBITMAP hmaskbmp = CreateCompatibleBitmap(hdc,nWidth,nHeight);
  565. HBITMAP hmaskbmpOld = (HBITMAP)SelectObject(maskmemDC,hmaskbmp);
  566. if (GetFocus()==m_hwnd)
  567. {
  568. DibBlt(memDC, 0, 0, -1, -1, m_hbmpKnobTab, 0, 0, SRCCOPY, 0);
  569. }
  570. else
  571. {
  572. DibBlt(memDC, 0, 0, -1, -1, m_hbmpKnob, 0, 0, SRCCOPY, 0);
  573. }
  574. DibBlt(maskmemDC, 0, 0, -1, -1, m_fDim ? m_hbmpLight : m_hbmpLightBright, 0, 0, SRCCOPY, 0);
  575. KMaskBlt(memDC,
  576. m_nLightX,
  577. m_nLightY,
  578. m_nLightWidth,
  579. m_nLightHeight,
  580. maskmemDC,
  581. 0,
  582. 0,
  583. (HBITMAP)m_hbmpLightMask,
  584. 0,
  585. 0,
  586. MAKEROP4(SRCAND,SRCCOPY));
  587. BitBlt(hdc,0,0,nWidth,nHeight,memDC,0,0,SRCCOPY);
  588. SelectObject(memDC,hbmpOld);
  589. SelectPalette(memDC,hpalmemOld,TRUE);
  590. RealizePalette(memDC);
  591. DeleteObject(hbmp);
  592. DeleteDC(memDC);
  593. SelectObject(maskmemDC, hmaskbmpOld);
  594. DeleteObject(hmaskbmp);
  595. DeleteDC(maskmemDC);
  596. SelectPalette(hdc,hpalOld,TRUE);
  597. RealizePalette(hdc);
  598. }