📄 hgraf_win32.c
字号:
/* ----------------------------------------------------------- *//* *//* ___ *//* |_| | |_/ SPEECH *//* | | | | \ RECOGNITION *//* ========= SOFTWARE */ /* *//* *//* ----------------------------------------------------------- *//* Copyright: Microsoft Corporation *//* 1995-2000 Redmond, Washington USA *//* http://www.microsoft.com *//* *//* Use of this software is governed by a License Agreement *//* ** See the file License for the Conditions of Use ** *//* ** This banner notice must not be removed ** *//* *//* ----------------------------------------------------------- *//* File: HGraf.win32.c: HGraf for Windows NT *//* ----------------------------------------------------------- *//* Win32 port Peter Silsbee */char *hgraf_version = "!HVER!HGraf(NT): 3.3 [CUED 28/04/05]";char *hgraf_vc_id = "$Id: HGraf_WIN32.c,v 1.1.1.1 2005/05/12 10:52:50 jal58 Exp $";/* define CAPTURE_ALT to allow application to respond to Alt-key presses. *//* "Normal" windows application behavior is to allow the system to handle it. */#define CAPTURE_ALT#include "HShell.h"#include "HMem.h"#include "HMath.h"#include "HGraf.h"#include <windows.h>#include <ctype.h>#include <stdio.h>#include <memory.h>#define DEF_FONTSIZE 12 /* default font size */#define MAX_POINT 64 /* max number of points for polygons */static MemHeap btnHeap; /* heap for HButton structures *//* -------------------- Global Windows variables: ------------------------*/static HWND theWindow = NULL; /* A handle to the graphics window */static HDC memDC = NULL; /* A handle to the memory device context */static HDC DCSaved; /* to store memDC when saving Metafile */static HBITMAP theBitmap; /* Internal representation of window contents *//* -------------------- Objects that draw ----------------------- */static HBRUSH theBrush = NULL; /* Used to fill solid areas */static HPEN thePen = NULL; /* Used to draw lines */static HPEN thinPen = NULL; /* Always has width 1, needed for outlining filled shapes */static HFONT theFont = NULL; /* Current font for text output *//* ------------ stuff that application keeps track of ------------*/static Boolean winCreated = FALSE; /* prevent duplicate windows */static Boolean WritingToMeta = FALSE; /* TRUE if spooling to a metafile */static unsigned char colours[MAX_COLOURS][3]; /* r,g,b */static unsigned char greys[MAX_GREYS];static int dispDEEP,dispWIDE,dispHIGH;static RECT ClientRect;static POINT winPoints[MAX_POINT];static int LineWidth = 1;static COLORREF CurrentColour = RGB(0,0,0);static POINT MousePos; /* updated when a WM_MOUSEMOVE occurs */ /* Win32 does not support direct querying of the mouse position */static char *FONTNAME = "Helvetica";#ifdef CAPTURE_ALTenum _AltState {ALT_UP,ALT_DOWN}; /* keep track of Alt key */typedef enum _AltState AltState;static AltState AltKeyState = ALT_UP;#endif#ifdef WIN32LRESULT CALLBACK HGWinFunc(HWND WindowHandle, unsigned int msg, WPARAM wParam, LPARAM lParam);/* Handle messages from Windows */KeyType HGetKeyType(char c);/* Utility routine to help decode key presses */#endif/* --------------------------- Initialisation ---------------------- */static ConfParam *cParm[MAXGLOBS]; /* config parameters */static int nParm = 0;static int trace = 0; /* Just for consistency *//* EXPORT->InitGraf: initialise memory and configuration parameters */void InitGraf(void){ int i; Register(hgraf_version,hgraf_vc_id); nParm = GetConfig("HGRAF", TRUE, cParm, MAXGLOBS); if (nParm>0){ if (GetConfInt(cParm,nParm,"TRACE",&i)) trace = i; }}/* EXPORT->HGetEvent: return next relevant event in event queue */HEventRec HGetEvent(Boolean anyEvent, void (*action)(void)){ HEventRec r={0,0,0,0,0}; static KeyType SavedKeyType; MSG msg; Boolean hasEvent = FALSE; HWND WindowHandle = (anyEvent) ? NULL : theWindow; do { if (action==NULL) { GetMessage(&msg,WindowHandle,0,0); hasEvent=TRUE; } else { hasEvent=PeekMessage(&msg,WindowHandle,0,0,PM_REMOVE); } if (hasEvent) { TranslateMessage(&msg); switch (msg.message) { case WM_LBUTTONDOWN: r.event = HMOUSEDOWN; r.x = MousePos.x = LOWORD(msg.lParam); r.y = MousePos.y = HIWORD(msg.lParam); SetCapture(theWindow); break; case WM_LBUTTONUP: r.event = HMOUSEUP; r.x = MousePos.x = LOWORD(msg.lParam); r.y = MousePos.y = HIWORD(msg.lParam); ReleaseCapture(); break; case WM_MOUSEMOVE: r.event = HMOUSEMOVE; r.x = MousePos.x = LOWORD(msg.lParam); r.y = MousePos.y = HIWORD(msg.lParam); break;#ifdef CAPTURE_ALT /* alt key events are normally intended for the system */ case WM_SYSKEYDOWN: r.c = (unsigned char) msg.wParam; if (r.c == VK_MENU) { r.ktype = COMMANDKEY; r.event = HKEYPRESS; r.x = MousePos.x; r.y = MousePos.y; AltKeyState = ALT_DOWN; break; } /* else fall through to regular keydown */#endif case WM_KEYDOWN: r.event = HKEYPRESS; r.x = MousePos.x; r.y = MousePos.y; r.c = (unsigned char) msg.wParam; SavedKeyType = r.ktype = HGetKeyType(r.c); if ((r.c != VK_DELETE) && (r.ktype != CONTROLKEY) && (r.ktype != COMMANDKEY) && (r.ktype != SHIFTKEY)) hasEvent = FALSE; /* other keys will be processed by WM_CHAR */ /* message which should arrive shortly */ break;#ifdef CAPTURE_ALT case WM_SYSCHAR:#endif case WM_CHAR: r.event = HKEYPRESS; r.x = MousePos.x; r.y = MousePos.y; r.c = (unsigned char) msg.wParam; r.ktype = SavedKeyType; //HGetKeyType(r.c); break;#ifdef CAPTURE_ALT case WM_SYSKEYUP: r.c = (unsigned char) msg.wParam; if (r.c == VK_MENU) { r.ktype = COMMANDKEY; r.event = HKEYRELEASE; r.x = MousePos.x; r.y = MousePos.y; AltKeyState = ALT_UP; break; } /* else fall through to regular keydown */#endif case WM_KEYUP: r.event = HKEYRELEASE; r.x = MousePos.x; r.y = MousePos.y; r.c = (unsigned char) msg.wParam; r.ktype = HGetKeyType(r.c); break; case WM_PAINT: DispatchMessage(&msg); /* force Win32 to remove message from */ /* queue even though application is dispatching this message. */ /* Applications should actually be able to ignore HREDRAW events. */ /* Fall through to next messages */ case WM_SIZING: case WM_MOVING: case WM_EXITSIZEMOVE: r.event = HREDRAW; break; default: hasEvent = FALSE; DispatchMessage(&msg); /* Win32 should handle other messages */ } } else if (action != NULL) { (*action)(); } } while (!hasEvent); return r;}/* EXPORT->HEventsPending: Return number of events pending *//* This doesn't seem to be supported in Win32. It is possible *//* to see if the queue is empty, but there is no way to see if *//* there is just one event or if there are many. This function *//* should probably return a Boolean value. Currently it returns 1 *//* if there are one or more events pending, and 0 if there are none. */int HEventsPending(void){ MSG msg; if (PeekMessage(&msg,theWindow,0,0,PM_NOREMOVE)) return 1; return 0;}/* EXPORT->HMousePos: return mouse pos in x, y, returns TRUE if the pointer is on the window *//* Win32: We only get mouse position information when (a) there is an event *//* when the mouse is positioned over the window, or (b) when we are capturing *//* the mouse. We only capture the mouse when the mouse button is depressed. *//* Thus, the mouse position determined from this function may not be up to *//* date. This shouldn't be a problem since the "focus" is not determined by *//* mouse position in Win32. That is, keyboard events that take place when the *//* mouse is outside the window still really do belong to our window, if the *//* event has been directed to our application. */Boolean HMousePos(int *x, int *y){ *x = MousePos.x; *y = MousePos.y; return (Boolean) IsInRect(*x,*y,ClientRect.left,ClientRect.top, ClientRect.right,ClientRect.bottom);}/* EXPORT: IsInRect: return TRUE iff (x,y) is in the rectangle (x0,y0,x1,y1) */ Boolean IsInRect(int x, int y, int x0, int y0, int x1, int y1){ return (x >= x0 && x<=x1 && y >= y0 && y <= y1);}/* ------------------------- Colour Handling ------------------------------ */#define GSTP 4static void InstallColours(void){ int pixVal=0; int c; int step; LOGPALETTE *pal; HPALETTE hpal,OldPal; HDC dc; /* WHITE */ colours[0][0] = 255; colours[0][1] = 255; colours[0][2] = 255; /* YELLOW */ colours[1][0] = 255; colours[1][1] = 255; colours[1][2] = 0; /* ORANGE */ colours[2][0] = 255; colours[2][1] = 128; colours[2][2] = 0; /* RED */ colours[3][0] = 255; colours[3][1] = 0; colours[3][2] = 0; /* MAUVE */ colours[4][0] = 196; colours[4][1] = 100; colours[4][2] = 255; /* PURPLE */ colours[5][0] = 128; colours[5][1] = 0; colours[5][2] = 128; /* DARK_BLUE */ colours[6][0] = 0; colours[6][1] = 0; colours[6][2] = 196; /* LIGHT_BLUE (CYAN) */ colours[7][0] = 0; colours[7][1] = 255; colours[7][2] = 255; /* DARK_GREEN */ colours[8][0] = 0; colours[8][1] = 128; colours[8][2] = 0; /* LIGHT_GREEN */ colours[9][0] = 0; colours[9][1] = 255; colours[9][2] = 0; /* DARK_BROWN */ colours[10][0] = 128;colours[10][1] = 64; colours[10][2] = 64; /* LIGHT_BROWN */ colours[11][0] = 196;colours[11][1] = 140;colours[11][2] = 140; /* LIGHT_GREY */ colours[12][0] = 196;colours[12][1] = 196;colours[12][2] = 196; /* GREY */ colours[13][0] = 128;colours[13][1] = 128;colours[13][2] = 128; /* DARK_GREY */ colours[14][0] = 64; colours[14][1] = 64; colours[14][2] = 64; /* BLACK */ colours[15][0] = 0; colours[15][1] = 0; colours[15][2] = 0; step = 256/MAX_GREYS; for (c = 0; c < MAX_GREYS; c++, pixVal+= step){ greys[c] = pixVal; } /* if display is 8 bits or less, create a palette containing the best match to our desired colors. If it is 16 bits or greater, matching will be no problem. */ if (dispDEEP <= 8){ pal = (LOGPALETTE *) New(&gcheap,2*sizeof(WORD) + (MAX_GREYS + MAX_COLOURS)*sizeof(PALETTEENTRY)); pal->palVersion = 0x300; pal->palNumEntries = MAX_GREYS + MAX_COLOURS; /* most important colors should be first in list. Black, White, the rest of the colors, then the greys. */ pal->palPalEntry[0].peRed = pal->palPalEntry[0].peGreen = pal->palPalEntry[0].peBlue = 0; pal->palPalEntry[0].peFlags = 0; pal->palPalEntry[1].peRed = pal->palPalEntry[1].peGreen = pal->palPalEntry[1].peBlue = 255; pal->palPalEntry[1].peFlags = 0; for (c=2;c<MAX_COLOURS;c++) { pal->palPalEntry[c].peRed = colours[c-1][0]; pal->palPalEntry[c].peGreen = colours[c-1][1]; pal->palPalEntry[c].peBlue = colours[c-1][2]; pal->palPalEntry[c].peFlags = 0; } for (c=0;c<MAX_GREYS;c++) { pal->palPalEntry[MAX_COLOURS+c].peRed = greys[c]; pal->palPalEntry[MAX_COLOURS+c].peGreen = greys[c]; pal->palPalEntry[MAX_COLOURS+c].peBlue = greys[c]; pal->palPalEntry[MAX_COLOURS+c].peFlags = 0; } hpal = CreatePalette(pal); OldPal = SelectPalette(memDC,hpal,FALSE); RealizePalette(memDC); SelectPalette(memDC,OldPal,FALSE); dc = GetDC(theWindow); OldPal = SelectPalette(dc,hpal,FALSE); RealizePalette(dc); SelectPalette(dc,OldPal,FALSE); ReleaseDC(theWindow,dc); DeleteObject(hpal); } /* if (dispDEEP <= 8) */}/* EXPORT-> HSetColour: Set current colour to c */void HSetColour(HColour c){ CurrentColour = RGB(colours[c][0],colours[c][1],colours[c][2]); if (theBrush) DeleteObject(theBrush); theBrush = CreateSolidBrush(CurrentColour); if (thePen) DeleteObject(thePen); thePen = CreatePen(PS_SOLID,LineWidth,CurrentColour); if (thinPen) DeleteObject(thinPen); thinPen = CreatePen(PS_SOLID,1,CurrentColour);}/* EXPORT-> HSetGrey: Set current colour to grey level g */void HSetGrey(int g){ CurrentColour = RGB(greys[g],greys[g],greys[g]); if (theBrush) DeleteObject(theBrush); theBrush = CreateSolidBrush(CurrentColour); if (thePen) DeleteObject(thePen); thePen = CreatePen(PS_SOLID,LineWidth,CurrentColour); if (thinPen) DeleteObject(thinPen); thinPen = CreatePen(PS_SOLID,1,CurrentColour);}/* CheckCorners: make sure (x0,y0) is north-west of (x1,y1) */static void CheckCorners(int *x0, int *y0, int *x1, int *y1){ int a,b,c,d; if (*x0<*x1) {a=*x0; c=*x1;} else {a=*x1; c=*x0;} if (*y0<*y1) {b=*y0; d=*y1;} else {b=*y1; d=*y0;} *x0=a; *y0=b; *x1=c; *y1=d;}/* EXPORT-> HDrawLines: Draw multiple lines */void HDrawLines(HPoint *points, int n)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -