From: Jimbo on
Hello have a graph application that draws a graph onto the client
area. It is supposed to draw 2 lines. One line from the closest x axis
value to the mouse & another line from the closest y axis value to the
mouse.

But these lines are not drawn & I am having an incredibly difficult
time figuring out why? Can you help me fix this.

I have supplied my code but I think that for someone to help me figure
out whats wrong that you will probably need to see every function of
my app so I have all my code here( its abit long).

So I will list the functions that are responsible for drawing the
lines to make it as easy as possible:
[b]conGraph.cpp[/b] Control Class implementation file
- void drawFocus(HDC hdc);
- void eraseFocus(HWND hwnd);
- bool findInstanceNearest(HWND hwnd, UINT msg, int mouse_x, int
mouse_y);

conGraph.cpp
[source]
#include <windows.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>

#include <stdio.h>
#include <stdlib.h>

#include <stdio.h>
#include <io.h>
#include <fcntl.h>

using namespace std;

#include "conGraph.h"

controller::controller()
{
// Set default values

m = 2;
b = -4;
operand = '+';

xMin = INT_MAX;
yMin = INT_MAX;
xMax = INT_MIN;
yMax = INT_MIN;

xZero = 20;
yZero = 450;
minCellDim = 10;
cellWidth = minCellDim;
cellHeight = minCellDim;
precision = 1;
xBegin = -25;
xEnd = 5;
range = int(xEnd-xBegin);
xCellNum = int((xMax-xMin)/precision);
yCellNum = int((yMax-yMin)/precision);

// Set default strokes
xBorder = CreatePen(PS_SOLID,1,RGB(255,0,0));
yBorder = CreatePen(PS_SOLID,1,RGB(255,0,0));
functionLine = CreatePen(PS_SOLID,2,RGB(0,220,40));
intervalLine = CreatePen(PS_SOLID,1,RGB(255,255,255));
graphRgn = CreateRectRgn(0,0,1,1);
focusRgn = CreateRectRgn(0,0,1,1);
}

