home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / ROTARY / ROTARY.C_ / ROTARY.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  16.7 KB  |  648 lines

  1. /*
  2.     Rotary.c
  3.  
  4.     This is sample app to show how to implement
  5.     non-rectangular controls.
  6.     
  7.     12-Aug-91   Created by NigelT
  8.     
  9. */
  10.  
  11. #include <windows.h>
  12. #include <math.h>
  13. #include "Rotary.h"
  14.  
  15. #define IDC_CONTROL 1           // child id
  16.  
  17. // ROP codes
  18.  
  19. #define DSa     0x008800C6L
  20. #define DSx     0x00660046L
  21.  
  22. // colors
  23.  
  24. #define rgbBlack RGB(0,0,0)
  25. #define rgbWhite RGB(255,255,255)
  26.  
  27. /* usefull global things */
  28.  
  29. HANDLE hInst;                   /* global instance handle */
  30. char *szAppName = "Rotary";
  31. HWND hMainWnd;                  /* handle of main window */
  32.  
  33. HWND hwndControl;
  34. BOOL bCaptured;
  35. WORD wControl = (MIN_UNITS + MAX_UNITS) / 2;
  36.  
  37.  
  38. // local functions
  39.  
  40. WORD CalcPos(WORD wMin, WORD wMax, int iXcenter, int iYcenter, int iXmouse, int iYmouse);
  41. void CalcPoint(WORD wMin, WORD wMax, WORD wPos, int iXcenter, int iYcenter, int iRad, LPPOINT lpPt); 
  42. void DrawStaticControl(HWND hWnd);
  43. long FAR PASCAL __export RotaryWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  44. long FAR PASCAL __export MainWndProc(HWND, UINT , WPARAM ,LPARAM);
  45. BOOL InitFirstInstance(HANDLE);
  46. HBITMAP GrabBackground(HWND hWnd);
  47. BOOL TransBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,int x0,int y0);
  48.  
  49.  
  50. /***************** Main entry point routine *************************/
  51.  
  52. int PASCAL WinMain(hInstance,hPrevInstance,lpszCmdLine,cmdShow)
  53. HANDLE hInstance,hPrevInstance;
  54. LPSTR lpszCmdLine;
  55. int cmdShow;
  56. {
  57.     MSG msg;
  58.  
  59.     hInst = hInstance;          /* save our instance handle */
  60.  
  61.     if (!hPrevInstance) {
  62.         if (! InitFirstInstance(hInstance)) {
  63.             return 1;
  64.         }
  65.     }
  66.  
  67.     /* create a window for the application */
  68.  
  69.     hMainWnd = CreateWindow(szAppName,          /* class name */
  70.                         szAppName,              /* caption text */
  71.                         WS_OVERLAPPEDWINDOW,    /* window style */
  72.                         CW_USEDEFAULT, 0,
  73.                         200, 250,
  74.                         (HWND)NULL,             /* handle of parent window */
  75.                         (HMENU)NULL,            /* menu handle (default class) */
  76.                         hInstance,              /* handle to window instance */
  77.                         (LPSTR)NULL             /* no params to pass on */
  78.                         );
  79.     
  80.     if (!hMainWnd) {
  81.         return 1;
  82.     }
  83.  
  84.     ShowWindow(hMainWnd, cmdShow); /* display window as open or icon */
  85.     UpdateWindow(hMainWnd);     /* paint it */
  86.     
  87.     // initialize the rotary control windows
  88.  
  89.     // show the window so it can grab the background
  90.  
  91.     ShowWindow(hwndControl, SW_NORMAL);
  92.  
  93.     // set the text, min and max values
  94.  
  95.     rcSetUnits(hwndControl, "Units");
  96.     rcSetMin(hwndControl, MIN_UNITS);
  97.     rcSetMax(hwndControl, MAX_UNITS);
  98.  
  99.     // set the current positions                      
  100.  
  101.     rcSetPos(hwndControl, wControl);
  102.  
  103.     /* Process messages for us */
  104.  
  105.     while (GetMessage(&msg, NULL, 0, 0)) {
  106.         TranslateMessage(&msg);
  107.         DispatchMessage(&msg);
  108.     }
  109.  
  110.     return (msg.wParam);
  111. }
  112.     
  113. /************* main window message handler ******************************/
  114.  
  115. long FAR PASCAL __export MainWndProc(hWnd, message, wParam, lParam)
  116. HWND hWnd;
  117. UINT message;
  118. WPARAM wParam;
  119. LPARAM lParam;
  120. {
  121.     PAINTSTRUCT ps;             /* paint structure */
  122.     
  123.     /* process any messages we want */
  124.  
  125.     switch(message) {
  126.     case WM_CREATE:
  127.     hwndControl = CreateWindow("rotary_control",
  128.                               "Control",
  129.                               WS_CHILD,
  130.                               20, 20,
  131.                               ROTARY_WIDTH, ROTARY_HEIGHT,
  132.                               hWnd,
  133.                               IDC_CONTROL,
  134.                               hInst,
  135.                               (LPSTR)NULL);
  136.         break;
  137.  
  138.     case WM_SIZE:
  139.         break;
  140.  
  141.     case WM_PAINT:
  142.         BeginPaint(hWnd, &ps);
  143.         EndPaint(hWnd, &ps);
  144.         break;
  145.  
  146.     case WM_DESTROY:
  147.         PostQuitMessage(0);
  148.         break;
  149.  
  150.     default:
  151.         return DefWindowProc(hWnd, message, wParam, lParam);
  152.         break;
  153.     }
  154.     return NULL;
  155. }
  156.  
  157. BOOL InitFirstInstance(hInstance)
  158. HANDLE hInstance;
  159. {
  160.     WNDCLASS wc;
  161.     
  162.     /* define the class of window we want to register */
  163.  
  164.     wc.lpszClassName    = szAppName;
  165.     wc.style            = CS_HREDRAW | CS_VREDRAW;
  166.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  167.     wc.hIcon            = LoadIcon(hInstance,"Icon");
  168.     wc.lpszMenuName     = NULL;
  169.     wc.hbrBackground    = (HBRUSH) (COLOR_APPWORKSPACE+1);
  170.     wc.hInstance        = hInstance;
  171.     wc.lpfnWndProc      = MainWndProc;
  172.     wc.cbClsExtra       = 0;
  173.     wc.cbWndExtra       = 0;
  174.     
  175.     if (! RegisterClass(&wc)) {
  176.         return FALSE; /* Initialisation failed */
  177.     }
  178.  
  179.     // register a class for the rotary controls
  180.  
  181.     wc.lpszClassName    = "rotary_control";
  182.     wc.style            = 0;
  183.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  184.     wc.hIcon            = NULL;
  185.     wc.lpszMenuName     = NULL;
  186.     wc.hbrBackground    = NULL;
  187.     wc.hInstance        = hInstance;
  188.     wc.lpfnWndProc      = RotaryWndProc;
  189.     wc.cbClsExtra       = 0;
  190.     wc.cbWndExtra       = sizeof(NPRINFO);
  191.     
  192.     if (! RegisterClass(&wc)) {
  193.         return FALSE; /* Initialisation failed */
  194.     }
  195.     
  196.     return TRUE;
  197. }
  198.  
  199. WORD CalcPos(WORD wMin, WORD wMax, int iXcenter, int iYcenter, int iXmouse, int iYmouse) 
  200. {
  201.     int dx, dy;
  202.     WORD wPos;
  203.     double a, min, max;
  204.  
  205.     // compute the x and y offsets
  206.     dx = iXmouse - iXcenter;
  207.     dy = iYmouse - iYcenter;
  208.  
  209.     // check for stupid case
  210.     if ((dx == 0) && (dy == 0)) {
  211.         dx = 1;
  212.         dy = 1; // force a position that works
  213.     }
  214.  
  215.     // get the angle in degrees
  216.     a = (57.3 * atan2((double)dy, (double)dx));        
  217.     if ((a > 45.0) && (a <= 90.)) {
  218.         a = 45.0;
  219.     } else if ((a > 90.0) && (a < 135.0)) {
  220.         a = 135.0;
  221.     }
  222.  
  223.     a -= 135.0;
  224.     if (a < 0.0) a += 360.0;
  225.  
  226.     // compute the control value
  227.     min = (double) wMin;
  228.     max = (double) wMax;
  229.     wPos = (WORD) (min + ((max - min) * a / 270.0));
  230.  
  231.     return wPos;
  232.  
  233. }
  234.  
  235. void CalcPoint(WORD wMin, WORD wMax, WORD wPos, int iXcenter, int iYcenter, int iRad, LPPOINT lpPt)  
  236. {
  237.     double a;  
  238.  
  239.     a = 2.36 + 4.71 * (double)(wPos - wMin) / (double)(wMax - wMin);
  240.  
  241.     lpPt->x = iXcenter + (int) ((double)iRad * cos(a));
  242.     lpPt->y = iYcenter + (int) ((double)iRad * sin(a));
  243.  
  244. }
  245.  
  246. void DrawControl(HWND hWnd)
  247. {
  248.     HBITMAP hbmOld, hbmOff, hbmOldOff;
  249.     HDC hDC, hdcMem, hdcOff;
  250.     RECT rcClient;
  251.     char text[40];
  252.     HPEN hpenOld, hpenDot;
  253.     HBRUSH hbrOld, hbrDot;
  254.     POINT pt;
  255.     NPRINFO npInfo;
  256.  
  257.     npInfo = (NPRINFO) GetWindowWord(hWnd, 0);
  258.     if (!npInfo->hbmBkGnd) {
  259.         return;
  260.     }
  261.  
  262.     hDC = GetDC(hWnd);
  263.     GetClientRect(hWnd, &rcClient);
  264.  
  265.     // create an off screen dc and a bitmap big enough
  266.  
  267.     hdcOff = CreateCompatibleDC(hDC);
  268.     hbmOff = CreateCompatibleBitmap(hDC, 
  269.                                     rcClient.right-rcClient.left,
  270.                                     rcClient.bottom-rcClient.top);
  271.     hbmOldOff = SelectObject(hdcOff, hbmOff);
  272.  
  273.     // blit the background image to the offscreen dc
  274.  
  275.     hdcMem = CreateCompatibleDC(hDC);
  276.     hbmOld = SelectObject(hdcMem, npInfo->hbmBkGnd);
  277.  
  278.     BitBlt(hdcOff,
  279.            rcClient.left,
  280.            rcClient.top,
  281.            rcClient.right-rcClient.left,
  282.            rcClient.bottom-rcClient.top,
  283.            hdcMem,
  284.            0, 0, 
  285.            SRCCOPY);
  286.  
  287.     SelectObject(hdcMem, hbmOld);
  288.     DeleteDC(hdcMem);
  289.  
  290.     // Draw the control value at the bottom
  291.  
  292.     wsprintf(text, "%d %s", npInfo->wPos, (LPSTR)npInfo->szUnits);
  293.     SetBkMode(hdcOff, TRANSPARENT);
  294.     SetTextColor(hdcOff, BLUE);
  295.     DrawText(hdcOff, text, -1, &rcClient, DT_SINGLELINE | DT_BOTTOM | DT_CENTER);
  296.  
  297.     // compute the angle of the dot
  298.  
  299.     CalcPoint(  npInfo->wMin, 
  300.                 npInfo->wMax, 
  301.                 npInfo->wPos,
  302.                 (rcClient.left + rcClient.right) / 2,
  303.                 (rcClient.top + rcClient.bottom) / 2,
  304.                 20, 
  305.                 &pt);
  306.  
  307.     hpenDot = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
  308.     hbrDot = CreateSolidBrush(RGB(255, 0, 0));
  309.     hpenOld = SelectObject(hdcOff, hpenDot);
  310.     hbrOld = SelectObject(hdcOff, hbrDot);
  311.     Ellipse(hdcOff, pt.x - 2, pt.y - 2, pt.x + 2, pt.y + 2);
  312.     SelectObject(hdcOff, hpenOld);
  313.     SelectObject(hdcOff, hbrOld);
  314.     DeleteObject(hpenDot);
  315.     DeleteObject(hbrDot);
  316.  
  317.     // blit the offscreen dc stuff to the screen dc
  318.  
  319.     BitBlt(hDC,
  320.            rcClient.left,
  321.            rcClient.top,
  322.            rcClient.right-rcClient.left,
  323.            rcClient.bottom-rcClient.top,
  324.            hdcOff,
  325.            0, 0, 
  326.            SRCCOPY);
  327.  
  328.     // tidy up the off screen stuff
  329.  
  330.     SelectObject(hdcOff, hbmOldOff);
  331.     DeleteObject(hbmOff);
  332.     DeleteDC(hdcOff);
  333.  
  334.     ReleaseDC(hWnd, hDC);
  335. }
  336.  
  337.  
  338. long FAR PASCAL __export RotaryWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  339. {
  340.     PAINTSTRUCT ps;
  341.     RECT rcWnd;
  342.     WORD w, xc, yc;
  343.     NPRINFO npInfo;
  344.  
  345.     npInfo = (NPRINFO) GetWindowWord(hWnd, 0);
  346.  
  347.     switch(message) {
  348.     case WM_CREATE:
  349.         npInfo = (NPRINFO) LocalAlloc(LPTR, sizeof(RINFO));
  350.         if (npInfo) {
  351.             SetWindowWord(hWnd, 0, (WORD) npInfo);
  352.             npInfo->wMin = 0;
  353.             npInfo->wMax = 255;
  354.             npInfo->wPos = 128;
  355.             lstrcpy(npInfo->szUnits, "");
  356.         }
  357.         break;
  358.  
  359.     case WM_COMMAND:
  360.         break;
  361.  
  362.     case WM_LBUTTONDOWN:
  363.         if (!bCaptured) {
  364.             SetCapture(hWnd);
  365.             bCaptured = TRUE;
  366.         }
  367.         // fall through
  368.  
  369.     case WM_MOUSEMOVE:
  370.         if (bCaptured) {
  371.             // get the coords of the center of the control
  372.             GetClientRect(hWnd, &rcWnd);
  373.             xc = (rcWnd.left + rcWnd.right) / 2;
  374.             yc = (rcWnd.top + rcWnd.bottom) / 2;
  375.             w = CalcPos(npInfo->wMin,
  376.                         npInfo->wMax,
  377.                         xc,
  378.                         yc,
  379.                         LOWORD(lParam),
  380.                         HIWORD(lParam));
  381.             npInfo->wPos = w;
  382.             DrawControl(hWnd);
  383.             SendMessage(GetParent(hWnd),
  384.                         RCN_DRAG,
  385.                         GetWindowWord(hWnd, GWW_ID),
  386.                         MAKELONG(hWnd, w));
  387.         }
  388.         break;
  389.  
  390.     case WM_LBUTTONUP:
  391.         if (bCaptured) {
  392.             ReleaseCapture();
  393.             bCaptured = FALSE;
  394.             SendMessage(GetParent(hWnd),
  395.                         RCN_RELEASE,
  396.                         GetWindowWord(hWnd, GWW_ID),
  397.                         MAKELONG(hWnd, npInfo->wPos));
  398.         }
  399.         break;
  400.  
  401.     case RC_SETMIN:
  402.         npInfo->wMin = wParam;
  403.         w = npInfo->wPos;           
  404.         if (w < wParam) {
  405.             npInfo->wPos = wParam;
  406.         }
  407. //      DrawControl(hWnd);
  408.         break;
  409.  
  410.     case RC_SETMAX:
  411.         npInfo->wMax = wParam;
  412.         w = npInfo->wPos;           
  413.         if (w > wParam) {
  414.             npInfo->wPos = wParam;
  415.         }
  416. //      DrawControl(hWnd);
  417.         break;
  418.  
  419.     case RC_SETPOS:
  420.         npInfo->wPos = wParam;
  421.         DrawControl(hWnd);
  422.         break;
  423.  
  424.     case RC_GETPOS:
  425.         return MAKELONG(npInfo->wPos, 0);
  426.         break;
  427.  
  428.     case RC_SETUNITS:
  429.         lstrcpy(npInfo->szUnits, (LPSTR)lParam);
  430.         break;
  431.  
  432.     case WM_PAINT:
  433.         BeginPaint(hWnd, &ps);
  434.         DrawControl(hWnd);
  435.         EndPaint(hWnd, &ps);
  436.         break;
  437.  
  438.     case WM_SHOWWINDOW:
  439.         // a good time to grab the background
  440.         if (!npInfo->hbmBkGnd) {
  441.             npInfo->hbmBkGnd = GrabBackground(hWnd);
  442.             DrawStaticControl(hWnd);
  443.         }
  444.         break;
  445.  
  446.     case WM_ERASEBKGND:
  447.         return TRUE; // say we erased it
  448.         break;
  449.  
  450.     case WM_DESTROY:
  451.         if (npInfo->hbmBkGnd) DeleteObject(npInfo->hbmBkGnd);
  452.         LocalFree((HANDLE) npInfo);
  453.         break;
  454.  
  455.     default:
  456.         return DefWindowProc(hWnd, message, wParam, lParam);
  457.         break;
  458.     }
  459.     return NULL;
  460. }
  461.  
  462.  
  463. //
  464. // Draw the bits of the control which don't vary on top of the
  465. // background bitmap
  466. //
  467.  
  468. void DrawStaticControl(HWND hWnd)
  469. {
  470.     NPRINFO npInfo;
  471.     HDC hdcOffScr, hdcControl, hDC;
  472.     HBITMAP hbmOldBkGnd, hbmOldControl, hbmControl;
  473.     BITMAP bm;
  474.     RECT rcClient;
  475.     int x, y;
  476.     char text[40];
  477.  
  478.     npInfo = (NPRINFO) GetWindowWord(hWnd, 0);
  479.     hDC = GetDC(hWnd);
  480.     hdcOffScr = CreateCompatibleDC(hDC);
  481.  
  482.     // select the raw background bmp into the dc
  483.     hbmOldBkGnd = SelectObject(hdcOffScr, npInfo->hbmBkGnd);
  484.  
  485.     // draw the control and title on top of it
  486.  
  487.     // load the bitmap we need
  488.     hbmControl = LoadBitmap(hInst, MAKEINTRESOURCE(IDR_CONTROL));
  489.     if (!hbmControl) {
  490.         return;
  491.     }
  492.  
  493.     // get the size of the bitmap so we can center it
  494.     GetObject(hbmControl, sizeof(bm), (LPSTR)&bm);
  495.  
  496.     // get the window size
  497.     GetClientRect(hWnd, &rcClient);
  498.  
  499.     x = (rcClient.right - rcClient.left - bm.bmWidth) / 2 + rcClient.left;
  500.     y = (rcClient.bottom - rcClient.top - bm.bmHeight) / 2 + rcClient.top;
  501.  
  502.     // draw the control
  503.     hdcControl = CreateCompatibleDC(hdcOffScr);
  504.     hbmOldControl = SelectObject(hdcControl, hbmControl);
  505.  
  506.     SetBkColor(hdcOffScr, RGB(0,0,255)); // transparency color is BLUE
  507.     TransBlt(hdcOffScr, 
  508.            x,
  509.            y,
  510.            bm.bmWidth,
  511.            bm.bmHeight,
  512.            hdcControl,
  513.            0, 0);
  514.  
  515.     SelectObject(hdcControl, hbmOldControl);
  516.  
  517.     DeleteDC(hdcControl);
  518.     DeleteObject(hbmControl);
  519.  
  520.     // Now put the caption at the top
  521.  
  522.     GetWindowText(hWnd, text, sizeof(text));
  523.     SetBkMode(hdcOffScr, TRANSPARENT);
  524.     SetTextColor(hdcOffScr, BLUE);
  525.     DrawText(hdcOffScr, text, -1, &rcClient, DT_TOP | DT_CENTER);
  526.  
  527.     SelectObject(hdcOffScr, hbmOldBkGnd);
  528.     DeleteDC(hdcOffScr);
  529.     ReleaseDC(hWnd, hDC);
  530. }
  531.  
  532. /**************************************************************************
  533.  
  534.     grab the background to a window
  535.  
  536. **************************************************************************/
  537.  
  538. HBITMAP GrabBackground(HWND hWnd)
  539. {
  540.     HDC hdcParent, hdcOffScr;
  541.     HBITMAP hbmOld, hbm;
  542.     RECT rc;
  543.     POINT pt;
  544.  
  545.     GetClientRect(hWnd, &rc);
  546.     hdcParent = GetDC(GetParent(hWnd));
  547.     hdcOffScr = CreateCompatibleDC(hdcParent);
  548.     hbm = CreateCompatibleBitmap(hdcParent,
  549.                                  rc.right - rc.left,
  550.                                  rc.bottom - rc.top);
  551.     hbmOld = SelectObject(hdcOffScr, hbm);
  552.  
  553.     // grab a chunk of the main window dc
  554.  
  555.     pt.x = rc.left;
  556.     pt.y = rc.top;
  557.     ClientToScreen(hWnd, &pt);
  558.     ScreenToClient(GetParent(hWnd), &pt);
  559.  
  560.     BitBlt(hdcOffScr,
  561.            0, 0,
  562.            rc.right-rc.left, rc.bottom-rc.top,
  563.            hdcParent,
  564.            pt.x, pt.y,
  565.            SRCCOPY);
  566.  
  567.     SelectObject(hdcOffScr, hbmOld);
  568.     DeleteDC(hdcOffScr);
  569.     ReleaseDC(GetParent(hWnd), hdcParent);
  570.  
  571.     return hbm;
  572. }
  573.  
  574. /*
  575.  *
  576.  * TransBlt() Transparent bitblt that uses the current
  577.  *            background color of the DC as the transparent color.
  578.  *
  579.  */
  580. BOOL TransBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,int x0,int y0)
  581. {
  582.     DWORD       rgbBk,rgbFg;
  583.     DWORD       rgbBkS;
  584.     HBITMAP         hbmMask;
  585.     HDC         hdcMask;
  586.     HBITMAP         hbmT;
  587.     BOOL        f = FALSE;
  588.  
  589.     //
  590.     //  Get the current DC color's
  591.     //
  592.     rgbBk = GetBkColor(hdcD);
  593.     rgbFg = GetTextColor(hdcD);
  594.     rgbBkS= GetBkColor(hdcS);
  595.  
  596.     SetTextColor(hdcD,rgbBlack);
  597.  
  598.     //
  599.     //  make a memory DC for use in color conversion
  600.     //
  601.     hdcMask = CreateCompatibleDC(hdcS);
  602.  
  603.     if (!hdcMask)
  604.         return FALSE;
  605.  
  606.     //
  607.     // create a mask bitmap and associated DC
  608.     //
  609.     hbmMask = CreateBitmap(dx, dy, 1, 1, NULL);
  610.  
  611.     if (!hbmMask)
  612.         goto errorDC;
  613.  
  614.     // select the mask bitmap into the mono DC
  615.  
  616.     hbmT = SelectObject(hdcMask, hbmMask);
  617.  
  618.     // do a color to mono bitblt to build the mask
  619.     // generate 1's where the source is equal to the background, else 0's
  620.  
  621.     SetBkColor(hdcS, rgbBk);
  622.     BitBlt(hdcMask, 0, 0, dx, dy, hdcS, x0, y0, SRCCOPY);
  623.  
  624.     // do a MaskBlt to copy the bitmap to the dest
  625.  
  626.     SetBkColor(hdcD,rgbWhite);
  627.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  628.     BitBlt(hdcD,x,y,dx,dy,hdcMask,0 ,0 ,DSa);
  629.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  630.  
  631.     f = TRUE;
  632.  
  633.     SelectObject(hdcMask, hbmT);
  634.     DeleteObject(hbmMask);
  635.  
  636.     //
  637.     // Restore the DC colors
  638.     //
  639.     SetBkColor(hdcS,rgbBkS);
  640.     SetBkColor(hdcD,rgbBk);
  641.     SetTextColor(hdcD,rgbFg);
  642.  
  643. errorDC:
  644.     DeleteDC(hdcMask);
  645.  
  646.     return f;
  647. }
  648.