Sign in to follow this  
gretty

Time Finding Function Problem

Recommended Posts

Hello I have a win32 c++ application that shows a map of the world & the local time at a selected city. But for some reason the local time is all random numbers when it was showing the correct time before with my function. I changed some things so you could select 12hr or 24hr time format but I cant see why my local time is not working now. Can you help me see why the time function broke. This is my application before I made the changes & the time works(is correct): http://www.mediafire.com/?nlmmzdzz3y4 - 120kb And here is the latest version of the app where the time comes out as like "18300:05 pm": http://www.mediafire.com/?ajzw3zzhkmm - 125kb PS: On a side note; what do you think of the code? Is it efficient, good, are there any mistakes or things that should be done better when making applications? And here is my code: class
#include <windows.h>
#include <windowsx.h>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <string>
#include <cmath>
#include <ctime>

#include "conWorldCoord.h"

using namespace std;

controller::controller()
{
    // Constructor 
    
    // Load Bitmaps - World map & dot
    mapImg = (HBITMAP)LoadImage(NULL,"worldMapScaled.bmp",IMAGE_BITMAP,0,0,
                                LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
                     
    cityImg = (HBITMAP)LoadImage(NULL,"dot.bmp",IMAGE_BITMAP,0,0,
                                 LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
    // if load fails                     
    if (cityImg==NULL || mapImg==NULL) {
         MessageBox(NULL,"Failed to load bitmaps","Error",MB_OK | MB_ICONERROR);
    }  
           
    // get cityBmp offsets 
    GetObject(cityImg,sizeof(bm),&bm);
    xImgOffset = bm.bmWidth/2;
    yImgOffset = bm.bmHeight/2;
    
    focus = "City Focus = ";
    cityStr = "New York";     // should be cityFocus->name;
    index = 0;
    timeFormat = false;       // False = 12 hr format | True = 24 hr format
    
    registerCities();         // register cities
}

void  controller::createGUI(HWND hwnd, HINSTANCE gInstance, UINT controlMsg[])
{
     // Post: create GUI 

     HFONT hfDefault;
     hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT); // set font
     focusStr = focus+cityStr+localTime();  // focusStr="City Focus = New York"
             
     HWND stCityFocus = CreateWindowEx(0,"Static",focusStr.c_str(),WS_BORDER | WS_CHILD | WS_VISIBLE | SS_CENTER, 
                                     30,400,250,16,hwnd,(HMENU)controlMsg[0],gInstance,NULL);
             
     HWND btPrev = CreateWindowEx(0,"Button","Prev",WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     410,400,70,20,hwnd,(HMENU)controlMsg[1],gInstance,NULL);
                                     
     HWND btNext = CreateWindowEx(0,"Button","Next",WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     490,400,70,20,hwnd,(HMENU)controlMsg[2],gInstance,NULL);
     
     // create radio buttons to select 24hr or 12hr time format
     HWND rdBtTime1 = CreateWindowEx(0,"Button","12hr",WS_BORDER | WS_VISIBLE | WS_CHILD | WS_GROUP | BS_AUTORADIOBUTTON,
                                    100,420,50,17,hwnd,(HMENU)controlMsg[3],gInstance,NULL); 
                                    
     HWND rdBtTime2 = CreateWindowEx(0,"Button","24hr",WS_BORDER | WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
                                    155,420,50,17,hwnd,(HMENU)controlMsg[4],gInstance,NULL); 
     
     // draw world map & dot                              
     stMapImg = CreateWindowEx(0,"Static","",WS_CHILD | WS_VISIBLE | SS_BITMAP,
                                  20,10,540,380,hwnd,(HMENU)controlMsg[5],gInstance,NULL);
                                     
     stDotImg = CreateWindowEx(0,"Static","",WS_CHILD | WS_VISIBLE | SS_BITMAP,
                               185-xImgOffset,140-yImgOffset,CW_USEDEFAULT, CW_USEDEFAULT,hwnd,
                               (HMENU)controlMsg[6],gInstance,NULL);
                
     // Set window fonts
     for (int i=0; i<5; i++) {
         SendMessage(GetDlgItem(hwnd,controlMsg[i]),WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0));
     }
     //SendMessage(btPrev,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0));
     //SendMessage(btNext,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0));
     //SendMessage(rdBtTime1,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0));
     //SendMessage(rdBtTime2,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0));
     
                     
     // Display bitmaps
     SendMessage(stMapImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)mapImg);
     SendMessage(stDotImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)cityImg);
     
     // Set 12hr format radiobutton as checked
     Button_SetCheck(rdBtTime1,BST_CHECKED);     
} 

