/*~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= ** ** FILE: POV.CPP ** DATE: 3/31/97 ** PROJ: ATLAS ** PROG: JKH ** COMMENTS: ** ** DESCRIPTION: Window class for a 360 degree Point Of View control ** ** ** ** NOTE: There are some issues with using extern "C" in this file. ** If you don't understand why they are there, you're not ** alone. For now, and probably for a while they will be ** here though, because I can't get this file and others ** that use these services to compile without them. ** Unfortunately the dynamics of this project don't really ** afford me the time at present to figure this out. ** TODO: figure this out ** ** HISTORY: ** DATE WHO WHAT ** ---- --- ---- ** 3/31/97 a-kirkh Wrote it. ** ** ** ** ** Copyright (C) Microsoft 1997. All Rights Reserved. ** **~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=*/ #include "cplsvr1.h" // for ghInst #include "dicputil.h" // for MAX_POVS #include "POV.H" //This module's stuff. #include // for _alloca #include "resrc1.h" //static HWND hPOVWnd = NULL; #define NUM_ARROW_POINTS 8 //static VERTICEINFO *paptVInfo; static const VERTICEINFO VInfo[] = {XARROWPOINT, YARROWPOINT, XARROWRIGHTOUT, YARROWRIGHTOUT, XARROWRIGHTIN, YARROWRIGHTIN, XARROWRIGHTBOTTOM, YARROWRIGHTBOTTOM, XARROWLEFTBOTTOM, YARROWLEFTBOTTOM, XARROWLEFTIN, YARROWLEFTIN, XARROWLEFTOUT, YARROWLEFTOUT, XARROWPOINT, YARROWPOINT}; static LPRECT prcOldRegionBox[MAX_POVS]; static LPRECT prcNewRegionBox[MAX_POVS]; #define DEF_POV_POS -1 static double degrees[MAX_POVS] = {DEF_POV_POS, DEF_POV_POS, DEF_POV_POS, DEF_POV_POS}; static BYTE nPOV = MAX_POVS; static HBRUSH hBrush[MAX_POVS]; static HRGN hRegion[MAX_POVS]; extern HINSTANCE ghInst; void SetDegrees(BYTE nPov, short *nDegrees, HWND hPOVWnd) { nPOV = nPov -= 1; LPPOINT paptPoints = (LPPOINT)_alloca(sizeof(POINT[NUM_ARROW_POINTS])); assert (paptPoints); // Create the proper brush for the axis! do { degrees[nPov] = (double)nDegrees[nPov] / DI_DEGREES; // if angle == 180, degrees comes in as 18000 paptPoints[0].x = GETXCOORD(VInfo[0].y, VInfo[0].x, degrees[nPov]); paptPoints[0].y = GETYCOORD(VInfo[0].y, VInfo[0].x, degrees[nPov]); paptPoints[1].x = GETXCOORD(VInfo[1].y, VInfo[1].x, degrees[nPov]); paptPoints[1].y = GETYCOORD(VInfo[1].y, VInfo[1].x, degrees[nPov]); paptPoints[2].x = GETXCOORD(VInfo[2].y, VInfo[2].x, degrees[nPov]); paptPoints[2].y = GETYCOORD(VInfo[2].y, VInfo[2].x, degrees[nPov]); paptPoints[3].x = GETXCOORD(VInfo[3].y, VInfo[3].x, degrees[nPov]); paptPoints[3].y = GETYCOORD(VInfo[3].y, VInfo[3].x, degrees[nPov]); paptPoints[4].x = GETXCOORD(VInfo[4].y, VInfo[4].x, degrees[nPov]); paptPoints[4].y = GETYCOORD(VInfo[4].y, VInfo[4].x, degrees[nPov]); paptPoints[5].x = GETXCOORD(VInfo[5].y, VInfo[5].x, degrees[nPov]); paptPoints[5].y = GETYCOORD(VInfo[5].y, VInfo[5].x, degrees[nPov]); paptPoints[6].x = GETXCOORD(VInfo[6].y, VInfo[6].x, degrees[nPov]); paptPoints[6].y = GETYCOORD(VInfo[6].y, VInfo[6].x, degrees[nPov]); paptPoints[7].x = GETXCOORD(VInfo[7].y, VInfo[7].x, degrees[nPov]); paptPoints[7].y = GETYCOORD(VInfo[7].y, VInfo[7].x, degrees[nPov]); if(hRegion[nPov]) { DeleteObject(hRegion[nPov]); hRegion[nPov]=NULL; } hRegion[nPov] = CreatePolygonRgn(paptPoints, NUM_ARROW_POINTS, WINDING); //hBrush[nPov] = CreateSolidBrush((nPov < 1) ? POV1_COLOUR : // (nPov < 2) ? POV2_COLOUR : // (nPov < 3) ? POV3_COLOUR : POV4_COLOUR); */ //if (hRegion[nPov] && hBrush[nPov]) //{ // GetRgnBox(hRegion[nPov], prcNewRegionBox[nPov]); // // //RedrawWindow(hPOVWnd, NULL, NULL, RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_ERASE); // InvalidateRect(hPOVWnd, prcOldRegionBox[nPov], TRUE); // InvalidateRect(hPOVWnd, prcNewRegionBox[nPov], TRUE); //} RECT R; GetClientRect(hPOVWnd,&R); POINT Pnt[2]; Pnt[0].x=R.left; Pnt[0].y=R.top; Pnt[1].x=R.right; Pnt[1].y=R.bottom; MapWindowPoints(hPOVWnd,GetParent(hPOVWnd),Pnt,2); R.left=Pnt[0].x; R.top=Pnt[0].y; R.right=Pnt[1].x; R.bottom=Pnt[1].y; InvalidateRect(GetParent(hPOVWnd), &R, TRUE); } while( nPov-- ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // FUNCTION : POVWndProc // REMARKS : The callback function for the POVHat Window. // // PARAMS : The usual callback funcs for message handling // // RETURNS : LRESULT - Depends on the message // CALLS : // NOTES : // WM_PAINT - Just calls DrawControl // // PM_MYJOYPOSCHANGED - This is a private (WM_USER) message that is // called whenever a change in the POV hat occurs. // LRESULT CALLBACK POVWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch( iMsg ) { // case WM_CREATE: // hPOVWnd = hWnd; // return FALSE; // case WM_DESTROY: // return FALSE; case WM_DESTROY: { BYTE nPov=nPOV; do { if(hRegion[nPov]) { DeleteObject(hRegion[nPov]); hRegion[nPov]=NULL; } }while(nPov--); } return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); // 1) Get client size information SetMapMode(hDC, MM_TEXT); RECT rClient; GetClientRect(hWnd, &rClient); BYTE nSizeX = (BYTE)rClient.right>>1; BYTE nSizeY = (BYTE)rClient.bottom>>1; // 2) Load the hub bitmap and display it //PREFIX #WI226648. False positive. There is no leak. DeleteObject frees. HBITMAP hPOVHubBitmap = (HBITMAP)LoadImage(ghInst, MAKEINTRESOURCE(IDB_POVHUB), IMAGE_BITMAP, 0, 0, NULL); assert(hPOVHubBitmap); DrawBitmap(hDC, hPOVHubBitmap, nSizeX-8, nSizeY-8); DeleteObject(hPOVHubBitmap); // 3) Setup the window to use symmetrical units on a 1000 X 1000 cartesian grid SetMapMode(hDC, MM_ISOTROPIC); SetWindowExtEx (hDC, 1000, 1000, NULL); SetViewportExtEx(hDC, nSizeX, -nSizeY, NULL); SetViewportOrgEx(hDC, nSizeX, nSizeY, NULL); // 4) Draw the circle upon which the arrow seems to rotate SelectObject(hDC, (HBRUSH)GetStockObject(NULL_BRUSH)); HPEN hPenOld = (HPEN)SelectObject(hDC, (HGDIOBJ)GetStockObject(DC_PEN)); SetDCPenColor( hDC, GetSysColor(COLOR_WINDOWTEXT) ); Ellipse(hDC, -CIRCLERADIUS, CIRCLERADIUS, CIRCLERADIUS, -CIRCLERADIUS); SelectObject(hDC, hPenOld); // 5) Paint the Arrow at the correct angle if POV active BYTE nPov = nPOV; HBRUSH hBrushOld; do { if( degrees[nPov] >= 0 ) { hBrush[nPov] = CreateSolidBrush((nPov < 1) ? POV1_COLOUR : (nPov < 2) ? POV2_COLOUR : (nPov < 3) ? POV3_COLOUR : POV4_COLOUR); hBrushOld = (HBRUSH)SelectObject(hDC, (HGDIOBJ)hBrush[nPov]); assert(hBrushOld); PaintRgn(hDC, hRegion[nPov]); // GetRgnBox returns zero if it fails... GetRgnBox(hRegion[nPov], prcOldRegionBox[nPov]); SelectObject(hDC, hBrushOld); if(hRegion[nPov]) { DeleteObject(hRegion[nPov]); hRegion[nPov]=NULL; } DeleteObject(hBrush[nPov] ); } } while( nPov-- ); EndPaint(hWnd, &ps); } //PREFIX #WI226648. False positive. See above. return(0); default: return(DefWindowProc(hWnd, iMsg,wParam, lParam)); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // FUNCTION : RegisterPOVClass // REMARKS : Registers the POV Hat window. // // PARAMS : hInstance - Used for the call to RegisterClassEx // // RETURNS : TRUE - if successfully registered // FALSE - failed to register // CALLS : RegisterClassEx // NOTES : // extern ATOM RegisterPOVClass() { LPWNDCLASSEX pPOVWndClass = (LPWNDCLASSEX)_alloca(sizeof(WNDCLASSEX)); assert (pPOVWndClass); ZeroMemory(pPOVWndClass, sizeof(WNDCLASSEX)); pPOVWndClass->cbSize = sizeof(WNDCLASSEX); pPOVWndClass->style = CS_HREDRAW; // | CS_VREDRAW; pPOVWndClass->lpfnWndProc = POVWndProc; pPOVWndClass->hInstance = ghInst; pPOVWndClass->hbrBackground = NULL; pPOVWndClass->lpszClassName = TEXT("POVHAT"); return(RegisterClassEx( pPOVWndClass )); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // FUNCTION : DrawBitmap // REMARKS : Copied verbatim from Petzold (WIN95 pg 190) // PARAMS : HDC - dc for drawing // HBITMAP - bitmap to draw // int xstart, ystart - where to place the bitmap // // RETURNS : void // CALLS : // NOTES : // void DrawBitmap(HDC hDC, HBITMAP hBitmap, BYTE xStart, BYTE yStart) { HDC hdcMem = CreateCompatibleDC(hDC); // Found by prefix: Millen Bug129155. manbugs 29339 // If CreateCompatibleDC fails, we should'nt proceed. if( hdcMem == NULL ) return; SelectObject(hdcMem, hBitmap); SetMapMode(hdcMem,GetMapMode(hDC)); // Be aware! This is the size of the current BITMAP... // IF IT CHANGES THIS WILL FAIL!!! POINT ptSize = {16, 16}; DPtoLP(hDC, &ptSize, 1); POINT ptOrg = {0,0}; DPtoLP(hdcMem, &ptOrg, 1); BitBlt(hDC, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y, SRCAND); DeleteDC(hdcMem); } //~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=EOF=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=