I hate asking for help, but stumped on something. I’m taking a class for programming mathematics, and the assignment is to make a Parabola output in a Graphics output via Windows API, (if that sounds correct.) The Logic is correct and works fine, its just the output I want to look different. The Parabola is represented as a series of dots but I would like to have lines connect the dots so it can be more visable to the user.
parabola.cpp
/* parabola2.cpp Draws a parabola with horizontal axis (pg 52) made up of line segments */ #include <stdio.h> #include <windows.h> #include "resource.h" // your path for this include may vary #include "GraphicsFramework.h" // Global variable to store the graphics framwork object GraphicsFramework* PGraphics; HWND HOutput = 0; // handle to the output control HWND HDialog = 0; // function to get the absolute value of an integer int Abs(int x) { if (x < 0) return -x; else return x; } // function to get the sign (+1 or -1) of an integer int Sign(int x) { if (x < 0) return -1; else return 1; } void DrawStuff() { COLORREF green = RGB(0, 255, 0); // green color to draw with COLORREF purple = RGB(255, 0, 255); // purple color to draw with char str[32]; // string to store user input int h, k; // parabola vertex double a; // parabola constant - might be a decimal int x, y; // loop and point variables int xPrev, yPrev; // previous point for drawng line segments int ymin, ymax; // limits for y loop RECT rect; // rectangle for the output window // get the user input from the edit boxes and // convert string input to integer GetDlgItemText(HDialog, IDC_EDIT_VERTEXX, str, 32); h = atoi(str); GetDlgItemText(HDialog, IDC_EDIT_VERTEXY, str, 32); k = atoi(str); GetDlgItemText(HDialog, IDC_EDIT_CONSTA, str, 32); a = atof(str); // use atof to allow user to enter a decimal // get the rect for this window GetClientRect(HOutput, &rect); // use the rectangle info to set up y loop limits ymin = -(rect.bottom - rect.top) / 2; ymax = (rect.bottom - rect.top) / 2; // clear the scene and add an axis PGraphics->ClearScene(RGB(0, 0, 0)); PGraphics->AddAxis(RGB(150, 150, 150), 10); // loop in y, calculate x and draw for (y = ymin; y <= ymax; y++) { x = (int)( a * (y-k) * (y-k) ) + h; PGraphics->AddPoint(x, y, green); } // draw the points PGraphics->Draw(); } /* DialogProc this is the window event handler for the main dialog */ BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_INITDIALOG: // dialog is initializing - store the picture box handle in a global variable for later HOutput = GetDlgItem(hwnd, IDC_PICTURE_OUTPUT); // instantiate and initialize our graphics framework object PGraphics = new GraphicsFramework(HOutput); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BTN_DRAW: // draw button was pressed DrawStuff(); break; case IDC_BTN_CLEAR: // clear button was pressed so clear the scene and draw the empty scene PGraphics->ClearScene(RGB(0, 0, 0)); PGraphics->Draw(); break; case IDCANCEL: // user is quitting so release the GraphicsFramework object and quit delete PGraphics; PostQuitMessage(0); break; } } return FALSE; } // this is the main function that starts the application int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow) { // create the main window // store its handle in a global if needed HDialog = CreateDialog (GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc); // make the dialog visible ShowWindow(HDialog, SW_SHOW); // standard windows message loop MSG msg; int status; while ((status = GetMessage (&msg, 0, 0, 0)) != 0) { if (status == -1) return -1; // avoid processing messages for the dialog if (!IsDialogMessage (HDialog, & msg)) { TranslateMessage ( & msg ); DispatchMessage ( & msg ); } } return (int)(msg.wParam); }
GraphicsFramework.h
// GraphicsFramework.h #ifndef GRAPHICSFRAMEWORK_H #define GRAPHICSFRAMEWORK_H #include <windows.h> // must include this for windows programs // A graphics framework class used to implement a drawing area within a windows control. // This class implements a back buffer as a memory bitmap which will store pixels and then // copy them with a call to the Draw method. class GraphicsFramework { private: HBITMAP memBMP; // back buffer HDC memHDC; HANDLE oldHDC; int wd, ht; int wdOver2; int htOver2; RECT rect; // rect for this window HWND hwnd; // handle to the output control public: GraphicsFramework() { this->hwnd = NULL; } // construct from a windows handle GraphicsFramework(HWND hwnd) { BITMAPINFO bmi; // bitmap info structure for creating the back buffer HDC hdc; this->hwnd = hwnd; // get the window's client rectangle and its center hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); wd = rect.right - rect.left; ht = rect.bottom - rect.top; wdOver2 = wd / 2; htOver2 = ht / 2; // set up a 32bit rgb dib for an offscreen (memory) render target (the back buffer) memHDC = CreateCompatibleDC(hdc); bmi.bmiHeader.biWidth = wd; bmi.bmiHeader.biHeight = ht; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biSizeImage = 0; memBMP = CreateDIBSection(memHDC, &bmi, DIB_RGB_COLORS, NULL, NULL, 0); // select this memory bmp for drawing // note: it will remain selected until destructor is called oldHDC = SelectObject(memHDC, memBMP); // release the device context ReleaseDC(hwnd, hdc); } ~GraphicsFramework() { // deselect and delete the memory dc that was selected in the constructor SelectObject(memHDC, oldHDC); DeleteObject(memBMP); DeleteDC(memHDC); } // this method copies the back buffer to the output window void Draw() { HDC graphics; // graphics device context graphics = GetDC(hwnd); // copy from offscreen memory bmp to screen BitBlt(graphics, 0, 0, wd, ht, memHDC, 0, 0, SRCCOPY); // release the device context ReleaseDC(hwnd, graphics); } void DrawPixel(int x, int y, COLORREF color) { if (x < -wdOver2 || x >= wdOver2 || y <= -htOver2 || y > htOver2) { // x and/or y is out of bounds so don't draw } else { // move origin from upper left to center of buffer // draw the pixel SetPixel(memHDC, wdOver2 + x, htOver2 - y, color); } } void ClearScene(COLORREF backColor) { // clear the offscreen memory bmp to backColor HBRUSH hBrush; // create the brush with specified color hBrush = CreateSolidBrush(backColor); // fill the rectangle with black rect.left = 0; rect.right = wd; rect.top = 0; rect.bottom = ht; FillRect(memHDC, &rect, hBrush); // release the brush DeleteObject(hBrush); } // add a point to be drawn void AddPoint(int x, int y, COLORREF color) { SetPixel(memHDC, wdOver2 + x, htOver2 - y, color); } // draw x and y axis in specifice color, with single dot every tic step void AddAxis(COLORREF color, int ticStep) { int x, y; // draw horizontal line for (x = -wdOver2; x <= wdOver2; x++) { if (x % ticStep == 0) { //pList.Add(x, 0, color); DrawPixel(x, 0, color); } } // draw vertical line for (y = -htOver2; y < htOver2; y++) { if (y % ticStep == 0){ //pList.Add(0, y, color); DrawPixel(0, y, color); } } } }; #endif
I found some stuff, but not sure how to implement it in my code as this is really the first time using graphics framework
// function to draw a line between the two points (x1,y1) and (x2,y2) void DrawLine(int x1, int y1, int x2, int y2, unsigned int color) { function body }
// set up first previous points,(xPrev,yPrev). yPrev = ymin; xPrev = (int)( a * (yPrev-k) * (yPrev-k) ) + h; //Then the for loop begins, it generates a point and draws a line // between those two points. // Part of what each iteration of the for loop does is as follows: //(i) It generates a point on the parabola (x,y). //(ii) It then draws a line between (xPrev, yPrev)and (x,y) by calling DrawLine. // loop in y, calculate x, and draw the line segment. for (y = ymin; y <= ymax; y++) { . . .
As I said it’s pretty much my first time using Graphics framework with really no resources. So any help turning these dots into lines would help greatly.