void controller::createGUI(HWND hwnd, HINSTANCE gInstance, UINT
controlMsg[])
{
// Post: Create GUI to alter graph

RECT rRect = {0};
GetClientRect(hwnd,&rRect);
HFONT hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
int dataCB[4] = {43,45,42,47};

int GUIx = 0;
int GUIy = rRect.bottom-100;

HWND stBorder = CreateWindowEx(0,"Static","",WS_BORDER| WS_CHILD|
WS_VISIBLE,//| SS_GRAYRECT,
GUIx,GUIy,rRect.right,100,hwnd,
(HMENU)controlMsg[3],gInstance,NULL);
HWND stfunctionLabel = CreateWindowEx(0,"Static","",WS_BORDER|
WS_CHILD| WS_VISIBLE,
GUIx+10,GUIy+15,150,33,hwnd,
(HMENU)controlMsg[4],gInstance,NULL);
HWND styLabel = CreateWindowEx(0,"Static"," y = ",WS_CHILD|
WS_VISIBLE,
GUIx+13,GUIy+18,25,20,hwnd,
(HMENU)controlMsg[5],gInstance,NULL);
HWND edMValue = CreateWindowEx(0,"Edit","m",WS_BORDER| WS_CHILD|
WS_VISIBLE| ES_NUMBER| ES_CENTER,
GUIx+42,GUIy+15,20,22,hwnd,
(HMENU)controlMsg[0],gInstance,NULL);
HWND stxLabel = CreateWindowEx(0,"Static","x",WS_CHILD|
WS_VISIBLE,
GUIx+65,GUIy+18,10,20,hwnd,
(HMENU)controlMsg[6],gInstance,NULL);
HWND cbOperand = CreateWindowEx(0,"Combobox","",WS_BORDER|
WS_CHILD| WS_VISIBLE| CBS_DROPDOWNLIST,
GUIx+76,GUIy+15,40,100,hwnd,
(HMENU)controlMsg[1],gInstance,NULL);
HWND edBValue = CreateWindowEx(0,"Edit","b",WS_BORDER| WS_CHILD|
WS_VISIBLE| ES_NUMBER| ES_CENTER,
GUIx+116,GUIy+15,20,22,hwnd,
(HMENU)controlMsg[2],gInstance,NULL);
HWND btDrawGrph = CreateWindowEx(0,"Button","Draw
Graph",WS_BORDER|WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,

rRect.right-87,rRect.bottom-40,80,33,hwnd,
(HMENU)controlMsg[7],gInstance,NULL);
HWND stLimitsLabel = CreateWindowEx(0,"Static","",WS_BORDER|
WS_CHILD|WS_VISIBLE,GUIx+10,GUIy+50,150,44,
hwnd,
(HMENU)controlMsg[8],gInstance,NULL);
HWND stXMin = CreateWindowEx(0,"Static","x min=",WS_CHILD|
WS_VISIBLE,GUIx+13,GUIy+52,50,20,
hwnd,
(HMENU)controlMsg[9],gInstance,NULL);
HWND edXMin = CreateWindowEx(0,"Edit","0",WS_BORDER|WS_CHILD|
WS_VISIBLE|ES_RIGHT,GUIx+48,GUIy+50,30,18,
hwnd,
(HMENU)controlMsg[10],gInstance,NULL);
HWND stRange = CreateWindowEx(0,"Static","Range=",WS_CHILD|
WS_VISIBLE,GUIx+83,GUIy+52,50,20,
hwnd,
(HMENU)controlMsg[11],gInstance,NULL);
HWND edRange = CreateWindowEx(0,"Edit","10",WS_BORDER|WS_CHILD|
WS_VISIBLE|ES_NUMBER|ES_RIGHT,GUIx+125,GUIy+50,30,18,
hwnd,
(HMENU)controlMsg[12],gInstance,NULL);
HWND stPrec = CreateWindowEx(0,"Static","Precision=",WS_CHILD|
WS_VISIBLE,GUIx+72,GUIy+72,50,17,
hwnd,
(HMENU)controlMsg[13],gInstance,NULL);
HWND edPrec = CreateWindowEx(0,"Edit","1",WS_BORDER|WS_CHILD|
WS_VISIBLE|ES_NUMBER|ES_RIGHT,GUIx+125,GUIy+70,30,18,
hwnd,
(HMENU)controlMsg[14],gInstance,NULL);
HWND stFocusPnt = CreateWindowEx(0,"Static","X = 0 Y =
0",WS_BORDER|WS_CHILD|WS_VISIBLE|SS_CENTER,
rRect.right-100,GUIy
+10,90,45,hwnd,(HMENU)controlMsg[15],gInstance,NULL);
// Set control fonts
for(int i=0; i<15; i++) {
SendDlgItemMessage(hwnd,controlMsg[i],WM_SETFONT,
(WPARAM)hfDefault,MAKELPARAM(FALSE,0));
}
// Add operand options to CB cbOperand
SendDlgItemMessage(hwnd,controlMsg[1],CB_ADDSTRING,0,(LPARAM)"
+");
SendDlgItemMessage(hwnd,controlMsg[1],CB_ADDSTRING,0,(LPARAM)"
-");
SendDlgItemMessage(hwnd,controlMsg[1],CB_ADDSTRING,0,(LPARAM)"
*");
SendDlgItemMessage(hwnd,controlMsg[1],CB_ADDSTRING,0,
(LPARAM)" /");
SendDlgItemMessage(hwnd,controlMsg[1],CB_SETCURSEL,0,0); //
select 1st cell of LB
}

void controller::resizeClientArea(HWND hwnd,UINT controlMsgs[])
{
// Post: Reallign controls when client area is resized

RECT rRect = {0};
GetClientRect(hwnd,&rRect);
int GUIx = 0;
int GUIy = rRect.bottom-100;


SetWindowPos(GetDlgItem(hwnd,controlMsgs[3]),HWND_TOPMOST,GUIx,GUIy,rRect.right,
100,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[4]),HWND_TOPMOST,GUIx
+10,GUIy+10,150,33,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[5]),HWND_TOPMOST,GUIx
+13,GUIy+18,25,20,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[0]),HWND_TOPMOST,GUIx
+42,GUIy+15,20,22,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[6]),HWND_TOPMOST,GUIx
+65,GUIy+18,10,20,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[2]),HWND_TOPMOST,GUIx
+116,GUIy+15,20,22,SWP_NOZORDER);

