Jump to content
  • Advertisement
Sign in to follow this  
gretty

Supposed to Draw Lines to mouse but doesn't

This topic is 2995 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello have a graph application that draws a graph onto the client area. It is also 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: conGraph.cpp 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
#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,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 = GetDlgItemInt(hwnd,msgs,&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();
   }       
}


winMain.cpp
#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;
}


Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!