7 Replies - 4389 Views - Last Post: 31 October 2010 - 05:30 PM Rate Topic: -----

#1 wwPOLARww  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 11-October 10

C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 11:04 AM

Windows API Help, Graphics Framework Cosmetic changes
I hate asking for help, but stumped on something. Im 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 its pretty much my first time using Graphics framework with really no resources. So any help turning these dots into lines would help greatly.

Is This A Good Question/Topic? 0
  • +

Replies To: C++ Windows API Help, Graphics Framework Cosmetic changes

#2 Munawwar  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 162
  • View blog
  • Posts: 457
  • Joined: 20-January 10

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 01:11 PM

I can't compile your program without the resource files/headers. So I can't say much without them :/

You can join each dot by calculating the slope of the line from two given dots and then interpolate the rest of the values. BUT, it will make your parabola made of straight lines and with sharp edges - may look bad.
Why don't you reduce the interval from y++ to say, y+=0.2, so that you can get more x values. If I am not wrong, you should get a smoother curve with that.
for (double y = ymin; y <= ymax; y+=0.2) {
   x = (int)( a * (y-k) * (y-k) ) + h;
   PGraphics->AddPoint(x, (int)y, green);
}


This post has been edited by Munawwar: 31 October 2010 - 01:39 PM

Was This Post Helpful? 0
  • +
  • -

#3 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 01:17 PM

draw a line from the last point drawn to the next point. to draw a line simply take the difference in y values and difference in x values and call them Yinc and Xinc respectively(you can call them what ever you want just for my point we will call them Yinc, Xinc). loop though each point by incrementing the pixel to be drawn's position by the Xinc and Yinv. i can see that i have not explained this very well so feel free to ask questions to clearfiy. hope this helps :)
Was This Post Helpful? 0
  • +
  • -

#4 wwPOLARww  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 11-October 10

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 01:59 PM

View PostMunawwar, on 31 October 2010 - 12:11 PM, said:

I can't compile your program without the resource files/headers. So I can't say much without them :/

You can join each dot by calculating the slope of the line from two given dots and then interpolate the rest of the values. BUT, it will make your parabola made of straight lines and with sharp edges - may look bad.
Why don't you reduce the interval from y++ to say, y+=0.2, so that you can get more x values. If I am not wrong, you should get a smoother curve with that.
for (double y = ymin; y <= ymax; y+=0.2) {
   x = (int)( a * (y-k) * (y-k) ) + h;
   PGraphics->AddPoint(x, (int)y, green);
}



Ok where would I implement this in my code? As I said before Im kind of coming into this assignment a little blind on how to code with graphics framework
Was This Post Helpful? 0
  • +
  • -

#5 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6087
  • View blog
  • Posts: 23,597
  • Joined: 23-August 08

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 02:46 PM

Looks a lot like this code here.
Was This Post Helpful? 0
  • +
  • -

#6 wwPOLARww  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 11-October 10

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 03:49 PM

View PostJackOfAllTrades, on 31 October 2010 - 01:46 PM, said:

Looks a lot like this code here.

Well, we were most likely than not enrolled in the same class at different times. But honestly after reading the post he was suffering from the same dilemma as I.
Was This Post Helpful? 0
  • +
  • -

#7 wwPOLARww  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 11-October 10

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 04:58 PM

Well figured it out and works like a dream.
 /*
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 drawLine(int xPrev, int yPrev, int x, int y)
{
	int x1 = xPrev;
	int y1 = yPrev;
	int x2 = x;
	int y2 = y;
	int dy = y2 - y1;
	int dx = x2 - x1;
	COLORREF purple = RGB(255, 0, 255);

	

	if (Abs(dy) > Abs(dx)) {
		// since there is a greater change in y than x we must
		// loop in y, calculate x and draw
		for (y=y1; y != y2; y += Sign(dy)) {
			x = x1 + (y - y1) * dx / dy;
			PGraphics->AddPoint(x, y, purple);
		}
	}else {
		// since there is a greater (or equal) change in x than y we must
		// loop in x, calculate y and draw
		for (x=x1; x != x2; x += Sign(dx)) {
			y = y1 + (x - x1) * dy / dx;
			PGraphics->AddPoint(x, y, purple);
	
		}
	}

	// draw the last pixel
	PGraphics->AddPoint(x2, y2, purple);

	// draw the points
	PGraphics->Draw();
}


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);

// set up first previous points,(xPrev,yPrev).
yPrev = ymin;
xPrev = (int)( a * (yPrev-k) * (yPrev-k) ) + h;

    // 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); 
		drawLine(xPrev, yPrev, x, y);
xPrev =x;
yPrev =y; 
    }

    // 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);
} 


My issue was making a function drawLine looping it to make the line connecting it to each segment, then calling it in DrawStuff
Was This Post Helpful? 1
  • +
  • -

#8 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6087
  • View blog
  • Posts: 23,597
  • Joined: 23-August 08

Re: C++ Windows API Help, Graphics Framework Cosmetic changes

Posted 31 October 2010 - 05:30 PM

Cool, glad you got it working. I noticed that code had the drawLine function yours didn't and thought it might provide a stepping-off point for you.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1