SetWindowPos(GetDlgItem(hwnd,controlMsgs[7]),HWND_TOPMOST,rRect.right-87,rRect.bottom-40,80,33,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[8]),HWND_TOPMOST,GUIx
+10,GUIy+47,150,44,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[9]),HWND_TOPMOST,GUIx
+13,GUIy+52,50,20,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[10]),HWND_TOPMOST,GUIx
+48,GUIy+50,30,18,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[11]),HWND_TOPMOST,GUIx
+83,GUIy+52,50,20,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[12]),HWND_TOPMOST,GUIx
+125,GUIy+50,30,18,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[13]),HWND_TOPMOST,GUIx
+72,GUIy+72,50,17,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[14]),HWND_TOPMOST,GUIx
+125,GUIy+70,30,18,SWP_NOZORDER);

SetWindowPos(GetDlgItem(hwnd,controlMsgs[15]),HWND_TOPMOST,rRect.right-100,GUIy
+10,90,45,SWP_NOZORDER);
SetWindowPos(GetDlgItem(hwnd,controlMsgs[1]),HWND_TOP,GUIx+76,GUIy
+15,40,100,SWP_NOZORDER);

precision = 1; // need to reset precision when window is resized
}

float controller::equation(float xVal)
{
// Post: Calculate Y value, ie, Determine y = mx(?)b, according to
the opperand type/value
// Maybe rename function to findYValue();

if (operand=='-') {
return ((m*xVal)-b);
}
else if (operand=='*') {
return ((m*xVal)*b);
}
else if (operand=='/') {
return ((m*xVal)/b);
}
else //if (operand=='+')
return ((m*xVal)+b);
}

void controller::plotActualGraph()
{
// Post: Create x,y data points for graph
// - xScaled = xZero + (x*cellWidth);
// - yScaled = yZero - (y*cellHeight);

functPnt.clear(); // clear vectors
xMax = INT_MIN;
yMax = INT_MIN;
xMin = INT_MAX;
yMin = INT_MAX;

// Calculate x,y values & store min & max x,y values
for (float xVal=xBegin; xVal<=xEnd; xVal+=1) { //precision) {

POINT *p = new POINT;
float yVal = equation(xVal); // determine y = mx + b
p->x = (LONG)xVal; p->y = (LONG)yVal;
functPnt.push_back(p);
// store min & max values
if (xVal > xMax) { xMax = xVal; }
if (yVal > yMax) { yMax = yVal; }
if (xVal < xMin) { xMin = xVal; }
if (yVal < yMin) { yMin = yVal; }
}

if (xMax < 0) {
xMax = 0;
}
if (yMax < 0) {
yMax = 0;
}
range = (xMax-xMin);
}

void controller::plotScaledGraph()
{
// Pre: Vector variables x & y MUST have been defined & given
values
// & cell dimensions & min/max values calculated
// Post: Create function line scaled to client area

scaledPnt.clear(); // clear vectors

for (int i=0; i<functPnt.size(); i+=1) { //(int)precision) {
// scale x,y values for optimal graphical display
POINT *p = new POINT;
float xVal = functPnt.at(i)->x;
float yVal = functPnt.at(i)->y;
float xTemp = xZero + ((xVal-xMin)*cellWidth);
float yTemp = yZero - ((yVal-yMin)*cellHeight);
p->x = (LONG)xTemp; p->y = (LONG)yTemp;
scaledPnt.push_back(p);
}
}

void controller::debugGraph()
{
// Post: Debugging function

cout << "Actual x,y values: \n";

for (int i=0; i<scaledPnt.size(); i++) {

//if (i%10 !=0) { cout << endl; }

cout << functPnt.at(i)->x << "," << functPnt.at(i)->y << " ";
cout << scaledPnt.at(i)->x << "," << scaledPnt.at(i)->y <<
"\n";
}
}

