// ---------------------------------------------------------------------------- // gwiz.h Tiny version of the graphics class gwin; and some globals. // This is not a true header file: it combines gwiz.h with gwiz.cpp // ---------------------------------------------------------------------------- // (c) Richard Hall December 2000 // ----------------------------------------------------------------------- // definitions needed by gwiz.h and gwiz.rc // ----------------------------------------------------------------------- #ifndef gwiz_defs #define gwiz_defs #define MENU_1 1 #define CM_EXIT 10 #define CM_CLEAR 20 #define CM_NUM 30 #define CM_NUMP 40 #define CM_PLOT 50 #define CM_PLOTP 60 #define CM_HELP 100 #endif // ---------------------------------------------------------- #include #include #include #include #include #include #include #ifndef gwiz_h #define gwiz_h // -------------------------------------------------------- // top-level functions #ifndef fptype_1 #define fptype_1 typedef double (*fptype1)( double); #endif #ifndef fptype_2 #define fptype_2 typedef double (*fptype2)( double,double); #endif #ifndef fptype_3 #define fptype_3 typedef double (*fptype3)( double,double,double); #endif // -------------------------------------------------------- // the fun function classes #ifndef fun_1 #define fun_1 class fun { public: virtual double f(double) = 0; }; #endif #ifndef fun_2 #define fun_2 class fun2 { public: virtual double f(double, double) = 0; }; #endif #ifndef fun_3 #define fun_3 class fun3 { public: virtual double f(double, double, double) = 0; }; #endif //--------------------------------------------------------------- // some global constants (defined in gwtiny.cpp) const extern double Pi; const extern double Piby2; const extern double Piby4; const extern double Piby180; const extern double Exp1; // ------------------------------------- // Global WinXX utilities ------------------------------------ inline void clear(HWND hwnd) { InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); } inline void close(HWND hwnd) { SendMessage (hwnd, WM_CLOSE, 0, 0L); } // ------------------------------------------------------------ class gwin { protected: HWND hwnd; HDC hdc,hdcprn, hdct; // screen, printer, temp DC int prn; // printer flag RECT rect; // hwnd RECT nrect; // new rect chosen by locate HRGN hrgn, hnrgn; // m = m0 + cx*(x - x0) // cx = pm/px, similarly (n,y) double x0,x1,y0,y1,px,py,cx,cy; // scale variables int m0,m1,n0,n1,pn,pm; // pixel versions of scales double x,y; // current position int m,n; // current integer position int mw,nw; // screen window size int mt,nt; // current window size int scan; // number of points for x plotting int clipped; // clip flag TEXTMETRIC tm; // font data int cw, ch; // character sizes public: gwin(HWND hwndi); void setprn(HDC hi, int xi, int yi); // after gwin::open void endprn(); // wind up printer void open(int p = 0); // default screen void locate(int a,int b,int c,int d, int cl = 1); // selects % of client rect (Cartesian) void preframe(); void scale(double x0i, double x1i, double y0i, double y1i, int scani); double getscale(int k); int getscan(); int mx(double x); int ny(double y); void move(double xi,double yi); void line(double xi,double yi); void clip(); void unclip(); void box(double s,double t,double u,double v); void frame(); void xplotd(fptype1 fun, double xa, double xb, int nn); void xplot(fptype1 fun) { xplotd(fun, x0, x1, scan);} void xplotd(fun *fu, double xa, double xb, int nn); inline void xplot(fun *fu) { xplotd(fu, x0, x1, scan);} void p(double x, double y, char *c); // print to screen void pf(double x, double y, char *fmt, ...); //format strings void respond(WPARAM wParam, LPARAM lParam); void close(); void cls(); // end declaration of class gwin }; #endif // ----------------------------------------------------------- // definitions // ----------------------------------------------------------- // definitions of constants const double Pi = 3.1415926535897932; const double Piby2 = 1.5707963267948966; const double Piby4 = 0.7853981633974483; const double Piby180 = 1.7453292519943296e-2; const double Exp1 = 2.7182818284590452; // -------------------------------------------------- gwin::gwin(HWND hwndi): hwnd(hwndi) {} void gwin::open(int p) { prn = p; // set printer flag hdc = GetDC(hwnd); SelectObject(hdc,GetStockObject (ANSI_FIXED_FONT)); GetClientRect(hwnd,&rect); mw = rect.right - rect.left; // screen width nw = rect.bottom - rect.top; // screen height mt = mw; nt = nw; // current dimensions for screen hrgn = CreateRectRgnIndirect(&rect); if (prn == 1) // output to printer { const int pnmax = 100; char pname[pnmax]; GetProfileString("windows", "device",pname,pname,pnmax); // Now extract substring up to first comma for (int i = 0; i < pnmax; i++) { if (pname[i] == ',') { pname[i] = '\0'; break;} } { if (MessageBox(hwnd,pname, "Shall we print to ",MB_YESNO) == IDYES) { hdcprn = CreateDC (pname, pname, NULL, NULL) ; int xn,yn; xn = GetDeviceCaps(hdcprn,HORZRES); yn = GetDeviceCaps(hdcprn,VERTRES); static DOCINFO di = { sizeof (DOCINFO), "", NULL } ; StartDoc(hdcprn,&di); StartPage(hdcprn); // Necessary for Win95 setprn(hdcprn,xn,yn); GetTextMetrics (hdcprn, &tm) ; cw = tm.tmAveCharWidth; ch = tm.tmHeight;} else prn = 0; } } } // end of gwin::open() // ----------------------------------------------------------- void gwin::setprn(HDC hi, int xi, int yi) // after gwin::open { prn = 1; hdct = hdc; hdc = hi; // keep old DC in hdct mt = xi; nt = yi; GetTextMetrics (hdc, &tm) ; // default printer font cw = tm.tmAveCharWidth; ch = tm.tmHeight; } void gwin::endprn() { prn = 0; // set flag hdc = hdct; // restore DC mt = mw; nt = nw; SelectObject(hdc,GetStockObject (ANSI_FIXED_FONT)); GetTextMetrics (hdc, &tm) ; cw = tm.tmAveCharWidth; ch = tm.tmHeight; } // ----------------------------------------------------------- void gwin::preframe() {int c = 0; if (clipped == 1) { c = 1; unclip(); } Rectangle(hdc, m0,n1,m1,n0); if (c == 1) clipped = 1; } // ----------------------------------------------------------- void gwin::locate(int a,int b,int c,int d, int cl) { // in the next 4 lines we avoid 'large' integers. m0 = nrect.left = int(mt*0.01*a); // new origin x n1 = nrect.top = int(nt*0.01*(100-d)); // new origin y m1 = nrect.right = int(mt*0.01*b); // new right n0 = nrect.bottom = int(nt*0.01*(100-c)); // new bottom hnrgn = CreateRectRgnIndirect(&nrect); SelectClipRgn(hdc,hnrgn); if (cl == 0) SelectClipRgn(hdc,NULL); pm = m1-m0; // current pixel width and height pn = n0-n1; clipped = cl;} // ----------------------------------------------------------- void gwin::scale(double x0i, double x1i, double y0i, double y1i, int scani) { x0 = x0i; x1 = x1i; y0 = y0i; y1 = y1i; scan = scani; px = (x1 - x0); py = y1 - y0; cx = pm*(1.0/px); cy = pn*(1.0/py); } // ----------------------------------------------------------- double gwin::getscale(int k) { double z = 0; switch(k) { case 1: z = x0; break; case 2: z = x1; break; case 3: z = y0; break; default: z = y1; } return z; } // ------------------------------------------------------------ int gwin::getscan() { return scan; } int gwin::mx(double x) { return int(m0 + cx*(x-x0)); } int gwin::ny(double y) { return int(n0 - cy*(y-y0)); } void gwin::clip() { clipped = 1; SelectClipRgn(hdc,hnrgn); } void gwin::unclip () { clipped = 0; SelectClipRgn(hdc,NULL); } void gwin::frame(){ box(x0,x1,y0,y1); } // ------------------------------------------------------------ void gwin::move(double xi,double yi) { x = xi; y = yi; // keep current position m = mx(x); n = ny(y); MoveToEx(hdc,m,n,NULL);} void gwin::line(double xi,double yi) // clipping by Win32 { x = xi; y = yi; m = mx(x); n = ny(y); LineTo(hdc,m,n); } // ------------------------------------------------------- void gwin::box(double s,double t,double u,double v) { move(s,u); line(t,u); line(t,v); line(s,v); line(s,u); } // ------------------------------------------------------- void gwin::xplotd(fptype1 fun, double xa, double xb, int nn) { double x,dx,y; dx = (xb - xa)/nn; x = xa; y = fun(x); move(x,y); for (int j = 1; j <= nn; j++) { x = xa + dx*j; y = fun(x); line(x,y); } } // ------------------------------------------------------------ void gwin::xplotd(fun *fu, double xa, double xb, int nn) { double x,dx,y; dx = (xb - xa)/nn; x = xa; y = fu->f(x); move(x,y); for (int j = 1; j <= nn; j++) { x = xa + dx*j; y = fu->f(x); line(x,y); } } // ------------------------------------------------------------ void gwin::p(double x, double y, char *c) { int len = strlen(c); TextOut(hdc, mx(x), ny(y), c, len); move(x,y); } // ------------------------------------------------------------ void gwin::pf(double x, double y, char *fmt, ...) // print format strings { char s[80]; va_list argptr; va_start(argptr, fmt); vsprintf(s,fmt, argptr); va_end(argptr); gwin::p(x,y,s);} // ------------------------------------------------------------ void gwin::close() { DeleteObject(hrgn); DeleteObject(hnrgn); if (prn == 1) { EndPage(hdcprn); // Necessary for Win95 EndDoc(hdcprn); DeleteDC(hdcprn); endprn(); MessageBox(hwnd,"Printing is Finished","Note",MB_OK); } ReleaseDC(hwnd,hdc); } // ------------------------------------------------------------- void gwin::cls() { clear(hwnd); } // end decl class gwin // ------- end definitions for class gwin -------------------- // ------------------------------------------------------------- void num(gwin &w, int p); // program items void plot(gwin &w, int p); // -------------------------------------------------------------------------------- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); // Win32 // NB For Win16 replace the above line by the 2 lines below //LRESULT FAR PASCAL _export WndProc(HWND hWnd, UINT message, // Win16 // WPARAM wParam, LPARAM lParam); // Other function prototypes. LRESULT PerformMenuCommand(HWND hWnd, WPARAM wParam,gwin &w); // Global instance handle. HINSTANCE hInstance; /////////////////////////////////////////////////////////// // WinMain /////////////////////////////////////////////////////////// int PASCAL WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR /*lpszCmdLine */, int nCmdShow) { WNDCLASS wndClass; HWND hwnd; MSG msg; // If there's no previous instance of this application, // define and register the window class. if (hPreviousInst == NULL) { wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hCurrentInst; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = MAKEINTRESOURCE(MENU_1); wndClass.lpszClassName = prog; RegisterClass(&wndClass); } hInstance = hCurrentInst; // Get the size of the screen. UINT width = GetSystemMetrics(SM_CXSCREEN) / 2; UINT height = GetSystemMetrics(SM_CYSCREEN) / 2; // Create a window of the previously defined class. hwnd = CreateWindow( prog, // Window class's name. prog, // Title bar text. WS_OVERLAPPEDWINDOW, // The window's style. 10, // X position. 10, // Y position. width, // Width. height, // Height. NULL, // Parent window's handle. NULL, // Menu handle. hCurrentInst, // Instance handle. NULL); // No additional data. // Display the window on the screen. ShowWindow(hwnd, nCmdShow); // Force the window to repaint itself. UpdateWindow(hwnd); // Start the message loop. while (GetMessage(&msg, NULL, NULL, NULL)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } /////////////////////////////////////////////////////////// // WndProc() // // This is the main window procedure, which is called by // Windows. /////////////////////////////////////////////////////////// LRESULT CALLBACK WndProc (HWND hwnd, UINT message, // Win 32 WPARAM wParam, LPARAM lParam) // NB For Win16 replace the above 2 lines by the two lines below //LRESULT FAR PASCAL _export WndProc(HWND hwnd, UINT message, // WPARAM wParam, LPARAM lParam) { static gwin w(hwnd); // Handle the messages to which the application // must respond. switch(message) { case WM_COMMAND: return PerformMenuCommand(hwnd, wParam,w); case WM_DESTROY: PostQuitMessage(0); return 0; } // Make sure all unhandled messages get returned to Windows. return DefWindowProc(hwnd, message, wParam, lParam); } /////////////////////////////////////////////////////////// // PerformMenuCommand() /////////////////////////////////////////////////////////// LRESULT PerformMenuCommand(HWND hwnd, WPARAM wParam,gwin &w) { switch(wParam) { case CM_EXIT : close(hwnd); return 0 ; case CM_CLEAR : clear(hwnd); return 0; case CM_NUM : num(w,0); return 0; case CM_NUMP : num(w,1); return 0; case CM_PLOT: plot(w,0); return 0; case CM_PLOTP: plot(w,1); return 0; case CM_HELP : MessageBox (hwnd, helpstr, "Help",MB_OK); return 0 ; } // end of switch return 0; }