void  controller::registerCities()
{
    // Post: Create/Declare & define city data
    city *NewYork = new city;
    city *London = new city;
    city *Sydney = new city;
    // store cities in global vector
    cityList.push_back(NewYork);
    cityList.push_back(London);
    cityList.push_back(Sydney);
    
    NewYork->name = "New York";
    NewYork->x = 185;      // should be AppWidth-150 etc.
    NewYork->y = 140;      // should be AppHeight-250 etc.
    NewYork->bias = 5*60;  // convert 5 hrs into minutes
    
    London->name = "London";
    London->x = 288;
    London->y = 110;
    London->bias = 0;
    
    Sydney->name = "Sydney";
    Sydney->x = 490;
    Sydney->y = 265;
    Sydney->bias = -10*60;
    
    //set focus city to 1st city
    focusCity = cityList.at(0);
}       
         
void  controller::setFocusCity(bool next)
{
     // Post: Sets cityFocus to next or previous city depending on bool next value
     
     // If next is true we want to advance our city focus
     if (next) {
         // make sure index is not > size of cityList vector
         if (index < cityList.size()-1) {
             index += 1;
         }
         else index = 0;
     }
     else if (!next) { // we want to focus on previous city
         
         if (index != 0) {
             index -= 1;
         }
         else index = cityList.size()-1;
     }
                      
     // append which city we are now focusing on
     focusCity = cityList.at(index);          
}

bool  controller::setFocusCity(int mouseX, int mouseY)
{
      // Post: finds closest city to mouse position/Coords & selects it
      
      city* nearestCity = instanceNearest(mouseX,mouseY);
      
      // if the closest city to mouse pos.. is not our focusCity(not already selected)
      if (nearestCity != focusCity) {
          focusCity = nearestCity;
          return true;
      }
      else return false;
}

void  controller::displayLocalTime(HWND hwnd, UINT cityName)
{
   // Post: Display focus citys' local time
   
   cityStr = focusCity->name;
   focusStr = focus+cityStr+localTime();
   SetDlgItemText(hwnd,cityName,(LPTSTR)focusStr.c_str());
}

void  controller::drawCityBmp(HWND hwnd, UINT bmpMapMsg, UINT bmpDotMsg)
{
     // Post: Draw dot bmp at location of current focus city
     
     // create bmp coords by compensating for x,y offset
     int xPos = (focusCity->x)-xImgOffset;
     int yPos = (focusCity->y)-yImgOffset;
     
     // reset city dot bmp position
     SetWindowPos(stDotImg,HWND_TOP,xPos,yPos,CW_USEDEFAULT, CW_USEDEFAULT,SWP_ASYNCWINDOWPOS);
          
     // Redraw world map & city dot    
     SendMessage(stMapImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)mapImg);
     SendMessage(stDotImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)cityImg);
}
         
float controller::pointDistance(int x1, int y1, int x2, int y2)
{
      return (sqrt( ((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)) ));
}

city* controller::instanceNearest(int x, int y)
{
     // Pre: cityList/instance count of object MUST be > 0
     // Post: returns the instance closest to specified point
     
     float dist = INT_MAX;
     int size = cityList.size();
     
     for (int i=0; i<size; i++) {
         
         float myDist = pointDistance(x,y,cityList.at(i)->x,cityList.at(i)->y);
         
         if (myDist < dist) {
             dist = myDist;
             index = i;     // record vector cityList index of focus
         }
     }
     
     return cityList.at(index);
}