void controller::calculateGraphStats(HWND hwnd)
{
// Post: Using the user specified precision, xBegin & range we
calculate the
// optimal cell height & width to fit the graph on screen.
In some cases
// the range may be too large for the graph to fit on the
screen. To solve
// this, the precision will be overwritten & set to a more
optimal number.

RECT rRect = {0};
GetClientRect(hwnd,&rRect); // get the client area dimensions

plotActualGraph(); // calculate/plot graph x,y values

// find optimal cell dimensions
int spaceWidth = (rRect.right-rRect.left)-60;
int spaceHeight = (rRect.bottom-rRect.top)-140;

xCellNum = int((xMax-xMin)/precision);
yCellNum = int((yMax-yMin)/precision);
cellWidth = int(spaceWidth/xCellNum);
cellHeight = int(spaceHeight/yCellNum);

// if range is too large for client width OR height
while (cellWidth<=minCellDim || cellHeight<=minCellDim) {
precision += 1;
xCellNum = int((xMax-xMin)/precision);
yCellNum = int((yMax-yMin)/precision);
cellWidth = int(spaceWidth/xCellNum);
cellHeight = int(spaceHeight/yCellNum);
}

setCentre(hwnd,rRect); // Find if the graph contains x or y
negative values
plotScaledGraph(); // Plot/fit graph to client area
}

void controller::setCentre(HWND hwnd, RECT hRect)
{
// Post: Obtain/Calculate the best position for graph within
client area
// & set beginning points of x(xXAxis,yXAxis) &
y(xYAxis,yYAxis) axis.

// Default x,y axis position |__
xZero = (hRect.left)+20;
yZero = (hRect.bottom)-120;
xXAxis = xZero;
yXAxis = yZero;
xYAxis = xZero;
yYAxis = yZero;

// if any x or y values are negative then they require x,y
borders to be
// moved
if (isNegative(functPnt,'x')) {
xYAxis += int( abs(cellWidth*(xMin/precision)));
}
if (isNegative(functPnt,'y')) {
yXAxis -= int( abs(cellHeight*(yMin/precision)));
}

graphRgn = CreateRectRgn(xXAxis,yYAxis,int(xXAxis+
(cellWidth*(xCellNum+0.1))),int(yYAxis-(cellHeight*(yCellNum+0.5))));
}

void controller::drawGraph(HDC hdc)
{
// Pre: Central client area point(xZero,yZero) must be defined
otherwise error
// Post: Draw graph

int graphSize = functPnt.size()-1;
float xBeg,yBeg;
float xEnd,yEnd;
drawIntervals(hdc);
drawBorders(hdc);
drawText(hdc);
/*
for (int i=0; i<graphSize; i++) {
// Get the lines start point(x,y values)
xBeg = scaledPnt.at(i)->x;
ybeg = scaledPnt.at(i)->y;
// Get the lines end point(x,y values)
xEnd = scaledPnt.at(i+1)->x;
yEnd = scaledPnt.at(i+1)->y;
// Draw line
drawLine(hdc,(int)xBeg,(int)yBeg,(int)xEnd,
(int)yEnd,functionLine);
}*/

// draw function line from start point to end of graphs range
drawLine(hdc,int(scaledPnt.at(0)->x),int(scaledPnt.at(0)-
>y),int(xXAxis+(cellWidth*xCellNum)),int(yYAxis-
(cellHeight*yCellNum)),functionLine);
}

void controller::drawBorders(HDC hdc)
{
// Post: draw x scale & y scale lines/borders
drawLine(hdc,xXAxis,yXAxis,int(xXAxis+(cellWidth*(xCellNum
+0.1))),yXAxis,xBorder); // draw x axis
drawLine(hdc,xYAxis,yYAxis,xYAxis,int(yYAxis-(cellHeight*(yCellNum
+0.5))),yBorder); // draw y axis
}

void controller::drawText(HDC hdc)
{
// Post: Draw intervals labels (1,2,3,5);

int xb = xXAxis-3;
int yb = yXAxis+5;
char num[33];
HFONT hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SelectObject(hdc,hfDefault); // select default font
SetBkMode(hdc,TRANSPARENT);
//SetTextColor(hdc,RGB(255,255,255));
// draw x axis numbers
for (float i=xMin; i<=xMax; i+=precision) {
itoa((int)i,num,10);
TextOut(hdc,xb,yb,(LPCTSTR)num,3);
xb += (int)cellWidth;
}

xb = xYAxis-17;
yb = yYAxis-6;
// draw y axis numbers
for (float i=yMin; i<=yMax; i+=precision) {
itoa((int)i,num,10);
TextOut(hdc,xb,yb,(LPCTSTR)num,3);
yb -= (int)cellHeight;
}
DeleteObject(hfDefault); // release dynamic data
}

void controller::drawIntervals(HDC hdc)
{
// Post: Draws a line/mark at each cell interval along x & y
axis

int x,y;

// draw x axis markers
for (int i=0, x=(int)xXAxis, y=(int)yXAxis; i<=xCellNum; i++, x
+=(int)cellWidth) {
drawLine(hdc,x,y,x,y+4,intervalLine);
}
// draw y axis markers
for (int i=0, x=(int)xYAxis, y=(int)yYAxis; i<=yCellNum; i++, y-
=(int)cellHeight) {
drawLine(hdc,x,y,x-4,y,intervalLine);
}
}

void controller::drawFocus(HDC hdc)
{
// Post: - Determine & identify regions above & below function line
// - Draw lines from focusPnt to X Axis & focusPnt to the Y
Axis

HRGN xLine, yLine;
POINT xRgn[2];
POINT yRgn[2];

xRgn[0].x = scaledFocusPnt.x-1; xRgn[0].y = scaledFocusPnt.y+1;
xRgn[1].x = scaledFocusPnt.x+1; xRgn[1].y = xYAxis;
yRgn[0].x = scaledFocusPnt.x-1; yRgn[0].y = scaledFocusPnt.y-1;
yRgn[1].x = xYAxis; yRgn[1].y = scaledFocusPnt.y+1;

xLine = CreateRectRgn(xRgn[0].x,xRgn[0].y,xRgn[1].x,xRgn[1].y);
yLine = CreateRectRgn(yRgn[0].x,yRgn[0].y,yRgn[1].x,yRgn[1].y);

CombineRgn(focusRgn,xLine,yLine,RGN_XOR);
DeleteObject(xLine);
DeleteObject(yLine);

// Here I have 2 options to draw the lines, BOTH dont work

// Option 1:
HBRUSH hb = CreateSolidBrush(RGB(0,220,40));
FillRgn(hdc,focusRgn,(HBRUSH)hb);
// Option 2:
//drawLine(hdc,xRgn[0].x,xRgn[0].y,xRgn[1].x,xRgn[1].y,xBorder); //
Custom function that simply draws a line
//drawLine(hdc,yRgn[0].x,yRgn[0].y,yRgn[1].x,yRgn[1].y,xBorder);
}

void controller::eraseFocus(HWND hwnd)
{
// Post: Erases focusPnt's lines by invalidating client area
InvalidateRgn(hwnd,focusRgn,true);
//InvalidateRgn(hwnd,xLine,true);
//InvalidateRgn(hwnd,yLine,true);
}

bool controller::isNegative(vector<POINT*> v,char axis)
{
// Post: returns true if vector contains negative values

if (axis=='x') {
for (int i=0; i<v.size(); i++) {
POINT *p = v.at(i);
// if number is negative
if (p->x < 0) {
return true;
}
}
return false; // vector contains no positive values
}
else if (axis=='y') {
for (int i=0; i<v.size(); i++) {
POINT *p = v.at(i);
if (p->y < 0) {
return true;
}
}
return false;
}
else return true; // axis value is invalid
}

void controller::drawLine(HDC hdc,int xBeg,int yBeg, int xEnd, int
yEnd, HPEN hPen)
{
// Post: draw x,y Line & any other required lines

SelectObject(hdc,hPen); // need to add code to check if
SelectObject fails

MoveToEx(hdc,xBeg,yBeg,NULL);
LineTo(hdc,xEnd,yEnd);
}