string controller::localTime()
{
    // Post: Returns focus cities local time
    // NOTE AT PRESENT: function doesn't compensate for Daylight savings. Need 2 change this
    
    SYSTEMTIME ut, cityTime;
    TIME_ZONE_INFORMATION tz;
    
    tz.Bias = focusCity->bias; 
    tz.StandardBias = 0;
    tz.DaylightBias = -60;
    
    GetSystemTime(&ut);    
    SystemTimeToTzSpecificLocalTime(&tz,&ut,&cityTime);

    // convert Universal time to focusCity time
    int hour = cityTime.wHour;
    int minute = cityTime.wMinute;
    
    // convert time from int to string
    stringstream out;
    
    // if time format == 12hr format
    if (!timeFormat) {
        // if hour is negative num
        if (hour <= 0) {
            out << (hour+12);
        }
        //else if (hour < 12) {   // && hour > 0
            //out << "0" << hour;
        //}
        else if (hour > 12) {
            out << (hour-12);
        }
        else out << hour;  // hour = 12pm
    }
    else out << hour; // time format == 24hr format
    
    if (minute < 10) {
        out << ":0" << minute;
    }
    else out << ":" << minute;
    
    string localT = "  Local Time = "+out.str();
    out.str(""); // clear stringstream
    
    return localT;
}

bool controller::setTimeFormat(bool state)
{
   // Post: Toggles time format display to either 12 hour format or 24 hour format
   
   if (state != timeFormat) {
       timeFormat = !timeFormat;
       return true;
   } 
   else return false;
   // could just as easily forgo 'if' statement & just say 
   //   timeFormat = state;
   // But want to show being precise & secure although at the risk of speed & efficiency
}

Winmain.cpp
/*
  Application: Displays a world map & a dot at position of the 
               city we are focused on
*/

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <string>
#include <cstdlib>

#include "conWorldCoord.h"

using namespace std;

#define IDB_NEXT  1
#define IDB_PREV  2
#define IDT_CNAME 3
#define IDB_MAP   4
#define IDB_DOT   5
#define IDB_12HR  6
#define IDB_24HR  7

static HINSTANCE gInstance;
controller control;
UINT controlMsgs[] = {IDT_CNAME,IDB_PREV,IDB_NEXT,IDB_12HR,IDB_24HR,IDB_MAP,IDB_DOT};


// 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 = "Custom Class";
    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,
        "Custom Class",
        "Displays the Local Time of World Cities",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 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)
{
    
    switch(msg)
    {
        case WM_CREATE:
        {                  
             // Create GUI
             control.createGUI(hwnd,gInstance,controlMsgs);
        }    
        break;
        case WM_PAINT: // Necessary to draw city focus dot
        {
             
        }
        break;
        case WM_LBUTTONDOWN:
                // select city closest to mouse position if not ALREADY selected
                if (control.setFocusCity(LOWORD(lParam),HIWORD(lParam))==true) {
                    control.drawCityBmp(hwnd,IDB_MAP,IDB_DOT);  // call function to draw dot on newly selected city
                    control.displayLocalTime(hwnd,IDT_CNAME);
                }
        break;
        case WM_COMMAND:
        {
             switch(LOWORD(wParam)) {
                         
                  case IDB_NEXT:
                  {       
                          control.setFocusCity(true);                 // advance focus to next city
                          control.drawCityBmp(hwnd,IDB_MAP,IDB_DOT);  // call function to draw dot on new city
                          control.displayLocalTime(hwnd,IDT_CNAME);
                  }
                  break; 
                  case IDB_PREV:
                  {     
                          control.setFocusCity(false);                // set focus to previous city
                          control.drawCityBmp(hwnd,IDB_MAP,IDB_DOT);  // call function to draw dot on new city
                          control.displayLocalTime(hwnd,IDT_CNAME);
                  }
                  break; 
                  case IDB_12HR:
                  {       // if not already set to 12hr format
                          if (control.setTimeFormat(false)==true) {
                             control.displayLocalTime(hwnd,IDT_CNAME);  // toggle time format to 12hr
                          }
                  }     
                  break;
                  case IDB_24HR:
                  {       // if not already set to 24hr format
                          if (control.setTimeFormat(true)==true) {
                             control.displayLocalTime(hwnd,IDT_CNAME);  // toggle time format to 24hr
                          }
                  }     
                  break;         
                  default:
                  break;
             }
        }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default: return DefWindowProc(hwnd, msg, wParam, lParam);
        break;
    }
}



Share this post