bool controller::getValues(HWND hwnd, UINT controlMsg[])
{
// Post: Retrives values from GUI controls to calculate & draw
graph

UINT msgs[] =
{controlMsg[0],controlMsg[2],controlMsg[10],controlMsg[12],controlMsg[14]};
int tempVars[5];

for (int i=0; i<5; i++) {
BOOL success;
tempVars[i] = GetDlgItemInt(hwnd,msgs[i],&success,true);
// if control input is invalid
if (!success) {
MessageBox(hwnd,"One or more input fields are blank or
invalid. \nValid input includes numerical data & '-' operand.",
"Error",MB_OK|MB_ICONERROR);
return false;
}
}

getOpperand(hwnd,controlMsg[1]); // Get operand (+,-,* or /)

// Range cannot be <= 0
if (tempVars[3]<=0) {
tempVars[3] = 1;
}
// Precision cannot be <= 0
if (tempVars[4]<=0) {
tempVars[4] = 1;
}

m = tempVars[0];
b = tempVars[1];
xBegin = tempVars[2];
range = tempVars[3];
precision = tempVars[4];
xEnd = (xBegin+range);
return true;
}

void controller::getOpperand(HWND hwnd, UINT msg)
{
// Post: sets operand according to Combobox selection

int cell = SendDlgItemMessage(hwnd,msg,CB_GETCURSEL,0,0);

switch(cell) {

case 0: operand = '+'; break;
case 1: operand = '-'; break;
case 2: operand = '*'; break;
case 3: operand = '/'; break;
default: operand = '+';
break;
}
}

bool controller::collisionRect(int mouse_x, int mouse_y)
{
// Post: Returns true if mouse collides with Graph region(above or
below the
// function line) else false

if (PtInRegion(graphRgn,mouse_x,mouse_y) != 0) {
return true;
}
else return false;
}

bool controller::findInstanceNearest(HWND hwnd, UINT msg, int mouse_x,
int mouse_y)
{
// Post: Finds the closest 'function line' point to mouse position
&
// updates Focus Point(static control text)

int xDist = INT_MAX;
int yDist = INT_MAX;
POINT closestPnt;

// find which axis is closest to mouse pos
int xAxisDist = abs(yXAxis-mouse_y);
int yAxisDist = abs(xYAxis-mouse_x);

if (xAxisDist <= yAxisDist) { // if x axis is closest
for (int i=0; i<scaledPnt.size(); i++) {
POINT *tempP = scaledPnt.at(i);
int xTemp = abs(mouse_x-(int)tempP->x);
int yTemp = abs(mouse_y-(int)tempP->y);

if (xTemp < xDist) {
xDist = xTemp;
closestPnt.x = (int)functPnt.at(i)->x;
closestPnt.y = (int)functPnt.at(i)->y;
}
}
}
else { // y axis is closest
for (int i=0; i<scaledPnt.size(); i++) {
POINT *tempP = scaledPnt.at(i);
int xTemp = abs(mouse_x-(int)tempP->x);
int yTemp = abs(mouse_y-(int)tempP->y);

if (yTemp < yDist) {
yDist = yTemp;
closestPnt.x = (int)functPnt.at(i)->x;
closestPnt.y = (int)functPnt.at(i)->y;
}
}
}

// if closestPnt == focusPnt
if ((closestPnt.x != focusPnt.x) && (closestPnt.y != focusPnt.y)) {
focusPnt = closestPnt;
scaledFocusPnt.x = LONG(xZero + ((focusPnt.x-xMin)*cellWidth));
scaledFocusPnt.y = LONG(yZero - ((focusPnt.y-yMin)*cellHeight));
char buf[MAX_PATH];
sprintf(buf,"(%i, %i)",focusPnt.x,focusPnt.y);
SendDlgItemMessage(hwnd,msg,WM_SETTEXT,0,(LPARAM)buf); //
Display closest pnt coords in Static Control
return true;
}
else return false; // no need to redraw focus because focus pnt
hasn't changed
}

void controller::garbageCollection()
{
// Post: Delete all dynamically created variables/objects. Release
data

DeleteObject(xBorder); // delete objects
DeleteObject(yBorder);
DeleteObject(functionLine);
DeleteObject(intervalLine);
DeleteObject(graphRgn);
DeleteObject(focusRgn);
// delete all POINT* objects:
while (!functPnt.empty()) {
delete functPnt.back();
functPnt.pop_back();
}
while (!scaledPnt.empty()) {
delete scaledPnt.back();
scaledPnt.pop_back();
}
}

[/source]

winMain.cpp
[source]
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

#include "conGraph.h"

#define IDE_MVALUE 1
#define IDC_OPERAND 2
#define IDE_BVALUE 3
#define IDS_BORDER 4
#define IDS_FUNCTION 5
#define IDS_YLABEL 6
#define IDS_XLABEL 7
#define IDB_DRAWGRAPH 8
#define IDS_BORDER2 9
#define IDS_XMIN 10
#define IDE_XMIN 11
#define IDS_RANGE 12
#define IDE_RANGE 13
#define IDS_PRECISION 14
#define IDE_PRECISION 15
#define IDS_FOCUSPNT 16

const char g_szClassName[] = "myWindowClass";
static HINSTANCE gInstance;
controller graphCon;
bool drawGraph = true; // do we need to redraw graph
bool drawFocus = false;
UINT controlMsgs[] =
{IDE_MVALUE,IDC_OPERAND,IDE_BVALUE,IDS_BORDER,IDS_FUNCTION,IDS_YLABEL,IDS_XLABEL,

IDB_DRAWGRAPH,IDS_BORDER2,IDS_XMIN,IDE_XMIN,IDS_RANGE,IDE_RANGE,IDS_PRECISION,
IDE_PRECISION,IDS_FOCUSPNT};

// Functions List //
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
lParam);


int WINAPI WinMain(HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = gInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

// if registration of main class fails
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}

// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Graph Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500, 500,
NULL, NULL, gInstance, NULL);

if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
lParam)
{
//HDC hdc;
switch(msg)
{
case WM_CREATE:

graphCon.createGUI(hwnd,gInstance,controlMsgs);
graphCon.calculateGraphStats(hwnd);
break;
case WM_SIZE:
// Reallign controls & graph when client window is
resized
RECT clientR;
GetClientRect(hwnd,&clientR);
// Check that client area is not less than minimum
width & height
if (clientR.right >400 && clientR.bottom >400 ) {
graphCon.resizeClientArea(hwnd,controlMsgs);
graphCon.calculateGraphStats(hwnd);
drawGraph = true;
InvalidateRect(hwnd,NULL,true);
}
else MessageBox(hwnd,"Graph cannot be drawn when
window is less than 400/400 pixels",
"Error",MB_OK|MB_ICONERROR);
break;
case WM_MOUSEMOVE:
{
if
(graphCon.collisionRect(LOWORD(lParam),HIWORD(lParam))==true) {
// if focusPnt has changed
if
(graphCon.findInstanceNearest(hwnd,IDS_FOCUSPNT,LOWORD(lParam),HIWORD(lParam))
== true) { // find nearest function line pnt to mouse
pos
drawFocus = true;
graphCon.eraseFocus(hwnd);
}
}
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam)) {

case IDB_DRAWGRAPH:
{ // Draw graph
// if all input variables are valid
if (graphCon.getValues(hwnd,controlMsgs)==true) {
graphCon.calculateGraphStats(hwnd);
drawGraph = true;

InvalidateRect(hwnd,NULL,true);
}
}
break;
default:
break;
}
}
break;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;

hdc = BeginPaint(hwnd,&ps);

if (drawFocus) {
graphCon.drawFocus(hdc);
drawFocus = false;
}
if (drawGraph) {
graphCon.drawGraph(hdc);
drawGraph = false;
}

EndPaint(hwnd,&ps);
}
break;
case WM_CLOSE:
graphCon.garbageCollection(); // release dynamic data
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

[/source]
 | 
Pages: 1
Prev: U++ 2232 released
Next: SwapBuffers()