Link to post
Share on other sites
no responses :(

I have the function where I believe the error maybe occuring so you dont have to go over mountains of code. But I have gone over it numerous times & cant seem to find why my time function gives the wrong time when it was working before?

I really encourage you to download the app, because its easy to see whats going wrong that way, plus its less than megabyte in size.

Function:

string controller::localTime()
{
// Post: Returns focus cities local time
// NOTE AT PRESENT: function doesn't compensate for Daylight savings. Need 2 change this

SYSTEMTIME ut, cityTime;
TIME_ZONE_INFORMATION tz;

tz.Bias = focusCity->bias;
tz.StandardBias = 0;
tz.DaylightBias = -60;

GetSystemTime(&ut);
SystemTimeToTzSpecificLocalTime(&tz,&ut,&cityTime);

// convert Universal time to focusCity time
int hour = cityTime.wHour;
int minute = cityTime.wMinute;

// convert time from int to string
stringstream out;

// if time format == 12hr format
if (!timeFormat) {
// if hour is negative num
if (hour <= 0) {
out << (hour+12);
}
//else if (hour < 12) { // && hour > 0
//out << "0" << hour;
//}
else if (hour > 12) {
out << (hour-12);
}
else out << hour; // hour = 12pm
}
else out << hour; // time format == 24hr format

if (minute < 10) {
out << ":0" << minute;
}
else out << ":" << minute;

string localT = " Local Time = "+out.str();
out.str(""); // clear stringstream

return localT;
}

bool controller::setTimeFormat(bool state)
{
// Post: Toggles time format display to either 12 hour format or 24 hour format

if (state != timeFormat) {
timeFormat = !timeFormat;
return true;
}
else return false;
// could just as easily forgo 'if' statement & just say
// timeFormat = state;
// But want to show being precise & secure although at the risk of speed & efficiency
}


Share this post


Link to post
Share on other sites
Quote:
Original post by gretty
no responses :(


Yeah, sheesh. You'd expect a flood of responses in the ten minutes since the post has been made.

Share this post


Link to post
Share on other sites
As useless as it is, I feel I need to correct you. This thread was made YESTURDAY

But I'd welcome contstuctive criticism.

Share this post


Link to post
Share on other sites
Quote:
Original post by the_edd
Quote:
Original post by gretty
no responses :(


Yeah, sheesh. You'd expect a flood of responses in the ten minutes since the post has been made.


One day and 10 minutes.


Try to zero out the structures:

ZeroMemory(&ut, sizeof(SYSTEMTIME));
ZeroMemory(&cityTime, sizeof(SYSTEMTIME));
ZeroMemory(&tz, ...)

Share this post


Link to post
Share on other sites
Quote:
Original post by gretty
As useless as it is, I feel I need to correct you. This thread was made YESTURDAY

But I'd welcome contstuctive criticism.


Apologies.

Have you tried diffing the code and making changes one by one to determine the first thing that breaks the old code? Your version control system could help with this.

Have you tried running the code through a debugger to find the first point where it diverges from your expectations?

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus

Try to zero out the structures:

ZeroMemory(&ut, sizeof(SYSTEMTIME));
ZeroMemory(&cityTime, sizeof(SYSTEMTIME));
ZeroMemory(&tz, ...)


Thanks :D

The time is correct again :)

Why does that happen? I thought that because those variables(ut,cityTYime & tz) are created in a function, then they would be destroyed when the function ends so then there would be no residual information in them the next time I use the function because they dont exist yet?

Or is this the junk information in them when I create them in the function?

Thanks again

Share this post


Link to post
Share on other sites
When you first create an object, all that happens is that the program picks a place for the object to live. So the contents of the object is just whatever was last in that memory location, which could be anything. That's why you have to clear it out yourself.

Share this post


Link to post
Share on other sites
Quote:
Original post by gretty
I thought that because those variables(ut,cityTYime & tz) are created in a function


They are allocated, but not initialized. So the memory they hold (on stack) is valid, but the values are whatever was on that part of stack memory before.


When working with C APIs (Windows is that), always initialize or zero the structures.

Share this post


Link to post
Share on other sites
Your registerCities function fails to make appropriate use of constructors.
Here's one take on how it could look:

void controller::registerCities()
{
// store cities in global vector
cityList.push_back(new city("New York", 185, 140, 5*HOURS_TO_MINUTES));
cityList.push_back(new city("London", 288, 110, 0*HOURS_TO_MINUTES));
cityList.push_back(new city("Sydney", 490, 265, -10*HOURS_TO_MINUTES));

//set focus city to 1st city
focusCity = cityList.front();
}

All that I've done here is show how the code looks when an appropriate constructor is used (coding the constructor is left as an exercise, but it's very simple). There's still the matter of whether this should be storing pointers rather than objects (prefer objects), and whether this information should be read from a config file rather than being hard-coded.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this